From 82cfe35242fa1545a795a38de4f1cd29e22bc9b3 Mon Sep 17 00:00:00 2001 From: Tat Uyen Tam Date: Tue, 3 Feb 2026 14:50:15 +1100 Subject: [PATCH] fix(cicd): resolve syntax problem in cloudbuild manifest --- .github/workflows/test-frontendsvc.yml | 3 +- README.md | 94 ++++++++++--------- backend/account_service/logs/combined.log | 80 ++++++++++++++++ backend/account_service/logs/error.log | 3 + backend/expense_service/logs/combined.log | 20 ++++ cloudbuild.yaml | 35 +------ k8s/cloud/mongodb-secret.yaml | 7 -- .../accountsvc-deployment.yaml | 11 ++- .../expensesvc-deployment.yaml | 6 +- .../frontendsvc-deployment.yaml | 2 +- k8s/gke/gke-secret.txt | 14 +++ k8s/{cloud => gke}/mongodb-deployment.yaml | 4 +- k8s/{cloud => gke}/mongodb-pvc.yaml | 0 k8s/{dashboard => local}/dashboard-admin.yaml | 0 14 files changed, 183 insertions(+), 96 deletions(-) delete mode 100644 k8s/cloud/mongodb-secret.yaml rename k8s/{cloud => cloudbuild}/accountsvc-deployment.yaml (81%) rename k8s/{cloud => cloudbuild}/expensesvc-deployment.yaml (88%) rename k8s/{cloud => cloudbuild}/frontendsvc-deployment.yaml (94%) create mode 100644 k8s/gke/gke-secret.txt rename k8s/{cloud => gke}/mongodb-deployment.yaml (91%) rename k8s/{cloud => gke}/mongodb-pvc.yaml (100%) rename k8s/{dashboard => local}/dashboard-admin.yaml (100%) diff --git a/.github/workflows/test-frontendsvc.yml b/.github/workflows/test-frontendsvc.yml index b70fb5a..33c5bfc 100644 --- a/.github/workflows/test-frontendsvc.yml +++ b/.github/workflows/test-frontendsvc.yml @@ -39,7 +39,8 @@ jobs: PORT: 3081 NODE_ENV: test MONGO_URI: mongodb://localhost:27017/spendwise - JWT_SECRET_KEY: MySecret + JWT_SECRET_KEY: TestSecret + SESSION_SECRET: TestSecret ACCOUNT_SERVICE_URL: http://localhost:3030 EXPENSE_SERVICE_URL: http://localhost:3032 run: | diff --git a/README.md b/README.md index 238f13f..e276c0d 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,9 @@ It provides tools for tracking spending over time. The system is built with a MongoDB database, modular microservices containerized via Docker, and deployed to Google Cloud. -The project is configured **CI with GitHub Actions**, any update on main branch will automatically trigger the test, build new image and push to **Docker Hub** -> GKE deployment will be done manually due to limited permission of provided GCP account restricting automated deployment. +The project is configured CI/CD workflow +- **CI with GitHub Actions**, any update on `main` branch will automatically trigger the test. +- **CD with Google Cloud Build**, merging changes into `main` automatically triggers a workflow that builds the application (Cloud Build), stores the images (Artifact Registry), and deploys them to production on Google Kubernetes Engine (GKE). ![Account](images/account.png) ![Expense](images/expense.png) @@ -18,24 +19,60 @@ The cloud‑native application consists of three services: frontend, account, an - 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**. -# CI-CD pipeline +# CI/CD Instruction +## Workflow Setup +The SpendWise project is designed with a fully automated CI/CD pipeline that ensures every code change is tested, validated, built, and deployed in a consistent and reproducible way. The automation is powered by **GitHub Actions** and **Google Cloud Build**, forming a seamless workflow from commit to production. -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` +### 1. GitHub Actions — Continuous Integration (CI) +Every push or pull request to the `main` branch triggers the CI workflow. This stage focuses on code quality and reliability: +- Install dependencies for each microservice +- Run automated tests +- Perform linting and static analysis +- Validate that each service builds successfully +Only when all checks pass does the pipeline allow the change to progress toward deployment. This ensures that broken code never reaches production. -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 +### 2. Cloud Build Trigger — Continuous Delivery (CD) +When changes are merged into `main`, GitHub automatically notifies **Google Cloud Build** through a build trigger configured in GCP. + +Cloud Build then executes a multi‑step pipeline: +- Build Docker images for the frontend, account, and expense services +- Tag each image using the commit SHA for traceability +- Push the images to **Artifact Registry** +- Apply updated Kubernetes manifests to the GKE cluster + +This creates a fully automated delivery pipeline where every deployment is versioned, reproducible, and auditable. + +### 3. Deployment to GKE — Automated Rollout +Once Cloud Build pushes the new images, it updates the running workloads in GKE: +- GKE performs a **rolling update**, replacing old pods with new ones +- Traffic is shifted gradually to avoid downtime +- If a deployment fails, GKE automatically rolls back to the previous stable version +This ensures that production deployments are safe, controlled, and fully automated. + + +## Manual Deployment (Workaround) +### Purpose +In cases where your Google Cloud account does not have sufficient permissions to allow fully automated deployment (for example, restricted IAM roles or disabled Cloud Build triggers), SpendWise can still be deployed manually. This fallback workflow ensures that updates can be delivered reliably even without full CI/CD privileges. + +The manual deployment process still uses **GitHub Actions for CI**, but replaces the automated CD stage with a manual deployment to GKE. + +### How It Works +Generally, the workflow is: commit & push → automated testing → automatic image build → automatic publish to Docker Hub → manually apply the new image in GKE. + +- In the GitHub Actions workflow, Docker images are built and pushed to Docker Hub after all tests pass. Each image is tagged with the `GITHUB_SHA` for uniqueness and easier maintenance. +- After the image is published, update the running service in GKE using `kubectl set image` and then trigger a rollout restart. Example for the account service: ```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 first time using `` tag -> we need to set new image tag for deployed image + # Ex: kubectl set image deployment/accountsvc-deployment accountsvc-container=dockeruser/sit737-account-service:1t11tt1 + + kubectl set image deployment/ =/: # For later updates -> we only need to restart the deployment to re-pull new image - kubectl rollout restart deployment/accountsvc-deployment + # Ex: kubectl rollout restart deployment accountsvc-deployment -n production + kubectl rollout restart deployment -n ``` -# Instruction +# Application Instruction ## Start the application ### Run all with docker compose - Start all services: @@ -99,37 +136,6 @@ docker push /spendwise-frontend > - 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) -### Google Cloud Setup - - - -```bash - -# 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 - -gcloud projects add-iam-policy-binding \ - --member="serviceAccount:@.iam.gserviceaccount.com" \ - --role="roles/" - -# Create k8s cluster -gcloud container clusters create \ - --enable-autoscaling --min-nodes 1 --max-nodes 4 \ - --num-nodes=1 \ - --zone= \ - --service-account @.iam.gserviceaccount.com -``` - -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 - -# Get credentials and switch to cloud context (kubectl) -gcloud container clusters get-credentials spendwise-k8s-cluster --location=australia-southeast1-b - - ### Deployment > Detail instruction for **GCP deployment** please refer to my documentation at [GCP Documentation](./docs/GCP.md) diff --git a/backend/account_service/logs/combined.log b/backend/account_service/logs/combined.log index b1116dd..f40b809 100644 --- a/backend/account_service/logs/combined.log +++ b/backend/account_service/logs/combined.log @@ -283,3 +283,83 @@ {"level":"info","message":"[ACCOUNT] POST at /logout: blacklisted token, logout successful","service":"account"} {"level":"error","message":"[ACCOUNT] GET at /status: request received, token was blacklisted","service":"account"} {"level":"info","message":"[ACCOUNT] DELETE at /: delete account for user sampletestuser222@gmail.com successful","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /: registration successful","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] DELETE at /: delete account for user sampletestuser222@gmail.com successful","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /: registration successful","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /logout: blacklisted token, logout successful","service":"account"} +{"level":"error","message":"[ACCOUNT] GET at /status: request received, token was blacklisted","service":"account"} +{"level":"info","message":"[ACCOUNT] DELETE at /: delete account for user sampletestuser222@gmail.com successful","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /: registration successful","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /logout: blacklisted token, logout successful","service":"account"} +{"level":"error","message":"[ACCOUNT] GET at /status: request received, token was blacklisted","service":"account"} +{"level":"info","message":"[ACCOUNT] DELETE at /: delete account for user sampletestuser222@gmail.com successful","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /: registration successful","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] POST at /login: JWT created, login successful","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] GET at /status: request received, token found for user [object Object]","service":"account"} +{"level":"info","message":"[ACCOUNT] DELETE at /: delete account for user sampletestuser222@gmail.com successful","service":"account"} diff --git a/backend/account_service/logs/error.log b/backend/account_service/logs/error.log index 7c44eaf..27385ca 100644 --- a/backend/account_service/logs/error.log +++ b/backend/account_service/logs/error.log @@ -65,3 +65,6 @@ {"level":"error","message":"[ACCOUNT] GET at /status: request received, token was blacklisted","service":"account"} {"level":"error","message":"[ACCOUNT] GET at /status: request received, token was blacklisted","service":"account"} {"level":"error","message":"[ACCOUNT] GET at /status: request received, token was blacklisted","service":"account"} +{"level":"error","message":"[ACCOUNT] GET at /status: request received, token was blacklisted","service":"account"} +{"level":"error","message":"[ACCOUNT] GET at /status: request received, token was blacklisted","service":"account"} +{"level":"error","message":"[ACCOUNT] GET at /status: request received, token was blacklisted","service":"account"} diff --git a/backend/expense_service/logs/combined.log b/backend/expense_service/logs/combined.log index 4154b3c..3fc23d9 100644 --- a/backend/expense_service/logs/combined.log +++ b/backend/expense_service/logs/combined.log @@ -43,3 +43,23 @@ {"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} {"level":"info","message":"[EXPENSE] DELETE at /: delete expense 691411d34df32b9895d7e9a2 successful","service":"expense"} {"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com, there isn't any registered expense","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com, there isn't any registered expense","service":"expense"} +{"level":"info","message":"[EXPENSE] POST at /: add expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] PUT at /: update expense 69803a87e43b2ea44baf1bee successful","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] DELETE at /: delete expense 69803a87e43b2ea44baf1bee successful","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com, there isn't any registered expense","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com, there isn't any registered expense","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com, there isn't any registered expense","service":"expense"} +{"level":"info","message":"[EXPENSE] POST at /: add expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] PUT at /: update expense 69803af9e43b2ea44baf1c05 successful","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] GET at /: get expense successful for sampletestuser222@gmail.com","service":"expense"} +{"level":"info","message":"[EXPENSE] DELETE at /: delete expense 69803af9e43b2ea44baf1c05 successful","service":"expense"} diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 8ac7076..daa3273 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -1,36 +1,3 @@ -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 @@ -90,7 +57,7 @@ steps: - name: 'gcr.io/cloud-builders/gke-deploy' args: - run - - --filename=k8s/cloud/ + - --filename=k8s/cloudbuild/ - --location=${_LOCATION} - --cluster=${_CLUSTER} - --namespace=${_NAMESPACE} diff --git a/k8s/cloud/mongodb-secret.yaml b/k8s/cloud/mongodb-secret.yaml deleted file mode 100644 index 4a7bc13..0000000 --- a/k8s/cloud/mongodb-secret.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: spendwise-mongo-secret -stringData: - mongo-user: myuser - mongo-password: myppass \ No newline at end of file diff --git a/k8s/cloud/accountsvc-deployment.yaml b/k8s/cloudbuild/accountsvc-deployment.yaml similarity index 81% rename from k8s/cloud/accountsvc-deployment.yaml rename to k8s/cloudbuild/accountsvc-deployment.yaml index 7c8784e..5947d6c 100644 --- a/k8s/cloud/accountsvc-deployment.yaml +++ b/k8s/cloudbuild/accountsvc-deployment.yaml @@ -14,24 +14,27 @@ spec: spec: containers: - name: accountsvc-container - image: spendwise-account-service:latest + image: __ARTIFACT_IMAGE__ ports: - containerPort: 3030 env: - name: MONGO_USER valueFrom: secretKeyRef: - name: spendwise-mongo-secret + name: spendwise-secret key: mongo-user # App gets MongoDB username from Secret - name: MONGO_PASSWORD valueFrom: secretKeyRef: - name: spendwise-mongo-secret + name: spendwise-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 + valueFrom: + secretKeyRef: + name: spendwise-secret + key: jwt-secret --- apiVersion: v1 kind: Service diff --git a/k8s/cloud/expensesvc-deployment.yaml b/k8s/cloudbuild/expensesvc-deployment.yaml similarity index 88% rename from k8s/cloud/expensesvc-deployment.yaml rename to k8s/cloudbuild/expensesvc-deployment.yaml index 3d2aace..0f77db8 100644 --- a/k8s/cloud/expensesvc-deployment.yaml +++ b/k8s/cloudbuild/expensesvc-deployment.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: expensesvc-container - image: spendwise-expense-service:latest + image: __ARTIFACT_IMAGE__ ports: - containerPort: 3032 env: @@ -23,12 +23,12 @@ spec: - name: MONGO_USER valueFrom: secretKeyRef: - name: spendwise-mongo-secret + name: spendwise-secret key: mongo-user # App gets MongoDB username from Secret - name: MONGO_PASSWORD valueFrom: secretKeyRef: - name: spendwise-mongo-secret + name: spendwise-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" diff --git a/k8s/cloud/frontendsvc-deployment.yaml b/k8s/cloudbuild/frontendsvc-deployment.yaml similarity index 94% rename from k8s/cloud/frontendsvc-deployment.yaml rename to k8s/cloudbuild/frontendsvc-deployment.yaml index 913b028..3a0a0dd 100644 --- a/k8s/cloud/frontendsvc-deployment.yaml +++ b/k8s/cloudbuild/frontendsvc-deployment.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: frontendsvc-container - image: spendwise-frontend:latest + image: __ARTIFACT_IMAGE__ ports: - containerPort: 3080 env: diff --git a/k8s/gke/gke-secret.txt b/k8s/gke/gke-secret.txt new file mode 100644 index 0000000..411a7d2 --- /dev/null +++ b/k8s/gke/gke-secret.txt @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Secret +metadata: + name: spendwise-secret +stringData: + mongo-user: myuser + mongo-password: myppass + jwt-secret: myjwtsecret + +# kubectl create secret generic spendwise-secret \ +# --from-literal=mongo-user="myuser" \ +# --from-literal=mongo-password="mypass" \ +# --from-literal=jwt-secret="myjwtsecret" \ +# -n production \ No newline at end of file diff --git a/k8s/cloud/mongodb-deployment.yaml b/k8s/gke/mongodb-deployment.yaml similarity index 91% rename from k8s/cloud/mongodb-deployment.yaml rename to k8s/gke/mongodb-deployment.yaml index 684e168..d95e976 100644 --- a/k8s/cloud/mongodb-deployment.yaml +++ b/k8s/gke/mongodb-deployment.yaml @@ -19,12 +19,12 @@ spec: - name: MONGO_INITDB_ROOT_USERNAME valueFrom: secretKeyRef: - name: spendwise-mongo-secret + name: spendwise-secret key: mongo-user - name: MONGO_INITDB_ROOT_PASSWORD valueFrom: secretKeyRef: - name: spendwise-mongo-secret + name: spendwise-secret key: mongo-password volumeMounts: - mountPath: /data/db diff --git a/k8s/cloud/mongodb-pvc.yaml b/k8s/gke/mongodb-pvc.yaml similarity index 100% rename from k8s/cloud/mongodb-pvc.yaml rename to k8s/gke/mongodb-pvc.yaml diff --git a/k8s/dashboard/dashboard-admin.yaml b/k8s/local/dashboard-admin.yaml similarity index 100% rename from k8s/dashboard/dashboard-admin.yaml rename to k8s/local/dashboard-admin.yaml