From fdd10a9fb2c822df30e40a6671057875fc286714 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 01:48:11 +1000 Subject: [PATCH 1/5] Remove Attach ACR step --- .github/workflows/backend-cd.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/backend-cd.yml b/.github/workflows/backend-cd.yml index 6035ed15..6472627b 100644 --- a/.github/workflows/backend-cd.yml +++ b/.github/workflows/backend-cd.yml @@ -38,10 +38,25 @@ jobs: - name: Set Kubernetes context (get AKS credentials) run: | az aks get-credentials --resource-group ${{ github.event.inputs.aks_resource_group }} --name ${{ github.event.inputs.aks_cluster_name }} --overwrite-existing + + - name: Ensure namespace exists + run: | + kubectl create namespace sit722 --dry-run=client -o yaml | kubectl apply -f - - - name: Attach ACR + - name: Create/refresh imagePullSecret (acr-auth) run: | - az aks update --name ${{ github.event.inputs.aks_cluster_name }} --resource-group ${{ github.event.inputs.aks_resource_group }} --attach-acr ${{ github.event.inputs.aks_acr_name }} + kubectl delete secret acr-auth -n sit722 --ignore-not-found + kubectl create secret docker-registry acr-auth \ + --namespace sit722 \ + --docker-server=${{ secrets.AZURE_CONTAINER_REGISTRY }} \ + --docker-username=${{ secrets.AZURE_CONTAINER_REGISTRY_NAME }} \ + --docker-password='${{ secrets.ACR_PASSWORD }}' \ + --docker-email="devnull@example.local" + kubectl get secret acr-auth -n sit722 + +# - name: Attach ACR +# run: | +# az aks update --name ${{ github.event.inputs.aks_cluster_name }} --resource-group ${{ github.event.inputs.aks_resource_group }} --attach-acr ${{ github.event.inputs.aks_acr_name }} - name: Deploy Backend Infrastructure (Namespace, ConfigMaps, Secrets, Databases) run: | From d1b41dd7f9b2bc0667267a91a608d555d9c1160e Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 04:27:45 +1000 Subject: [PATCH 2/5] Update frontend API endpoints for product/order services --- frontend/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/main.js b/frontend/main.js index f321fd91..2676fc6f 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -4,8 +4,8 @@ document.addEventListener('DOMContentLoaded', () => { // API endpoints for the Product and Order services. // These ports (30000 for Product, 30001 for Order) are mapped // from the Docker containers to the host machine in docker-compose.yml for Example 2. - const PRODUCT_API_BASE_URL = '_PRODUCT_API_URL_'; - const ORDER_API_BASE_URL = '_ORDER_API_URL_'; + const PRODUCT_API_BASE_URL = 'http://172.188.196.47:8000'; + const ORDER_API_BASE_URL = 'http://4.144.233.236:8001'; // Product Service is named 'product-service-w04e2' and exposes port 8000 internally. //const PRODUCT_API_BASE_URL = 'http://product-service-w04e2:8000'; From 9dfefe4eff2a66210f819a8f0afdeec44f05c98e Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 13:50:36 +1000 Subject: [PATCH 3/5] Update frontend with real product and order API IPs --- frontend/main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/main.js b/frontend/main.js index 2676fc6f..5bca83c6 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -5,7 +5,8 @@ document.addEventListener('DOMContentLoaded', () => { // These ports (30000 for Product, 30001 for Order) are mapped // from the Docker containers to the host machine in docker-compose.yml for Example 2. const PRODUCT_API_BASE_URL = 'http://172.188.196.47:8000'; - const ORDER_API_BASE_URL = 'http://4.144.233.236:8001'; + const ORDER_API_BASE_URL = 'http://4.144.233.236:8001'; + // Product Service is named 'product-service-w04e2' and exposes port 8000 internally. //const PRODUCT_API_BASE_URL = 'http://product-service-w04e2:8000'; From eb3fd7ae521ef0a41c93043c9767eb1f8509cb6a Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 13:51:12 +1000 Subject: [PATCH 4/5] CD fixes: namespace, imagePullSecret, LB IP wait, frontend update --- .github/workflows/backend-cd.yml | 29 +++++++++++++++++++---------- .github/workflows/frontend-cd.yml | 12 ++++++------ k8s/frontend.yaml | 2 +- k8s/order-service.yaml | 4 +++- k8s/product-service.yaml | 4 +++- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/.github/workflows/backend-cd.yml b/.github/workflows/backend-cd.yml index 6472627b..c3420791 100644 --- a/.github/workflows/backend-cd.yml +++ b/.github/workflows/backend-cd.yml @@ -6,15 +6,15 @@ on: aks_cluster_name: description: 'Name of the AKS Cluster to deploy to' required: true - default: '' + default: 'sit722-aks' aks_resource_group: description: 'Resource Group of the AKS Cluster' required: true - default: '' + default: 'SIT722-RG' aks_acr_name: - description: 'Name of ACR' + description: 'Azure Container Registry name (not FQDN)' required: true - default: '' + default: '223313284acr' jobs: deploy_backend: @@ -30,7 +30,7 @@ jobs: uses: actions/checkout@v4 - name: Log in to Azure - uses: azure/login@v1 + uses: azure/login@v2 with: creds: ${{ secrets.AZURE_CREDENTIALS }} enable-AzPSSession: true @@ -39,6 +39,9 @@ jobs: run: | az aks get-credentials --resource-group ${{ github.event.inputs.aks_resource_group }} --name ${{ github.event.inputs.aks_cluster_name }} --overwrite-existing + - name: Setup kubectl + uses: azure/setup-kubectl@v4 + - name: Ensure namespace exists run: | kubectl create namespace sit722 --dry-run=client -o yaml | kubectl apply -f - @@ -74,16 +77,19 @@ jobs: kubectl apply -f product-service.yaml kubectl apply -f order-service.yaml - - name: Wait for Backend LoadBalancer IPs + - name: Wait for Backend LoadBalancer IPs run: | + echo "Sanity check: services across namespaces" + kubectl get svc -A + echo "Waiting for Product, Order LoadBalancer IPs to be assigned (up to 5 minutes)..." PRODUCT_IP="" ORDER_IP="" for i in $(seq 1 60); do echo "Attempt $i/60 to get IPs..." - PRODUCT_IP=$(kubectl get service product-service-w08e1 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - ORDER_IP=$(kubectl get service order-service-w08e1 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + PRODUCT_IP=$(kubectl get service product-service-w08e1 -n sit722 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + ORDER_IP=$(kubectl get service order-service-w08e1 -n sit722 -o jsonpath='{.status.loadBalancer.ingress[0].ip}') if [[ -n "$PRODUCT_IP" && -n "$ORDER_IP" ]]; then echo "All backend LoadBalancer IPs assigned!" @@ -95,10 +101,13 @@ jobs: done if [[ -z "$PRODUCT_IP" || -z "$ORDER_IP" ]]; then + echo "DEBUG: describe services in sit722" + kubectl describe svc product-service-w08e1 -n sit722 || true + kubectl describe svc order-service-w08e1 -n sit722 || true echo "Error: One or more LoadBalancer IPs not assigned after timeout." - exit 1 # Fail the job if IPs are not obtained + exit 1 fi - + # These are environment variables for subsequent steps in the *same job* # And used to set the job outputs echo "PRODUCT_IP=$PRODUCT_IP" >> $GITHUB_ENV diff --git a/.github/workflows/frontend-cd.yml b/.github/workflows/frontend-cd.yml index 0a0879c8..edbea9ca 100644 --- a/.github/workflows/frontend-cd.yml +++ b/.github/workflows/frontend-cd.yml @@ -10,19 +10,19 @@ on: product_api_ip: description: 'External IP of Product Service' required: true - default: 'http://:8000' + default: 'http://172.188.196.47:8000' order_api_ip: description: 'External IP of Order Service (e.g., http://Y.Y.Y.Y:8001)' required: true - default: 'http://:8001' + default: 'http://4.144.233.236:8001' aks_cluster_name: - description: 'Name of the AKS Cluster to deploy to' + description: 'AKS cluster name' required: true - default: '' + default: 'sit722-aks' aks_resource_group: - description: 'Resource Group of the AKS Cluster' + description: 'AKS resource group' required: true - default: '<' + default: 'SIT722-RG' workflow_call: inputs: diff --git a/k8s/frontend.yaml b/k8s/frontend.yaml index 1948536d..a66b1cfb 100644 --- a/k8s/frontend.yaml +++ b/k8s/frontend.yaml @@ -18,7 +18,7 @@ spec: spec: containers: - name: frontend-container - image: durgeshsamariya.azurecr.io/frontend:latest + image: 223313284acr.azurecr.io/frontend:latest imagePullPolicy: Always ports: - containerPort: 80 diff --git a/k8s/order-service.yaml b/k8s/order-service.yaml index c9d92e4d..58bd9423 100644 --- a/k8s/order-service.yaml +++ b/k8s/order-service.yaml @@ -16,9 +16,11 @@ spec: labels: app: order-service spec: + imagePullSecrets: + - name: acr-auth containers: - name: order-service-container - image: durgeshsamariya.azurecr.io/order_service:latest + image: 223313284acr.azurecr.io/order_service:latest imagePullPolicy: Always ports: - containerPort: 8000 diff --git a/k8s/product-service.yaml b/k8s/product-service.yaml index 0cbbd505..91c18d30 100644 --- a/k8s/product-service.yaml +++ b/k8s/product-service.yaml @@ -16,9 +16,11 @@ spec: labels: app: product-service spec: + imagePullSecrets: + - name: acr-auth containers: - name: product-service-container - image: durgeshsamariya.azurecr.io/product_service:latest + image: 223313284acr.azurecr.io/product_service:latest imagePullPolicy: Always ports: - containerPort: 8000 From 569909289c08afbc02be91d62d1436b7203473b1 Mon Sep 17 00:00:00 2001 From: cyber-Elvis Date: Wed, 1 Oct 2025 13:51:45 +1000 Subject: [PATCH 5/5] chore: ignore sp_output.json --- .gitignore | Bin 4338 -> 4566 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index cfa76a7f9df7a7dce47fb09d3a358402e7cb4a04..8776beb499dbeaab1953caa4d60bb3e664a3d91c 100644 GIT binary patch delta 1963 zcmZ8i&u<(x6yAs=ZKs)}2mw_=Wl)NOBGx(ZLllHWnjbWWlvTD#D-apHGu~Y%v$nB4 zn~adi0jY2Vt@uNF=fI7>fO0{I3uh#5-1wenvJG5pzxTfP?DyVh`|nquEPuCh7Ds7n zs*Gntk)~^Lw8~8NX{Phfu)Jj|mKEH&IEtg?WFrx$UMMHEf@YODUF&yw_Hj3k*k(8F zdTm9m-IUH-*(*KZ$y#D~cFYG-4FK#^eyCL(^-9?*a%`H5u_&}@i^0H=2v?f)i7GVD zN!3_bGZ(T4CB}E&!fd$p1aghzm|I9ELm>*NzyIs`59zpYZA;bHFfpl|=S3lMmi2L> zV2q>P^?N(pTiyG00-b87LD_in!OZqdJo$R2gMzKH5m&M=oDWqnBC8#y@TAZKRLDrv z#)|n<07=M2A-rh&p>*wBT9KhzRc)sF?knjNkFY3LrpLnafk><{8rj9s(2oje&*=DG zpVFl2=^P8q`I4=YKuwJ!r5$#4-m%kB5l2% zw}$)!3I;m!ean?AI5jzNVx&VTjf}~>dBoK~C(f7s{(EFWJiroy{+lQiMGndPRM;+YF_9jj}G zQk^Eb&dQNcJ|sYl%iLNDS_W29j81ijBw<4xV0o4VZ0Wfj2x4hGdHl?CdoW8=sa}eb zXU9fMMLnYkJLhaSR`+Eg(p>a;S&%C{=pv+lW z&`nxn+PZgu5o^}t$BnvK#*-hT8#q04rUHvVh$FlKwLBFllRa%j(rA+Ndjgz={y)Ic zF;VvaG+uMKNOf|fif$L9sky-KL(EBLM~--OaZP)7Dk~CS;Q)ck4f8EsGjQhW&2{*r zHvo`^${vWBG85nG_~(ZVMf|5!MD0kN3O z1#i&nJ^UXW?1Pt(&k!a`~aRcF_!Iy=NwT+q^nXCe?J6v0T_JpCJ` zbsFEq?@JG`(c9N(`yZ~|-UciSCOJ^yXFL~GE>7|I)oRx=t+b_EWy@nlBWoSC95kvG Hx1!d+Jnc@C delta 1605 zcmZuxL2n#26jn+SQY+b{O@*o!%AgG@TCpAwsDf}xlMPL(gjKg~5U81WJ>FSoXKZ78 zH#-v5Uf{qDxA z^wraw6NKBP?Ms2WL!PHGO4*3zQZ-qY8JKZnVU%Ygmm~$Cf^qfBc{fHd+<7}jif9Xd zQ>_>g9iy{8W4XurM6+0hZJIN%;bS!Uo1!OUgt;)5DC-__bj3pc>_y+%SBW??IX$3>3L{eIG@=%oI?zf{upnc+}B zz!X)0^7ts*@v14lM_2Vr9%1`(t6jF_=XOT^5v0Ag43d1*tG=npJ(k?NCirIU{2erankV z^|=^Fsieb#2^;bSQBV^nQ`G>eUEcKyV%pamU|*yqI%6OqAnXr)A9QpmU2T4G9}ZoW zqMJZ-=|D*?Y!L3=RE|o^9?w~lvK|@c5CPa;rwNs!$1`6%#8f2{BiEaM-UyQsJqt@YLxb9+vyJS#dl?4fOR0-!C!4aJ@ zYNMGT5nMv=nBrkNvnR0ZfmG~&7HNQIG+-42udM%wEjFNWUwcu)!DBzpt`koE44)b} z?F%Mw+ofiaEn!pIUjdO-(uAi7xtEr2ZF-%0Z`IQvnXz z;VmoNr^_Ec2OGHeR`0qSE9(xgeB{1ZIlhYOn5T>c?pD`WP297Ucif%Yf%~j>dl_L8 zK<{@y)z;mQwG$Vw_F?_|?zh$J?(fxmuR&ZqGVr8Vi9LY(e|{x3OlEaEv3BFCuR(Dg kUcT+2Hd4E<*N)s@YbWmL%DXjqyaLEG0q?#0=E@8I0R6ra1ONa4