From 493f4a884e06bd54c195a586648acfeb8a1e6752 Mon Sep 17 00:00:00 2001 From: Ricardo Campos Date: Mon, 12 Aug 2024 17:58:03 -0300 Subject: [PATCH 01/13] feat: add backup files - tmp - wip issue #1268 --- tools/pg-test-portforward.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/pg-test-portforward.sh b/tools/pg-test-portforward.sh index d1e3c5278..c84f41482 100755 --- a/tools/pg-test-portforward.sh +++ b/tools/pg-test-portforward.sh @@ -49,10 +49,9 @@ fi # 3. Get DB name, user and password echo "Getting credentials..." -SECRETS=$(oc extract secret/nr-spar-$TARGET_ENV-database -n b9d53b-$TARGET_ENV --to=- 2> /dev/null) -DB_NAME=$(echo $SECRETS | cut -d ' ' -f 1) -DB_USER=$(echo $SECRETS | cut -d ' ' -f 3) -DB_PASS=$(echo $SECRETS | cut -d ' ' -f 2) +DB_NAME=$(oc extract secret/nr-spar-$TARGET_ENV-database -n b9d53b-$TARGET_ENV --keys=database-name --to=- 2> /dev/null) +DB_USER=$(oc extract secret/nr-spar-$TARGET_ENV-database -n b9d53b-$TARGET_ENV --keys=database-user --to=- 2> /dev/null) +DB_PASS=$(oc extract secret/nr-spar-$TARGET_ENV-database -n b9d53b-$TARGET_ENV --keys=database-password --to=- 2> /dev/null) echo "Use this information to set up the database connection with '$TARGET_ENV' on your end:" echo "- DB_HOST = localhost" echo "- DB_PORT = $PORT" From 6c7ab208c0a32c448708d74491433a26b3084c35 Mon Sep 17 00:00:00 2001 From: Ricardo Campos Date: Mon, 12 Aug 2024 17:58:29 -0300 Subject: [PATCH 02/13] feat: add backup files - tmp - wip issue #1268 --- backup/Dockerfile | 14 ++++++++++++++ backup/help.txt | 6 ++++++ backup/pg-simple-backup.sh | 31 +++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 backup/Dockerfile create mode 100644 backup/help.txt create mode 100755 backup/pg-simple-backup.sh diff --git a/backup/Dockerfile b/backup/Dockerfile new file mode 100644 index 000000000..63337971b --- /dev/null +++ b/backup/Dockerfile @@ -0,0 +1,14 @@ +FROM postgis/postgis:15-master + +# Enable pgcrypto extension on startup +RUN sed -i '/EXISTS postgis_tiger_geocoder;*/a CREATE EXTENSION IF NOT EXISTS pgcrypto;' \ + /docker-entrypoint-initdb.d/10_postgis.sh + +WORKDIR /app +COPY pg-simple-backup.sh . + +RUN mkdir /mnt/bkp + +# User, port and Healthcheck +#USER postgres +ENTRYPOINT [ "/app/pg-simple-backup.sh", "$${POSTGRES_USER}", "$${POSTGRES_DB}", "15432" ] diff --git a/backup/help.txt b/backup/help.txt new file mode 100644 index 000000000..e4a567d01 --- /dev/null +++ b/backup/help.txt @@ -0,0 +1,6 @@ +docker build -t backup . + +docker run -it \ + --network=host \ + -v .:/mnt/bkp \ + backup diff --git a/backup/pg-simple-backup.sh b/backup/pg-simple-backup.sh new file mode 100755 index 000000000..09167cd34 --- /dev/null +++ b/backup/pg-simple-backup.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# -*- coding: utf-8 -*- + +## +# DB access +## +DB_USER="nr-spar" +DB_NAME="nr-spar" +DB_PORT="15432" +echo "User=$DB_USER" +echo "DB=$DB_NAME" +echo "Port=$DB_PORT" + +## +# File name +## +FILENAME_PREFIX="spar_pg_bkp" + +# %F -> 2024-08-12 +# %T -> 16:44:58 +# Here for more: https://www.man7.org/linux/man-pages/man1/date.1.html +FILENAME_SUFIX=$(date +"%F_%T") +FILENAME=$FILENAME_PREFIX"_"$FILENAME_SUFIX +echo "Filename=$FILENAME" + +# -F specifies that the output should be in tar format +PG_DUMP="pg_dump" +COMM="$PG_DUMP -U \"$DB_USER\" -W -F t \"$DB_NAME\" > /mnt/bkp/$FILENAME.tar" +echo "Command=$COMM" + +pg_dump -h localhost -p $DB_PORT -U "$DB_USER" -W -F t "$DB_NAME" > /mnt/bkp/$FILENAME.tar \ No newline at end of file From c252602143f8bf776e11f8aa2e36a9ee3234fbb2 Mon Sep 17 00:00:00 2001 From: Ricardo Campos Date: Fri, 23 Aug 2024 17:07:35 -0300 Subject: [PATCH 03/13] feat: add backup-deploy workflow - wip issue #1268 --- backup/Dockerfile | 14 -- backup/help.txt | 6 - backup/pg-simple-backup.sh | 31 ---- common/backup-deploy.yml | 324 +++++++++++++++++++++++++++++++++++++ common/openshift.init.yml | 59 +++++++ 5 files changed, 383 insertions(+), 51 deletions(-) delete mode 100644 backup/Dockerfile delete mode 100644 backup/help.txt delete mode 100755 backup/pg-simple-backup.sh create mode 100644 common/backup-deploy.yml diff --git a/backup/Dockerfile b/backup/Dockerfile deleted file mode 100644 index 63337971b..000000000 --- a/backup/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM postgis/postgis:15-master - -# Enable pgcrypto extension on startup -RUN sed -i '/EXISTS postgis_tiger_geocoder;*/a CREATE EXTENSION IF NOT EXISTS pgcrypto;' \ - /docker-entrypoint-initdb.d/10_postgis.sh - -WORKDIR /app -COPY pg-simple-backup.sh . - -RUN mkdir /mnt/bkp - -# User, port and Healthcheck -#USER postgres -ENTRYPOINT [ "/app/pg-simple-backup.sh", "$${POSTGRES_USER}", "$${POSTGRES_DB}", "15432" ] diff --git a/backup/help.txt b/backup/help.txt deleted file mode 100644 index e4a567d01..000000000 --- a/backup/help.txt +++ /dev/null @@ -1,6 +0,0 @@ -docker build -t backup . - -docker run -it \ - --network=host \ - -v .:/mnt/bkp \ - backup diff --git a/backup/pg-simple-backup.sh b/backup/pg-simple-backup.sh deleted file mode 100755 index 09167cd34..000000000 --- a/backup/pg-simple-backup.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# -*- coding: utf-8 -*- - -## -# DB access -## -DB_USER="nr-spar" -DB_NAME="nr-spar" -DB_PORT="15432" -echo "User=$DB_USER" -echo "DB=$DB_NAME" -echo "Port=$DB_PORT" - -## -# File name -## -FILENAME_PREFIX="spar_pg_bkp" - -# %F -> 2024-08-12 -# %T -> 16:44:58 -# Here for more: https://www.man7.org/linux/man-pages/man1/date.1.html -FILENAME_SUFIX=$(date +"%F_%T") -FILENAME=$FILENAME_PREFIX"_"$FILENAME_SUFIX -echo "Filename=$FILENAME" - -# -F specifies that the output should be in tar format -PG_DUMP="pg_dump" -COMM="$PG_DUMP -U \"$DB_USER\" -W -F t \"$DB_NAME\" > /mnt/bkp/$FILENAME.tar" -echo "Command=$COMM" - -pg_dump -h localhost -p $DB_PORT -U "$DB_USER" -W -F t "$DB_NAME" > /mnt/bkp/$FILENAME.tar \ No newline at end of file diff --git a/common/backup-deploy.yml b/common/backup-deploy.yml new file mode 100644 index 000000000..212bca233 --- /dev/null +++ b/common/backup-deploy.yml @@ -0,0 +1,324 @@ +kind: Template +apiVersion: "template.openshift.io/v1" +metadata: + name: ${NAME} +labels: + app: ${NAME}-${ZONE} +parameters: + - name: NAME + displayName: Name + description: The name assigned to all of the resources. Use 'backup-{database name}' depending on your database provider + required: true + value: backup-postgres + - name: ZONE + description: Deployment zone, e.g. pr-### or prod + required: true + - name: SOURCE_IMAGE_NAME + displayName: Source Image Name + description: The name of the image to use for this resource. Use 'backup-{database name}' depending on your database provider + required: true + value: backup-postgres + - name: COMPONENT + displayName: App Name + description: Used to group resources together. Defaults to backup-container + required: true + value: backup-container + - name: ROLE + displayName: ROLE + description: The role assigned to all of the resources. Defaults to backup-container + required: true + value: backup-container + - name: NAMESPACE_NAME + displayName: Namespace Name + description: The name of the namespace being deployed to.. + required: true + value: devex-von-image + - name: IMAGE_NAMESPACE + displayName: Image Namespace + description: The namespace of the OpenShift project containing the imagestream for the application. + required: true + value: + - name: DATABASE_SERVICE_NAME + displayName: Database Service Name + description: Used for backward compatibility only. Not needed when using the recommended 'backup.conf' configuration. The name of the database service. + required: false + value: "postgresql" + - name: DATABASE_DEPLOYMENT_NAME + displayName: Database Deployment Name + description: The name associated to the database deployment resources. In particular, this is used to wire up the credentials associated to the database. + required: true + value: postgresql + - name: DATABASE_USER_KEY_NAME + displayName: Database User Key Name + description: The database user key name stored in database deployment resources specified by DATABASE_DEPLOYMENT_NAME. + required: true + value: database-user + - name: DATABASE_PASSWORD_KEY_NAME + displayName: Database Password Key Name + description: The database password key name stored in database deployment resources specified by DATABASE_DEPLOYMENT_NAME. + required: true + value: database-password + - name: MSSQL_SA_PASSWORD + displayName: MSSQL SA Password + description: The database password to use for the local backup database. + required: false + - name: BACKUP_STRATEGY + displayName: Backup Strategy + description: The strategy to use for backups; for example daily, or rolling. + required: true + value: rolling + - name: BACKUP_DIR + displayName: The root backup directory + description: The name of the root backup directory. The backup volume will be mounted to this directory. + required: true + value: /backups/ + - name: NUM_BACKUPS + displayName: The number of backup files to be retained + description: Used for backward compatibility only. Ignored when using the recommended `rolling` backup strategy. The number of backup files to be retained. Used for the `daily` backup strategy. + required: false + value: "" + - name: DAILY_BACKUPS + displayName: Number of Daily Backups to Retain + description: The number of daily backup files to be retained. Used for the `rolling` backup strategy. + required: false + value: "6" + - name: WEEKLY_BACKUPS + displayName: Number of Weekly Backups to Retain + 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: BACKUP_PERIOD + displayName: Period (d,m,s) between backups in a format used by the sleep command + description: Used for backward compatibility only. Ignored when using the recommended `backup.conf` and cron backup strategy. Period (d,m,s) between backups in a format used by the sleep command + required: false + value: "1d" + - name: CONFIG_FILE_NAME + displayName: Config File Name + description: The name of the configuration file. + required: true + value: backup.conf + - name: CONFIG_MAP_NAME + displayName: Config Map Name + description: The name of the configuration map. + required: true + value: backup-conf + - name: CONFIG_MOUNT_PATH + displayName: Config Mount Path + description: The path to use to mount the config file. + required: true + value: / + - name: BACKUP_VOLUME_NAME + displayName: Backup Volume Name + description: The name of the persistent volume used to store the backups. + required: true + value: backup + - name: BACKUP_VOLUME_SIZE + displayName: Backup Volume Size + description: The size of the persistent volume used to store the backups, e.g. 512Mi, 1Gi, 2Gi. Ensure this is sized correctly. Refer to the container documentation for details. + required: true + value: 5Gi + - name: BACKUP_VOLUME_CLASS + displayName: Backup Volume Class + description: The class of the persistent volume used to store the backups; netapp-file-standard is the recommended default. + required: true + value: netapp-file-backup + - name: VERIFICATION_VOLUME_NAME + displayName: Verification Volume Name + description: The name for the verification volume, used for restoring and verifying backups. + required: false + value: backup-verification + - name: VERIFICATION_VOLUME_SIZE + displayName: Backup Volume Size + description: The size of the persistent volume used for restoring and verifying backups, e.g. 512Mi, 1Gi, 2Gi. Ensure this is sized correctly. It should be large enough to contain your largest database. + required: true + value: 1Gi + - name: VERIFICATION_VOLUME_CLASS + displayName: Backup Volume Class + description: The class of the persistent volume used for restoring and verifying backups; netapp-file-standard, netapp-block-standard. + required: true + value: netapp-file-standard + - name: VERIFICATION_VOLUME_MOUNT_PATH + displayName: Verification Volume Mount Path + description: The path on which to mount the verification volume. This is used by the database server to contain the database configuration and data files. For Mongo, please use /var/lib/mongodb/data . For MSSQL, please use /var/opt/mssql/data. For MariaDB, please use /var/lib/mysql/data + required: true + value: /var/lib/pgsql/data + - name: CPU_REQUEST + displayName: Resources CPU Request + description: The resources CPU request (in cores) for this build. + required: true + value: 25m + - name: CPU_LIMIT + displayName: Resources CPU Limit + description: The resources CPU limit (in cores) for this build. + required: true + value: 75m + - name: MEMORY_REQUEST + displayName: Resources Memory Request + description: The resources Memory request (in Mi, Gi, etc) for this build. + required: true + value: 2Gi + - name: MEMORY_LIMIT + displayName: Resources Memory Limit + description: The resources Memory limit (in Mi, Gi, etc) for this build. + required: true + value: 4Gi +objects: + - kind: PersistentVolumeClaim + apiVersion: v1 + metadata: + name: ${BACKUP_VOLUME_NAME} + labels: + name: ${NAME} + app: ${COMPONENT} + role: ${ROLE} + env: ${ZONE} + spec: + storageClassName: ${BACKUP_VOLUME_CLASS} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: ${BACKUP_VOLUME_SIZE} + - kind: PersistentVolumeClaim + apiVersion: v1 + metadata: + name: ${VERIFICATION_VOLUME_NAME} + labels: + name: ${NAME} + app: ${COMPONENT} + role: ${ROLE} + env: ${ZONE} + spec: + storageClassName: ${VERIFICATION_VOLUME_CLASS} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: ${VERIFICATION_VOLUME_SIZE} + - kind: Deployment + apiVersion: apps/v1 + metadata: + labels: + app: ${NAME}-${ZONE} + name: ${NAME}-${ZONE}-${COMPONENT} + spec: + strategy: + type: Recreate + ##triggers: + ## - type: ConfigChange + ## - type: ImageChange + ## imageChangeParams: + ## automatic: true + ## containerNames: + ## - ${NAME} + ## from: + ## kind: ImageStreamTag + ## namespace: ${IMAGE_NAMESPACE} + ## name: ${SOURCE_IMAGE_NAME}:${ZONE} + replicas: 1 + selector: + name: ${NAME} + matchLabels: + deployment: ${NAME}-${ZONE}-${COMPONENT} + template: + metadata: + labels: + app: ${NAME}-${ZONE} + deployment: ${NAME}-${ZONE}-${COMPONENT} + spec: + volumes: + - name: ${BACKUP_VOLUME_NAME} + persistentVolumeClaim: + claimName: ${BACKUP_VOLUME_NAME} + - name: ${VERIFICATION_VOLUME_NAME} + persistentVolumeClaim: + claimName: ${VERIFICATION_VOLUME_NAME} + - name: ${NAME}-config-volume + configMap: + name: ${CONFIG_MAP_NAME} + items: + - key: ${CONFIG_FILE_NAME} + path: ${CONFIG_FILE_NAME} + containers: + - name: ${NAME}-${ZONE} + image: "" + imagePullPolicy: Always + env: + - name: BACKUP_STRATEGY + value: ${BACKUP_STRATEGY} # 'rolling' + - name: BACKUP_DIR + value: ${BACKUP_DIR} # '/backups/' + - name: NUM_BACKUPS + value: ${NUM_BACKUPS} # ignored if 'rolling' above + - name: DAILY_BACKUPS + value: ${DAILY_BACKUPS} # 6 (days to retain) + - name: WEEKLY_BACKUPS + value: ${WEEKLY_BACKUPS} # 4 (weeks) + - name: MONTHLY_BACKUPS + value: ${MONTHLY_BACKUPS} # 1 + - name: BACKUP_PERIOD + value: ${BACKUP_PERIOD} # 1d (1 day) + - name: DATABASE_SERVICE_NAME + value: ${DATABASE_SERVICE_NAME} # 'postgresql' + - name: DATABASE_NAME + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-name + - name: TABLE_SCHEMA + value: ${NAME} # 'nr-spar' + - name: DATABASE_USER + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-user + - name: DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-password + - name: FTP_URL + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-backup-ftp + key: ftp-url + - name: FTP_USER + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-backup-ftp + key: ftp-user + - name: FTP_PASSWORD + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-backup-ftp + key: ftp-password + - name: WEBHOOK_URL + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-backup-webhook + key: webhook-url + - name: ENVIRONMENT_FRIENDLY_NAME + value: ${ZONE} + - name: ENVIRONMENT_NAME + value: ${ZONE} + resources: + requests: + cpu: ${CPU_REQUEST} + memory: ${MEMORY_REQUEST} + limits: + cpu: ${CPU_LIMIT} + memory: ${MEMORY_LIMIT} + volumeMounts: + - name: ${BACKUP_VOLUME_NAME} + mountPath: ${BACKUP_DIR} + - name: ${VERIFICATION_VOLUME_NAME} + mountPath: ${VERIFICATION_VOLUME_MOUNT_PATH} + - name: ${NAME}-config-volume + mountPath: ${CONFIG_MOUNT_PATH}${CONFIG_FILE_NAME} + subPath: ${CONFIG_FILE_NAME} + diff --git a/common/openshift.init.yml b/common/openshift.init.yml index 1da33db29..613252b56 100644 --- a/common/openshift.init.yml +++ b/common/openshift.init.yml @@ -37,6 +37,41 @@ parameters: - name: VITE_USER_POOLS_WEB_CLIENT_ID description: Cognito user pools web client ID required: true + - name: WEBHOOK_URL + displayName: Webhook URL + description: The URL of the webhook to use for notifications. If not specified, the webhook integration feature is disabled. + required: false + value: "" + - name: WEBHOOK_URL_HOST + displayName: Webhook URL Hostname + description: Webhook URL Hostname. The backup-deploy.overrides.sh will parse this from the supplied WEBHOOK_URL, and fetch it from a secret for updates. + required: false + value: + - name: FTP_SECRET_KEY + displayName: FTP Secret Key + description: The FTP secret key is used to wire up the credentials associated to the FTP. + required: false + value: ftp-secret + - name: FTP_URL + displayName: FTP Server URL + description: The URL of the backup FTP server + required: false + value: "" + - name: FTP_URL_HOST + displayName: Ftp URL Hostname + description: Ftp URL Hostname. The backup-deploy.overrides.sh will parse this from the supplied FTP_URL, and fetch it from a secret for updates. + required: false + value: + - name: FTP_USER + displayName: FTP user name + description: FTP user name + required: false + value: "" + - name: FTP_PASSWORD + displayName: FTP password + description: FTP password + required: false + value: "" objects: - apiVersion: v1 kind: Secret @@ -88,6 +123,30 @@ objects: app: ${NAME}-${ZONE} stringData: vite-user-pools-web-client-id: ${VITE_USER_POOLS_WEB_CLIENT_ID} + -- + - apiVersion: v1 + kind: Secret + metadata: + name: ${NAME}-${ZONE}-backup-webhook + labels: + app: ${NAME}-${ZONE} + stringData: + webhook-url: ${WEBHOOK_URL} + webhook-url-host: ${WEBHOOK_URL_HOST} + -- + - kind: Secret + apiVersion: v1 + metadata: + name: ${NAME}-${ZONE}-backup-ftp + labels: + app: ${NAME}-${ZONE} + type: Opaque + stringData: + ftp-url: ${FTP_URL} + ftp-user: ${FTP_USER} + ftp-password: ${FTP_PASSWORD} + ftp-url-host: ${FTP_URL_HOST} + -- - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: From 6c0f97325f0f81c038598e0f18755f9ba5b3d52b Mon Sep 17 00:00:00 2001 From: Ricardo Campos Date: Mon, 26 Aug 2024 18:49:49 -0300 Subject: [PATCH 04/13] feat: add backup deployment file issue #1268 --- common/backup-deploy.yml | 164 +++++++++++---------------------------- 1 file changed, 44 insertions(+), 120 deletions(-) diff --git a/common/backup-deploy.yml b/common/backup-deploy.yml index 212bca233..8f8891b85 100644 --- a/common/backup-deploy.yml +++ b/common/backup-deploy.yml @@ -6,137 +6,63 @@ labels: app: ${NAME}-${ZONE} parameters: - name: NAME - displayName: Name - description: The name assigned to all of the resources. Use 'backup-{database name}' depending on your database provider - required: true - value: backup-postgres + description: Product name + value: nr-spar - name: ZONE description: Deployment zone, e.g. pr-### or prod required: true - - name: SOURCE_IMAGE_NAME - displayName: Source Image Name - description: The name of the image to use for this resource. Use 'backup-{database name}' depending on your database provider - required: true - value: backup-postgres - name: COMPONENT displayName: App Name description: Used to group resources together. Defaults to backup-container - required: true value: backup-container - name: ROLE displayName: ROLE description: The role assigned to all of the resources. Defaults to backup-container required: true value: backup-container - - name: NAMESPACE_NAME - displayName: Namespace Name - description: The name of the namespace being deployed to.. - required: true - value: devex-von-image - - name: IMAGE_NAMESPACE - displayName: Image Namespace - description: The namespace of the OpenShift project containing the imagestream for the application. - required: true - value: - name: DATABASE_SERVICE_NAME displayName: Database Service Name description: Used for backward compatibility only. Not needed when using the recommended 'backup.conf' configuration. The name of the database service. - required: false - value: "postgresql" - - name: DATABASE_DEPLOYMENT_NAME - displayName: Database Deployment Name - description: The name associated to the database deployment resources. In particular, this is used to wire up the credentials associated to the database. - required: true value: postgresql - - name: DATABASE_USER_KEY_NAME - displayName: Database User Key Name - description: The database user key name stored in database deployment resources specified by DATABASE_DEPLOYMENT_NAME. - required: true - value: database-user - - name: DATABASE_PASSWORD_KEY_NAME - displayName: Database Password Key Name - description: The database password key name stored in database deployment resources specified by DATABASE_DEPLOYMENT_NAME. - required: true - value: database-password - - name: MSSQL_SA_PASSWORD - displayName: MSSQL SA Password - description: The database password to use for the local backup database. - required: false - name: BACKUP_STRATEGY displayName: Backup Strategy description: The strategy to use for backups; for example daily, or rolling. - required: true value: rolling - - name: BACKUP_DIR - displayName: The root backup directory - description: The name of the root backup directory. The backup volume will be mounted to this directory. - required: true - value: /backups/ - name: NUM_BACKUPS displayName: The number of backup files to be retained - description: Used for backward compatibility only. Ignored when using the recommended `rolling` backup strategy. The number of backup files to be retained. Used for the `daily` backup strategy. + description: (Is this needed since it'll be ignored?) Used for backward compatibility only. Ignored when using the recommended `rolling` backup strategy. The number of backup files to be retained. Used for the `daily` backup strategy. required: false value: "" - name: DAILY_BACKUPS displayName: Number of Daily Backups to Retain description: The number of daily backup files to be retained. Used for the `rolling` backup strategy. - required: false - value: "6" + value: "3" - name: WEEKLY_BACKUPS displayName: Number of Weekly Backups to Retain description: The number of weekly backup files to be retained. Used for the `rolling` backup strategy. - required: false - value: "4" + value: "2" - 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: BACKUP_PERIOD displayName: Period (d,m,s) between backups in a format used by the sleep command description: Used for backward compatibility only. Ignored when using the recommended `backup.conf` and cron backup strategy. Period (d,m,s) between backups in a format used by the sleep command - required: false value: "1d" - - name: CONFIG_FILE_NAME - displayName: Config File Name - description: The name of the configuration file. - required: true - value: backup.conf - - name: CONFIG_MAP_NAME - displayName: Config Map Name - description: The name of the configuration map. - required: true - value: backup-conf - - name: CONFIG_MOUNT_PATH - displayName: Config Mount Path - description: The path to use to mount the config file. - required: true - value: / - - name: BACKUP_VOLUME_NAME - displayName: Backup Volume Name - description: The name of the persistent volume used to store the backups. - required: true - value: backup - name: BACKUP_VOLUME_SIZE displayName: Backup Volume Size description: The size of the persistent volume used to store the backups, e.g. 512Mi, 1Gi, 2Gi. Ensure this is sized correctly. Refer to the container documentation for details. required: true - value: 5Gi + value: 500Mi - name: BACKUP_VOLUME_CLASS displayName: Backup Volume Class description: The class of the persistent volume used to store the backups; netapp-file-standard is the recommended default. required: true value: netapp-file-backup - - name: VERIFICATION_VOLUME_NAME - displayName: Verification Volume Name - description: The name for the verification volume, used for restoring and verifying backups. - required: false - value: backup-verification - name: VERIFICATION_VOLUME_SIZE displayName: Backup Volume Size description: The size of the persistent volume used for restoring and verifying backups, e.g. 512Mi, 1Gi, 2Gi. Ensure this is sized correctly. It should be large enough to contain your largest database. - required: true - value: 1Gi + value: 200Mi - name: VERIFICATION_VOLUME_CLASS displayName: Backup Volume Class description: The class of the persistent volume used for restoring and verifying backups; netapp-file-standard, netapp-block-standard. @@ -171,7 +97,7 @@ objects: - kind: PersistentVolumeClaim apiVersion: v1 metadata: - name: ${BACKUP_VOLUME_NAME} + name: ${NAME}-${ZONE}-backup-volume labels: name: ${NAME} app: ${COMPONENT} @@ -187,7 +113,7 @@ objects: - kind: PersistentVolumeClaim apiVersion: v1 metadata: - name: ${VERIFICATION_VOLUME_NAME} + name: ${NAME}-${ZONE}-backup-verification labels: name: ${NAME} app: ${COMPONENT} @@ -200,6 +126,17 @@ objects: resources: requests: storage: ${VERIFICATION_VOLUME_SIZE} + - kind: ConfigMap + apiVersion: v1 + metadata: + name: ${NAME}-${ZONE}-backup-config + data: + backup.conf: | + here + here + here + her + her - kind: Deployment apiVersion: apps/v1 metadata: @@ -209,17 +146,6 @@ objects: spec: strategy: type: Recreate - ##triggers: - ## - type: ConfigChange - ## - type: ImageChange - ## imageChangeParams: - ## automatic: true - ## containerNames: - ## - ${NAME} - ## from: - ## kind: ImageStreamTag - ## namespace: ${IMAGE_NAMESPACE} - ## name: ${SOURCE_IMAGE_NAME}:${ZONE} replicas: 1 selector: name: ${NAME} @@ -232,46 +158,46 @@ objects: deployment: ${NAME}-${ZONE}-${COMPONENT} spec: volumes: - - name: ${BACKUP_VOLUME_NAME} + - name: ${NAME}-${ZONE}-backup-volume persistentVolumeClaim: - claimName: ${BACKUP_VOLUME_NAME} - - name: ${VERIFICATION_VOLUME_NAME} + claimName: ${NAME}-${ZONE}-backup-volume + - name: ${NAME}-${ZONE}-backup-verification persistentVolumeClaim: - claimName: ${VERIFICATION_VOLUME_NAME} - - name: ${NAME}-config-volume + claimName: ${NAME}-${ZONE}-backup-verification + - name: ${NAME}-${ZONE}-backup-config configMap: - name: ${CONFIG_MAP_NAME} + name: backup-conf items: - - key: ${CONFIG_FILE_NAME} - path: ${CONFIG_FILE_NAME} + - key: backup.conf + path: backup.conf containers: - - name: ${NAME}-${ZONE} - image: "" + - name: ${NAME} + image: "bcgovimages/backup-container:2.9.0" imagePullPolicy: Always env: - name: BACKUP_STRATEGY - value: ${BACKUP_STRATEGY} # 'rolling' + value: ${BACKUP_STRATEGY} - name: BACKUP_DIR - value: ${BACKUP_DIR} # '/backups/' + value: /backups - name: NUM_BACKUPS - value: ${NUM_BACKUPS} # ignored if 'rolling' above + value: ${NUM_BACKUPS} - name: DAILY_BACKUPS - value: ${DAILY_BACKUPS} # 6 (days to retain) + value: ${DAILY_BACKUPS} - name: WEEKLY_BACKUPS - value: ${WEEKLY_BACKUPS} # 4 (weeks) + value: ${WEEKLY_BACKUPS} - name: MONTHLY_BACKUPS - value: ${MONTHLY_BACKUPS} # 1 + value: ${MONTHLY_BACKUPS} - name: BACKUP_PERIOD - value: ${BACKUP_PERIOD} # 1d (1 day) + value: ${BACKUP_PERIOD} - name: DATABASE_SERVICE_NAME - value: ${DATABASE_SERVICE_NAME} # 'postgresql' + value: ${DATABASE_SERVICE_NAME} - name: DATABASE_NAME valueFrom: secretKeyRef: name: ${NAME}-${ZONE}-database key: database-name - name: TABLE_SCHEMA - value: ${NAME} # 'nr-spar' + value: ${NAME} - name: DATABASE_USER valueFrom: secretKeyRef: @@ -314,11 +240,9 @@ objects: cpu: ${CPU_LIMIT} memory: ${MEMORY_LIMIT} volumeMounts: - - name: ${BACKUP_VOLUME_NAME} - mountPath: ${BACKUP_DIR} - - name: ${VERIFICATION_VOLUME_NAME} + - name: ${NAME}-${ZONE}-backup-volume + mountPath: /backups + - name: ${NAME}-${ZONE}-backup-verification mountPath: ${VERIFICATION_VOLUME_MOUNT_PATH} - - name: ${NAME}-config-volume - mountPath: ${CONFIG_MOUNT_PATH}${CONFIG_FILE_NAME} - subPath: ${CONFIG_FILE_NAME} - + - name: ${NAME}-${ZONE}-backup-config + mountPath: /backup.conf From ad80b2ba922080c02e9faeb6e1e63710e2dc99a6 Mon Sep 17 00:00:00 2001 From: Ricardo Campos Date: Tue, 1 Oct 2024 16:28:52 -0300 Subject: [PATCH 05/13] chore: discard changes, switching gears to replicate forest client implementation --- common/backup-deploy.yml | 248 -------------------------------------- common/openshift.init.yml | 59 --------- 2 files changed, 307 deletions(-) delete mode 100644 common/backup-deploy.yml diff --git a/common/backup-deploy.yml b/common/backup-deploy.yml deleted file mode 100644 index 8f8891b85..000000000 --- a/common/backup-deploy.yml +++ /dev/null @@ -1,248 +0,0 @@ -kind: Template -apiVersion: "template.openshift.io/v1" -metadata: - name: ${NAME} -labels: - app: ${NAME}-${ZONE} -parameters: - - name: NAME - description: Product name - value: nr-spar - - name: ZONE - description: Deployment zone, e.g. pr-### or prod - required: true - - name: COMPONENT - displayName: App Name - description: Used to group resources together. Defaults to backup-container - value: backup-container - - name: ROLE - displayName: ROLE - description: The role assigned to all of the resources. Defaults to backup-container - required: true - value: backup-container - - name: DATABASE_SERVICE_NAME - displayName: Database Service Name - description: Used for backward compatibility only. Not needed when using the recommended 'backup.conf' configuration. The name of the database service. - value: postgresql - - name: BACKUP_STRATEGY - displayName: Backup Strategy - description: The strategy to use for backups; for example daily, or rolling. - value: rolling - - name: NUM_BACKUPS - displayName: The number of backup files to be retained - description: (Is this needed since it'll be ignored?) Used for backward compatibility only. Ignored when using the recommended `rolling` backup strategy. The number of backup files to be retained. Used for the `daily` backup strategy. - required: false - value: "" - - name: DAILY_BACKUPS - displayName: Number of Daily Backups to Retain - description: The number of daily backup files to be retained. Used for the `rolling` backup strategy. - value: "3" - - name: WEEKLY_BACKUPS - displayName: Number of Weekly Backups to Retain - description: The number of weekly backup files to be retained. Used for the `rolling` backup strategy. - value: "2" - - 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. - value: "1" - - name: BACKUP_PERIOD - displayName: Period (d,m,s) between backups in a format used by the sleep command - description: Used for backward compatibility only. Ignored when using the recommended `backup.conf` and cron backup strategy. Period (d,m,s) between backups in a format used by the sleep command - value: "1d" - - name: BACKUP_VOLUME_SIZE - displayName: Backup Volume Size - description: The size of the persistent volume used to store the backups, e.g. 512Mi, 1Gi, 2Gi. Ensure this is sized correctly. Refer to the container documentation for details. - required: true - value: 500Mi - - name: BACKUP_VOLUME_CLASS - displayName: Backup Volume Class - description: The class of the persistent volume used to store the backups; netapp-file-standard is the recommended default. - required: true - value: netapp-file-backup - - name: VERIFICATION_VOLUME_SIZE - displayName: Backup Volume Size - description: The size of the persistent volume used for restoring and verifying backups, e.g. 512Mi, 1Gi, 2Gi. Ensure this is sized correctly. It should be large enough to contain your largest database. - value: 200Mi - - name: VERIFICATION_VOLUME_CLASS - displayName: Backup Volume Class - description: The class of the persistent volume used for restoring and verifying backups; netapp-file-standard, netapp-block-standard. - required: true - value: netapp-file-standard - - name: VERIFICATION_VOLUME_MOUNT_PATH - displayName: Verification Volume Mount Path - description: The path on which to mount the verification volume. This is used by the database server to contain the database configuration and data files. For Mongo, please use /var/lib/mongodb/data . For MSSQL, please use /var/opt/mssql/data. For MariaDB, please use /var/lib/mysql/data - required: true - value: /var/lib/pgsql/data - - name: CPU_REQUEST - displayName: Resources CPU Request - description: The resources CPU request (in cores) for this build. - required: true - value: 25m - - name: CPU_LIMIT - displayName: Resources CPU Limit - description: The resources CPU limit (in cores) for this build. - required: true - value: 75m - - name: MEMORY_REQUEST - displayName: Resources Memory Request - description: The resources Memory request (in Mi, Gi, etc) for this build. - required: true - value: 2Gi - - name: MEMORY_LIMIT - displayName: Resources Memory Limit - description: The resources Memory limit (in Mi, Gi, etc) for this build. - required: true - value: 4Gi -objects: - - kind: PersistentVolumeClaim - apiVersion: v1 - metadata: - name: ${NAME}-${ZONE}-backup-volume - labels: - name: ${NAME} - app: ${COMPONENT} - role: ${ROLE} - env: ${ZONE} - spec: - storageClassName: ${BACKUP_VOLUME_CLASS} - accessModes: - - ReadWriteOnce - resources: - requests: - storage: ${BACKUP_VOLUME_SIZE} - - kind: PersistentVolumeClaim - apiVersion: v1 - metadata: - name: ${NAME}-${ZONE}-backup-verification - labels: - name: ${NAME} - app: ${COMPONENT} - role: ${ROLE} - env: ${ZONE} - spec: - storageClassName: ${VERIFICATION_VOLUME_CLASS} - accessModes: - - ReadWriteOnce - resources: - requests: - storage: ${VERIFICATION_VOLUME_SIZE} - - kind: ConfigMap - apiVersion: v1 - metadata: - name: ${NAME}-${ZONE}-backup-config - data: - backup.conf: | - here - here - here - her - her - - kind: Deployment - apiVersion: apps/v1 - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - strategy: - type: Recreate - replicas: 1 - selector: - name: ${NAME} - matchLabels: - deployment: ${NAME}-${ZONE}-${COMPONENT} - template: - metadata: - labels: - app: ${NAME}-${ZONE} - deployment: ${NAME}-${ZONE}-${COMPONENT} - spec: - volumes: - - name: ${NAME}-${ZONE}-backup-volume - persistentVolumeClaim: - claimName: ${NAME}-${ZONE}-backup-volume - - name: ${NAME}-${ZONE}-backup-verification - persistentVolumeClaim: - claimName: ${NAME}-${ZONE}-backup-verification - - name: ${NAME}-${ZONE}-backup-config - configMap: - name: backup-conf - items: - - key: backup.conf - path: backup.conf - containers: - - name: ${NAME} - image: "bcgovimages/backup-container:2.9.0" - imagePullPolicy: Always - env: - - name: BACKUP_STRATEGY - value: ${BACKUP_STRATEGY} - - name: BACKUP_DIR - value: /backups - - name: NUM_BACKUPS - value: ${NUM_BACKUPS} - - name: DAILY_BACKUPS - value: ${DAILY_BACKUPS} - - name: WEEKLY_BACKUPS - value: ${WEEKLY_BACKUPS} - - name: MONTHLY_BACKUPS - value: ${MONTHLY_BACKUPS} - - name: BACKUP_PERIOD - value: ${BACKUP_PERIOD} - - name: DATABASE_SERVICE_NAME - value: ${DATABASE_SERVICE_NAME} - - name: DATABASE_NAME - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-database - key: database-name - - name: TABLE_SCHEMA - value: ${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 - - name: FTP_URL - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-backup-ftp - key: ftp-url - - name: FTP_USER - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-backup-ftp - key: ftp-user - - name: FTP_PASSWORD - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-backup-ftp - key: ftp-password - - name: WEBHOOK_URL - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-backup-webhook - key: webhook-url - - name: ENVIRONMENT_FRIENDLY_NAME - value: ${ZONE} - - name: ENVIRONMENT_NAME - value: ${ZONE} - resources: - requests: - cpu: ${CPU_REQUEST} - memory: ${MEMORY_REQUEST} - limits: - cpu: ${CPU_LIMIT} - memory: ${MEMORY_LIMIT} - volumeMounts: - - name: ${NAME}-${ZONE}-backup-volume - mountPath: /backups - - name: ${NAME}-${ZONE}-backup-verification - mountPath: ${VERIFICATION_VOLUME_MOUNT_PATH} - - name: ${NAME}-${ZONE}-backup-config - mountPath: /backup.conf diff --git a/common/openshift.init.yml b/common/openshift.init.yml index 613252b56..1da33db29 100644 --- a/common/openshift.init.yml +++ b/common/openshift.init.yml @@ -37,41 +37,6 @@ parameters: - name: VITE_USER_POOLS_WEB_CLIENT_ID description: Cognito user pools web client ID required: true - - name: WEBHOOK_URL - displayName: Webhook URL - description: The URL of the webhook to use for notifications. If not specified, the webhook integration feature is disabled. - required: false - value: "" - - name: WEBHOOK_URL_HOST - displayName: Webhook URL Hostname - description: Webhook URL Hostname. The backup-deploy.overrides.sh will parse this from the supplied WEBHOOK_URL, and fetch it from a secret for updates. - required: false - value: - - name: FTP_SECRET_KEY - displayName: FTP Secret Key - description: The FTP secret key is used to wire up the credentials associated to the FTP. - required: false - value: ftp-secret - - name: FTP_URL - displayName: FTP Server URL - description: The URL of the backup FTP server - required: false - value: "" - - name: FTP_URL_HOST - displayName: Ftp URL Hostname - description: Ftp URL Hostname. The backup-deploy.overrides.sh will parse this from the supplied FTP_URL, and fetch it from a secret for updates. - required: false - value: - - name: FTP_USER - displayName: FTP user name - description: FTP user name - required: false - value: "" - - name: FTP_PASSWORD - displayName: FTP password - description: FTP password - required: false - value: "" objects: - apiVersion: v1 kind: Secret @@ -123,30 +88,6 @@ objects: app: ${NAME}-${ZONE} stringData: vite-user-pools-web-client-id: ${VITE_USER_POOLS_WEB_CLIENT_ID} - -- - - apiVersion: v1 - kind: Secret - metadata: - name: ${NAME}-${ZONE}-backup-webhook - labels: - app: ${NAME}-${ZONE} - stringData: - webhook-url: ${WEBHOOK_URL} - webhook-url-host: ${WEBHOOK_URL_HOST} - -- - - kind: Secret - apiVersion: v1 - metadata: - name: ${NAME}-${ZONE}-backup-ftp - labels: - app: ${NAME}-${ZONE} - type: Opaque - stringData: - ftp-url: ${FTP_URL} - ftp-user: ${FTP_USER} - ftp-password: ${FTP_PASSWORD} - ftp-url-host: ${FTP_URL_HOST} - -- - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: From 17bca32b88b5af9624efb7927e8722a4c54694f0 Mon Sep 17 00:00:00 2001 From: Ricardo Campos Date: Wed, 2 Oct 2024 14:58:55 -0300 Subject: [PATCH 06/13] ci: add backup routine for SPAR issue #1268 --- .github/workflows/.backup.yml | 33 +++++ .github/workflows/.deploy.yml | 21 ++++ common/openshift.backup.yml | 231 ++++++++++++++++++++++++++++++++++ 3 files changed, 285 insertions(+) create mode 100644 .github/workflows/.backup.yml create mode 100644 common/openshift.backup.yml diff --git a/.github/workflows/.backup.yml b/.github/workflows/.backup.yml new file mode 100644 index 000000000..35630ecd7 --- /dev/null +++ b/.github/workflows/.backup.yml @@ -0,0 +1,33 @@ +name: .Backup + +on: + workflow_call: + inputs: + ### Required + # Nothing! Only `secrets: inherit` is required + + ### Typical / recommended + environment: + description: GitHub/OpenShift environment; usually PR number, test or prod + default: '' + required: false + type: string + target: + description: Deployment target; usually PR number, test or prod + default: ${{ github.event.number }} + required: false + type: string + +jobs: + backup: + name: Backup + environment: ${{ inputs.environment }} + runs-on: ubuntu-24.04 + steps: + - name: Backup database before update + continue-on-error: true + run: | + oc login --token=${{ secrets.OC_TOKEN }} --server=${{ secrets.OC_SERVER }} + oc project ${{ vars.OC_NAMESPACE }} + # Run a backup before deploying a new version + oc create job --from=cronjob/${{ github.event.repository.name }}-${{ inputs.target }}-database-backup ${{ github.event.repository.name }}-${{ inputs.target }}-database-backup-$(date +%Y%m%d%H%M%S) diff --git a/.github/workflows/.deploy.yml b/.github/workflows/.deploy.yml index b3ee203e6..602d4481c 100644 --- a/.github/workflows/.deploy.yml +++ b/.github/workflows/.deploy.yml @@ -105,6 +105,27 @@ jobs: ${{ github.event_name == 'pull_request' && '-p MEMORY_REQUEST=100Mi' || '' }} ${{ github.event_name == 'pull_request' && '-p MEMORY_LIMIT=200Mi' || '' }} + - name: Deploy Database Backup + uses: bcgov-nr/action-deployer-openshift@v3.0.1 + with: + file: common/openshift.backup.yml + oc_namespace: ${{ vars.OC_NAMESPACE }} + oc_server: ${{ secrets.OC_SERVER }} + oc_token: ${{ secrets.OC_TOKEN }} + oc_version: "4.13" + overwrite: true + parameters: + -p ZONE=${{ env.ZONE }} -p NAME=${{ github.event.repository.name }} + -p PG_DB_IMAGE=postgis/postgis:15-master + + - name: Backup + if: steps.triggers.outputs.core == 'true' || steps.triggers.outputs.sync == 'true' + secrets: inherit + uses: ./.github/workflows/.deploy.yml + with: + environment: ${{ inputs.environment }} + target: ${{ inputs.target }} + deploy: name: Deploy environment: ${{ inputs.environment }} diff --git a/common/openshift.backup.yml b/common/openshift.backup.yml new file mode 100644 index 000000000..7f05b6be1 --- /dev/null +++ b/common/openshift.backup.yml @@ -0,0 +1,231 @@ +apiVersion: template.openshift.io/v1 +kind: Template +labels: + app: ${NAME}-${ZONE} + app.kubernetes.io/part-of: ${NAME}-${ZONE} +parameters: + - name: NAME + description: Product name + value: nr-spar + - name: COMPONENT + description: Component name + value: database-backup + - name: ZONE + description: Deployment zone, e.g. pr-### or prod + required: true + - name: RESTORE_DIR + description: Directory to be used for restoring the backup + value: /tmp/restore + - name: REGISTRY + description: Container registry to import from (internal is image-registry.openshift-image-registry.svc:5000) + value: ghcr.io + - name: BACKUP_DIR + description: "The name of the root backup directory" + required: true + value: /tmp/backup + - name: NUM_BACKUPS + description: The number of backup files to be retained + required: false + value: "5" + - 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" + - name: PVC_SIZE + description: Volume space available for data, e.g. 512Mi, 2Gi. + value: 256Mi + - name: PG_DB_IMAGE + description: PostgreSQL Image (namespace/name:tag) to be used for backup + required: true +objects: + - kind: PersistentVolumeClaim + apiVersion: v1 + metadata: + name: ${NAME}-${ZONE}-${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}-${COMPONENT} + labels: + app: ${NAME}-${ZONE} + cronjob: ${NAME}-${ZONE} + spec: + schedule: "0 0 * * *" + 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}-${COMPONENT} + image: ${REGISTRY}/${PG_DB_IMAGE} + command: ["/bin/sh", "-c"] + args: + - | + pg_dump \ + -U ${POSTGRESQL_USER} \ + -h ${NAME}-${ZONE}-database \ + -d ${POSTGRESQL_DATABASE} \ + --data-only \ + --schema=nr-spar \ + --inserts \ + --no-comments \ + --on-conflict-do-nothing \ + --no-sync \ + --exclude-table=nrfc.client_type_code \ + --exclude-table=nrfc.submission_status_code \ + --exclude-table=nrfc.submission_type_code \ + --exclude-table=nrfc.province_code \ + --exclude-table=nrfc.country_code \ + --exclude-table=nrfc.contact_type_code \ + --exclude-table=nrfc.business_type_code \ + --exclude-table=nrfc.district_code \ + --file=${BACKUP_DIR}/backup_$(date +%Y-%m-%d).sql \ + && + find "${BACKUP_DIR}" -type f -mtime +$NUM_BACKUPS -exec rm -f {} \; && + cp -r ${BACKUP_DIR}/backup_$(date +%Y-%m-%d).sql ${RESTORE_DIR}/W0__restore.sql + volumeMounts: + - mountPath: "${BACKUP_DIR}" + name: ${NAME}-${ZONE}-${COMPONENT} + - mountPath: "${RESTORE_DIR}" + name: ${NAME}-${ZONE}-${COMPONENT} + env: + - name: RESTORE_DIR + value: "${RESTORE_DIR}" + - name: BACKUP_DIR + value: "${BACKUP_DIR}" + - name: NUM_BACKUPS + value: "${NUM_BACKUPS}" + - name: POSTGRESQL_DATABASE + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-name + - name: POSTGRESQL_USER + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-user + - name: POSTGRESQL_PASSWORD + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-password + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-password + volumes: + - name: ${NAME}-${ZONE}-${COMPONENT} + persistentVolumeClaim: + claimName: ${NAME}-${ZONE}-${COMPONENT} + restartPolicy: "Never" + terminationGracePeriodSeconds: 30 + activeDeadlineSeconds: 1600 + dnsPolicy: "ClusterFirst" + serviceAccountName: "${JOB_SERVICE_ACCOUNT}" + serviceAccount: "${JOB_SERVICE_ACCOUNT}" + - kind: CronJob + apiVersion: "batch/v1" + metadata: + name: ${NAME}-${ZONE}-${COMPONENT}-restore + labels: + app: ${NAME}-${ZONE} + cronjob: ${NAME}-${ZONE} + spec: + schedule: "0 0 31 2 *" + 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}-${COMPONENT}-restore + image: ${REGISTRY}/${PG_DB_IMAGE} + command: ["/bin/sh", "-c"] + args: + - | + find ${RESTORE_DIR} -type f -name "*.sql" -print0 | sort -zV | + while IFS= read -r -d '' sql_file; do + echo "Running SQL file: $sql_file" + psql -h ${TARGET_HOST} -U ${POSTGRESQL_USER} -d ${POSTGRESQL_DATABASE} -f $sql_file + done + volumeMounts: + - mountPath: "${RESTORE_DIR}" + name: ${NAME}-${ZONE}-${COMPONENT} + env: + - name: RESTORE_DIR + value: "${RESTORE_DIR}" + - name: POSTGRESQL_DATABASE + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-name + - name: POSTGRESQL_USER + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-user + - name: POSTGRESQL_PASSWORD + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-password + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: ${NAME}-${ZONE}-database + key: database-password + volumes: + - name: ${NAME}-${ZONE}-${COMPONENT} + persistentVolumeClaim: + claimName: ${NAME}-${ZONE}-${COMPONENT} + restartPolicy: "Never" + terminationGracePeriodSeconds: 30 + activeDeadlineSeconds: 1600 + dnsPolicy: "ClusterFirst" + serviceAccountName: "${JOB_SERVICE_ACCOUNT}" + serviceAccount: "${JOB_SERVICE_ACCOUNT}" From a1fb7e435c6072dc7dcb653570b7283a28966284 Mon Sep 17 00:00:00 2001 From: Derek Roberts Date: Wed, 2 Oct 2024 13:12:55 -0700 Subject: [PATCH 07/13] Replace workflow with post_rollout param --- .github/workflows/.backup.yml | 33 --------------------------------- .github/workflows/.deploy.yml | 16 +++++----------- 2 files changed, 5 insertions(+), 44 deletions(-) delete mode 100644 .github/workflows/.backup.yml diff --git a/.github/workflows/.backup.yml b/.github/workflows/.backup.yml deleted file mode 100644 index 35630ecd7..000000000 --- a/.github/workflows/.backup.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: .Backup - -on: - workflow_call: - inputs: - ### Required - # Nothing! Only `secrets: inherit` is required - - ### Typical / recommended - environment: - description: GitHub/OpenShift environment; usually PR number, test or prod - default: '' - required: false - type: string - target: - description: Deployment target; usually PR number, test or prod - default: ${{ github.event.number }} - required: false - type: string - -jobs: - backup: - name: Backup - environment: ${{ inputs.environment }} - runs-on: ubuntu-24.04 - steps: - - name: Backup database before update - continue-on-error: true - run: | - oc login --token=${{ secrets.OC_TOKEN }} --server=${{ secrets.OC_SERVER }} - oc project ${{ vars.OC_NAMESPACE }} - # Run a backup before deploying a new version - oc create job --from=cronjob/${{ github.event.repository.name }}-${{ inputs.target }}-database-backup ${{ github.event.repository.name }}-${{ inputs.target }}-database-backup-$(date +%Y%m%d%H%M%S) diff --git a/.github/workflows/.deploy.yml b/.github/workflows/.deploy.yml index 602d4481c..2b9ac3c25 100644 --- a/.github/workflows/.deploy.yml +++ b/.github/workflows/.deploy.yml @@ -106,6 +106,9 @@ jobs: ${{ github.event_name == 'pull_request' && '-p MEMORY_LIMIT=200Mi' || '' }} - name: Deploy Database Backup + if: steps.triggers.outputs.core == 'true' || steps.triggers.outputs.sync == 'true' + env: + CRONJOB: ${{ github.event.repository.name }}-${{ inputs.target }}-database-backup uses: bcgov-nr/action-deployer-openshift@v3.0.1 with: file: common/openshift.backup.yml @@ -114,17 +117,8 @@ jobs: oc_token: ${{ secrets.OC_TOKEN }} oc_version: "4.13" overwrite: true - parameters: - -p ZONE=${{ env.ZONE }} -p NAME=${{ github.event.repository.name }} - -p PG_DB_IMAGE=postgis/postgis:15-master - - - name: Backup - if: steps.triggers.outputs.core == 'true' || steps.triggers.outputs.sync == 'true' - secrets: inherit - uses: ./.github/workflows/.deploy.yml - with: - environment: ${{ inputs.environment }} - target: ${{ inputs.target }} + parameters: -p ZONE=${{ env.ZONE }} -p PG_DB_IMAGE=postgis/postgis:15-master + post_rollout: oc create job --from=cronjob/${{ env.CRONJOB }} ${{ env.CRONJOB }}-$(date +%Y%m%d%H%M%S) deploy: name: Deploy From 744a27a7d443ad54478b3c2c8b8eddba209f6978 Mon Sep 17 00:00:00 2001 From: Derek Roberts Date: Wed, 2 Oct 2024 13:22:53 -0700 Subject: [PATCH 08/13] Roll backup into standard deployments --- .github/workflows/.deploy.yml | 27 +++++++-------------------- common/openshift.backup.yml | 6 ++++++ 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/.github/workflows/.deploy.yml b/.github/workflows/.deploy.yml index 2b9ac3c25..d5cfc6a1b 100644 --- a/.github/workflows/.deploy.yml +++ b/.github/workflows/.deploy.yml @@ -105,21 +105,6 @@ jobs: ${{ github.event_name == 'pull_request' && '-p MEMORY_REQUEST=100Mi' || '' }} ${{ github.event_name == 'pull_request' && '-p MEMORY_LIMIT=200Mi' || '' }} - - name: Deploy Database Backup - if: steps.triggers.outputs.core == 'true' || steps.triggers.outputs.sync == 'true' - env: - CRONJOB: ${{ github.event.repository.name }}-${{ inputs.target }}-database-backup - uses: bcgov-nr/action-deployer-openshift@v3.0.1 - with: - file: common/openshift.backup.yml - oc_namespace: ${{ vars.OC_NAMESPACE }} - oc_server: ${{ secrets.OC_SERVER }} - oc_token: ${{ secrets.OC_TOKEN }} - oc_version: "4.13" - overwrite: true - parameters: -p ZONE=${{ env.ZONE }} -p PG_DB_IMAGE=postgis/postgis:15-master - post_rollout: oc create job --from=cronjob/${{ env.CRONJOB }} ${{ env.CRONJOB }}-$(date +%Y%m%d%H%M%S) - deploy: name: Deploy environment: ${{ inputs.environment }} @@ -129,24 +114,26 @@ jobs: timeout-minutes: 10 strategy: matrix: - name: [backend, frontend, oracle-api] + name: [backend, backup, frontend, oracle-api] include: - name: backend file: backend/openshift.deploy.yml - overwrite: true parameters: -p AWS_COGNITO_ISSUER_URI=https://cognito-idp.ca-central-1.amazonaws.com/${{ vars.VITE_USER_POOLS_ID }} verification_path: "health" + - name: backup + file: common/openshift.backup.yml + parameters: + -p ZONE=${{ env.ZONE }} -p PG_DB_IMAGE=postgis/postgis:15-master + post_rollout: oc create job --from=cronjob/${{ env.CRONJOB }} ${{ env.CRONJOB }}-$(date +%Y%m%d%H%M%S) - name: frontend file: frontend/openshift.deploy.yml - overwrite: true parameters: -p FAM_MODDED_ZONE=${{ needs.init.outputs.fam-modded-zone }} -p VITE_SPAR_BUILD_VERSION=snapshot-${{ inputs.target || github.event.number }} -p VITE_USER_POOLS_ID=${{ vars.VITE_USER_POOLS_ID }} - name: oracle-api file: oracle-api/openshift.deploy.yml - overwrite: true parameters: -p AWS_COGNITO_ISSUER_URI=https://cognito-idp.ca-central-1.amazonaws.com/${{ vars.VITE_USER_POOLS_ID }} ${{ github.event_name == 'pull_request' && '-p CPU_LIMIT=100m' || '' }} @@ -162,7 +149,7 @@ jobs: oc_namespace: ${{ vars.OC_NAMESPACE }} oc_server: ${{ vars.OC_SERVER }} oc_token: ${{ secrets.OC_TOKEN }} - overwrite: ${{ matrix.overwrite }} + overwrite: true parameters: -p TAG=${{ inputs.tag }} -p ZONE=${{ inputs.target }} diff --git a/common/openshift.backup.yml b/common/openshift.backup.yml index 7f05b6be1..efe2be683 100644 --- a/common/openshift.backup.yml +++ b/common/openshift.backup.yml @@ -48,6 +48,12 @@ parameters: - name: PG_DB_IMAGE description: PostgreSQL Image (namespace/name:tag) to be used for backup required: true + - name: TAG + description: Dummy param, for convenience + - name: MIN_REPLICAS + description: Dummy param, for convenience + - name: MAX_REPLICAS + description: Dummy param, for convenience objects: - kind: PersistentVolumeClaim apiVersion: v1 From 42b13d1a54215415d35fb64b91152df16aee17b0 Mon Sep 17 00:00:00 2001 From: Derek Roberts Date: Wed, 2 Oct 2024 13:29:44 -0700 Subject: [PATCH 09/13] Fix envar --- .github/workflows/.deploy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/.deploy.yml b/.github/workflows/.deploy.yml index d5cfc6a1b..b86837000 100644 --- a/.github/workflows/.deploy.yml +++ b/.github/workflows/.deploy.yml @@ -107,6 +107,8 @@ jobs: deploy: name: Deploy + env: + CRONJOB: ${{ github.event.repository.name }}-${{ inputs.target }}-database-backup environment: ${{ inputs.environment }} if: needs.init.outputs.deploy_core == 'true' needs: [init] From 6b384ce1228f163e6c4e3feba2fce0340798aecc Mon Sep 17 00:00:00 2001 From: Derek Roberts Date: Wed, 2 Oct 2024 13:34:31 -0700 Subject: [PATCH 10/13] Fix envar --- .github/workflows/.deploy.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/.deploy.yml b/.github/workflows/.deploy.yml index b86837000..b46e392fb 100644 --- a/.github/workflows/.deploy.yml +++ b/.github/workflows/.deploy.yml @@ -107,8 +107,6 @@ jobs: deploy: name: Deploy - env: - CRONJOB: ${{ github.event.repository.name }}-${{ inputs.target }}-database-backup environment: ${{ inputs.environment }} if: needs.init.outputs.deploy_core == 'true' needs: [init] @@ -127,7 +125,7 @@ jobs: file: common/openshift.backup.yml parameters: -p ZONE=${{ env.ZONE }} -p PG_DB_IMAGE=postgis/postgis:15-master - post_rollout: oc create job --from=cronjob/${{ env.CRONJOB }} ${{ env.CRONJOB }}-$(date +%Y%m%d%H%M%S) + post_rollout: oc create job --from=cronjob/${{ github.event.repository.name }}-${{ inputs.target }}-database-backup ${{ github.event.repository.name }}-${{ inputs.target }}-database-backup-$(date +%Y%m%d%H%M%S) - name: frontend file: frontend/openshift.deploy.yml parameters: From 0fcb72d702819d4b4044473e1f7a2e5251ed6ed8 Mon Sep 17 00:00:00 2001 From: Derek Roberts Date: Wed, 2 Oct 2024 13:36:10 -0700 Subject: [PATCH 11/13] Fix envar --- .github/workflows/.deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/.deploy.yml b/.github/workflows/.deploy.yml index b46e392fb..1ec30829e 100644 --- a/.github/workflows/.deploy.yml +++ b/.github/workflows/.deploy.yml @@ -124,7 +124,7 @@ jobs: - name: backup file: common/openshift.backup.yml parameters: - -p ZONE=${{ env.ZONE }} -p PG_DB_IMAGE=postgis/postgis:15-master + -p PG_DB_IMAGE=postgis/postgis:15-master post_rollout: oc create job --from=cronjob/${{ github.event.repository.name }}-${{ inputs.target }}-database-backup ${{ github.event.repository.name }}-${{ inputs.target }}-database-backup-$(date +%Y%m%d%H%M%S) - name: frontend file: frontend/openshift.deploy.yml From fef75b729f528b0110441b797d41fa3677581277 Mon Sep 17 00:00:00 2001 From: Derek Roberts Date: Wed, 2 Oct 2024 13:46:46 -0700 Subject: [PATCH 12/13] Fix param --- .github/workflows/.deploy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/.deploy.yml b/.github/workflows/.deploy.yml index 1ec30829e..49c0dc175 100644 --- a/.github/workflows/.deploy.yml +++ b/.github/workflows/.deploy.yml @@ -156,6 +156,7 @@ jobs: ${{ github.event_name == 'pull_request' && '-p MIN_REPLICAS=1' || '' }} ${{ github.event_name == 'pull_request' && '-p MAX_REPLICAS=1' || '' }} ${{ matrix.parameters }} + post_rollout: ${{ matrix.post_rollout || '' }} verification_path: ${{ matrix.verification_path }} verification_retry_attempts: 5 verification_retry_seconds: 20 From 5b4a432af48c835ff3c59581ce1c7eff75b75806 Mon Sep 17 00:00:00 2001 From: Ricardo Campos Date: Thu, 3 Oct 2024 11:26:46 -0300 Subject: [PATCH 13/13] fix: table names to be excluded issue #1268 --- common/openshift.backup.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/common/openshift.backup.yml b/common/openshift.backup.yml index efe2be683..c5ae2b3d5 100644 --- a/common/openshift.backup.yml +++ b/common/openshift.backup.yml @@ -109,14 +109,16 @@ objects: --no-comments \ --on-conflict-do-nothing \ --no-sync \ - --exclude-table=nrfc.client_type_code \ - --exclude-table=nrfc.submission_status_code \ - --exclude-table=nrfc.submission_type_code \ - --exclude-table=nrfc.province_code \ - --exclude-table=nrfc.country_code \ - --exclude-table=nrfc.contact_type_code \ - --exclude-table=nrfc.business_type_code \ - --exclude-table=nrfc.district_code \ + --exclude-table=nr-spar.cone_collection_method_list \ + --exclude-table=nr-spar.gametic_methodology_list \ + --exclude-table=nr-spar.genetic_class_list \ + --exclude-table=nr-spar.genetic_worth_list \ + --exclude-table=nr-spar.method_of_payment_list \ + --exclude-table=nr-spar.seedlot_source_list \ + --exclude-table=nr-spar.seedlot_status_list \ + --exclude-table=nr-spar.etl_execution_log_hist \ + --exclude-table=nr-spar.etl_execution_map \ + --exclude-table=nr-spar.etl_execution_schedule \ --file=${BACKUP_DIR}/backup_$(date +%Y-%m-%d).sql \ && find "${BACKUP_DIR}" -type f -mtime +$NUM_BACKUPS -exec rm -f {} \; &&