Staging
Input: For the staging part of the pipeline to function, it requires images for the frontend and backend in the docker hub. It also needs Azure to have a configured resource group to put the Kubernetes in. It also needs a DNS zone and a network watcher so that it can create DNS records.
Output: The output of this segment of the pipeline is the application having been deployed to Azure and tested to ensure that the frontend, backend, and database are all able to connect and function properly. DNS records should be created that make the application accessible at staging.wadestern.com.
Steps
Create_kubernetes_cluster
create_kubernetes_cluster:
docker:
- image: dudesm00thie/wadeazcli
user: root
steps:
- checkout
- run:
name: Login to Azure
command: |
az login --service-principal --username "${AZURE_CLIENT_ID}" --password "${AZURE_CLIENT_SECRET}" --tenant "${AZURE_TENANT_ID}"
- run:
name: Configure SSH Key
command: |
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
echo "$SSH_PUBLIC_KEY" > ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/id_rsa.pub
- run:
name: Create Kubernetes Cluster
command: |
az aks create -g buypotatoResourceGroup -n buypotatoStaging --node-count 2 --ssh-key-value ~/.ssh/id_rsa.pub
az aks get-credentials --resource-group buypotatoResourceGroup --name buypotatoStaging
- persist_to_workspace:
root: /root
paths:
- .kube/config
This step is responsible for generating the Kubernetes cluster. First, it logs in to Azure using my credentials which are stored as a CircleCI secret. Then it generates an SSH key to be used in the Kubernetes cluster creation step. It then creates the cluster inside of the buypotatoResourceGroup. After creating the Kubernetes cluster, it gets the credentials for it and persists them to the workspace so that other steps can easily access the cluster.
Setup_dns_and_deploy
setup_dns_and_deploy:
docker:
- image: dudesm00thie/kubeaz:latest
user: root
steps:
- checkout
- attach_workspace:
at: /root
- run:
name: Login to Azure
command: |
az login --service-principal --username "${AZURE_CLIENT_ID}" --password "${AZURE_CLIENT_SECRET}" --tenant "${AZURE_TENANT_ID}"
- run:
name: Set Vars
command: |
PRINCIPAL_ID=$(az aks show --resource-group buypotatoResourceGroup --name buypotatoStaging \
--query "identityProfile.kubeletidentity.objectId" --output tsv)
AZURE_DNS_ZONE="staging.wadestern.com"
AZURE_DNS_ZONE_RESOURCE_GROUP="buypotatoResourceGroup"
DNS_ID=/subscriptions/a24f845d-8972-45b6-ab3d-9dd9e598dbeb/resourceGroups/buypotatoresourcegroup/providers/Microsoft.Network/dnszones/staging.wadestern.com
echo $PRINCIPAL_ID
echo $AZURE_DNS_ZONE
echo $AZURE_DNS_ZONE_RESOURCE_GROUP
echo $DNS_ID
az role assignment create --role "DNS Zone Contributor" --assignee "${PRINCIPAL_ID}" --scope "${DNS_ID}"
- run:
name: Create kubernetes secret and namespace
command: |
kubectl --kubeconfig=/root/.kube/config create secret generic azure-config-file --namespace "default" --from-file /root/project/deploy/azure.json
kubectl --kubeconfig=/root/.kube/config create --namespace "default" --filename /root/project/deploy/azure-external-dns.yaml
- run:
name: Deploy backend to Kubernetes
command: kubectl --kubeconfig=/root/.kube/config apply -f /root/project/deploy/staging-backend-deploy.yaml
- run:
name: Deploy frontend to Kubernetes
command: kubectl --kubeconfig=/root/.kube/config apply -f /root/project/deploy/staging-frontend-deploy.yaml
- run:
name: Wait for external-dns pod to be running
command: |
end=$((SECONDS+180))
while [[ $SECONDS -lt $end ]]; do
if kubectl --kubeconfig=/root/.kube/config get pods -n buypotatostaging | grep -q "0/"; then
sleep 10
else
break
fi
done
This step is responsible for setting up the tool that will create DNS records when it sees the frontend and backend get deployed to the Kubernetes cluster. It also deploys the frontend and backend then it has a wait step to help the next step in the pipeline.
Puppeteer_testing
puppeteer_testing:
working_directory: ~/repo/testing
docker:
- image: mudbone67/node-pup-chr
environment:
prodorstaging: staging
steps:
- checkout:
path: ~/repo
- run:
name: Update NPM
command: npm install -g npm
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: Install Dependencies
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
paths:
- ./node_modules
- run:
name: Wait
command: sleep 120
- run:
name: List Environment Variables
command: printenv
- run:
name: Run tests
command: npm test -- --forceExit
The last step for the staging part of the pipeline is to run the puppeteer tests to ensure that all parts of the application are running and that they are able to communicate with each other. This job involves setting up the container and installing all of the necessary dependencies. There is a 2-minute pause in this step to allow the pods in the Kubernetes that were set up in the previous step to be ready and for the DNS record to be updated. The pipeline then runs the puppeteer test which tries to log in to the application and checks if it was successful. Logging in requires the backend to get the data from the database, the database to send the data to the backend, and the frontend to send the request to the backend. If the login works, it demonstrates that all of the parts of the application are functioning and able to communicate with each other.