diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 192d3c0..c59bc4d 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -19,12 +19,11 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - name: [database, backend-go, backend-java, backend-py, frontend] + name: [database, backend-go, backend-java, backend-py] include: - name: database file: database/openshift.deploy.yml overwrite: false - repository: bcgov/quickstart-openshift - name: backend-go file: backend-go/openshift.deploy.yml overwrite: true @@ -36,10 +35,6 @@ jobs: file: backend-py/openshift.deploy.yml overwrite: true parameters: -p PROMOTE_MIGRATION=${{ github.repository }}/migrations-py:test - - name: frontend - file: frontend/openshift.deploy.yml - overwrite: true - repository: bcgov/quickstart-openshift steps: - uses: bcgov-nr/action-deployer-openshift@v2.0.0 with: @@ -121,12 +116,11 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - name: [database, backend-go, backend-java, backend-py, frontend] + name: [database, backend-go, backend-java, backend-py] include: - name: database file: database/openshift.deploy.yml overwrite: false - repository: bcgov/quickstart-openshift - name: backend-go file: backend-go/openshift.deploy.yml overwrite: true @@ -141,11 +135,6 @@ jobs: overwrite: true parameters: -p MIN_REPLICAS=1 -p MAX_REPLICAS=2 -p PROMOTE_MIGRATION=${{ github.repository }}/migrations-py:test - - name: frontend - file: frontend/openshift.deploy.yml - overwrite: true - parameters: -p MIN_REPLICAS=1 -p MAX_REPLICAS=2 - repository: bcgov/quickstart-openshift steps: - uses: bcgov-nr/action-deployer-openshift@v2.0.0 with: diff --git a/.github/workflows/pr-open.yml b/.github/workflows/pr-open.yml index 7c0c456..dce230c 100644 --- a/.github/workflows/pr-open.yml +++ b/.github/workflows/pr-open.yml @@ -31,7 +31,6 @@ jobs: Thanks for the PR! Deployments, as required, will be available below: - - [Frontend](https://${{ env.PREFIX }}-frontend.${{ env.DOMAIN }}) - [Backend](https://${{ env.PREFIX }}-backend.${{ env.DOMAIN }}) - [Backend-java](https://${{ env.PREFIX }}-backend-java.${{ env.DOMAIN }}) - [Backend-py](https://${{ env.PREFIX }}-backend-py.${{ env.DOMAIN }}) @@ -53,10 +52,10 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - package: [database, backend-go, backend-java, backend-py, migrations-go, migrations-py, frontend] + package: [database, backend-go, backend-java, backend-py, migrations-go, migrations-py] include: - package: database - repository: bcgov/quickstart-openshift + triggers: ('database/') - package: backend-go triggers: ('backend-go/') - package: backend-java @@ -69,8 +68,6 @@ jobs: - package: migrations-go triggers: ('backend-go/db') build_context: ./backend-go/db - - package: frontend - repository: bcgov/quickstart-openshift steps: - uses: bcgov-nr/action-builder-ghcr@v1.3.0 with: @@ -92,13 +89,12 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - name: [database, backend-go, backend-java, backend-py, frontend] + name: [database, backend-go, backend-java, backend-py] include: - name: database file: database/openshift.deploy.yml overwrite: false - repository: bcgov/quickstart-openshift - triggers: ('backend-go' 'backend-java' 'backend-py') + triggers: ('database' 'backend-go' 'backend-java' 'backend-py') - name: backend-go file: backend-go/openshift.deploy.yml overwrite: true @@ -119,12 +115,6 @@ jobs: -p PROMOTE=${{ github.repository }}/backend-py:${{ github.event.number }} -p PROMOTE_MIGRATION=${{ github.repository }}/migrations-py:${{ github.event.number }} triggers: ('backend-py/') - - name: frontend - file: frontend/openshift.deploy.yml - overwrite: true - parameters: -p MIN_REPLICAS=1 -p MAX_REPLICAS=2 - repository: bcgov/quickstart-openshift - triggers: ('database/' 'backend/' 'frontend/') steps: - uses: bcgov-nr/action-deployer-openshift@v2.0.0 with: diff --git a/database/Dockerfile b/database/Dockerfile new file mode 100644 index 0000000..ad9f680 --- /dev/null +++ b/database/Dockerfile @@ -0,0 +1,5 @@ +FROM ghcr.io/bcgov/nr-containers/postgres:15.4 + +# Health check and non-privileged user +HEALTHCHECK --interval=15s --timeout=5s --retries=3 CMD [ "pg_isready" ] +USER postgres diff --git a/database/openshift.deploy.yml b/database/openshift.deploy.yml new file mode 100644 index 0000000..45c42ea --- /dev/null +++ b/database/openshift.deploy.yml @@ -0,0 +1,364 @@ +apiVersion: template.openshift.io/v1 +kind: Template +parameters: + - name: NAME + description: Module name + required: true + - name: COMPONENT + description: Component name + value: database + - name: ZONE + description: Deployment zone, e.g. pr-### or prod + required: true + - name: REGISTRY + description: Container registry to import from (internal is image-registry.openshift-image-registry.svc:5000) + value: ghcr.io + - name: ORG_NAME + description: Organization name, e.g. bcgov + value: bcgov + - name: IMAGE_TAG + description: Image tag to use + value: latest + - name: PVC_MOUNT_PATH + description: Where to mount the PVC, subpath (e.g. data/) + value: /var/lib/postgresql + - name: DB_PVC_SIZE + description: Volume space available for data, e.g. 512Mi, 2Gi. + displayName: Database Volume Capacity + required: true + value: 256Mi + - name: REGISTRY + description: Container registry to import from (internal is image-registry.openshift-image-registry.svc:5000) + value: ghcr.io + - name: PG_DATABASE + description: Postgres database name + value: database + - name: DB_PASSWORD + description: Password for the PostgreSQL connection user. + from: "[a-zA-Z0-9]{16}" + generate: expression + ### Backup-Container starts here ### + - name: BACKUP_COMPONENT + description: BACKUP_COMPONENT name + value: database-backup + - name: "DATABASE_DEFAULT_PORT" + description: "The configured port for the database service" + value: "5432" + - name: "BACKUP_STRATEGY" + description: "The strategy to use for backups; for example daily, or rolling." + required: true + value: "rolling" + - name: "BACKUP_DIR" + description: "The name of the root backup directory" + required: true + value: "/backups/" + - name: "NUM_BACKUPS" + description: "The number of backup files to be retained. Used for the `daily` backup strategy. Ignored when using the `rolling` backup strategy." + required: false + value: "5" + - name: "DAILY_BACKUPS" + description: "The number of daily backup files to be retained. Used for the `rolling` backup strategy." + required: false + value: "7" + - name: "WEEKLY_BACKUPS" + description: "The number of weekly backup files to be retained. Used for the `rolling` backup strategy." + required: false + value: "4" + - name: "MONTHLY_BACKUPS" + displayName: "Number of Monthly Backups to Retain" + description: "The number of monthly backup files to be retained. Used for the `rolling` backup strategy." + required: false + value: "1" + - name: "JOB_SERVICE_ACCOUNT" + description: "Name of the Service Account To Exeucte the Job As." + value: "default" + required: true + - name: "SUCCESS_JOBS_HISTORY_LIMIT" + description: "The number of successful jobs that will be retained" + value: "5" + required: true + - name: "FAILED_JOBS_HISTORY_LIMIT" + description: "The number of failed jobs that will be retained" + value: "2" + required: true + - name: "JOB_BACKOFF_LIMIT" + description: "The number of attempts to try for a successful job outcome" + value: "0" + - description: Volume space available for data, e.g. 512Mi, 2Gi. + name: PVC_SIZE + value: 256Mi + - name: CRON_MINUTES + description: Random number, 0-60, for scheduling cronjobs + from: "[0-5]{1}[0-9]{1}" + generate: expression +objects: + - apiVersion: v1 + kind: Secret + metadata: + name: "${NAME}-${ZONE}-${PG_DATABASE}" + labels: + app: "${NAME}-${ZONE}" + stringData: + database-name: "${NAME}" + database-password: "${DB_PASSWORD}" + database-user: "${NAME}" + - apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + name: allow-from-openshift-ingress + labels: + template: openshift-test + spec: + podSelector: {} + ingress: + - from: + - namespaceSelector: + matchLabels: + network.openshift.io/policy-group: ingress + policyTypes: + - Ingress + - apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + name: allow-same-namespace + labels: + template: quickstart-network-security-policy + spec: + podSelector: {} + ingress: + - from: + - podSelector: {} + policyTypes: + - Ingress + - kind: PersistentVolumeClaim + apiVersion: v1 + metadata: + name: "${NAME}-${ZONE}-${COMPONENT}" + labels: + app: "${NAME}-${ZONE}" + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "${DB_PVC_SIZE}" + storageClassName: netapp-file-standard + - kind: ImageStream + apiVersion: v1 + metadata: + name: "${NAME}-${ZONE}-${COMPONENT}" + labels: + app: "${NAME}-${ZONE}" + spec: + lookupPolicy: + local: false + tags: + - name: "${IMAGE_TAG}" + from: + kind: DockerImage + name: "${REGISTRY}/${ORG_NAME}/${NAME}/${COMPONENT}:${ZONE}" + referencePolicy: + type: Local + - kind: DeploymentConfig + apiVersion: v1 + metadata: + name: "${NAME}-${ZONE}-${COMPONENT}" + labels: + app: "${NAME}-${ZONE}" + spec: + replicas: 1 + triggers: + - type: ConfigChange + - type: ImageChange + imageChangeParams: + automatic: true + containerNames: + - "${NAME}" + from: + kind: ImageStreamTag + name: "${NAME}-${ZONE}-${COMPONENT}:${IMAGE_TAG}" + selector: + deploymentconfig: "${NAME}-${ZONE}-${COMPONENT}" + strategy: + type: Recreate + recreateParams: + timeoutSeconds: 600 + activeDeadlineSeconds: 21600 + template: + metadata: + name: "${NAME}-${ZONE}-${COMPONENT}" + labels: + app: "${NAME}-${ZONE}" + deploymentconfig: "${NAME}-${ZONE}-${COMPONENT}" + spec: + volumes: + - name: "${NAME}-${ZONE}-${COMPONENT}" + persistentVolumeClaim: + claimName: "${NAME}-${ZONE}-${COMPONENT}" + containers: + - name: "${NAME}" + image: "${NAME}-${ZONE}-${COMPONENT}:${IMAGE_TAG}" + ports: + - containerPort: 5432 + protocol: TCP + readinessProbe: + exec: + command: + - /usr/bin/env + - bash + - -c + - psql -q -U $POSTGRES_USER -d $POSTGRES_DB -c 'SELECT 1' + failureThreshold: 5 + initialDelaySeconds: 30 + periodSeconds: 15 + timeoutSeconds: 1 + livenessProbe: + exec: + command: + - /usr/bin/env + - bash + - -c + - psql -q -U $POSTGRES_USER -d $POSTGRES_DB -c 'SELECT 1' + failureThreshold: 5 + initialDelaySeconds: 30 + periodSeconds: 15 + timeoutSeconds: 1 + env: + - name: POSTGRES_DB + valueFrom: + secretKeyRef: + name: "${NAME}-${ZONE}-${COMPONENT}" + key: database-name + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: "${NAME}-${ZONE}-${COMPONENT}" + key: database-password + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: "${NAME}-${ZONE}-${COMPONENT}" + key: database-user + volumeMounts: + - name: "${NAME}-${ZONE}-${COMPONENT}" + mountPath: "${PVC_MOUNT_PATH}" + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + imagePullPolicy: Always + restartPolicy: Always + terminationGracePeriodSeconds: 30 + dnsPolicy: ClusterFirst + schedulerName: default-scheduler + - apiVersion: v1 + kind: Service + metadata: + labels: + app: "${NAME}-${ZONE}" + name: "${NAME}-${ZONE}-${COMPONENT}" + spec: + ports: + - name: postgresql + nodePort: 0 + port: 5432 + protocol: TCP + targetPort: 5432 + selector: + deploymentconfig: "${NAME}-${ZONE}-${COMPONENT}" + sessionAffinity: None + type: ClusterIP + ### Backup-Container starts here ### + - kind: PersistentVolumeClaim + apiVersion: v1 + metadata: + name: "${NAME}-${ZONE}-${BACKUP_COMPONENT}" + labels: + app: "${NAME}-${ZONE}" + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "${PVC_SIZE}" + storageClassName: netapp-file-standard + - kind: CronJob + apiVersion: "batch/v1" + metadata: + name: "${NAME}-${ZONE}-${BACKUP_COMPONENT}" + labels: + app: "${NAME}-${ZONE}" + cronjob: "${NAME}-${ZONE}" + spec: + schedule: "${CRON_MINUTES} 8 * * *" # Run daily at 8:xx AM UTC + concurrencyPolicy: "Replace" + successfulJobsHistoryLimit: "${{SUCCESS_JOBS_HISTORY_LIMIT}}" + failedJobsHistoryLimit: "${{FAILED_JOBS_HISTORY_LIMIT}}" + jobTemplate: + metadata: + labels: + app: "${NAME}-${ZONE}" + cronjob: "${NAME}-${ZONE}" + spec: + backoffLimit: "${{JOB_BACKOFF_LIMIT}}" + template: + metadata: + labels: + app: "${NAME}-${ZONE}" + cronjob: "${NAME}-${ZONE}" + spec: + containers: + - name: "${NAME}-${ZONE}" + image: "bcgovimages/backup-container:latest" + command: + - "/bin/bash" + - "-c" + - "/backup.sh -1" + volumeMounts: + - mountPath: "${BACKUP_DIR}" + name: "backup" + env: + - name: BACKUP_DIR + value: "${BACKUP_DIR}" + - name: BACKUP_STRATEGY + value: "${BACKUP_STRATEGY}" + optional: true + - name: NUM_BACKUPS + value: "${NUM_BACKUPS}" + optional: true + - name: DAILY_BACKUPS + value: "${DAILY_BACKUPS}" + optional: true + - name: WEEKLY_BACKUPS + value: "${WEEKLY_BACKUPS}" + optional: true + - name: MONTHLY_BACKUPS + value: "${MONTHLY_BACKUPS}" + optional: true + - name: DATABASE_SERVICE_NAME + value: "${NAME}-${ZONE}-database" + - name: DEFAULT_PORT + value: "${DATABASE_DEFAULT_PORT}" + - name: POSTGRES_DATABASE + valueFrom: + secretKeyRef: + name: "${NAME}-${ZONE}-database" + key: "database-name" + - name: DATABASE_USER + valueFrom: + secretKeyRef: + name: "${NAME}-${ZONE}-database" + key: "database-user" + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: "${NAME}-${ZONE}-database" + key: "database-password" + volumes: + - name: backup + persistentVolumeClaim: + claimName: "${NAME}-${ZONE}-${BACKUP_COMPONENT}" + restartPolicy: "Never" + terminationGracePeriodSeconds: 30 + activeDeadlineSeconds: 1600 + dnsPolicy: "ClusterFirst" + serviceAccountName: "${JOB_SERVICE_ACCOUNT}" + serviceAccount: "${JOB_SERVICE_ACCOUNT}"