diff --git a/.github/workflows/docker-image-accountsvc.yml b/.github/workflows/docker-image-accountsvc.yml deleted file mode 100644 index 0338934..0000000 --- a/.github/workflows/docker-image-accountsvc.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Docker Image CI - Account Sevice - -on: - push: - branches: [ "main" ] - paths: - - "account_service/**" - - ".github/workflows/docker-image-accountsvc.yml" - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Start MongoDB container - run: docker run -d -p 27017:27017 --name test-mongo mongo:6 - - # Test - - name: Run test for account service - env: - PORT: 3030 - NODE_ENV: test - JWT_SECRET_KEY: MySecret - MONGO_URI: mongodb://localhost:27017/spendwise - run: | - cd account_service - npm install - npm test - - # Containerization - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Build and push Docker image - run: | - docker build -t tut888/sit737-account-service:autobuild ./account_service - docker push tut888/sit737-account-service:autobuild - diff --git a/.github/workflows/docker-image-expensesvc.yml b/.github/workflows/docker-image-expensesvc.yml deleted file mode 100644 index fff9808..0000000 --- a/.github/workflows/docker-image-expensesvc.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Docker Image CI - Expense Sevice - -on: - push: - branches: [ "main" ] - paths: - - "expense_service/**" - - ".github/workflows/docker-image-expensesvc.yml" - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Start MongoDB container - run: docker run -d -p 27017:27017 --name test-mongo mongo:6 - - # Test - - name: Install dependencies for account service - run: | - cd account_service - npm install - - - name: Run test for expense service - env: - PORT: 3032 - NODE_ENV: test - MONGO_URI: mongodb://localhost:27017/spendwise - run: | - cd expense_service - npm install - npm test - - # Containerization - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Build and push Docker image - run: | - docker build -t tut888/sit737-expense-service:autobuild ./expense_service - docker push tut888/sit737-expense-service:autobuild diff --git a/.github/workflows/test-accountsvc.yml b/.github/workflows/test-accountsvc.yml new file mode 100644 index 0000000..b3e761d --- /dev/null +++ b/.github/workflows/test-accountsvc.yml @@ -0,0 +1,36 @@ +name: Test - Account Sevice + +on: + push: + branches: [ "main" ] + paths: + - "backend/account_service/**" + - ".github/workflows/**-accountsvc.yml" + + pull_request: + branches: [ "main" ] + paths: + - "backend/account_service/**" + - ".github/workflows/**-accountsvc.yml" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Start MongoDB container + run: docker run -d -p 27017:27017 --name test-mongo mongo:6 + + # Test + - name: Run test for account service + env: + PORT: 3030 + NODE_ENV: test + JWT_SECRET_KEY: MySecret + MONGO_URI: mongodb://localhost:27017/spendwise + run: | + cd backend/account_service + npm install + npm test \ No newline at end of file diff --git a/.github/workflows/test-expensesvc.yml b/.github/workflows/test-expensesvc.yml new file mode 100644 index 0000000..dc58dfc --- /dev/null +++ b/.github/workflows/test-expensesvc.yml @@ -0,0 +1,41 @@ +name: Test - Expense Sevice + +on: + push: + branches: [ "main" ] + paths: + - "backend/expense_service/**" + - ".github/workflows/**-expensesvc.yml" + + pull_request: + branches: [ "main" ] + paths: + - "backend/expense_service/**" + - ".github/workflows/**-expensesvc.yml" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Start MongoDB container + run: docker run -d -p 27017:27017 --name test-mongo mongo:6 + + # Test + - name: Install dependencies for account service + run: | + cd backend/account_service + npm install + + - name: Run test for expense service + env: + PORT: 3032 + NODE_ENV: test + MONGO_URI: mongodb://localhost:27017/spendwise + run: | + cd backend/expense_service + npm install + npm test + \ No newline at end of file diff --git a/.github/workflows/docker-image-frontendsvc.yml b/.github/workflows/test-frontendsvc.yml similarity index 59% rename from .github/workflows/docker-image-frontendsvc.yml rename to .github/workflows/test-frontendsvc.yml index 4e116bf..b70fb5a 100644 --- a/.github/workflows/docker-image-frontendsvc.yml +++ b/.github/workflows/test-frontendsvc.yml @@ -1,11 +1,17 @@ -name: Docker Image CI - Frontend Sevice +name: Test - Frontend Sevice on: push: branches: [ "main" ] paths: - "frontend/**" - - ".github/workflows/docker-image-frontendsvc.yml" + - ".github/workflows//**-frontendsvc.yml" + + pull_request: + branches: [ "main" ] + paths: + - "frontend/**" + - ".github/workflows/**-frontendsvc.yml" jobs: build: @@ -20,12 +26,12 @@ jobs: # Test - name: Install dependencies for account service run: | - cd account_service + cd backend/account_service npm install - name: Install dependencies for expense service run: | - cd expense_service + cd backend/expense_service npm install - name: Run test for frontend service @@ -39,16 +45,4 @@ jobs: run: | cd frontend npm install - npm run test:e2e - - # Containerization - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Build and push Docker image - run: | - docker build -t tut888/sit737-frontend-service:autobuild ./frontend - docker push tut888/sit737-frontend-service:autobuild + npm run test:e2e \ No newline at end of file diff --git a/README.md b/README.md index 6ae5650..238f13f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ - -# SpendWise: SIT737-2025-Task 11.1HD +# SpendWise - Microservice with CI/CD on GCP SpendWise is a cloud-native application project that enables users to manage and monitor personal expenses. It provides tools for tracking spending over time. @@ -12,379 +11,169 @@ The project is configured **CI with GitHub Actions**, any update on main branch ![Account](images/account.png) ![Expense](images/expense.png) -# Table of Contents -- [About the project](#about-the-project) - - [How to run](#how-to-run) - - [How to test](#how-to-test) - - [CI-CD instruction](#ci-cd-instruction) -- [Containerization](#containerization) -- [Google Cloud Platform Deployment](#google-cloud-platform-deployment) - - [GCP Kubernetes Cluster setup](#gcp-kubernetes-cluster-setup) - - [Apply Deployment and Service](#apply-deployment-and-service) - - [Check the running pods and services](#check-the-running-pods-and-services) -- [Monitoring the application](#monitoring-the-application) - - [Monitoring in the Cloud Console Web UI (requires permission)](#monitoring-in-the-cloud-console-web-ui) - - [Monitoring with commands](#monitoring-with-commands) -- [Project clean up](#project-clean-up-optional) -- [Troubleshooting](#troubleshooting) - - [Useful commands](#useful-commands) - - [Some encountered issues](#useful-commands) - # About the project The cloud‑native application consists of three services: frontend, account, and expense. - The **frontend** acts as the **main entry point**, exposed via an **external IP address** and accessed by users. It communicates with the account and expense services to process user requests. - The **account and expense services** communicate with the frontend and with each other through **cluster IPs**, restricting external access. - The application uses a **centralized authentication system with JWT**, requiring all protected resources to verify user credentials through the dedicated account service before granting access. This ensures secure and **consistent authorization across all microservices**. -## How to run + +# CI-CD pipeline + +CI/CD workflow is created using GitHub Actions. However, due to limited permission, **CI/CD workflow stop at publishing image to Docker Hub**. +- Current workflow is: commit & push -> trigger auto testing -> auto build image -> auto publish to Docker Hub +- The later step after publishing image is apply changes to GKE. The example of workflow configuration is commented at `.github/workflows/docker-image-accountsvc.yml` + +As a workaround, below is an alternative solution for GKE deployment: +- Use the tag `autobuild` for automated-built image by GitHub Actions, avoid using original tag in deployment `.yaml` file in case the new image has error +- Manually apply the changes to GKE using `set image` and `rollout restart` commands. Below code is example for account service deployment + ```bash + # For first time using `autobuild` tag -> we need to set new image tag for deployed image + kubectl set image deployment/accountsvc-deployment accountsvc-container=tut888/sit737-account-service:autobuild + + # For later updates -> we only need to restart the deployment to re-pull new image + kubectl rollout restart deployment/accountsvc-deployment + ``` + +# Instruction +## Start the application ### Run all with docker compose -Start all services with: -``` -docker compose up -``` -Access the application (frontend): `http://localhost:3380` +- Start all services: + ```bash + docker compose up + ``` +- Access the application (frontend): `http://localhost:3380` ### Run individually -Start all services: -- Account service - ``` - cd account_service - npm install - npm start - ``` -- Expense service - ``` - cd expense_service - npm install - npm start - ``` -- Frontend service - ``` - cd frontend +- Start service one by one (Account, Expense and Frontend): + ```bash + cd npm install npm start ``` - Access the application (frontend): `http://localhost:3081` -## How to test +## Run the test > **The project configured CI/CD with GitHub Actions, any update on main branch will automatically trigger the test and build new images.** > - Account service & expense service: unit testing with Mocha/Chai > - Frontend service: end to end testing with Cypress For manually run the test, type below commmands -- Test account service: +- Test backend services: ``` - cd account_service + cd npm test ``` -- Test expense service: - ``` - cd expense_service - npm test - ``` -- Test frontend service: +- Test frontend: ``` cd frontend npm run test:e2e ``` -## CI-CD instruction -CI/CD workflow is created using GitHub Actions. However, due to limited permission, **CI/CD workflow stop at publishing image to Docker Hub**. -- Current workflow is: commit & push -> trigger auto testing -> auto build image -> auto publish to Docker Hub -- The later step after publishing image is apply changes to GKE. The example of workflow configuration is commented at `.github/workflows/docker-image-accountsvc.yml` - -As a workaround, below is an alternative solution for GKE deployment: -- Use the tag `autobuild` for automated-built image by GitHub Actions, avoid using original tag in deployment `.yaml` file in case the new image has error -- Manually apply the changes to GKE using `set image` and `rollout restart` commands. Below code is example for account service deployment - ```bash - # For first time using `autobuild` tag -> we need to set new image tag for deployed image - kubectl set image deployment/accountsvc-deployment accountsvc-container=tut888/sit737-account-service:autobuild - - # For later updates -> we only need to restart the deployment to re-pull new image - kubectl rollout restart deployment/accountsvc-deployment - ``` +## Containerize with Docker +> Prerequisite: +> - Docker Desktop must be installed +> - Detail instruction please refer to my documentation at [Docker Documentation](./docs/DOCKER.md) -# Containerization Each service is developed separately in its own directory, with a corresponding Dockerfile. -Run the following commands to containerize the application into Docker images +Run the following commands to containerize all images at once ```bash -docker build -t sit737-account-service ./account_service -docker build -t sit737-expense-service ./expense_service -docker build -t sit737-frontend-service ./frontend +docker compose build ``` Tag the images and push them to Docker Hub: ```bash -docker tag sit737-account-service tut888/sit737-account-service -docker push tut888/sit737-account-service +docker tag spendwise-account-service /spendwise-account-service +docker push /spendwise-account-service -docker tag sit737-frontend-service tut888/sit737-frontend-service -docker push tut888/sit737-frontend-service +docker tag spendwise-expense-service /spendwise-expense-service +docker push /spendwise-expense-service -docker tag sit737-expense-service tut888/sit737-expense-service -docker push tut888/sit737-expense-service +docker tag spendwise-frontend /spendwise-frontend +docker push /spendwise-frontend ``` -# Google Cloud Platform Deployment -## GCP Kubernetes Cluster setup -> Prerequisite: -> - A Google Cloud Console account & project -> - Google Cloud SDK Shell installed and configured on your computer -> -> These steps have already been completed in **Task 5.2D** at [TUT888/sit737-2025/tree/prac5d](https://github.com/TUT888/sit737-2025/tree/prac5d) +## Deploy with Kubernetes +> Prerequisite: +> - Docker Desktop must be installed, Kubernetes must be enabled. Alternatively, any other k8s engine such as Minikube can also be used for your preference. +> - Detail instruction please refer to my documentation at [Kubernetes Documentation](./docs/KUBERNETES.md) -Use the Google Cloud SDK Shell to remotely connect to the GCP platform and apply configuration files stored locally. +### Google Cloud Setup -### Login -- Open the Google Cloud SDK Shell. -- Log in and configure the project: - ```bash - gcloud auth login - gcloud config set project # Ex: sit737-25t1-fname-lname-xxxxxx - gcloud config set compute/zone # Ex: australia-southeast1-b - ``` -### Create Kubernetes Cluster -We can create a Kubernetes Cluster by providing its name, number of nodes and the compute zone. In this case, our cluster has: -- Name: `simple-k8s-cluster` -- Number of nodes: 1 node (one virtual machine/instance) per zone. If we set `--num-nodes=3`, GCP would spin up 3 virtual machines (nodes), allowing your workloads to be distributed across them for high availability, scalability, and resilience. - -The command ```bash -gcloud container clusters create simple-k8s-cluster --num-nodes=1 --zone=australia-southeast1-b -``` -After successfully created a cluster, we confirm it by listing all cluster with: -```bash -gcloud container clusters list -``` +# Create service account with optional display name +gcloud iam service-accounts create --display-name +# Check your created accounts +gcloud iam service-accounts list --project +# Assign roles for service account (we need it for permission to access the resources) +# Some common roles are: container.admin, artifactregistry.reader, logging.logWriter monitoring.metricWriter -### Authenicate the cluster +gcloud projects add-iam-policy-binding \ + --member="serviceAccount:@.iam.gserviceaccount.com" \ + --role="roles/" -Before using, we must authenticate `kubectl` with the newly created cluster by getting credential with following command: -```bash -gcloud container clusters get-credentials simple-k8s-cluster --location=australia-southeast1-b +# Create k8s cluster +gcloud container clusters create \ + --enable-autoscaling --min-nodes 1 --max-nodes 4 \ + --num-nodes=1 \ + --zone= \ + --service-account @.iam.gserviceaccount.com ``` -## Apply Deployment and Service -Navigate to your project directory where the deployment `.yaml` files are stored -```bash -cd -``` +gcloud container clusters create spendwise-k8s-cluster --num-nodes=1 --zone=australia-southeast1-b --enable-autoscaling --min-nodes 1 --max-nodes 4 --service-account spendwise-gke@spendwise-486202.iam.gserviceaccount.com --enable-ip-alias -Apply the MongoDB deployment: -```bash -kubectl apply -f mongodb-pvc.yaml -kubectl apply -f mongodb-secret.yaml -kubectl apply -f mongodb-deployment.yaml -``` +# Get credentials and switch to cloud context (kubectl) +gcloud container clusters get-credentials spendwise-k8s-cluster --location=australia-southeast1-b -Apply the service deployments -```bash -kubectl apply -f frontendsvc-deployment.yaml -kubectl apply -f accountsvc-deployment.yaml -kubectl apply -f expensesvc-deployment.yaml -``` -## Check the running pods and services -### Check the running pods +### Deployment +> Detail instruction for **GCP deployment** please refer to my documentation at [GCP Documentation](./docs/GCP.md) -If 3 replicas are specified in the deployment YAML, you should see 3 pods running. In this case, only 1 replica is used -```bash -kubectl get pods -``` +- Check and swith to your target **kubectl context** + - Check context + ```bash + # Get all contexts + kubectl config get-contexts -### Check the running services -```bash -kubectl get services -``` -The Cloud Shell should return a table like: -| NAME | TYPE | CLUSTER-IP | EXTERNAL-IP | PORT(S) | AGE | -| --- | --- | --- | --- | --- | --- | -| kubernetes | ClusterIP | 11.222.224.1 | none | 443/TCP | 15m | -| frontendsvc-service | LoadBalancer | 11.222.224.210 | **pending** | 3080:30142/TCP | 12s | -| accountsvc-service | ClusterIP | 11.222.231.12 | none | 3330/TCP | 10s | -| expensesvc-service | ClusterIP | 11.222.236.138 | none | 3332/TCP | 9s | -| my-mongo-svc | ClusterIP | 11.222.236.138 | none | 27017/TCP | 20s | - -Once the `EXTERNAL-IP` is ready, it will appear. Access the application using -``` -http://:3080/ -``` - -For example, if the `EXTERNAL-IP` shows 11.222.3.101, we can access our application with: -``` -http://11.222.3.101:3080/ -``` - -**Then the deployment is completed!** - -# Monitoring the application -## Monitoring in the Cloud Console Web UI -Google Cloud Platform provides a web-based UI for application monitoring. -Steps: - -1. Open Google Cloud Console. -2. Navigate to the **Monitoring** tab in the side menu. -3. Select **Metrics Explorer**. -4. Set the resource type to Kubernetes Container. -5. Choose metrics to view, such as: - - `kubernetes.io/container/cpu/request_utilization` - - `kubernetes.io/container/memory/request_utilization` - -> **Note:** If you do not have permission to set the resource type to Kubernetes Container, use the CLI commands in the next section - -**In this task, since I don't have the permission to set the *Resource Type* to *Kubernetes Container*, the monitoring will be done using the commands in next section** - -## Monitoring with commands -### View resource usage -Get pod-level CPU and memory usage: -```bash -kubectl top pod -``` - -Get pod network details for a specific pod: -```bash -kubectl describe pod -``` - -Get node-level (cluster) resource usage: -```bash -kubectl top nodes -``` + # Check current context + kubectl config current-context + ``` + - Switch context + ```bash + # Option 1: Use docker desktop (local deployment) + kubectl config use-context docker-desktop -### View the logs -```bash -kubectl logs -``` - -Example output from the account service: -> Server started: http://localhost:3030
-> Connected to MongoDB
-> info: [ACCOUNT] GET at /status: request received, session unavailable {"service":"account"}
-> info: [ACCOUNT] GET at /status: request received, session unavailable {"service":"account"}
-> error: [ACCOUNT] POST at /login: login failed, user email is invalid {"service":"account"}
-> info: [ACCOUNT] GET at /status: request received, session unavailable {"service":"account"} - -# Project clean up (Optional) -If the app is no longer needed, delete the deployment to avoid unnecessary costs: -- GCP charges for each external IP tied to a LoadBalancer (even if idle). -- Charges stop only after the LoadBalancer service is deleted.. - -To stop the service: -- Identify the service with - ```bash - kubectl get service - ``` -- Get ther service name and delete it with + # Option 2: Use Google Cloud Platform (cloud deployment) + # YOU SHOULD HAVE SUCCESSFULLY LOGGED IN AND COMPLETED GOOGLE CLOUD SETUP + kubectl config use-context gke_project-id_cluster-name_region + ``` +- Navigate to your project directory where the deployment `.yaml` files are stored ```bash - kubectl delete service + cd k8s/local ``` - -To free all other resources: -```bash -# Delete the deployment -kubectl delete deployment - -# Delete entire cluster (will remove all workloads and charges) -gcloud container clusters delete --zone -``` - -# Troubleshooting -## Useful commands -During the deployment process, you may encounter various issues. Below are useful commands commonly used to troubleshoot and identify the root causes: - -### Monitor component status -Check the status of deployed components (e.g., Running, Pending, ImagePullBackOff, etc.) -```bash -# Get the running pods -kubectl get pods - -# Get the running service -kubectl get service - -# Get the storage class -kubectl get storageclass - -# Get the persistent volume claim -kubectl get pvc -``` - -### Inspect pod events -Describe a specific pod to review events and investigate issues such as image pulling errors, resource limits, or readiness probe failures -```bash -kubectl describe pod -``` - -### View pod logs -View the logs of a specific pod to identify error messages or runtime issues: -```bash -kubectl logs -``` - -### Test inter-service communication -Execute a command inside a running pod (e.g., the frontend service) to test connectivity with another service (e.g., the account service) -```bash -# Replace with the actual pod name of the service you want to use for the test (e.g., a frontend pod) -kubectl exec -it -- curl http://accountsvc-service:3330/status -``` - -## Some encountered issues -### Docker Hub authentication - -If your deployment use images from your Docker Hub, you mush login to docker to have image pulling permission: -```bash -docker login -``` - -Then you can revoke the login session with: -```bash -docker logout -``` - -### Kubernetes Cluster Creation -**VPC Network** - -If you encountered errors related to networks (has no network named "default"), we need to create the default Virtual Private Cloud (VPC) network and its subnets -- Create network: +- Apply the MongoDB deployment: ```bash - gcloud compute networks create default --subnet-mode=auto + kubectl apply -f mongodb-pvc.yaml + kubectl apply -f mongodb-secret.yaml + kubectl apply -f mongodb-deployment.yaml ``` -- View the network list: +- Apply the service deployments ```bash - gcloud compute networks list + kubectl apply -f frontendsvc-deployment.yaml + kubectl apply -f accountsvc-deployment.yaml + kubectl apply -f expensesvc-deployment.yaml ``` -Then try to run the cluster creation command again - -**Google CLoud SDK Shell plugin** - -If you encountered errors related to plugins (`gke-gcloud-auth-plugin` is needed for continued use of `kubectl`), you may need to install the plugin in your Google Cloud SDK Shell with following command: -```bash -gcloud components install gke-gcloud-auth-plugin -``` -Confirm the installed plugin version: +### Troubleshooting +During the deployment process, you may encounter various issues. Variety of commands can be used to troubleshoot and identify the root causes, some of them are ```bash -gke-gcloud-auth-plugin --version +kubectl get +kubectl describe +kubectl logs ``` -### Kubectl Context problem (Docker Desktop vs Google Cloud SDK) -While working with `kubectl` commands in our local machine, we need to check which context is we currently working on. -- To get all context, run: - ```bash - kubectl config get-contexts - ``` -- To check current working context, run: - ```bash - kubectl config current-context - ``` -- To use context, run: - ```bash - # Use docker desktop - kubectl config use-context docker-desktop - # Use google cloud - kubectl config use-context gke_project-id_cluster-name_region - ``` diff --git a/account_service/.dockerignore b/backend/account_service/.dockerignore similarity index 100% rename from account_service/.dockerignore rename to backend/account_service/.dockerignore diff --git a/account_service/.gitignore b/backend/account_service/.gitignore similarity index 100% rename from account_service/.gitignore rename to backend/account_service/.gitignore diff --git a/account_service/Dockerfile b/backend/account_service/Dockerfile similarity index 100% rename from account_service/Dockerfile rename to backend/account_service/Dockerfile diff --git a/account_service/controllers/accountController.js b/backend/account_service/controllers/accountController.js similarity index 100% rename from account_service/controllers/accountController.js rename to backend/account_service/controllers/accountController.js diff --git a/account_service/controllers/authController.js b/backend/account_service/controllers/authController.js similarity index 100% rename from account_service/controllers/authController.js rename to backend/account_service/controllers/authController.js diff --git a/account_service/database/connectDB.js b/backend/account_service/database/connectDB.js similarity index 100% rename from account_service/database/connectDB.js rename to backend/account_service/database/connectDB.js diff --git a/account_service/logger.js b/backend/account_service/logger.js similarity index 100% rename from account_service/logger.js rename to backend/account_service/logger.js diff --git a/account_service/logs/combined.log b/backend/account_service/logs/combined.log similarity index 100% rename from account_service/logs/combined.log rename to backend/account_service/logs/combined.log diff --git a/account_service/logs/error.log b/backend/account_service/logs/error.log similarity index 100% rename from account_service/logs/error.log rename to backend/account_service/logs/error.log diff --git a/account_service/models/blacklist.js b/backend/account_service/models/blacklist.js similarity index 100% rename from account_service/models/blacklist.js rename to backend/account_service/models/blacklist.js diff --git a/account_service/models/user.js b/backend/account_service/models/user.js similarity index 100% rename from account_service/models/user.js rename to backend/account_service/models/user.js diff --git a/account_service/package-lock.json b/backend/account_service/package-lock.json similarity index 100% rename from account_service/package-lock.json rename to backend/account_service/package-lock.json diff --git a/account_service/package.json b/backend/account_service/package.json similarity index 100% rename from account_service/package.json rename to backend/account_service/package.json diff --git a/account_service/routes/accountRouter.js b/backend/account_service/routes/accountRouter.js similarity index 100% rename from account_service/routes/accountRouter.js rename to backend/account_service/routes/accountRouter.js diff --git a/account_service/routes/authRouter.js b/backend/account_service/routes/authRouter.js similarity index 100% rename from account_service/routes/authRouter.js rename to backend/account_service/routes/authRouter.js diff --git a/account_service/server.js b/backend/account_service/server.js similarity index 100% rename from account_service/server.js rename to backend/account_service/server.js diff --git a/account_service/test/account.test.js b/backend/account_service/test/account.test.js similarity index 100% rename from account_service/test/account.test.js rename to backend/account_service/test/account.test.js diff --git a/expense_service/.dockerignore b/backend/expense_service/.dockerignore similarity index 100% rename from expense_service/.dockerignore rename to backend/expense_service/.dockerignore diff --git a/expense_service/.gitignore b/backend/expense_service/.gitignore similarity index 100% rename from expense_service/.gitignore rename to backend/expense_service/.gitignore diff --git a/expense_service/Dockerfile b/backend/expense_service/Dockerfile similarity index 100% rename from expense_service/Dockerfile rename to backend/expense_service/Dockerfile diff --git a/expense_service/controllers/expenseController.js b/backend/expense_service/controllers/expenseController.js similarity index 100% rename from expense_service/controllers/expenseController.js rename to backend/expense_service/controllers/expenseController.js diff --git a/expense_service/database/connectDB.js b/backend/expense_service/database/connectDB.js similarity index 100% rename from expense_service/database/connectDB.js rename to backend/expense_service/database/connectDB.js diff --git a/expense_service/logger.js b/backend/expense_service/logger.js similarity index 100% rename from expense_service/logger.js rename to backend/expense_service/logger.js diff --git a/expense_service/logs/combined.log b/backend/expense_service/logs/combined.log similarity index 100% rename from expense_service/logs/combined.log rename to backend/expense_service/logs/combined.log diff --git a/expense_service/logs/error.log b/backend/expense_service/logs/error.log similarity index 100% rename from expense_service/logs/error.log rename to backend/expense_service/logs/error.log diff --git a/expense_service/middlewares/authentication.js b/backend/expense_service/middlewares/authentication.js similarity index 100% rename from expense_service/middlewares/authentication.js rename to backend/expense_service/middlewares/authentication.js diff --git a/expense_service/models/expense.js b/backend/expense_service/models/expense.js similarity index 100% rename from expense_service/models/expense.js rename to backend/expense_service/models/expense.js diff --git a/expense_service/models/user.js b/backend/expense_service/models/user.js similarity index 100% rename from expense_service/models/user.js rename to backend/expense_service/models/user.js diff --git a/expense_service/package-lock.json b/backend/expense_service/package-lock.json similarity index 100% rename from expense_service/package-lock.json rename to backend/expense_service/package-lock.json diff --git a/expense_service/package.json b/backend/expense_service/package.json similarity index 100% rename from expense_service/package.json rename to backend/expense_service/package.json diff --git a/expense_service/routes/expenseRouter.js b/backend/expense_service/routes/expenseRouter.js similarity index 100% rename from expense_service/routes/expenseRouter.js rename to backend/expense_service/routes/expenseRouter.js diff --git a/expense_service/server.js b/backend/expense_service/server.js similarity index 100% rename from expense_service/server.js rename to backend/expense_service/server.js diff --git a/expense_service/test/expense.test.js b/backend/expense_service/test/expense.test.js similarity index 100% rename from expense_service/test/expense.test.js rename to backend/expense_service/test/expense.test.js diff --git a/cloudbuild.yaml b/cloudbuild.yaml new file mode 100644 index 0000000..8ac7076 --- /dev/null +++ b/cloudbuild.yaml @@ -0,0 +1,101 @@ +options: + logging: CLOUD_LOGGING_ONLY # Send logs to Google Cloud Logging + +substitutions: + _IMAGE_NAME: "gcr.io/${PROJECT_ID}/gcpdevops-prod:${SHORT_SHA}" + +steps: + # Step 1: Build Docker image with SHA-based tagging + - name: 'gcr.io/cloud-builders/docker' + args: ['build', '-t', '${_IMAGE_NAME}', '.'] + + # Step 2: Push Docker image to Google Artifact Registry + - name: 'gcr.io/cloud-builders/docker' + args: ['push', '${_IMAGE_NAME}'] + + # Step 3: Replace placeholder `__IMAGE__` in `gke.yaml` with actual image name + - name: 'gcr.io/cloud-builders/gcloud' + entrypoint: 'bash' + args: + - "-c" + - | + sed -i "s|__IMAGE__|${_IMAGE_NAME}|g" gke.yaml + + # Step 4: Deploy to Google Kubernetes Engine (GKE) + - name: "gcr.io/cloud-builders/gke-deploy" + args: + - run + - --image=${_IMAGE_NAME} # Correct image reference + - --location=us-central1-a + - --cluster=gcp-devops-project + - --namespace=development + - --filename=gke.yaml + +# GCP cloud build for production +options: + logging: CLOUD_LOGGING_ONLY + +substitutions: + _REGION: "australia-southeast1" + _REPO: "spendwise" + _CLUSTER: "spendwise-k8s-cluster" + _LOCATION: "australia-southeast1-b" + _NAMESPACE: "production" + +steps: + # --- BUILD AND PUSH IMAGES TO ARTIFACT REGISTRY --- # + # Account + - name: 'gcr.io/cloud-builders/docker' + args: [ + 'build', '-t', + '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/account:${SHORT_SHA}', + './backend/account_service' + ] + + - name: 'gcr.io/cloud-builders/docker' + args: [ + 'push', + '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/account:${SHORT_SHA}' + ] + + # Expense + - name: 'gcr.io/cloud-builders/docker' + args: [ + 'build', '-t', + '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/expense:${SHORT_SHA}', + './backend/expense_service' + ] + + - name: 'gcr.io/cloud-builders/docker' + args: [ + 'push', + '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/expense:${SHORT_SHA}' + ] + + # Frontend + - name: 'gcr.io/cloud-builders/docker' + args: [ + 'build', '-t', + '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/frontend:${SHORT_SHA}', + './frontend' + ] + + - name: 'gcr.io/cloud-builders/docker' + args: [ + 'push', + '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/frontend:${SHORT_SHA}' + ] + + # --- DEPLOY TO GKE --- # + - name: 'gcr.io/cloud-builders/gke-deploy' + args: + - run + - --filename=k8s/cloud/ + - --location=${_LOCATION} + - --cluster=${_CLUSTER} + - --namespace=${_NAMESPACE} + +images: + - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/account:${SHORT_SHA}' + - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/expense:${SHORT_SHA}' + - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/frontend:${SHORT_SHA}' \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 818e61f..ffbd017 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -7,7 +7,7 @@ services: - "27018:27017" account-service: - build: ./account_service + build: ./backend/account_service container_name: account-service ports: - "3330:3030" @@ -19,7 +19,7 @@ services: - mongo expense-service: - build: ./expense_service + build: ./backend/expense_service container_name: expense-service ports: - "3332:3032" diff --git a/docs/DOCKER.md b/docs/DOCKER.md new file mode 100644 index 0000000..2b8d0c9 --- /dev/null +++ b/docs/DOCKER.md @@ -0,0 +1,99 @@ +# Docker - Docker Desktop & Docker Hub + +This is a **generic how-to documentation** for using Docker Dekstop and Docker Hub. + +# Prerequisite +**Docker Desktop** must be installed. Please find [official documentation](https://docs.docker.com/desktop/setup/install/windows-install/) for detail installation instruction. + +# Usage +## Dockerfile & Docker Image (Containerization) +1. Create a `Dockerfile` in the project folder (root) + ```bash + # Specify the base image with specific version (e.g. node version) + FROM + + # Define the path to the application + WORKDIR /code + + # Copy and install dependencies + COPY + + RUN !> \ + + + # Copy application code from the directory in your computer to the image + COPY + + # Expose the app to specified port + EXPOSE + + # Specify the commands in list, ex: ["node", "server.js"] + CMD + ``` +2. Build the Docker image, tagging is optional but highly recommended, specify the project folder, which should also include `Dockerfile` in there + ```bash + docker build -t : + + # Ex: docker build -t frontend-image:demo ./frontend + ``` +3. Use the Docker Image to start a container, mapping the host machine port (where we access the application from our computer) to container's internal port + ```bash + docker run -p : : + + # Ex: docker run -p 8080:3000 frontend-image:demo + ``` +4. Access the application using `host-port` + ```bash + http://localhost: + + # Ex: http://localhost:8080 + ``` + +## Docker Compose +1. Define a [`docker-compose.yaml`](../docker-compose.yaml) file, defining and configuring all services in a single file + - Specify the version + - Define the services, each needs to include + - The directory to build the application (must include `Dockerfile`) + - Container name for the service + - Mapping the ports (`host-machine-port`:`container-port`) + - Container health check setting + - Container restart condition +2. Build all images (optional) + ```bash + docker compose build + ``` +3. Start all services with below commands, if the images haven't been built yet, it will automatically build and run afterwards. + ```bash + docker compose up + ``` + +## Docker Hub +1. Login to Docker + - Go to DockerHub and generate personal access token + - Login with below command and your credentials + ```bash + docker login + ``` +2. Tag and push the image to DockerHub + ```bash + docker tag / + docker push / + ``` + +## Monitoring +Check the container's status +```bash +docker ps +``` + +## Troubleshooting + +If you have problem with **push** or **pull** images, ensure you already logged in and have image pulling permission: +```bash +docker login +``` + +Then you can revoke the login session with: +```bash +docker logout +``` \ No newline at end of file diff --git a/docs/GCP.md b/docs/GCP.md new file mode 100644 index 0000000..4a011c1 --- /dev/null +++ b/docs/GCP.md @@ -0,0 +1,266 @@ +# Google Cloud Platform + +This is a **generic how-to documentation** for using Google Cloud Platform (GCP): +- [Google Cloud CLI](#google-cloud-cli) +- GCP Services + - [Artifact Registry](#artifact-registry) + - [Google Kubernetes Engine (GKE)](#google-kubernetes-engine-gke) + +# Google Cloud Console +1. Set up your account + - Use your browser to sign in to your Google Account, or create a new one if needed. + - Go to Google Cloud Console > Billing > Enable Billing Account and link it with your payment method. +2. Create new project + - Go to and create new project. + - Save your project ID, as it will be required later during deployment. + +# Google Cloud CLI +> The Google Cloud CLI (gcloud CLI) is the primary set of command-line tools for Google Cloud. +> - It must be installed in your computer to run. +> - Alternatively, you can use the Google Cloud SDK Shell (Cloud Shell) to run the commands in the cloud. It’s accessible in your browser through the Google Cloud Console when you’re logged in with your Google account. + +Step by step instruction for setting up Google Cloud CLI in your computer +1. Download and install the Google Cloud CLI +2. Configure the CLI using one of following option: + - Run following command to config all at once + ```bash + # Below command includes + # - Login to your google account by following the instruction + # - Choose the target project you working with + # - Configure the default region (optional) + gcloud init + ``` + - Run following commands to config one by one + - To login + ```bash + gcloud auth login + ``` + - To set working project: + ```bash + gcloud config set project + ``` + - To set compute zone + ```bash + gcloud config set compute/zone + ``` + +# Artifact Registry +> Prerequisite: +> - A Google Cloud Console account & project [#Google Cloud Console](#google-cloud-console) +> - Google Cloud CLI installed and configured on your computer: [#Google Cloud CLI](#google-cloud-cli) + +Use the Google Cloud SDK Shell to remotely connect to the GCP platform and apply configuration files stored locally. + +Before proceeding with the instructions below, ensure that you: +- Are logged into the correct account. If not, run `gcloud auth login`. +- Have the correct project set. If not, run `gcloud config set project `. + +## Setup Google Cloud registry/repository +1. Access the Google Cloud Platform and choose your project. If not yet created, follows [#Google Cloud Console](#google-cloud-console) +2. Search and go to **Artifact Registry** and enable the API service. Alternatively, run below command in your console + ```bash + gcloud services enable artifactregistry.googleapis.com + ``` +3. Create a new repository in **Artifact Registry**, choosing Docker format with Standard mode + +## Authenticate to a repository +1. List all hostnames in the helper + ```bash + gcloud auth configure-docker + ``` +2. Add target hostname (current region) to the Docker configuration file + ```bash + gcloud auth configure-docker -docker.pkg.dev + ``` + +## Publish the image to the registry +After creating the Google Cloud repository, we should be provided the path to the repo with this format: `LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY`. We will use this format to tag and push the image to the cloud. +1. Tag the image with the repo name + ```bash + docker tag / + ``` +2. Push the image to the cloud + ```bash + docker push / + ``` + +# Google Kubernetes Engine (GKE) +## Kubernetes Cluster setup +> Prerequisite: +> - A Google Cloud Console account & project [#Google Cloud Console](#google-cloud-console) +> - Google Cloud CLI installed and configured on your computer: [#Google Cloud CLI](#google-cloud-cli) + +Use the Google Cloud SDK Shell to remotely connect to the GCP platform and apply configuration files stored locally. + +Before proceeding with the instructions below, ensure that you: +- Are logged into the correct account. If not, run `gcloud auth login`. +- Have the correct project set. If not, run `gcloud config set project `. + +### Setup Google Kubernetes Engine +1. Access the Google Cloud Platform and choose your project. If not yet created, follows [#Google Cloud Console](#google-cloud-console) +2. Search and go to **Kubernetes Engine** and enable the API service. Alternatively, run below command in your console + +### Create Kubernetes Cluster + +We can create a Kubernetes Cluster by providing its name, number of nodes and the compute zone. In this case, our cluster has: +- Name: `simple-k8s-cluster` +- Number of nodes: 1 node (one virtual machine/instance) per zone. If we set `--num-nodes=3`, GCP would spin up 3 virtual machines (nodes), allowing your workloads to be distributed across them for high availability, scalability, and resilience. + +The command +```bash +gcloud container clusters create simple-k8s-cluster --num-nodes=1 --zone=australia-southeast1-b +``` + +After successfully created a cluster, we confirm it by listing all cluster with: +```bash +gcloud container clusters list +``` + +### Authenicate the cluster + +Before using, we must authenticate `kubectl` with the newly created cluster by getting credential with following command: +```bash +gcloud container clusters get-credentials simple-k8s-cluster --location=australia-southeast1-b +``` + +## Apply Deployment and Service +Navigate to your project directory where the deployment `.yaml` files are stored +```bash +cd +``` + +Apply the all configuration and deployments, normally the order should be: +1. Configuration, secrets, other dependencies, etc. +2. Database and storage, etc. +3. Service deployment + +```bash +kubectl apply -f .yaml +``` + +## Check the running pods and services +### Check the running pods + +If 3 replicas are specified in the deployment YAML, you should see 3 pods running. In this case, only 1 replica is used +```bash +kubectl get pods +``` + +### Check the running services +```bash +kubectl get services +``` +The Cloud Shell should return a table like: +| NAME | TYPE | CLUSTER-IP | EXTERNAL-IP | PORT(S) | AGE | +| --- | --- | --- | --- | --- | --- | +| kubernetes | ClusterIP | 11.222.224.1 | none | 443/TCP | 15m | +| frontendsvc-service | LoadBalancer | 11.222.224.210 | **pending** | 3080:30142/TCP | 12s | +| accountsvc-service | ClusterIP | 11.222.231.12 | none | 3330/TCP | 10s | +| expensesvc-service | ClusterIP | 11.222.236.138 | none | 3332/TCP | 9s | +| my-mongo-svc | ClusterIP | 11.222.236.138 | none | 27017/TCP | 20s | + +Once the `EXTERNAL-IP` is ready, it will appear. Access the application using +``` +http://:3080/ +``` + +For example, if the `EXTERNAL-IP` shows 11.222.3.101, we can access our application with: +``` +http://11.222.3.101:3080/ +``` + +**Then the deployment is completed!** + +## Monitoring the application +### Monitoring in the Cloud Console Web UI +Google Cloud Platform provides a web-based UI for application monitoring. +Steps: + +1. Open Google Cloud Console. +2. Navigate to the **Monitoring** tab in the side menu. +3. Select **Metrics Explorer**. +4. Set the resource type to Kubernetes Container. +5. Choose metrics to view, such as: + - `kubernetes.io/container/cpu/request_utilization` + - `kubernetes.io/container/memory/request_utilization` + +### Monitoring with commands +#### View resource usage +Get pod-level CPU and memory usage: +```bash +kubectl top pod +``` + +Get pod network details for a specific pod: +```bash +kubectl describe pod +``` + +Get node-level (cluster) resource usage: +```bash +kubectl top nodes +``` + +#### View the logs +```bash +kubectl logs +``` + +Example output from the account service: +> Server started: http://localhost:3030
+> Connected to MongoDB
+> info: [ACCOUNT] GET at /status: request received, session unavailable {"service":"account"}
+> info: [ACCOUNT] GET at /status: request received, session unavailable {"service":"account"}
+> error: [ACCOUNT] POST at /login: login failed, user email is invalid {"service":"account"}
+> info: [ACCOUNT] GET at /status: request received, session unavailable {"service":"account"} + +## Project clean up (Optional) +If the app is no longer needed, delete the deployment to avoid unnecessary costs: +- GCP charges for each external IP tied to a LoadBalancer (even if idle). +- Charges stop only after the LoadBalancer service is deleted.. + +To stop the service: +- Identify the service with + ```bash + kubectl get service + ``` +- Get ther service name and delete it with + ```bash + kubectl delete service + ``` + +To free all other resources: +```bash +# Delete the deployment +kubectl delete deployment + +# Delete entire cluster (will remove all workloads and charges) +gcloud container clusters delete --zone +``` + +# Troubleshooting +## Kubernetes Cluster Creation +**VPC Network** + +If you encountered errors related to networks **(has no network named "default")**, we need to create the default Virtual Private Cloud (VPC) network and its subnets +- Create network: + ```bash + gcloud compute networks create default --subnet-mode=auto + ``` +- View the network list: + ```bash + gcloud compute networks list + ``` +Then try to run the cluster creation command again + +**Google CLoud SDK Shell plugin** + +If you encountered errors related to plugins **(`gke-gcloud-auth-plugin` is needed for continued use of `kubectl`)**, you may need to install the plugin in your Google Cloud SDK Shell with following command: +```bash +gcloud components install gke-gcloud-auth-plugin +``` + +Confirm the installed plugin version: +```bash +gke-gcloud-auth-plugin --version +``` \ No newline at end of file diff --git a/docs/KUBERNETES.md b/docs/KUBERNETES.md new file mode 100644 index 0000000..a1a6fc7 --- /dev/null +++ b/docs/KUBERNETES.md @@ -0,0 +1,144 @@ +# Kubernetes + +This is a **generic how-to documentation** for using Kubernetes with Docker Desktop. + +# Prerequisite +- **Docker Desktop** must be installed: [Docker - Prerequisite](./DOCKER.md#prerequisite) +- **Kubernetes** must be enabled: + 1. Activate Hyper-V + + > **Control Panel > Turn Windows Features On or Off > Select Hyper-V** + 2. Install and enable Kubernetes from setting + + > **Start Docker Desktop > Setting > Kubernetes > Enable Kubernetes > Apply and Restart** + +# Usage +## Kubernetes Cluster setup +1. Activate Hyper-V: + + **Control Panel** > **Turn Windows Features On or Off** > **Select Hyper-V** + +2. Install and enable Kubernetes: + + **Start Docker** > **Setting** > **Kubernetes** > **Enable Kubernetes** > **Apply and Restart** + +## Kubernetes Context (Docker Desktop vs Cloud Provider) +While working with `kubectl` commands in our local machine and manual cloud deployment (e.g. **Google Cloud SDK**), it is essential to use the right context. +- To get all context, run: + ```bash + kubectl config get-contexts + ``` +- To check current working context, run: + ```bash + kubectl config current-context + ``` +- To use context, run: + ```bash + # Use docker desktop + kubectl config use-context docker-desktop + + # Use google cloud + kubectl config use-context gke_project-id_cluster-name_region + ``` + +## Kubernetes Dashboard (Optional) +1. Deploy the Dashboard UI: + ```bash + kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml + ``` + +2. Create admin user for dashboard: + - Specify user information and assign role in `.yaml` file: [dashboard-admin.yaml](../k8s/dashboard/dashboard-admin.yaml) + - Apply the configuration: + ```bash + kubectl apply -f dashboard-admin.yaml + ``` + +3. Login to Dashboard + - Create login token for created user + ```bash + kubectl -n kubernetes-dashboard create token admin-user + ``` + - Launch the dashboard (serving on localhost:8001 by default) + ```bash + kubectl proxy + ``` + - Use the generated token to login and access the dashboard using below URL: + ```bash + http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/ + ``` + +## Kubernetes Deployment +### Deployment +1. Create `.yaml` configuration files, some common files are + - Credential & Configuration: secrets, config maps, etc + - Database: persistent volume claims, database image deployment, etc + - Service: deployment with target image, service config, etc +2. Apply the files + ```bash + kubectl apply -f .yaml + ``` + +### Direct Changes +#### Update image tag +We can manually apply the changes to k8s using `set image` and `rollout restart` commands. Below code is example for account service deployment +```bash +# For first time using `newtag` tag -> we need to set new image tag for deployed image +kubectl set image deployment/accountsvc-deployment accountsvc-container=tut888/sit737-account-service:newtag + +# For later updates -> we only need to restart the deployment to re-pull new image +kubectl rollout restart deployment/accountsvc-deployment +``` + +## Monitoring and Interaction +### Port-forwarding +- To forward the traffic, creating a temporary tunnel from your laptop to the cluster: + > The `` and `` must match with your service configuration + ```bash + kubectl port-forward service/ : + ``` +- Access the application: + ```bash + http://localhost: + ``` + +### Monitor component status +Check the status of deployed components (e.g., Running, Pending, ImagePullBackOff, etc.) +```bash +# Get the running pods +kubectl get pods + +# Get the running service +kubectl get service + +# Get the storage class +kubectl get storageclass + +# Get the persistent volume claim +kubectl get pvc +``` + +### Inspect pod +Describe a specific pod to review events and investigate issues such as image pulling errors, resource limits, or readiness probe failures +```bash +kubectl describe pod +``` + +View the logs of a specific pod to identify error messages or runtime issues: +```bash +kubectl logs +``` + +### Check inter-service communication +Execute a command inside a running pod (e.g., the frontend service) to test connectivity with another service (e.g., the account service) +```bash +# Replace with the actual pod name of the service you want to use for the test (e.g., a frontend pod) +kubectl exec -it -- curl http://accountsvc-service:3330/status +``` + +## Clean Up +```bash +kubectl delete + +# Ex: kubectl delete deployment account-svc-deployment +``` \ No newline at end of file diff --git a/frontend/cypress/downloads/downloads.htm b/frontend/cypress/downloads/downloads.htm index 628abfc..1cb8d39 100644 Binary files a/frontend/cypress/downloads/downloads.htm and b/frontend/cypress/downloads/downloads.htm differ diff --git a/frontend/logs/combined.log b/frontend/logs/combined.log index 3c19aa1..32260ed 100644 --- a/frontend/logs/combined.log +++ b/frontend/logs/combined.log @@ -190,3 +190,104 @@ {"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} {"level":"info","message":"[FRONTEND] POST at /logout: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} {"level":"info","message":"[FRONTEND] GET at /: request received with login status undefined, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /register: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /register: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /register: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] PUT at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] DELETE at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /register: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /register: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /account: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /logout: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status undefined, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] HEAD at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /register: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /register: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /account: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /logout: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status undefined, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /register: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /register: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] PUT at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] POST at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] DELETE at /expense: request received with login status true, user: sampletestuser222@gmail.com","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /login: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /: request received with login status false, user: none","service":"frontend"} +{"level":"info","message":"[FRONTEND] GET at /register: request received with login status false, user: none","service":"frontend"} diff --git a/frontend/package.json b/frontend/package.json index 18d2660..96c2fcf 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,7 +8,7 @@ "start:test": "cross-env NODE_ENV=test node app.js", "cypress:open": "npx cypress open", "test:e2eopen": "start-server-and-test start:alltest http://localhost:3081 cypress:open", - "start:alltest": "concurrently \"cd ../account_service && cross-env PORT=3030 npm run start:test\" \"cd ../expense_service && cross-env PORT=3032 npm run start:test\" \"cd ../frontend && cross-env PORT=3081 npm run start:test\"", + "start:alltest": "concurrently \"cd ../backend/account_service && cross-env PORT=3030 npm run start:test\" \"cd ../backend/expense_service && cross-env PORT=3032 npm run start:test\" \"cd ../frontend && cross-env PORT=3081 npm run start:test\"", "cypress:run": "cypress run --browser chrome", "test:e2e": "start-server-and-test start:alltest http://localhost:3081 cypress:run" }, diff --git a/k8s/accountsvc-deployment.yaml b/k8s/cloud/accountsvc-deployment.yaml similarity index 79% rename from k8s/accountsvc-deployment.yaml rename to k8s/cloud/accountsvc-deployment.yaml index 4f878ef..7c8784e 100644 --- a/k8s/accountsvc-deployment.yaml +++ b/k8s/cloud/accountsvc-deployment.yaml @@ -14,22 +14,22 @@ spec: spec: containers: - name: accountsvc-container - image: tut888/sit737-account-service:latest # pull from docker hub + image: spendwise-account-service:latest ports: - containerPort: 3030 env: - name: MONGO_USER valueFrom: secretKeyRef: - name: my-mongo-secret + name: spendwise-mongo-secret key: mongo-user # App gets MongoDB username from Secret - name: MONGO_PASSWORD valueFrom: secretKeyRef: - name: my-mongo-secret + name: spendwise-mongo-secret key: mongo-password # App gets MongoDB password from Secret - name: MONGO_URI - value: "mongodb://$(MONGO_USER):$(MONGO_PASSWORD)@my-mongo-svc:27017/spendwise?authSource=admin" + value: "mongodb://$(MONGO_USER):$(MONGO_PASSWORD)@spendwise-mongo-svc:27017/spendwise?authSource=admin" - name: JWT_SECRET_KEY value: "MySecret" # For demo only. It should be hidden, not being exposed like this --- diff --git a/k8s/expensesvc-deployment.yaml b/k8s/cloud/expensesvc-deployment.yaml similarity index 78% rename from k8s/expensesvc-deployment.yaml rename to k8s/cloud/expensesvc-deployment.yaml index ff848ab..3d2aace 100644 --- a/k8s/expensesvc-deployment.yaml +++ b/k8s/cloud/expensesvc-deployment.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: expensesvc-container - image: tut888/sit737-expense-service:latest # pull from docker hub + image: spendwise-expense-service:latest ports: - containerPort: 3032 env: @@ -23,15 +23,15 @@ spec: - name: MONGO_USER valueFrom: secretKeyRef: - name: my-mongo-secret + name: spendwise-mongo-secret key: mongo-user # App gets MongoDB username from Secret - name: MONGO_PASSWORD valueFrom: secretKeyRef: - name: my-mongo-secret + name: spendwise-mongo-secret key: mongo-password # App gets MongoDB password from Secret - name: MONGO_URI - value: "mongodb://$(MONGO_USER):$(MONGO_PASSWORD)@my-mongo-svc:27017/spendwise?authSource=admin" + value: "mongodb://$(MONGO_USER):$(MONGO_PASSWORD)@spendwise-mongo-svc:27017/spendwise?authSource=admin" --- apiVersion: v1 kind: Service diff --git a/k8s/frontendsvc-deployment.yaml b/k8s/cloud/frontendsvc-deployment.yaml similarity index 90% rename from k8s/frontendsvc-deployment.yaml rename to k8s/cloud/frontendsvc-deployment.yaml index f37bc6b..913b028 100644 --- a/k8s/frontendsvc-deployment.yaml +++ b/k8s/cloud/frontendsvc-deployment.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: frontendsvc-container - image: tut888/sit737-frontend-service:latest # pull from docker hub + image: spendwise-frontend:latest ports: - containerPort: 3080 env: diff --git a/k8s/mongodb-deployment.yaml b/k8s/cloud/mongodb-deployment.yaml similarity index 69% rename from k8s/mongodb-deployment.yaml rename to k8s/cloud/mongodb-deployment.yaml index 4a53d45..684e168 100644 --- a/k8s/mongodb-deployment.yaml +++ b/k8s/cloud/mongodb-deployment.yaml @@ -1,16 +1,16 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: my-mongo + name: spendwise-mongo spec: replicas: 1 selector: matchLabels: - app: my-mongo + app: spendwise-mongo template: metadata: labels: - app: my-mongo + app: spendwise-mongo spec: containers: - image: mongo @@ -19,31 +19,31 @@ spec: - name: MONGO_INITDB_ROOT_USERNAME valueFrom: secretKeyRef: - name: my-mongo-secret + name: spendwise-mongo-secret key: mongo-user - name: MONGO_INITDB_ROOT_PASSWORD valueFrom: secretKeyRef: - name: my-mongo-secret + name: spendwise-mongo-secret key: mongo-password volumeMounts: - mountPath: /data/db - name: my-mongo-volume + name: spendwise-mongo-volume ports: - containerPort: 27017 volumes: - - name: my-mongo-volume + - name: spendwise-mongo-volume persistentVolumeClaim: - claimName: my-mongo-pvc + claimName: spendwise-mongo-pvc --- apiVersion: v1 kind: Service metadata: - name: my-mongo-svc + name: spendwise-mongo-svc spec: type: ClusterIP selector: - app: my-mongo + app: spendwise-mongo ports: - protocol: TCP port: 27017 diff --git a/k8s/mongodb-pvc.yaml b/k8s/cloud/mongodb-pvc.yaml similarity index 85% rename from k8s/mongodb-pvc.yaml rename to k8s/cloud/mongodb-pvc.yaml index 00a7a42..19862dd 100644 --- a/k8s/mongodb-pvc.yaml +++ b/k8s/cloud/mongodb-pvc.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: my-mongo-pvc + name: spendwise-mongo-pvc spec: accessModes: - ReadWriteOnce diff --git a/k8s/mongodb-secret.yaml b/k8s/cloud/mongodb-secret.yaml similarity index 75% rename from k8s/mongodb-secret.yaml rename to k8s/cloud/mongodb-secret.yaml index 8267981..4a7bc13 100644 --- a/k8s/mongodb-secret.yaml +++ b/k8s/cloud/mongodb-secret.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Secret metadata: - name: my-mongo-secret + name: spendwise-mongo-secret stringData: mongo-user: myuser mongo-password: myppass \ No newline at end of file diff --git a/k8s/dashboard/dashboard-admin.yaml b/k8s/dashboard/dashboard-admin.yaml new file mode 100644 index 0000000..4b7c691 --- /dev/null +++ b/k8s/dashboard/dashboard-admin.yaml @@ -0,0 +1,20 @@ +# Create identity +apiVersion: v1 +kind: ServiceAccount +metadata: + name: admin-user + namespace: kubernetes-dashboard +--- +# Assign role to identity +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: admin-user +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: admin-user + namespace: kubernetes-dashboard \ No newline at end of file diff --git a/k8s/local/accountsvc-deployment.yaml b/k8s/local/accountsvc-deployment.yaml new file mode 100644 index 0000000..5c709b2 --- /dev/null +++ b/k8s/local/accountsvc-deployment.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: accountsvc-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: accountsvc + template: + metadata: + labels: + app: accountsvc + spec: + containers: + - name: accountsvc-container + image: spendwise-account-service:latest + imagePullPolicy: Never + ports: + - containerPort: 3030 + env: + - name: MONGO_USER + valueFrom: + secretKeyRef: + name: spendwise-mongo-secret + key: mongo-user # App gets MongoDB username from Secret + - name: MONGO_PASSWORD + valueFrom: + secretKeyRef: + name: spendwise-mongo-secret + key: mongo-password # App gets MongoDB password from Secret + - name: MONGO_URI + value: "mongodb://$(MONGO_USER):$(MONGO_PASSWORD)@spendwise-mongo-svc:27017/spendwise?authSource=admin" + - name: JWT_SECRET_KEY + value: "MySecret" # For demo only. It should be hidden, not being exposed like this +--- +apiVersion: v1 +kind: Service +metadata: + name: accountsvc-service +spec: + type: ClusterIP + selector: + app: accountsvc + ports: + - port: 3330 + targetPort: 3030 \ No newline at end of file diff --git a/k8s/local/expensesvc-deployment.yaml b/k8s/local/expensesvc-deployment.yaml new file mode 100644 index 0000000..ce9c200 --- /dev/null +++ b/k8s/local/expensesvc-deployment.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: expensesvc-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: expensesvc + template: + metadata: + labels: + app: expensesvc + spec: + containers: + - name: expensesvc-container + image: spendwise-expense-service:latest + imagePullPolicy: Never + ports: + - containerPort: 3032 + env: + - name: ACCOUNT_SERVICE_URL + value: "http://accountsvc-service:3330" + - name: MONGO_USER + valueFrom: + secretKeyRef: + name: spendwise-mongo-secret + key: mongo-user # App gets MongoDB username from Secret + - name: MONGO_PASSWORD + valueFrom: + secretKeyRef: + name: spendwise-mongo-secret + key: mongo-password # App gets MongoDB password from Secret + - name: MONGO_URI + value: "mongodb://$(MONGO_USER):$(MONGO_PASSWORD)@spendwise-mongo-svc:27017/spendwise?authSource=admin" +--- +apiVersion: v1 +kind: Service +metadata: + name: expensesvc-service +spec: + type: ClusterIP + selector: + app: expensesvc + ports: + - port: 3332 + targetPort: 3032 \ No newline at end of file diff --git a/k8s/local/frontendsvc-deployment.yaml b/k8s/local/frontendsvc-deployment.yaml new file mode 100644 index 0000000..381e051 --- /dev/null +++ b/k8s/local/frontendsvc-deployment.yaml @@ -0,0 +1,37 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontendsvc-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: frontendsvc + template: + metadata: + labels: + app: frontendsvc + spec: + containers: + - name: frontendsvc-container + image: spendwise-frontend:latest + imagePullPolicy: Never + ports: + - containerPort: 3080 + env: + - name: ACCOUNT_SERVICE_URL + value: "http://accountsvc-service:3330" + - name: EXPENSE_SERVICE_URL + value: "http://expensesvc-service:3332" +--- +apiVersion: v1 +kind: Service +metadata: + name: frontendsvc-service +spec: + type: LoadBalancer + selector: + app: frontendsvc + ports: + - port: 3080 # Internal service port -> use for port forwarding + targetPort: 3080 # Container port \ No newline at end of file diff --git a/k8s/local/mongodb-deployment.yaml b/k8s/local/mongodb-deployment.yaml new file mode 100644 index 0000000..684e168 --- /dev/null +++ b/k8s/local/mongodb-deployment.yaml @@ -0,0 +1,50 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spendwise-mongo +spec: + replicas: 1 + selector: + matchLabels: + app: spendwise-mongo + template: + metadata: + labels: + app: spendwise-mongo + spec: + containers: + - image: mongo + name: mongo + env: + - name: MONGO_INITDB_ROOT_USERNAME + valueFrom: + secretKeyRef: + name: spendwise-mongo-secret + key: mongo-user + - name: MONGO_INITDB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: spendwise-mongo-secret + key: mongo-password + volumeMounts: + - mountPath: /data/db + name: spendwise-mongo-volume + ports: + - containerPort: 27017 + volumes: + - name: spendwise-mongo-volume + persistentVolumeClaim: + claimName: spendwise-mongo-pvc +--- +apiVersion: v1 +kind: Service +metadata: + name: spendwise-mongo-svc +spec: + type: ClusterIP + selector: + app: spendwise-mongo + ports: + - protocol: TCP + port: 27017 + targetPort: 27017 \ No newline at end of file diff --git a/k8s/local/mongodb-pvc.yaml b/k8s/local/mongodb-pvc.yaml new file mode 100644 index 0000000..11521a2 --- /dev/null +++ b/k8s/local/mongodb-pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: spendwise-mongo-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + # storageClassName: standard \ No newline at end of file diff --git a/k8s/local/mongodb-secret.yaml b/k8s/local/mongodb-secret.yaml new file mode 100644 index 0000000..4a7bc13 --- /dev/null +++ b/k8s/local/mongodb-secret.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: spendwise-mongo-secret +stringData: + mongo-user: myuser + mongo-password: myppass \ No newline at end of file