From 26ac6fb2cee5c1b4ee4cf8d21017220380d429d0 Mon Sep 17 00:00:00 2001 From: Trevor Richards Date: Tue, 3 Dec 2024 16:24:56 -0800 Subject: [PATCH] feat: convert dev to deployments --- .../deploy-to-openshift-backend-dev.yml | 20 +- .../deploy-to-openshift-frontend-dev.yml | 20 +- tools/openshift/backend.deployment.yaml | 223 ++++++++++++++++++ tools/openshift/frontend.deployment.yaml | 204 ++++++++++++++++ 4 files changed, 447 insertions(+), 20 deletions(-) create mode 100644 tools/openshift/backend.deployment.yaml create mode 100644 tools/openshift/frontend.deployment.yaml diff --git a/.github/workflows/deploy-to-openshift-backend-dev.yml b/.github/workflows/deploy-to-openshift-backend-dev.yml index cd1661c0..38855d03 100644 --- a/.github/workflows/deploy-to-openshift-backend-dev.yml +++ b/.github/workflows/deploy-to-openshift-backend-dev.yml @@ -1,18 +1,18 @@ name: 1 DEV - Deploy Backend env: - # 🖊️ EDIT your repository secrets to log into your OpenShift cluster and set up the context. + # EDIT your repository secrets to log into your OpenShift cluster and set up the context. # See https://github.com/redhat-actions/oc-login#readme for how to retrieve these values. # To get a permanent token, refer to https://github.com/redhat-actions/oc-login/wiki/Using-a-Service-Account-for-GitHub-Actions OPENSHIFT_SERVER: ${{ secrets.OPENSHIFT_SERVER }} OPENSHIFT_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} - # 🖊️ EDIT to set the kube context's namespace after login. Leave blank to use your user's default namespace. + # EDIT to set the kube context's namespace after login. Leave blank to use your user's default namespace. OPENSHIFT_NAMESPACE: ${{ secrets.OFM_NAMESPACE_NO_ENV }}-dev COMMON_NAMESPACE: ${{ secrets.COMMON_NAMESPACE_NO_ENV }} # SPLUNK_TOKEN: ${{ secrets.SPLUNK_TOKEN }} - # 🖊️ EDIT to change the image registry settings. + # EDIT to change the image registry settings. # Registries such as GHCR, Quay.io, and Docker Hub are supported. IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }} IMAGE_REGISTRY_USER: ${{ github.actor }} @@ -81,19 +81,19 @@ jobs: core.error(`Secret "${name}" is not set`); return true; } - core.info(`✔️ Secret "${name}" is set`); + core.info(`Secret "${name}" is set`); return false; }); if (missingSecrets.length > 0) { - core.setFailed(`❌ At least one required secret is not set in the repository. \n` + + core.setFailed(`At least one required secret is not set in the repository. \n` + "You can add it using:\n" + "GitHub UI: https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository \n" + "GitHub CLI: https://cli.github.com/manual/gh_secret_set \n" + "Also, refer to https://github.com/redhat-actions/oc-login#getting-started-with-the-action-or-see-example"); } else { - core.info(`✅ All the required secrets are set`); + core.info(`All the required secrets are set`); } - name: Check out repository with branch [${{ env.BRANCH }}] @@ -147,7 +147,7 @@ jobs: oc login --token=${{ env.OPENSHIFT_TOKEN }} --server=${{ env.OPENSHIFT_SERVER }} oc project ${{ env.OPENSHIFT_NAMESPACE }} # Cancel any rollouts in progress - oc rollout cancel dc/${{ env.APP_NAME }}-${{ env.APP_NAME_BACKEND }}-${{ env.APP_ENVIRONMENT }} 2> /dev/null \ + oc rollout cancel deployment/${{ env.APP_NAME }}-${{ env.APP_NAME_BACKEND }}-${{ env.APP_ENVIRONMENT }} 2> /dev/null \ || true && echo "No rollout in progress" # Create the image stream if it doesn't exist @@ -157,7 +157,7 @@ jobs: # Process and apply deployment template oc process \ - -f tools/openshift/backend.dc.yaml \ + -f tools/openshift/backend.deployment.yaml \ -p APP_NAME=${{ env.APP_NAME }} \ -p REPO_NAME=${{ env.REPO_NAME }} \ -p BRANCH=${{ env.BRANCH }} \ @@ -190,11 +190,11 @@ jobs: ${{ secrets.SPLUNK_TOKEN }} # Start rollout (if necessary) and follow it - oc rollout latest dc/${{ env.APP_NAME }}-${{ env.APP_NAME_BACKEND }}-${{ env.APP_ENVIRONMENT }} 2> /dev/null \ + oc rollout restart deployment/${{ env.APP_NAME }}-${{ env.APP_NAME_BACKEND }}-${{ env.APP_ENVIRONMENT }} 2> /dev/null \ || true && echo "Rollout in progress" # Get status, returns 0 if rollout is successful - oc rollout status dc/${{ env.APP_NAME }}-${{ env.APP_NAME_BACKEND }}-${{ env.APP_ENVIRONMENT }} + oc rollout status deployment/${{ env.APP_NAME }}-${{ env.APP_NAME_BACKEND }}-${{ env.APP_ENVIRONMENT }} # - name: ZAP Scan # uses: zaproxy/action-full-scan@v0.8.0 diff --git a/.github/workflows/deploy-to-openshift-frontend-dev.yml b/.github/workflows/deploy-to-openshift-frontend-dev.yml index 3c3a5f85..56111de4 100644 --- a/.github/workflows/deploy-to-openshift-frontend-dev.yml +++ b/.github/workflows/deploy-to-openshift-frontend-dev.yml @@ -1,17 +1,17 @@ name: 1 DEV - Deploy Frontend env: - # 🖊️ EDIT your repository secrets to log into your OpenShift cluster and set up the context. + # EDIT your repository secrets to log into your OpenShift cluster and set up the context. # See https://github.com/redhat-actions/oc-login#readme for how to retrieve these values. # To get a permanent token, refer to https://github.com/redhat-actions/oc-login/wiki/Using-a-Service-Account-for-GitHub-Actions OPENSHIFT_SERVER: ${{ secrets.OPENSHIFT_SERVER }} OPENSHIFT_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} - # 🖊️ EDIT to set the kube context's namespace after login. Leave blank to use your user's default namespace. + # EDIT to set the kube context's namespace after login. Leave blank to use your user's default namespace. OPENSHIFT_NAMESPACE: ${{ secrets.OFM_NAMESPACE_NO_ENV }}-dev # SPLUNK_TOKEN: ${{ secrets.SPLUNK_TOKEN }} - # 🖊️ EDIT to change the image registry settings. + # EDIT to change the image registry settings. # Registries such as GHCR, Quay.io, and Docker Hub are supported. IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }} IMAGE_REGISTRY_USER: ${{ github.actor }} @@ -89,19 +89,19 @@ jobs: core.error(`Secret "${name}" is not set`); return true; } - core.info(`✔️ Secret "${name}" is set`); + core.info(`Secret "${name}" is set`); return false; }); if (missingSecrets.length > 0) { - core.setFailed(`❌ At least one required secret is not set in the repository. \n` + + core.setFailed(`At least one required secret is not set in the repository. \n` + "You can add it using:\n" + "GitHub UI: https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository \n" + "GitHub CLI: https://cli.github.com/manual/gh_secret_set \n" + "Also, refer to https://github.com/redhat-actions/oc-login#getting-started-with-the-action-or-see-example"); } else { - core.info(`✅ All the required secrets are set`); + core.info(`All the required secrets are set`); } - name: Check out repository with branch [${{ env.BRANCH }}] @@ -155,7 +155,7 @@ jobs: oc login --token=${{ env.OPENSHIFT_TOKEN }} --server=${{ env.OPENSHIFT_SERVER }} oc project ${{ env.OPENSHIFT_NAMESPACE }} # Cancel any rollouts in progress - oc rollout cancel dc/${{ env.APP_NAME }}-${{ env.APP_NAME_FRONTEND }}-${{ env.APP_ENVIRONMENT }} 2> /dev/null \ + oc rollout cancel deployment/${{ env.APP_NAME }}-${{ env.APP_NAME_FRONTEND }}-${{ env.APP_ENVIRONMENT }} 2> /dev/null \ || true && echo "No rollout in progress" # Create the image stream if it doesn't exist @@ -164,7 +164,7 @@ jobs: oc tag ${{ steps.push-image-frontend.outputs.registry-path }} ${{ env.IMAGE_NAME }}:${{ env.TAG }} # Process and apply deployment template - oc process -f tools/openshift/frontend.dc.yaml \ + oc process -f tools/openshift/frontend.deployment.yaml \ -p APP_NAME=${{ env.APP_NAME }} \ -p REPO_NAME=${{ env.REPO_NAME }} \ -p BRANCH=${{ env.BRANCH }} \ @@ -184,11 +184,11 @@ jobs: | oc apply -f - # Start rollout (if necessary) and follow it - oc rollout latest dc/${{ env.APP_NAME }}-${{ env.APP_NAME_FRONTEND }}-${{ env.APP_ENVIRONMENT }} 2> /dev/null \ + oc rollout restart deployment/${{ env.APP_NAME }}-${{ env.APP_NAME_FRONTEND }}-${{ env.APP_ENVIRONMENT }} 2> /dev/null \ || true && echo "Rollout in progress" # Get status, returns 0 if rollout is successful - oc rollout status dc/${{ env.APP_NAME }}-${{ env.APP_NAME_FRONTEND }}-${{ env.APP_ENVIRONMENT }} + oc rollout status deployment/${{ env.APP_NAME }}-${{ env.APP_NAME_FRONTEND }}-${{ env.APP_ENVIRONMENT }} cypress-run: needs: openshift-ci-cd diff --git a/tools/openshift/backend.deployment.yaml b/tools/openshift/backend.deployment.yaml new file mode 100644 index 00000000..8eef1a0a --- /dev/null +++ b/tools/openshift/backend.deployment.yaml @@ -0,0 +1,223 @@ +--- +apiVersion: template.openshift.io/v1 +kind: Template +labels: + template: '${REPO_NAME}-template' +metadata: + name: '${REPO_NAME}-backend-dc' +objects: + - apiVersion: apps/v1 + kind: Deployment + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + labels: + app: '${APP_NAME}-backend-${BRANCH}' + branch: '${BRANCH}' + name: '${APP_NAME}-backend-${ENVIRONMENT}' + spec: + replicas: ${{MIN_REPLICAS}} + selector: + matchLabels: + app: '${APP_NAME}-backend-${BRANCH}' + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 25% + maxSurge: 25% + template: + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + labels: + app: '${APP_NAME}-backend-${BRANCH}' + spec: + containers: + - image: image-registry.openshift-image-registry.svc:5000/${NAMESPACE}/${REPO_NAME}-backend:${TAG} + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 20 + failureThreshold: 5 + httpGet: + path: '/api/health' + port: 8080 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + name: '${APP_NAME}-backend-${ENVIRONMENT}' + ports: + - containerPort: 8080 + protocol: TCP + - containerPort: 443 + protocol: TCP + envFrom: + - configMapRef: + name: ofm-backend-${ENVIRONMENT}-config-map + readinessProbe: + initialDelaySeconds: 10 + failureThreshold: 5 + httpGet: + path: '/api/health' + port: 8080 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + resources: + requests: + cpu: '${MIN_CPU}' + memory: '${MIN_MEM}' + limits: + cpu: '${MAX_CPU}' + memory: '${MAX_MEM}' + volumeMounts: + - name: log-storage + mountPath: /logs + - image: artifacts.developer.gov.bc.ca/docker-remote/fluent/fluent-bit:1.5.7 + name: '${APP_NAME}-fluent-bit-sidecar-${ENVIRONMENT}' + imagePullPolicy: Always + imagePullSecrets: + - name: artifactory-creds + readinessProbe: + tcpSocket: + port: 2020 + initialDelaySeconds: 10 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + livenessProbe: + httpGet: + path: / + port: 2020 + initialDelaySeconds: 10 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 5 + successThreshold: 1 + ports: + - containerPort: 2020 + protocol: TCP + name: metrics + resources: + requests: + cpu: '5m' + memory: '25Mi' + limits: + cpu: '10m' + memory: '50Mi' + volumeMounts: + - name: log-storage + mountPath: /mnt/log + - name: flb-sc-config-volume + mountPath: /fluent-bit/etc/ + volumes: + - name: log-storage + emptyDir: {} + - name: flb-sc-config-volume + configMap: + name: ${APP_NAME}-flb-sc-config-map + test: false + - apiVersion: v1 + kind: Service + metadata: + annotations: + service.alpha.openshift.io/serving-cert-secret-name: 'ofm-backend-cert' + openshift.io/generated-by: OpenShiftNewApp + labels: + app: '${APP_NAME}-backend-${BRANCH}' + name: '${APP_NAME}-backend-${ENVIRONMENT}' + spec: + ports: + - name: 8080-tcp + port: 8080 + protocol: TCP + targetPort: 8080 + - name: 443-https + port: 443 + protocol: TCP + targetPort: 443 + selector: + app: '${APP_NAME}-backend-${BRANCH}' + - apiVersion: v1 + kind: Route + metadata: + name: '${APP_NAME}-backend-${ENVIRONMENT}' + labels: + app: '${APP_NAME}-backend-${BRANCH}' + annotations: + openshift.io/host.generated: 'true' + router.openshift.io/cookie-same-site: 'Strict' + spec: + host: '${HOST_ROUTE}' + path: /api + port: + targetPort: 8080-tcp + tls: + termination: edge + insecureEdgeTerminationPolicy: Redirect + to: + kind: Service + name: '${APP_NAME}-backend-${ENVIRONMENT}' + weight: 100 + wildcardPolicy: None + - apiVersion: autoscaling/v2 + kind: HorizontalPodAutoscaler + metadata: + name: '${APP_NAME}-backend-${ENVIRONMENT}-cpu-autoscaler' + spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: '${APP_NAME}-backend-${ENVIRONMENT}' + subresource: scale + minReplicas: ${{MIN_REPLICAS}} + maxReplicas: ${{MAX_REPLICAS}} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 90 +parameters: + - name: REPO_NAME + description: Application repository name + required: true + - name: BRANCH + description: Job identifier (i.e. 'pr-5' OR 'master') + required: true + - name: NAMESPACE + description: Target namespace reference (i.e. 'k8vopl-dev') + required: true + - name: ENVIRONMENT + description: The environment being created ('dev', 'test', 'uat', 'prod') + required: true + - name: APP_NAME + description: Application name + required: true + - name: HOST_ROUTE + description: The host the route will use to expose service outside cluster + required: true + - name: TAG + description: The identifying tag for this specific deployment + required: true + - name: MIN_REPLICAS + description: The minimum amount of replicas + required: true + - name: MAX_REPLICAS + description: The maximum amount of replicas + required: true + - name: MIN_CPU + description: The minimum amount of cpu + required: true + - name: MAX_CPU + description: The maximum amount of cpu + required: true + - name: MIN_MEM + description: The minimum amount of memory + required: true + - name: MAX_MEM + description: The maximum amount of memory + required: true diff --git a/tools/openshift/frontend.deployment.yaml b/tools/openshift/frontend.deployment.yaml new file mode 100644 index 00000000..aa186cf9 --- /dev/null +++ b/tools/openshift/frontend.deployment.yaml @@ -0,0 +1,204 @@ +--- +apiVersion: template.openshift.io/v1 +kind: Template +labels: + template: '${REPO_NAME}-template' +metadata: + name: '${REPO_NAME}-frontend-dc' +objects: + - apiVersion: apps/v1 + kind: Deployment + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + labels: + app: '${APP_NAME}-frontend-${BRANCH}' + branch: '${BRANCH}' + name: '${APP_NAME}-frontend-${ENVIRONMENT}' + spec: + replicas: ${{MIN_REPLICAS}} + selector: + matchLabels: + app: '${APP_NAME}-frontend-${BRANCH}' + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 25% + maxSurge: 25% + template: + metadata: + annotations: + openshift.io/generated-by: OpenShiftNewApp + labels: + app: '${APP_NAME}-frontend-${BRANCH}' + spec: + containers: + - image: image-registry.openshift-image-registry.svc:5000/${NAMESPACE}/${REPO_NAME}-frontend:${TAG} + imagePullPolicy: Always + volumeMounts: + - name: js-runtime-config + mountPath: '/srv/js/config' + livenessProbe: + failureThreshold: 3 + httpGet: + path: '/' + port: 2015 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: '${APP_NAME}-frontend-${ENVIRONMENT}' + ports: + - containerPort: 2015 + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: '/' + port: 2015 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: '${MIN_CPU}' + memory: '${MIN_MEM}' + limits: + cpu: '${MAX_CPU}' + memory: '${MAX_MEM}' + volumes: + - name: js-runtime-config + configMap: + name: ofm-frontend-${ENVIRONMENT}-config-map + test: false + - apiVersion: v1 + kind: Service + metadata: + annotations: + service.alpha.openshift.io/serving-cert-secret-name: 'ofm-frontend-cert' + openshift.io/generated-by: OpenShiftNewApp + labels: + app: '${APP_NAME}-frontend-${BRANCH}' + name: '${APP_NAME}-frontend-${ENVIRONMENT}' + spec: + ports: + - name: 2015-tcp + port: 2015 + protocol: TCP + targetPort: 2015 + selector: + app: '${APP_NAME}-frontend-${BRANCH}' + - apiVersion: v1 + kind: Route + metadata: + name: '${APP_NAME}-frontend-${ENVIRONMENT}' + labels: + app: '${APP_NAME}-frontend-${BRANCH}' + annotations: + openshift.io/host.generated: 'true' + router.openshift.io/cookie-same-site: 'Strict' + spec: + to: + kind: Service + name: '${APP_NAME}-frontend-${ENVIRONMENT}' + weight: 100 + port: + targetPort: 2015-tcp + tls: + termination: edge + insecureEdgeTerminationPolicy: Redirect + wildcardPolicy: None + - apiVersion: autoscaling/v2 + kind: HorizontalPodAutoscaler + metadata: + name: '${APP_NAME}-frontend-${ENVIRONMENT}-cpu-autoscaler' + spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: '${APP_NAME}-frontend-${ENVIRONMENT}' + subresource: scale + minReplicas: ${{MIN_REPLICAS}} + maxReplicas: ${{MAX_REPLICAS}} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 90 + - apiVersion: v1 + kind: ConfigMap + metadata: + name: ofm-frontend-${ENVIRONMENT}-config-map + namespace: '${NAMESPACE}' + data: + config.js: | + const config = { + BANNER_ENVIRONMENT: '${BANNER_ENVIRONMENT}', + BANNER_COLOR: '${BANNER_COLOR}', + TDAD_CONTACT_EMAIL: '${TDAD_CONTACT_EMAIL}', + IRREGULAR_EXPENSE_FORM_URL: '${IRREGULAR_EXPENSE_FORM_URL}' + }; +parameters: + - name: REPO_NAME + description: Application repository name + required: true + - name: BRANCH + description: Job identifier (i.e. 'pr-5' OR 'master') + required: true + - name: NAMESPACE + description: Target namespace reference (i.e. 'k8vopl-dev') + required: true + - name: ENVIRONMENT + description: The environment being created ('dev', 'test', 'uat', 'prod') + required: true + - name: APP_NAME + description: Application name + required: true + - name: HOST_ROUTE + description: The host the route will use to expose service outside cluster + required: false + - name: TAG + description: The identifying tag for this specific deployment + required: true + - name: MIN_REPLICAS + description: The minimum amount of replicas + required: true + - name: MAX_REPLICAS + description: The maximum amount of replicas + required: true + - name: MIN_CPU + description: The minimum amount of cpu + required: true + - name: MAX_CPU + description: The maximum amount of cpu + required: true + - name: MIN_MEM + description: The minimum amount of memory + required: true + - name: MAX_MEM + description: The maximum amount of memory + required: true + - name: CA_CERT + description: The CA Certificate + required: false + - name: CERTIFICATE + description: The Certificate + required: false + - name: PRIVATE_KEY + description: The private key + required: false + - name: BANNER_ENVIRONMENT + description: The title for the application banner. It which indicates what environment is running + required: false + - name: BANNER_COLOR + description: The CSS color for the BANNER_ENVIRONMENT background + required: false + - name: TDAD_CONTACT_EMAIL + description: The contact email for 10 dollar a day daycare centers + required: false + - name: IRREGULAR_EXPENSE_FORM_URL + description: The URL to download the Irregular Expense application form. + required: false