From 47daa5c813ccdef231b416d402772c660f040c04 Mon Sep 17 00:00:00 2001 From: Kjeld Schouten Date: Mon, 4 Dec 2023 01:49:27 +0100 Subject: [PATCH] feat(common): rework and update cnpg code (#509) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Description** This PR aims to rework and update cnpg code to expose more features of CNPG to our users. Primarily a big change would be the support of more backup and restore options. - add some missing options for both cluster and pooler - seperates cluster and pooler sections - add labels/annotions for pooler and cluster seperatly as well as cnpg-wide labels-annotations - Simplify storage logic - Disable metrics by default **โš™๏ธ Type of change** - [x] โš™๏ธ Feature/App addition - [x] ๐Ÿช› Bugfix - [x] โš ๏ธ Breaking change (fix or feature that would cause existing functionality to not work as expected) - [x] ๐Ÿ”ƒ Refactor of current code **๐Ÿงช How Has This Been Tested?** **๐Ÿ“ƒ Notes:** It will be very loosely inspired by the work done here, mostly because it gives some nice values.yaml structure on how to deal with the many backup options: https://github.com/cloudnative-pg/charts/pull/106 It's going to be flagged as "breaking", because of the shear scope and the fact it would likely also include a change in standard operating procedures when it comes to backup-and-restore for our users. **โœ”๏ธ Checklist:** - [ ] โš–๏ธ My code follows the style guidelines of this project - [ ] ๐Ÿ‘€ I have performed a self-review of my own code - [ ] #๏ธโƒฃ I have commented my code, particularly in hard-to-understand areas - [ ] ๐Ÿ“„ I have made corresponding changes to the documentation - [ ] โš ๏ธ My changes generate no new warnings - [ ] ๐Ÿงช I have added tests to this description that prove my fix is effective or that my feature works - [ ] โฌ†๏ธ I increased versions for any altered app according to semantic versioning **โž• App addition** If this PR is an app addition please make sure you have done the following. - [ ] ๐Ÿชž I have opened a PR on [truecharts/containers](https://github.com/truecharts/containers) adding the container to TrueCharts mirror repo. - [ ] ๐Ÿ–ผ๏ธ I have added an icon in the Chart's root directory called `icon.png` --- _Please don't blindly check all the boxes. Read them and only check those that apply. Those checkboxes are there for the reviewer to see what is this all about and the status of this PR with a quick glance._ --------- Co-authored-by: Stavros kois Co-authored-by: Stavros Kois <47820033+stavros-k@users.noreply.github.com> --- cspell.config.yaml | 4 +- library/common-test/Chart.yaml | 2 +- .../tests/cnpg/backup_metadata_test.yaml | 242 ++++++++ .../tests/cnpg/backup_name_test.yaml | 62 ++ .../backup_provider_secret_spec_test.yaml | 123 ++++ .../cnpg/backup_provider_validation_test.yaml | 156 +++++ .../tests/cnpg/backup_spec_test.yaml | 61 ++ .../tests/cnpg/backup_validation_test.yaml | 44 ++ .../tests/cnpg/cluster_backup_spec_test.yaml | 223 +++++++ .../tests/cnpg/cluster_metadata_test.yaml | 178 ++++++ .../tests/cnpg/cluster_name_test.yaml | 42 ++ .../cnpg/cluster_recovery_spec_test.yaml | 532 +++++++++++++++++ .../tests/cnpg/cluster_spec_test.yaml | 370 ++++++++++++ .../tests/cnpg/cluster_validation_test.yaml | 558 ++++++++++++++++++ .../tests/cnpg/credentials_test.yaml | 151 +++++ .../tests/cnpg/custom_conf_test.yaml | 35 -- .../tests/cnpg/pooler_metadata_test.yaml | 178 ++++++ .../tests/cnpg/pooler_name_test.yaml | 54 ++ .../tests/cnpg/pooler_spec_test.yaml | 96 +++ .../tests/cnpg/pooler_validation_test.yaml | 22 + .../tests/cnpg/recovery_configmap_test.yaml | 33 ++ .../cnpg/scheduled_backup_metadata_test.yaml | 254 ++++++++ .../cnpg/scheduled_backup_name_test.yaml | 66 +++ .../cnpg/scheduled_backup_spec_test.yaml | 74 +++ .../cnpg/scheduled_backup_stop_test.yaml | 161 +++++ .../scheduled_backup_validation_test.yaml | 142 +++++ library/common-test/tests/cnpg/stop_test.yaml | 28 +- .../tests/pod/restart_policy_test.yaml | 10 +- library/common/Chart.yaml | 2 +- .../common/templates/class/_cnpgCluster.tpl | 69 --- .../common/templates/class/_cnpgPooler.tpl | 35 -- .../common/templates/class/cnpg/_backup.tpl | 40 ++ .../common/templates/class/cnpg/_cluster.tpl | 212 +++++++ .../common/templates/class/cnpg/_pooler.tpl | 59 ++ .../templates/class/cnpg/_scheduledBackup.tpl | 57 ++ .../common/templates/lib/_tc_capabilities.tpl | 10 - .../templates/lib/cnpg/_clusterName.tpl | 20 + .../lib/cnpg/_dbCredentialSecrets.tpl | 84 +++ .../templates/lib/cnpg/_poolerMetrics.tpl | 9 +- .../templates/lib/cnpg/_recoveryValue.tpl | 7 + .../common/templates/lib/cnpg/_urlsSecret.tpl | 14 - .../common/templates/lib/cnpg/_userSecret.tpl | 9 - .../templates/lib/cnpg/backup/_spawner.tpl | 14 + .../templates/lib/cnpg/backup/_validation.tpl | 7 + .../lib/cnpg/barmanObjectStore/_azure.tpl | 49 ++ .../lib/cnpg/barmanObjectStore/_google.tpl | 40 ++ .../lib/cnpg/barmanObjectStore/_s3.tpl | 43 ++ .../templates/lib/cnpg/cluster/_backup.tpl | 19 + .../lib/cnpg/cluster/_boostrapRecovery.tpl | 21 + .../_bootstrapRecoveryExternalCluster.tpl | 16 + .../lib/cnpg/cluster/_bootstrapStandalone.tpl | 72 +++ .../lib/cnpg/cluster/_validation.tpl | 102 ++++ .../templates/lib/cnpg/pooler/_spawner.tpl | 41 ++ .../templates/lib/cnpg/pooler/_validation.tpl | 15 + .../templates/lib/cnpg/providers/_azure.tpl | 27 + .../lib/cnpg/providers/_backupValidation.tpl | 14 + .../templates/lib/cnpg/providers/_google.tpl | 14 + .../cnpg/providers/_providerSecretSpawner.tpl | 28 + .../cnpg/providers/_recoveryValidation.tpl | 14 + .../templates/lib/cnpg/providers/_s3.tpl | 19 + .../lib/cnpg/providers/_validation.tpl | 11 + .../lib/cnpg/scheduledBackup/_spawner.tpl | 18 + .../lib/cnpg/scheduledBackup/_validation.tpl | 30 + .../templates/lib/pod/_restartPolicy.tpl | 4 +- .../common/templates/spawner/_certificate.tpl | 2 +- library/common/templates/spawner/_cnpg.tpl | 158 +++-- library/common/values.yaml | 258 +++++++- 67 files changed, 5250 insertions(+), 314 deletions(-) create mode 100644 library/common-test/tests/cnpg/backup_metadata_test.yaml create mode 100644 library/common-test/tests/cnpg/backup_name_test.yaml create mode 100644 library/common-test/tests/cnpg/backup_provider_secret_spec_test.yaml create mode 100644 library/common-test/tests/cnpg/backup_provider_validation_test.yaml create mode 100644 library/common-test/tests/cnpg/backup_spec_test.yaml create mode 100644 library/common-test/tests/cnpg/backup_validation_test.yaml create mode 100644 library/common-test/tests/cnpg/cluster_backup_spec_test.yaml create mode 100644 library/common-test/tests/cnpg/cluster_metadata_test.yaml create mode 100644 library/common-test/tests/cnpg/cluster_name_test.yaml create mode 100644 library/common-test/tests/cnpg/cluster_recovery_spec_test.yaml create mode 100644 library/common-test/tests/cnpg/cluster_spec_test.yaml create mode 100644 library/common-test/tests/cnpg/cluster_validation_test.yaml create mode 100644 library/common-test/tests/cnpg/credentials_test.yaml delete mode 100644 library/common-test/tests/cnpg/custom_conf_test.yaml create mode 100644 library/common-test/tests/cnpg/pooler_metadata_test.yaml create mode 100644 library/common-test/tests/cnpg/pooler_name_test.yaml create mode 100644 library/common-test/tests/cnpg/pooler_spec_test.yaml create mode 100644 library/common-test/tests/cnpg/pooler_validation_test.yaml create mode 100644 library/common-test/tests/cnpg/recovery_configmap_test.yaml create mode 100644 library/common-test/tests/cnpg/scheduled_backup_metadata_test.yaml create mode 100644 library/common-test/tests/cnpg/scheduled_backup_name_test.yaml create mode 100644 library/common-test/tests/cnpg/scheduled_backup_spec_test.yaml create mode 100644 library/common-test/tests/cnpg/scheduled_backup_stop_test.yaml create mode 100644 library/common-test/tests/cnpg/scheduled_backup_validation_test.yaml delete mode 100644 library/common/templates/class/_cnpgCluster.tpl delete mode 100644 library/common/templates/class/_cnpgPooler.tpl create mode 100644 library/common/templates/class/cnpg/_backup.tpl create mode 100644 library/common/templates/class/cnpg/_cluster.tpl create mode 100644 library/common/templates/class/cnpg/_pooler.tpl create mode 100644 library/common/templates/class/cnpg/_scheduledBackup.tpl create mode 100644 library/common/templates/lib/cnpg/_clusterName.tpl create mode 100644 library/common/templates/lib/cnpg/_dbCredentialSecrets.tpl create mode 100644 library/common/templates/lib/cnpg/_recoveryValue.tpl delete mode 100644 library/common/templates/lib/cnpg/_urlsSecret.tpl delete mode 100644 library/common/templates/lib/cnpg/_userSecret.tpl create mode 100644 library/common/templates/lib/cnpg/backup/_spawner.tpl create mode 100644 library/common/templates/lib/cnpg/backup/_validation.tpl create mode 100644 library/common/templates/lib/cnpg/barmanObjectStore/_azure.tpl create mode 100644 library/common/templates/lib/cnpg/barmanObjectStore/_google.tpl create mode 100644 library/common/templates/lib/cnpg/barmanObjectStore/_s3.tpl create mode 100644 library/common/templates/lib/cnpg/cluster/_backup.tpl create mode 100644 library/common/templates/lib/cnpg/cluster/_boostrapRecovery.tpl create mode 100644 library/common/templates/lib/cnpg/cluster/_bootstrapRecoveryExternalCluster.tpl create mode 100644 library/common/templates/lib/cnpg/cluster/_bootstrapStandalone.tpl create mode 100644 library/common/templates/lib/cnpg/cluster/_validation.tpl create mode 100644 library/common/templates/lib/cnpg/pooler/_spawner.tpl create mode 100644 library/common/templates/lib/cnpg/pooler/_validation.tpl create mode 100644 library/common/templates/lib/cnpg/providers/_azure.tpl create mode 100644 library/common/templates/lib/cnpg/providers/_backupValidation.tpl create mode 100644 library/common/templates/lib/cnpg/providers/_google.tpl create mode 100644 library/common/templates/lib/cnpg/providers/_providerSecretSpawner.tpl create mode 100644 library/common/templates/lib/cnpg/providers/_recoveryValidation.tpl create mode 100644 library/common/templates/lib/cnpg/providers/_s3.tpl create mode 100644 library/common/templates/lib/cnpg/providers/_validation.tpl create mode 100644 library/common/templates/lib/cnpg/scheduledBackup/_spawner.tpl create mode 100644 library/common/templates/lib/cnpg/scheduledBackup/_validation.tpl diff --git a/cspell.config.yaml b/cspell.config.yaml index 526c795b..982ba4f2 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -1,3 +1,5 @@ words: + - cnpg + - netshoot - tailscale - - Velero + - velero diff --git a/library/common-test/Chart.yaml b/library/common-test/Chart.yaml index 2d3d11c7..34a2e909 100644 --- a/library/common-test/Chart.yaml +++ b/library/common-test/Chart.yaml @@ -3,7 +3,7 @@ appVersion: "" dependencies: - name: common repository: file://../common - version: ~15.3.0 + version: ~16.0.0 deprecated: false description: Helper chart to test different use cases of the common library home: https://github.com/truecharts/apps/tree/master/charts/library/common-test diff --git a/library/common-test/tests/cnpg/backup_metadata_test.yaml b/library/common-test/tests/cnpg/backup_metadata_test.yaml new file mode 100644 index 00000000..4ba54496 --- /dev/null +++ b/library/common-test/tests/cnpg/backup_metadata_test.yaml @@ -0,0 +1,242 @@ +suite: cnpg backup metadata test +templates: + - common.yaml +chart: + appVersion: &appVer v9.9.9 +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should pass with cnpg manualBackups backup created with labels and annotations + set: + operator: + verify: + enabled: false + label1: label1 + label2: global_label2 + label3: label3 + annotation1: annotation1 + annotation2: global_annotation2 + annotation3: annotation3 + global: + labels: + g_label1: global_label1 + g_label2: "{{ .Values.label2 }}" + annotations: + g_annotation1: global_annotation1 + g_annotation2: "{{ .Values.annotation2 }}" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + labels: + label1: "{{ .Values.label1 }}" + label2: label2 + annotations: + annotation1: "{{ .Values.annotation1 }}" + annotation2: annotation2 + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + labels: + label5: label5 + annotations: + annotation5: annotation5 + manualBackups: + - name: today + labels: + label3: "{{ .Values.label3 }}" + label4: label4 + annotations: + annotation3: "{{ .Values.annotation3 }}" + annotation4: annotation4 + asserts: + - documentIndex: &backupDoc 0 + isKind: + of: Backup + - documentIndex: *backupDoc + equal: + path: metadata.annotations + value: + annotation1: annotation1 + annotation2: annotation2 + annotation3: annotation3 + annotation4: annotation4 + annotation5: annotation5 + g_annotation1: global_annotation1 + g_annotation2: global_annotation2 + - documentIndex: *backupDoc + equal: + path: metadata.labels + value: + app: common-test-1.0.0 + release: test-release-name + helm-revision: "0" + helm.sh/chart: common-test-1.0.0 + app.kubernetes.io/name: common-test + app.kubernetes.io/instance: test-release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: *appVer + cnpg.io/cluster: test-release-name-common-test-cnpg-my-pg + g_label1: global_label1 + g_label2: global_label2 + label1: label1 + label2: label2 + label3: label3 + label4: label4 + label5: label5 + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: test-release-namespace + + - it: should pass with cnpg manualBackups backup created with namespace + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + namespace: some-namespace + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + manualBackups: + - name: today + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: some-namespace + + - it: should pass with cnpg manualBackups backup created with object namespace from tpl + set: + operator: + verify: + enabled: false + key: some-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + namespace: "{{ .Values.key }}" + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + manualBackups: + - name: today + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: some-namespace + + - it: should pass with cnpg manualBackups backup created with namespace from global with tpl + set: + operator: + verify: + enabled: false + key: global-namespace + global: + namespace: "{{ .Values.key }}" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + manualBackups: + - name: today + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: global-namespace + + - it: should pass with cnpg manualBackups backup created with namespace from root with tpl + set: + operator: + verify: + enabled: false + key: local-namespace + namespace: "{{ .Values.key }}" + global: + namespace: global-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + manualBackups: + - name: today + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: local-namespace + + - it: should pass with cnpg manualBackups backup created with namespace in TrueNAS SCALE + set: + operator: + verify: + enabled: false + global: + ixChartContext: + iAmNotEmpty: true + storageClassName: some-storage-class + namespace: ix-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + manualBackups: + - name: today + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: ix-namespace diff --git a/library/common-test/tests/cnpg/backup_name_test.yaml b/library/common-test/tests/cnpg/backup_name_test.yaml new file mode 100644 index 00000000..346089f1 --- /dev/null +++ b/library/common-test/tests/cnpg/backup_name_test.yaml @@ -0,0 +1,62 @@ +suite: cnpg backup name test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct name + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + manualBackups: + - name: today + my-pg2: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + manualBackups: + - name: other + asserts: + - documentIndex: &backupDoc 0 + isKind: + of: Backup + - documentIndex: *backupDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *backupDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-backup-today + - documentIndex: &otherbackupDoc 3 + isKind: + of: Backup + - documentIndex: *otherbackupDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *otherbackupDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg2-backup-other diff --git a/library/common-test/tests/cnpg/backup_provider_secret_spec_test.yaml b/library/common-test/tests/cnpg/backup_provider_secret_spec_test.yaml new file mode 100644 index 00000000..70e3b788 --- /dev/null +++ b/library/common-test/tests/cnpg/backup_provider_secret_spec_test.yaml @@ -0,0 +1,123 @@ +suite: cnpg backup provider secret spec test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should create secret for azure provider with connection string + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + manualBackups: + - name: today + asserts: + - documentIndex: &secretDoc 3 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-backup-azure-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + CONNECTION_STRING: some-connection-string + STORAGE_ACCOUNT: "" + STORAGE_KEY: "" + STORAGE_SAS_TOKEN: "" + + - it: should create secret for google provider with application credentials + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: google + destinationPath: some-path + google: + applicationCredentials: some-credentials + manualBackups: + - name: today + asserts: + - documentIndex: *secretDoc + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-backup-google-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + APPLICATION_CREDENTIALS: some-credentials + + - it: should create secret for s3 provider with application credentials + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: s3 + destinationPath: some-path + endpointURL: some-url + s3: + secretKey: some-secret-key + accessKey: some-access-key + manualBackups: + - name: today + asserts: + - documentIndex: *secretDoc + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-backup-s3-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + ACCESS_SECRET_KEY: some-secret-key + ACCESS_KEY_ID: some-access-key diff --git a/library/common-test/tests/cnpg/backup_provider_validation_test.yaml b/library/common-test/tests/cnpg/backup_provider_validation_test.yaml new file mode 100644 index 00000000..516f7f79 --- /dev/null +++ b/library/common-test/tests/cnpg/backup_provider_validation_test.yaml @@ -0,0 +1,156 @@ +suite: cnpg backup provider validation test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should fail with invalid provider + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: invalid + manualBackups: + - name: today + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected [backups.provider] to be one of [azure, s3, google], but got [invalid] + + - it: should fail with missing "provider" object + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: azure + manualBackups: + - name: today + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected [backups.azure] to be defined when [backups.provider] is set to [azure] + + - it: should fail with missing storageAccount or connectionString with azure provider + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: azure + azure: + storageKey: test + manualBackups: + - name: today + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected [backups.azure.storageAccount] OR [backups.azure.connectionString] to be defined and non-empty when provider is set to [azure] + + - it: should fail with missing storageKey or storageSasToken with azure provider + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: azure + azure: + storageAccount: test + manualBackups: + - name: today + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected [backups.azure.storageKey] OR [backups.azure.storageSasToken] to be defined and non-empty when provider is set to [azure] + + - it: should fail with both storageKey and storageSasToken defined with azure provider + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: azure + azure: + storageAccount: test + storageKey: test + storageSasToken: test + manualBackups: + - name: today + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected only one of [backups.azure.storageKey, backups.azure.storageSasToken] to be defined and non-empty when provider is set to [azure] + + - it: should fail with applicationCredentials missing with google provider + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: google + google: + gkeEnvironment: false + manualBackups: + - name: today + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected [backups.google.applicationCredentials] to be defined and non-empty when provider is set to [google] + + - it: should fail with accessKey missing with s3 provider + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: s3 + s3: + secretKey: test + manualBackups: + - name: today + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected [backups.s3.accessKey] to be defined and non-empty when provider is set to [s3] + + - it: should fail with secretKey missing with s3 provider + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: s3 + s3: + accessKey: test + manualBackups: + - name: today + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected [backups.s3.secretKey] to be defined and non-empty when provider is set to [s3] diff --git a/library/common-test/tests/cnpg/backup_spec_test.yaml b/library/common-test/tests/cnpg/backup_spec_test.yaml new file mode 100644 index 00000000..5865e9f5 --- /dev/null +++ b/library/common-test/tests/cnpg/backup_spec_test.yaml @@ -0,0 +1,61 @@ +suite: cnpg backup spec test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct spec + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + manualBackups: + - name: today + - name: before-upgrade + asserts: + - documentIndex: &cnpgDoc 0 + isKind: + of: Backup + - documentIndex: *cnpgDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *cnpgDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-backup-today + - documentIndex: *cnpgDoc + equal: + path: spec + value: + cluster: + name: test-release-name-common-test-cnpg-my-pg + - documentIndex: &otherCnpgDoc 1 + isKind: + of: Backup + - documentIndex: *otherCnpgDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *otherCnpgDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-backup-before-upgrade + - documentIndex: *otherCnpgDoc + equal: + path: spec + value: + cluster: + name: test-release-name-common-test-cnpg-my-pg diff --git a/library/common-test/tests/cnpg/backup_validation_test.yaml b/library/common-test/tests/cnpg/backup_validation_test.yaml new file mode 100644 index 00000000..7ea2747f --- /dev/null +++ b/library/common-test/tests/cnpg/backup_validation_test.yaml @@ -0,0 +1,44 @@ +suite: cnpg backup validation test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should fail without name in manualBackups backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + manualBackups: + - name: + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected non-empty [name] in [backups.manualBackups] entry + + - it: should fail with invalid name in manualBackups backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + manualBackups: + - name: _invalid + asserts: + - failedTemplate: + errorMessage: Name [test-release-name-common-test-cnpg-my-pg-backup-_invalid] is not valid. Must start and end with an alphanumeric lowercase character. It can contain '-'. And must be at most 253 characters. diff --git a/library/common-test/tests/cnpg/cluster_backup_spec_test.yaml b/library/common-test/tests/cnpg/cluster_backup_spec_test.yaml new file mode 100644 index 00000000..d41b0021 --- /dev/null +++ b/library/common-test/tests/cnpg/cluster_backup_spec_test.yaml @@ -0,0 +1,223 @@ +suite: cnpg cluster backup spec test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct spec with backups (azure) + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + asserts: + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-backup-azure-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + CONNECTION_STRING: some-connection-string + STORAGE_ACCOUNT: "" + STORAGE_KEY: "" + STORAGE_SAS_TOKEN: "" + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + backup: + target: primary + retentionPolicy: 10d + barmanObjectStore: + wal: + compression: gzip + encryption: AES256 + data: + compression: gzip + encryption: AES256 + jobs: 2 + endpointURL: null + destinationPath: some-path + azureCredentials: + connectionString: + key: CONNECTION_STRING + name: test-release-name-common-test-cnpg-my-pg-provider-backup-azure-creds + storageAccount: + key: STORAGE_ACCOUNT + name: test-release-name-common-test-cnpg-my-pg-provider-backup-azure-creds + storageKey: + key: STORAGE_KEY + name: test-release-name-common-test-cnpg-my-pg-provider-backup-azure-creds + storageSasToken: + key: STORAGE_SAS_TOKEN + name: test-release-name-common-test-cnpg-my-pg-provider-backup-azure-creds + + - it: should generate correct spec with backups (google) + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: google + destinationPath: some-path + google: + applicationCredentials: some-credentials + asserts: + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-backup-google-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + APPLICATION_CREDENTIALS: some-credentials + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + backup: + target: primary + retentionPolicy: 10d + barmanObjectStore: + wal: + compression: gzip + encryption: AES256 + data: + compression: gzip + encryption: AES256 + jobs: 2 + endpointURL: null + destinationPath: some-path + googleCredentials: + gkeEnvironment: false + applicationCredentials: + key: APPLICATION_CREDENTIALS + name: test-release-name-common-test-cnpg-my-pg-provider-backup-google-creds + + - it: should generate correct spec with backups (s3) + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: s3 + destinationPath: some-path + endpointURL: some-url + s3: + accessKey: some-access-key + secretKey: some-secret-key + asserts: + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-backup-s3-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + ACCESS_KEY_ID: some-access-key + ACCESS_SECRET_KEY: some-secret-key + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + backup: + target: primary + retentionPolicy: 10d + barmanObjectStore: + wal: + compression: gzip + encryption: AES256 + data: + compression: gzip + encryption: AES256 + jobs: 2 + endpointURL: some-url + destinationPath: some-path + s3Credentials: + accessKeyId: + key: ACCESS_KEY_ID + name: test-release-name-common-test-cnpg-my-pg-provider-backup-s3-creds + secretAccessKey: + key: ACCESS_SECRET_KEY + name: test-release-name-common-test-cnpg-my-pg-provider-backup-s3-creds diff --git a/library/common-test/tests/cnpg/cluster_metadata_test.yaml b/library/common-test/tests/cnpg/cluster_metadata_test.yaml new file mode 100644 index 00000000..38b24174 --- /dev/null +++ b/library/common-test/tests/cnpg/cluster_metadata_test.yaml @@ -0,0 +1,178 @@ +suite: cnpg cluster metadata test +templates: + - common.yaml +chart: + appVersion: &appVer v9.9.9 +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should pass with cnpg created with labels and annotations + set: + operator: + verify: + enabled: false + label1: label1 + label2: global_label2 + label3: label3 + annotation1: annotation1 + annotation2: global_annotation2 + annotation3: annotation3 + global: + labels: + g_label1: global_label1 + g_label2: "{{ .Values.label2 }}" + annotations: + g_annotation1: global_annotation1 + g_annotation2: "{{ .Values.annotation2 }}" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + labels: + label1: "{{ .Values.label1 }}" + label2: label2 + annotations: + annotation1: "{{ .Values.annotation1 }}" + annotation2: annotation2 + cluster: + labels: + label3: "{{ .Values.label3 }}" + annotations: + annotation3: "{{ .Values.annotation3 }}" + asserts: + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isSubset: + path: metadata.annotations + content: + annotation1: annotation1 + annotation2: annotation2 + annotation3: annotation3 + g_annotation1: global_annotation1 + g_annotation2: global_annotation2 + cnpg.io/hibernation: "off" + - documentIndex: *clusterDoc + matchRegex: + path: metadata.annotations.rollme + pattern: ^[a-zA-Z0-9]{5}$ + - documentIndex: *clusterDoc + equal: + path: metadata.labels + value: + app: common-test-1.0.0 + release: test-release-name + helm-revision: "0" + helm.sh/chart: common-test-1.0.0 + app.kubernetes.io/name: common-test + app.kubernetes.io/instance: test-release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: *appVer + cnpg.io/reload: "on" + g_label1: global_label1 + g_label2: global_label2 + label1: label1 + label2: label2 + label3: label3 + - documentIndex: *clusterDoc + equal: + path: metadata.namespace + value: test-release-namespace + + - it: should pass with cnpg created with namespace + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + namespace: some-namespace + asserts: + - documentIndex: *clusterDoc + equal: + path: metadata.namespace + value: some-namespace + + - it: should pass with cnpg created with object namespace from tpl + set: + operator: + verify: + enabled: false + key: some-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + namespace: "{{ .Values.key }}" + asserts: + - documentIndex: *clusterDoc + equal: + path: metadata.namespace + value: some-namespace + + - it: should pass with cnpg created with namespace from global with tpl + set: + operator: + verify: + enabled: false + key: global-namespace + global: + namespace: "{{ .Values.key }}" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: *clusterDoc + equal: + path: metadata.namespace + value: global-namespace + + - it: should pass with cnpg created with namespace from root with tpl + set: + operator: + verify: + enabled: false + key: local-namespace + namespace: "{{ .Values.key }}" + global: + namespace: global-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: *clusterDoc + equal: + path: metadata.namespace + value: local-namespace + + - it: should pass with cnpg created with namespace in TrueNAS SCALE + set: + operator: + verify: + enabled: false + global: + ixChartContext: + iAmNotEmpty: true + storageClassName: some-storage-class + namespace: ix-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: *clusterDoc + equal: + path: metadata.namespace + value: ix-namespace diff --git a/library/common-test/tests/cnpg/cluster_name_test.yaml b/library/common-test/tests/cnpg/cluster_name_test.yaml new file mode 100644 index 00000000..22fd6d10 --- /dev/null +++ b/library/common-test/tests/cnpg/cluster_name_test.yaml @@ -0,0 +1,42 @@ +suite: cnpg cluster name test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct name + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + my-pg2: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: &otherclusterDoc 3 + isKind: + of: Cluster + - documentIndex: *otherclusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *otherclusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg2 diff --git a/library/common-test/tests/cnpg/cluster_recovery_spec_test.yaml b/library/common-test/tests/cnpg/cluster_recovery_spec_test.yaml new file mode 100644 index 00000000..5d20ff09 --- /dev/null +++ b/library/common-test/tests/cnpg/cluster_recovery_spec_test.yaml @@ -0,0 +1,532 @@ +suite: cnpg cluster recovery spec test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct spec with recovery/backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: backup + backupName: some-backup-name + asserts: + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + equal: + path: spec + value: + enableSuperuserAccess: true + primaryUpdateStrategy: unsupervised + primaryUpdateMethod: switchover + logLevel: info + instances: 2 + nodeMaintenanceWindow: + reusePVC: true + inProgress: false + resources: + limits: + cpu: 4000m + memory: 8Gi + requests: + cpu: 10m + memory: 50Mi + storage: + pvcTemplate: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Gi + walStorage: + pvcTemplate: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Gi + bootstrap: + recovery: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + owner: test-user + database: test-db + backup: + name: some-backup-name + + - it: should generate correct spec with recovery/objectStore (google) + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: google + google: + applicationCredentials: some-credentials + bucket: some-bucket + path: some-path + pitrTarget: + time: "2021-01-01T00:00:00Z" + asserts: + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-recovery-google-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + APPLICATION_CREDENTIALS: some-credentials + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + bootstrap: + recovery: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + owner: test-user + database: test-db + source: objectStoreRecoveryCluster + recoveryTarget: + targetTime: "2021-01-01T00:00:00Z" + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + externalClusters: + - name: objectStoreRecoveryCluster + barmanObjectStore: + destinationPath: gs://some-bucket/some-path + endpointURL: null + googleCredentials: + applicationCredentials: + key: APPLICATION_CREDENTIALS + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-google-creds + gkeEnvironment: false + + - it: should generate correct spec with recovery/objectStore (google - destinationPath) + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: google + destinationPath: gs://some-bucket + google: + applicationCredentials: some-credentials + pitrTarget: + time: "2021-01-01T00:00:00Z" + asserts: + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-recovery-google-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + APPLICATION_CREDENTIALS: some-credentials + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + bootstrap: + recovery: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + owner: test-user + database: test-db + source: objectStoreRecoveryCluster + recoveryTarget: + targetTime: "2021-01-01T00:00:00Z" + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + externalClusters: + - name: objectStoreRecoveryCluster + barmanObjectStore: + destinationPath: gs://some-bucket + endpointURL: null + googleCredentials: + applicationCredentials: + key: APPLICATION_CREDENTIALS + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-google-creds + gkeEnvironment: false + + - it: should generate correct spec with recovery/objectStore (s3) + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: s3 + s3: + accessKey: some-access-key + secretKey: some-secret-key + bucket: some-bucket + path: some-path + region: some-region + asserts: + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-recovery-s3-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + ACCESS_KEY_ID: some-access-key + ACCESS_SECRET_KEY: some-secret-key + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + bootstrap: + recovery: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + owner: test-user + database: test-db + source: objectStoreRecoveryCluster + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + externalClusters: + - name: objectStoreRecoveryCluster + barmanObjectStore: + destinationPath: s3://some-bucket/some-path + endpointURL: https://s3.some-region.amazonaws.com + s3Credentials: + accessKeyId: + key: ACCESS_KEY_ID + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-s3-creds + secretAccessKey: + key: ACCESS_SECRET_KEY + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-s3-creds + + - it: should generate correct spec with recovery/objectStore (s3 - destinationPath/endpointURL) + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: s3 + destinationPath: s3://some-bucket + endpointURL: some-endpoint-url + s3: + accessKey: some-access-key + secretKey: some-secret-key + asserts: + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-recovery-s3-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + ACCESS_KEY_ID: some-access-key + ACCESS_SECRET_KEY: some-secret-key + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + bootstrap: + recovery: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + owner: test-user + database: test-db + source: objectStoreRecoveryCluster + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + externalClusters: + - name: objectStoreRecoveryCluster + barmanObjectStore: + destinationPath: s3://some-bucket + endpointURL: some-endpoint-url + s3Credentials: + accessKeyId: + key: ACCESS_KEY_ID + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-s3-creds + secretAccessKey: + key: ACCESS_SECRET_KEY + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-s3-creds + + - it: should generate correct spec with recovery/objectStore (azure) + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: azure + azure: + connectionString: some-connection-string + storageAccount: some-storage-account + serviceName: some-service-name + containerName: some-container-name + path: some-path + asserts: + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + CONNECTION_STRING: some-connection-string + STORAGE_ACCOUNT: some-storage-account + STORAGE_KEY: "" + STORAGE_SAS_TOKEN: "" + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + bootstrap: + recovery: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + owner: test-user + database: test-db + source: objectStoreRecoveryCluster + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + externalClusters: + - name: objectStoreRecoveryCluster + barmanObjectStore: + destinationPath: https://some-storage-account.some-service-name.core.windows.net/some-container-name/some-path + endpointURL: null + azureCredentials: + connectionString: + key: CONNECTION_STRING + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds + storageAccount: + key: STORAGE_ACCOUNT + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds + storageKey: + key: STORAGE_KEY + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds + storageSasToken: + key: STORAGE_SAS_TOKEN + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds + + - it: should generate correct spec with recovery/objectStore (azure - destinationPath) + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: azure + destinationPath: https://some-storage-account.some-service-name.core.windows.net/some-container-name + azure: + connectionString: some-connection-string + asserts: + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds + - documentIndex: *secretDoc + equal: + path: stringData + value: + CONNECTION_STRING: some-connection-string + STORAGE_ACCOUNT: "" + STORAGE_KEY: "" + STORAGE_SAS_TOKEN: "" + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + bootstrap: + recovery: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + owner: test-user + database: test-db + source: objectStoreRecoveryCluster + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + externalClusters: + - name: objectStoreRecoveryCluster + barmanObjectStore: + destinationPath: https://some-storage-account.some-service-name.core.windows.net/some-container-name + endpointURL: null + azureCredentials: + connectionString: + key: CONNECTION_STRING + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds + storageAccount: + key: STORAGE_ACCOUNT + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds + storageKey: + key: STORAGE_KEY + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds + storageSasToken: + key: STORAGE_SAS_TOKEN + name: test-release-name-common-test-cnpg-my-pg-provider-recovery-azure-creds diff --git a/library/common-test/tests/cnpg/cluster_spec_test.yaml b/library/common-test/tests/cnpg/cluster_spec_test.yaml new file mode 100644 index 00000000..7f0f0c14 --- /dev/null +++ b/library/common-test/tests/cnpg/cluster_spec_test.yaml @@ -0,0 +1,370 @@ +suite: cnpg cluster spec test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct spec + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: &clusterDoc 1 + isKind: + of: Cluster + - documentIndex: *clusterDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *clusterDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg + - documentIndex: *clusterDoc + equal: + path: spec + value: + enableSuperuserAccess: true + primaryUpdateStrategy: unsupervised + primaryUpdateMethod: switchover + logLevel: info + instances: 2 + nodeMaintenanceWindow: + reusePVC: true + inProgress: false + resources: + limits: + cpu: 4000m + memory: 8Gi + requests: + cpu: 10m + memory: 50Mi + storage: + pvcTemplate: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Gi + walStorage: + pvcTemplate: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Gi + bootstrap: + initdb: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + database: test-db + owner: test-user + dataChecksums: false + + - it: should override options + set: + operator: + verify: + enabled: false + ext1: some-extension + ext2: some-other-extension + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + cluster: + enableSuperuserAccess: false + primaryUpdateStrategy: supervised + primaryUpdateMethod: restart + logLevel: debug + instances: 3 + initdb: + dataChecksums: true + encoding: some-encoding + localeCollate: some-locale + localeCtype: some-locale + walSegmentSize: 16 + postInitApplicationSQL: + - CREATE EXTENSION IF NOT EXISTS {{ .Values.ext1 }}; + - CREATE EXTENSION IF NOT EXISTS {{ .Values.ext2 }}; + postInitSQL: + - CREATE EXTENSION IF NOT EXISTS {{ .Values.ext1 }}1; + - CREATE EXTENSION IF NOT EXISTS {{ .Values.ext2 }}2; + postInitTemplateSQL: + - CREATE EXTENSION IF NOT EXISTS {{ .Values.ext1 }}1; + - CREATE EXTENSION IF NOT EXISTS {{ .Values.ext2 }}2; + nodeMaintenanceWindow: + reusePVC: false + inProgress: true + resources: + limits: + cpu: 2000m + memory: 4Gi + requests: + cpu: 20m + memory: 100Mi + storage: + size: 200Gi + accessModes: + - ReadWriteMany + walStorage: + size: 200Gi + accessModes: + - ReadWriteMany + asserts: + - documentIndex: *clusterDoc + isKind: + of: Cluster + - documentIndex: *clusterDoc + equal: + path: spec + value: + enableSuperuserAccess: false + primaryUpdateStrategy: supervised + primaryUpdateMethod: restart + logLevel: debug + instances: 3 + nodeMaintenanceWindow: + reusePVC: false + inProgress: true + resources: + limits: + cpu: 2000m + memory: 4Gi + requests: + cpu: 20m + memory: 100Mi + storage: + pvcTemplate: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 200Gi + walStorage: + pvcTemplate: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 200Gi + bootstrap: + initdb: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + database: test-db + owner: test-user + dataChecksums: true + encoding: some-encoding + localeCollate: some-locale + localeCtype: some-locale + walSegmentSize: 16 + postInitApplicationSQL: + - CREATE EXTENSION IF NOT EXISTS some-extension; + - CREATE EXTENSION IF NOT EXISTS some-other-extension; + postInitSQL: + - CREATE EXTENSION IF NOT EXISTS some-extension1; + - CREATE EXTENSION IF NOT EXISTS some-other-extension2; + postInitTemplateSQL: + - CREATE EXTENSION IF NOT EXISTS some-extension1; + - CREATE EXTENSION IF NOT EXISTS some-other-extension2; + + - it: should override resources from top level + set: + operator: + verify: + enabled: false + resources: + limits: + cpu: 2000m + memory: 4Gi + requests: + cpu: 20m + memory: 100Mi + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: *clusterDoc + isKind: + of: Cluster + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + resources: + limits: + cpu: 2000m + memory: 4Gi + requests: + cpu: 20m + memory: 100Mi + + - it: should pass with custom-conf + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: app + database: app + cluster: + postgresql: + key1: value1 + key2: '{{ printf "test-tpl" }}' + preloadLibraries: + - pg_stat_statements + - pg_cron + asserts: + - documentIndex: *clusterDoc + isKind: + of: Cluster + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + postgresql: + parameters: + key1: value1 + key2: test-tpl + shared_preload_libraries: + - pg_stat_statements + - pg_cron + + - it: should pass with timescaledb + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: app + database: app + type: timescaledb + cluster: + initdb: + postInitApplicationSQL: + - CREATE EXTENSION IF NOT EXISTS some-extension; + postgresql: + key1: value1 + key2: '{{ printf "test-tpl" }}' + preloadLibraries: + - pg_stat_statements + - pg_cron + asserts: + - documentIndex: *clusterDoc + isKind: + of: Cluster + - documentIndex: *clusterDoc + isSubset: + path: spec + content: + postgresql: + parameters: + key1: value1 + key2: test-tpl + shared_preload_libraries: + - pg_stat_statements + - pg_cron + - timescaledb + bootstrap: + initdb: + secret: + name: test-release-name-common-test-cnpg-my-pg-user + database: app + owner: app + dataChecksums: false + postInitApplicationSQL: + - CREATE EXTENSION IF NOT EXISTS some-extension; + - CREATE EXTENSION IF NOT EXISTS timescaledb; + + - it: should pass with enabled monitoring + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: app + database: app + type: timescaledb + monitoring: + enablePodMonitor: true + asserts: + - documentIndex: *clusterDoc + isKind: + of: Cluster + - documentIndex: *clusterDoc + equal: + path: spec.monitoring + value: + enablePodMonitor: true + disableDefaultQueries: false + + - it: should pass with override monitoring + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: app + database: app + type: timescaledb + monitoring: + enablePodMonitor: true + disableDefaultQueries: true + customQueries: + - name: test-query + query: test-query + metrics: + - a-gauge: + usage: GAUGE + description: test-metric + - a-counter: + usage: COUNTER + description: test-metric + - name: test-query2 + query: test-query2 + metrics: + - a-gauge: + usage: GAUGE + description: test-metric + - a-counter: + usage: COUNTER + description: test-metric + - name: test-query3 + query: test-query3 + expandObjectName: false + key: test-key + asserts: + - documentIndex: *clusterDoc + isKind: + of: Cluster + - documentIndex: *clusterDoc + equal: + path: spec.monitoring + value: + enablePodMonitor: true + disableDefaultQueries: true + customQueriesConfigMap: + - name: test-release-name-common-test-cnpg-my-pg-test-query + key: custom-queries + - name: test-release-name-common-test-cnpg-my-pg-test-query2 + key: custom-queries + - name: test-query3 + key: test-key diff --git a/library/common-test/tests/cnpg/cluster_validation_test.yaml b/library/common-test/tests/cnpg/cluster_validation_test.yaml new file mode 100644 index 00000000..5c5699bf --- /dev/null +++ b/library/common-test/tests/cnpg/cluster_validation_test.yaml @@ -0,0 +1,558 @@ +suite: cnpg cluster validation test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should fail without user + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + database: test-db + asserts: + - failedTemplate: + errorMessage: CNPG - Expected a non-empty [user] key + + - it: should fail without database + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + asserts: + - failedTemplate: + errorMessage: CNPG - Expected a non-empty [database] key + + - it: should fail with invalid version + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + version: invalid + asserts: + - failedTemplate: + errorMessage: CNPG - Expected [version] to be one of [legacy], but got [invalid] + + - it: should fail with hibernate not a bool + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + hibernate: invalid + asserts: + - failedTemplate: + errorMessage: CNPG - Expected [hibernate] to be a boolean, but got [string] + + - it: should fail with invalid mode + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Cluster - Expected [mode] to be one of [standalone, replica, recovery], but got [invalid] + + - it: should fail with invalid type + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + type: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Cluster - Expected [type] to be one of [postgresql, postgis, timescaledb], but got [invalid] + + - it: should fail with invalid log level + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + cluster: + logLevel: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Cluster - Expected [cluster.logLevel] to be one of [error, warning, info, debug, trace], but got [invalid] + + - it: should fail with invalid primaryUpdateStrategy + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + cluster: + primaryUpdateStrategy: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Cluster - Expected [cluster.primaryUpdateStrategy] to be one of [supervised, unsupervised], but got [invalid] + + - it: should fail with invalid primaryUpdateMethod + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + cluster: + primaryUpdateMethod: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Cluster - Expected [cluster.primaryUpdateMethod] to be one of [switchover, restart], but got [invalid] + + - it: should fail with invalid walSegmentSize + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + cluster: + initdb: + walSegmentSize: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Cluster - Expected [cluster.initdb.walSegmentSize] to be an integer, but got [string] + + - it: should fail with too large walSegmentSize + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + cluster: + initdb: + walSegmentSize: 1025 + asserts: + - failedTemplate: + errorMessage: CNPG Cluster - Expected [cluster.initdb.walSegmentSize] to be between 1 and 1024, but got [1025] + + - it: should fail without recovery object when mode is recovery + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - Expected a non-empty [recovery] key + + - it: should fail with invalid recovery method + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - Expected [recovery.method] to be one of [backup, object_store, pg_basebackup], but got [invalid] + + - it: should fail without backupName on recovery method backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: backup + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - Expected a non-empty [recovery.backupName] key + + - it: should fail with invalid provider on recovery method object_store + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - Expected [recovery.provider] to be one of [azure, s3, google], but got [invalid] + + - it: should fail with missing "provider" key on recovery method object_store + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: google + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - Expected [recovery.google] to be defined when [recovery.provider] is set to [google] + + - it: should fail with missing destinationPath and google bucket on recovery method object_store + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: google + google: + applicationCredentials: some-credentials + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - You need to specify [recovery.google.bucket] or [recovery.destinationPath] + + - it: should fail with missing destinationPath and s3 bucket on recovery method object_store + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: s3 + s3: + accessKey: some-access-key + secretKey: some-secret-key + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - You need to specify [recovery.s3.bucket] or [recovery.destinationPath] + + - it: should fail with missing endpointURL and s3 region on recovery method object_store + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: s3 + s3: + accessKey: some-access-key + secretKey: some-secret-key + bucket: some-bucket + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - You need to specify [recovery.s3.region] or [recovery.endpointURL] + + - it: should fail with missing destinationPath and azure storageAccount on recovery method object_store + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: azure + azure: + connectionString: some-connection-string + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - You need to specify [recovery.azure.storageAccount] or [recovery.destinationPath] + + - it: should fail with missing destinationPath and azure serviceName on recovery method object_store + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: azure + azure: + connectionString: some-connection-string + storageAccount: some-storage-account + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - You need to specify [recovery.azure.serviceName] or [recovery.destinationPath] + + - it: should fail with missing destinationPath and azure containerName on recovery method object_store + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + mode: recovery + recovery: + method: object_store + provider: azure + azure: + connectionString: some-connection-string + storageAccount: some-storage-account + serviceName: some-service-name + asserts: + - failedTemplate: + errorMessage: CNPG Recovery - You need to specify [recovery.azure.containerName] or [recovery.destinationPath] + + - it: should fail with invalid target when backups are enabled + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + target: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected [backups.target] to be one of [primary, prefer-standby], but got [invalid] + + - it: should fail with invalid retentionPolicy when backups are enabled + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + target: primary + retentionPolicy: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Backup - Expected [backups.retentionPolicy] to match regex [^[1-9][0-9]*[dwm]$], got [invalid] + + - it: should fail with missing destinationPath and google bucket on backups + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: google + target: primary + retentionPolicy: 1d + google: + applicationCredentials: some-credentials + asserts: + - failedTemplate: + errorMessage: CNPG Backup - You need to specify [backups.google.bucket] or [backups.destinationPath] + + - it: should fail with missing destinationPath and s3 bucket on backups + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: s3 + target: primary + retentionPolicy: 1d + s3: + accessKey: some-access-key + secretKey: some-secret-key + asserts: + - failedTemplate: + errorMessage: CNPG Backup - You need to specify [backups.s3.bucket] or [backups.destinationPath] + + - it: should fail with missing endpointURL and s3 region on backups + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: s3 + target: primary + retentionPolicy: 1d + s3: + accessKey: some-access-key + secretKey: some-secret-key + bucket: some-bucket + asserts: + - failedTemplate: + errorMessage: CNPG Backup - You need to specify [backups.s3.region] or [backups.endpointURL] + + - it: should fail with missing destinationPath and azure storageAccount on backups + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + target: primary + retentionPolicy: 1d + azure: + connectionString: some-connection-string + asserts: + - failedTemplate: + errorMessage: CNPG Backup - You need to specify [backups.azure.storageAccount] or [backups.destinationPath] + + - it: should fail with missing destinationPath and azure serviceName on backups + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + target: primary + retentionPolicy: 1d + azure: + connectionString: some-connection-string + storageAccount: some-storage-account + asserts: + - failedTemplate: + errorMessage: CNPG Backup - You need to specify [backups.azure.serviceName] or [backups.destinationPath] + + - it: should fail with missing destinationPath and azure containerName on backups + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + target: primary + retentionPolicy: 1d + azure: + connectionString: some-connection-string + storageAccount: some-storage-account + serviceName: some-service-name + asserts: + - failedTemplate: + errorMessage: CNPG Backup - You need to specify [backups.azure.containerName] or [backups.destinationPath] diff --git a/library/common-test/tests/cnpg/credentials_test.yaml b/library/common-test/tests/cnpg/credentials_test.yaml new file mode 100644 index 00000000..82637038 --- /dev/null +++ b/library/common-test/tests/cnpg/credentials_test.yaml @@ -0,0 +1,151 @@ +suite: cnpg credentials test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct secret + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: &secretDoc 3 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: type + value: kubernetes.io/basic-auth + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-user + - documentIndex: *secretDoc + equal: + path: stringData.username + value: test-user + - documentIndex: *secretDoc + matchRegex: + path: stringData.password + pattern: ^[a-zA-Z0-9]{62}$ + + - documentIndex: &secretDoc 2 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-urls + - documentIndex: *secretDoc + isSubset: + path: stringData + content: + porthost: test-release-name-common-test-cnpg-my-pg-rw:5432 + host: test-release-name-common-test-cnpg-my-pg-rw + jdbc: jdbc:postgresql://test-release-name-common-test-cnpg-my-pg-rw:5432/test-db + - documentIndex: *secretDoc + matchRegex: + path: stringData.std + pattern: postgresql://test-user:[a-zA-Z0-9]{62}@test-release-name-common-test-cnpg-my-pg-rw:5432/test-db + - documentIndex: *secretDoc + matchRegex: + path: stringData.nossl + pattern: postgresql://test-user:[a-zA-Z0-9]{62}@test-release-name-common-test-cnpg-my-pg-rw:5432/test-db\?sslmode=disable + + - it: should generate correct secret with ro pooler + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + pooler: + createRO: true + asserts: + - documentIndex: &secretDoc 3 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-urls + - documentIndex: *secretDoc + isSubset: + path: stringData + content: + porthost: test-release-name-common-test-cnpg-my-pg-rw:5432 + host: test-release-name-common-test-cnpg-my-pg-rw + jdbc: jdbc:postgresql://test-release-name-common-test-cnpg-my-pg-rw:5432/test-db + hostRO: test-release-name-common-test-cnpg-my-pg-ro + jdbcRO: jdbc:postgresql://test-release-name-common-test-cnpg-my-pg-ro:5432/test-db + porthostRO: test-release-name-common-test-cnpg-my-pg-ro:5432 + - documentIndex: *secretDoc + matchRegex: + path: stringData.std + pattern: postgresql://test-user:[a-zA-Z0-9]{62}@test-release-name-common-test-cnpg-my-pg-rw:5432/test-db + - documentIndex: *secretDoc + matchRegex: + path: stringData.nossl + pattern: postgresql://test-user:[a-zA-Z0-9]{62}@test-release-name-common-test-cnpg-my-pg-rw:5432/test-db\?sslmode=disable + - documentIndex: *secretDoc + matchRegex: + path: stringData.stdRO + pattern: postgresql://test-user:[a-zA-Z0-9]{62}@test-release-name-common-test-cnpg-my-pg-ro:5432/test-db + - documentIndex: *secretDoc + matchRegex: + path: stringData.nosslRO + pattern: postgresql://test-user:[a-zA-Z0-9]{62}@test-release-name-common-test-cnpg-my-pg-ro:5432/test-db\?sslmode=disable + + - it: should generate correct secret with password set + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + password: test-password + asserts: + - documentIndex: &secretDoc 3 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: type + value: kubernetes.io/basic-auth + - documentIndex: *secretDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-user + - documentIndex: *secretDoc + equal: + path: stringData.username + value: test-user + - documentIndex: *secretDoc + equal: + path: stringData.password + value: test-password diff --git a/library/common-test/tests/cnpg/custom_conf_test.yaml b/library/common-test/tests/cnpg/custom_conf_test.yaml deleted file mode 100644 index dd6d0c5c..00000000 --- a/library/common-test/tests/cnpg/custom_conf_test.yaml +++ /dev/null @@ -1,35 +0,0 @@ -suite: cnpg custom conf test -templates: - - common.yaml -release: - name: test-release-name - namespace: test-release-namespace -tests: - - it: should pass with custom-conf - set: - operator: - verify: - enabled: false - cnpg: - main: - enabled: true - primary: true - user: app - database: app - postgresql: - key1: value1 - key2: '{{ printf "test-tpl" }}' - asserts: - - documentIndex: &clusterDoc 0 - isKind: - of: Cluster - - documentIndex: *clusterDoc - isAPIVersion: - of: postgresql.cnpg.io/v1 - - documentIndex: *clusterDoc - isSubset: - path: spec - content: - postgresql: - key1: value1 - key2: test-tpl diff --git a/library/common-test/tests/cnpg/pooler_metadata_test.yaml b/library/common-test/tests/cnpg/pooler_metadata_test.yaml new file mode 100644 index 00000000..e5dc21b7 --- /dev/null +++ b/library/common-test/tests/cnpg/pooler_metadata_test.yaml @@ -0,0 +1,178 @@ +suite: cnpg pooler metadata test +templates: + - common.yaml +chart: + appVersion: &appVer v9.9.9 +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should pass with cnpg pooler created with labels and annotations + set: + operator: + verify: + enabled: false + label1: label1 + label2: global_label2 + label3: label3 + annotation1: annotation1 + annotation2: global_annotation2 + annotation3: annotation3 + global: + labels: + g_label1: global_label1 + g_label2: "{{ .Values.label2 }}" + annotations: + g_annotation1: global_annotation1 + g_annotation2: "{{ .Values.annotation2 }}" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + labels: + label1: "{{ .Values.label1 }}" + label2: label2 + annotations: + annotation1: "{{ .Values.annotation1 }}" + annotation2: annotation2 + pooler: + labels: + label3: "{{ .Values.label3 }}" + annotations: + annotation3: "{{ .Values.annotation3 }}" + asserts: + - documentIndex: &poolerDoc 0 + isKind: + of: Pooler + - documentIndex: *poolerDoc + isSubset: + path: metadata.annotations + content: + annotation1: annotation1 + annotation2: annotation2 + annotation3: annotation3 + g_annotation1: global_annotation1 + g_annotation2: global_annotation2 + cnpg.io/hibernation: "off" + - documentIndex: *poolerDoc + matchRegex: + path: metadata.annotations.rollme + pattern: '^[0-9a-zA-Z]{5}$' + - documentIndex: *poolerDoc + equal: + path: metadata.labels + value: + app: common-test-1.0.0 + release: test-release-name + helm-revision: "0" + helm.sh/chart: common-test-1.0.0 + app.kubernetes.io/name: common-test + app.kubernetes.io/instance: test-release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: *appVer + cnpg.io/reload: "on" + g_label1: global_label1 + g_label2: global_label2 + label1: label1 + label2: label2 + label3: label3 + - documentIndex: *poolerDoc + equal: + path: metadata.namespace + value: test-release-namespace + + - it: should pass with cnpg pooler created with namespace + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + namespace: some-namespace + asserts: + - documentIndex: *poolerDoc + equal: + path: metadata.namespace + value: some-namespace + + - it: should pass with cnpg pooler created with object namespace from tpl + set: + operator: + verify: + enabled: false + key: some-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + namespace: "{{ .Values.key }}" + asserts: + - documentIndex: *poolerDoc + equal: + path: metadata.namespace + value: some-namespace + + - it: should pass with cnpg pooler created with namespace from global with tpl + set: + operator: + verify: + enabled: false + key: global-namespace + global: + namespace: "{{ .Values.key }}" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: *poolerDoc + equal: + path: metadata.namespace + value: global-namespace + + - it: should pass with cnpg pooler created with namespace from root with tpl + set: + operator: + verify: + enabled: false + key: local-namespace + namespace: "{{ .Values.key }}" + global: + namespace: global-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: *poolerDoc + equal: + path: metadata.namespace + value: local-namespace + + - it: should pass with cnpg pooler created with namespace in TrueNAS SCALE + set: + operator: + verify: + enabled: false + global: + ixChartContext: + iAmNotEmpty: true + storageClassName: some-storage-class + namespace: ix-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + asserts: + - documentIndex: *poolerDoc + equal: + path: metadata.namespace + value: ix-namespace diff --git a/library/common-test/tests/cnpg/pooler_name_test.yaml b/library/common-test/tests/cnpg/pooler_name_test.yaml new file mode 100644 index 00000000..502295f8 --- /dev/null +++ b/library/common-test/tests/cnpg/pooler_name_test.yaml @@ -0,0 +1,54 @@ +suite: cnpg pooler name test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct name + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + my-pg2: + enabled: true + user: test-user + database: test-db + pooler: + createRO: true + asserts: + - documentIndex: &poolerDoc 0 + isKind: + of: Pooler + - documentIndex: *poolerDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *poolerDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-pooler-rw + - documentIndex: &otherpoolerDoc 2 + isKind: + of: Pooler + - documentIndex: *otherpoolerDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *otherpoolerDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg2-pooler-rw + - documentIndex: &otherpoolerDoc 3 + isKind: + of: Pooler + - documentIndex: *otherpoolerDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *otherpoolerDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg2-pooler-ro diff --git a/library/common-test/tests/cnpg/pooler_spec_test.yaml b/library/common-test/tests/cnpg/pooler_spec_test.yaml new file mode 100644 index 00000000..8ec230df --- /dev/null +++ b/library/common-test/tests/cnpg/pooler_spec_test.yaml @@ -0,0 +1,96 @@ +suite: cnpg pooler spec test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct spec + set: + param: someValue + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + my-pg2: + enabled: true + user: test-user + database: test-db + pooler: + createRO: true + poolMode: transaction + instances: 1 + parameters: + some: value + someOther: "{{ .Values.param }}" + asserts: + - documentIndex: &poolerDoc 0 + isKind: + of: Pooler + - documentIndex: *poolerDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *poolerDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-pooler-rw + - documentIndex: *poolerDoc + equal: + path: spec + value: + cluster: + name: test-release-name-common-test-cnpg-my-pg + instances: 2 + type: rw + pgbouncer: + poolMode: session + - documentIndex: &otherpoolerDoc 2 + isKind: + of: Pooler + - documentIndex: *otherpoolerDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *otherpoolerDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg2-pooler-rw + - documentIndex: *otherpoolerDoc + equal: + path: spec + value: + cluster: + name: test-release-name-common-test-cnpg-my-pg2 + instances: 1 + type: rw + pgbouncer: + poolMode: transaction + parameters: + some: value + someOther: someValue + - documentIndex: &otherpoolerDoc 3 + isKind: + of: Pooler + - documentIndex: *otherpoolerDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *otherpoolerDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg2-pooler-ro + - documentIndex: *otherpoolerDoc + equal: + path: spec + value: + cluster: + name: test-release-name-common-test-cnpg-my-pg2 + instances: 1 + type: ro + pgbouncer: + poolMode: transaction + parameters: + some: value + someOther: someValue diff --git a/library/common-test/tests/cnpg/pooler_validation_test.yaml b/library/common-test/tests/cnpg/pooler_validation_test.yaml new file mode 100644 index 00000000..57ad4fee --- /dev/null +++ b/library/common-test/tests/cnpg/pooler_validation_test.yaml @@ -0,0 +1,22 @@ +suite: cnpg pooler validation test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should fail with invalid poolMode + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + pooler: + poolMode: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Pooler - Expected [poolMode] to be one of [session, transaction], but got [invalid] diff --git a/library/common-test/tests/cnpg/recovery_configmap_test.yaml b/library/common-test/tests/cnpg/recovery_configmap_test.yaml new file mode 100644 index 00000000..4fb70422 --- /dev/null +++ b/library/common-test/tests/cnpg/recovery_configmap_test.yaml @@ -0,0 +1,33 @@ +suite: cnpg recovery configmap test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should create configmap with recovery string when forceRecovery is enabled + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + forceRecovery: true + user: test-user + database: test-db + asserts: + - documentIndex: &configMapDoc 2 + isKind: + of: ConfigMap + - documentIndex: *configMapDoc + isAPIVersion: + of: v1 + - documentIndex: *configMapDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-recovery-string + - documentIndex: *configMapDoc + matchRegex: + path: data.recovery-string + pattern: ^[a-zA-Z0-9]{5}$ diff --git a/library/common-test/tests/cnpg/scheduled_backup_metadata_test.yaml b/library/common-test/tests/cnpg/scheduled_backup_metadata_test.yaml new file mode 100644 index 00000000..cf8ded65 --- /dev/null +++ b/library/common-test/tests/cnpg/scheduled_backup_metadata_test.yaml @@ -0,0 +1,254 @@ +suite: cnpg scheduled backup metadata test +templates: + - common.yaml +chart: + appVersion: &appVer v9.9.9 +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should pass with cnpg scheduledBackup backup created with labels and annotations + set: + operator: + verify: + enabled: false + label1: label1 + label2: global_label2 + label3: label3 + annotation1: annotation1 + annotation2: global_annotation2 + annotation3: annotation3 + global: + labels: + g_label1: global_label1 + g_label2: "{{ .Values.label2 }}" + annotations: + g_annotation1: global_annotation1 + g_annotation2: "{{ .Values.annotation2 }}" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + labels: + label1: "{{ .Values.label1 }}" + label2: label2 + annotations: + annotation1: "{{ .Values.annotation1 }}" + annotation2: annotation2 + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + labels: + label5: label5 + annotations: + annotation5: annotation5 + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + backupOwnerReference: self + labels: + label3: "{{ .Values.label3 }}" + label4: label4 + annotations: + annotation3: "{{ .Values.annotation3 }}" + annotation4: annotation4 + asserts: + - documentIndex: &backupDoc 0 + isKind: + of: ScheduledBackup + - documentIndex: *backupDoc + equal: + path: metadata.annotations + value: + annotation1: annotation1 + annotation2: annotation2 + annotation3: annotation3 + annotation4: annotation4 + annotation5: annotation5 + g_annotation1: global_annotation1 + g_annotation2: global_annotation2 + - documentIndex: *backupDoc + equal: + path: metadata.labels + value: + app: common-test-1.0.0 + release: test-release-name + helm-revision: "0" + helm.sh/chart: common-test-1.0.0 + app.kubernetes.io/name: common-test + app.kubernetes.io/instance: test-release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: *appVer + cnpg.io/cluster: test-release-name-common-test-cnpg-my-pg + g_label1: global_label1 + g_label2: global_label2 + label1: label1 + label2: label2 + label3: label3 + label4: label4 + label5: label5 + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: test-release-namespace + + - it: should pass with cnpg scheduledBackup backup created with namespace + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + namespace: some-namespace + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + backupOwnerReference: self + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: some-namespace + + - it: should pass with cnpg scheduledBackup backup created with object namespace from tpl + set: + operator: + verify: + enabled: false + key: some-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + namespace: "{{ .Values.key }}" + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + backupOwnerReference: self + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: some-namespace + + - it: should pass with cnpg scheduledBackup backup created with namespace from global with tpl + set: + operator: + verify: + enabled: false + key: global-namespace + global: + namespace: "{{ .Values.key }}" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + backupOwnerReference: self + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: global-namespace + + - it: should pass with cnpg scheduledBackup backup created with namespace from root with tpl + set: + operator: + verify: + enabled: false + key: local-namespace + namespace: "{{ .Values.key }}" + global: + namespace: global-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + backupOwnerReference: self + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: local-namespace + + - it: should pass with cnpg scheduledBackup backup created with namespace in TrueNAS SCALE + set: + operator: + verify: + enabled: false + global: + ixChartContext: + iAmNotEmpty: true + storageClassName: some-storage-class + namespace: ix-namespace + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + backupOwnerReference: self + asserts: + - documentIndex: *backupDoc + equal: + path: metadata.namespace + value: ix-namespace diff --git a/library/common-test/tests/cnpg/scheduled_backup_name_test.yaml b/library/common-test/tests/cnpg/scheduled_backup_name_test.yaml new file mode 100644 index 00000000..9110ae44 --- /dev/null +++ b/library/common-test/tests/cnpg/scheduled_backup_name_test.yaml @@ -0,0 +1,66 @@ +suite: cnpg scheduled backup name test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct name + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + backupOwnerReference: self + my-pg2: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: weekly + schedule: "0 0 * * 0" + backupOwnerReference: self + asserts: + - documentIndex: &backupDoc 0 + isKind: + of: ScheduledBackup + - documentIndex: *backupDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *backupDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-sched-backup-daily + - documentIndex: &otherbackupDoc 3 + isKind: + of: ScheduledBackup + - documentIndex: *otherbackupDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *otherbackupDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg2-sched-backup-weekly diff --git a/library/common-test/tests/cnpg/scheduled_backup_spec_test.yaml b/library/common-test/tests/cnpg/scheduled_backup_spec_test.yaml new file mode 100644 index 00000000..92a93e4a --- /dev/null +++ b/library/common-test/tests/cnpg/scheduled_backup_spec_test.yaml @@ -0,0 +1,74 @@ +suite: cnpg scheduled backup spec test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should generate correct spec + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + suspend: true + - name: weekly + schedule: "0 0 * * 0" + immediate: true + backupOwnerReference: cluster + asserts: + - documentIndex: &cnpgDoc 0 + isKind: + of: ScheduledBackup + - documentIndex: *cnpgDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *cnpgDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-sched-backup-daily + - documentIndex: *cnpgDoc + equal: + path: spec + value: + schedule: "0 0 * * *" + backupOwnerReference: none + suspend: true + immediate: false + cluster: + name: test-release-name-common-test-cnpg-my-pg + - documentIndex: &otherCnpgDoc 1 + isKind: + of: ScheduledBackup + - documentIndex: *otherCnpgDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *otherCnpgDoc + equal: + path: metadata.name + value: test-release-name-common-test-cnpg-my-pg-sched-backup-weekly + - documentIndex: *otherCnpgDoc + equal: + path: spec + value: + schedule: "0 0 * * 0" + backupOwnerReference: cluster + suspend: false + immediate: true + cluster: + name: test-release-name-common-test-cnpg-my-pg diff --git a/library/common-test/tests/cnpg/scheduled_backup_stop_test.yaml b/library/common-test/tests/cnpg/scheduled_backup_stop_test.yaml new file mode 100644 index 00000000..e828d926 --- /dev/null +++ b/library/common-test/tests/cnpg/scheduled_backup_stop_test.yaml @@ -0,0 +1,161 @@ +suite: cnpg scheduled backup stop test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should pass with hibernate + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + hibernate: true + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + suspend: false + backupOwnerReference: self + asserts: + - documentIndex: &backupDoc 0 + isKind: + of: ScheduledBackup + - documentIndex: *backupDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *backupDoc + equal: + path: spec.suspend + value: true + + - it: should set suspend on stopAll + set: + operator: + verify: + enabled: false + global: + stopAll: true + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + hibernate: false + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + suspend: false + backupOwnerReference: self + asserts: + - documentIndex: &backupDoc 0 + isKind: + of: ScheduledBackup + - documentIndex: *backupDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *backupDoc + equal: + path: spec.suspend + value: true + + - it: should set suspend on ixChartContext - isStopped (true) + set: + operator: + verify: + enabled: false + global: + namespace: ix-something + ixChartContext: + storageClassName: some-storage-class + isStopped: true + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + hibernate: false + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + suspend: false + backupOwnerReference: self + asserts: + - documentIndex: &backupDoc 0 + isKind: + of: ScheduledBackup + - documentIndex: *backupDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *backupDoc + equal: + path: spec.suspend + value: true + + - it: should not suspend on ixChartContext - isStopped (false) + set: + operator: + verify: + enabled: false + global: + namespace: ix-something + ixChartContext: + storageClassName: some-storage-class + isStopped: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + hibernate: false + backups: + enabled: true + target: primary + retentionPolicy: 10d + provider: azure + destinationPath: some-path + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + backupOwnerReference: self + asserts: + - documentIndex: &backupDoc 0 + isKind: + of: ScheduledBackup + - documentIndex: *backupDoc + isAPIVersion: + of: postgresql.cnpg.io/v1 + - documentIndex: *backupDoc + equal: + path: spec.suspend + value: false diff --git a/library/common-test/tests/cnpg/scheduled_backup_validation_test.yaml b/library/common-test/tests/cnpg/scheduled_backup_validation_test.yaml new file mode 100644 index 00000000..2bb53b11 --- /dev/null +++ b/library/common-test/tests/cnpg/scheduled_backup_validation_test.yaml @@ -0,0 +1,142 @@ +suite: cnpg scheduled backup validation test +templates: + - common.yaml +release: + name: test-release-name + namespace: test-release-namespace +tests: + - it: should fail without name in scheduledBackups backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + scheduledBackups: + - name: + asserts: + - failedTemplate: + errorMessage: CNPG Scheduled Backup - Expected non-empty [name] in [backups.scheduledBackups] entry + + - it: should fail without schedule in scheduledBackups backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + asserts: + - failedTemplate: + errorMessage: CNPG Scheduled Backup - Expected non-empty [schedule] in [backups.scheduledBackups] entry + + - it: should fail with invalid backupOwnerReference in scheduledBackups backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + scheduledBackups: + - name: daily + schedule: "0 0 * * *" + backupOwnerReference: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Scheduled Backup - Expected [backupOwnerReference] in [backups.scheduledBackups] entry to be one of [none, self, cluster], but got [invalid] + + - it: should fail with invalid name in scheduledBackups backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + scheduledBackups: + - name: _invalid + schedule: "0 0 * * *" + backupOwnerReference: self + asserts: + - failedTemplate: + errorMessage: Name [test-release-name-common-test-cnpg-my-pg-sched-backup-_invalid] is not valid. Must start and end with an alphanumeric lowercase character. It can contain '-'. And must be at most 253 characters. + + - it: should fail with suspend not a bool in scheduledBackups backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + scheduledBackups: + - name: _invalid + schedule: "0 0 * * *" + backupOwnerReference: self + suspend: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Scheduled Backup - Expected [suspend] in [backups.scheduledBackups] entry to be a boolean, but got [string] + + - it: should fail with immediate not a bool in scheduledBackups backup + set: + operator: + verify: + enabled: false + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + backups: + enabled: true + provider: azure + azure: + connectionString: some-connection-string + scheduledBackups: + - name: _invalid + schedule: "0 0 * * *" + backupOwnerReference: self + immediate: invalid + asserts: + - failedTemplate: + errorMessage: CNPG Scheduled Backup - Expected [immediate] in [backups.scheduledBackups] entry to be a boolean, but got [string] diff --git a/library/common-test/tests/cnpg/stop_test.yaml b/library/common-test/tests/cnpg/stop_test.yaml index a1a8c460..21e873c6 100644 --- a/library/common-test/tests/cnpg/stop_test.yaml +++ b/library/common-test/tests/cnpg/stop_test.yaml @@ -11,15 +11,14 @@ tests: verify: enabled: false cnpg: - main: + mypg: enabled: true - primary: true user: app database: app instances: 2 hibernate: true asserts: - - documentIndex: &clusterDoc 0 + - documentIndex: &clusterDoc 1 isKind: of: Cluster - documentIndex: *clusterDoc @@ -30,7 +29,7 @@ tests: path: metadata.annotations content: cnpg.io/hibernation: "on" - - documentIndex: &poolerDoc 1 + - documentIndex: &poolerDoc 0 isKind: of: Pooler - documentIndex: *poolerDoc @@ -50,15 +49,14 @@ tests: global: stopAll: true cnpg: - main: + mypg: enabled: true - primary: true user: app database: app hibernate: false instances: 2 asserts: - - documentIndex: &clusterDoc 0 + - documentIndex: *clusterDoc isKind: of: Cluster - documentIndex: *clusterDoc @@ -69,7 +67,7 @@ tests: path: metadata.annotations content: cnpg.io/hibernation: "on" - - documentIndex: &poolerDoc 1 + - documentIndex: *poolerDoc isKind: of: Pooler - documentIndex: *poolerDoc @@ -92,15 +90,14 @@ tests: storageClassName: some-storage-class isStopped: true cnpg: - main: + mypg: enabled: true - primary: true user: app database: app hibernate: false instances: 2 asserts: - - documentIndex: &clusterDoc 0 + - documentIndex: *clusterDoc isKind: of: Cluster - documentIndex: *clusterDoc @@ -111,7 +108,7 @@ tests: path: metadata.annotations content: cnpg.io/hibernation: "on" - - documentIndex: &poolerDoc 1 + - documentIndex: *poolerDoc isKind: of: Pooler - documentIndex: *poolerDoc @@ -134,15 +131,14 @@ tests: storageClassName: some-storage-class isStopped: false cnpg: - main: + mypg: enabled: true - primary: true user: app database: app hibernate: false instances: 2 asserts: - - documentIndex: &clusterDoc 0 + - documentIndex: *clusterDoc isKind: of: Cluster - documentIndex: *clusterDoc @@ -153,7 +149,7 @@ tests: path: metadata.annotations content: cnpg.io/hibernation: "off" - - documentIndex: &poolerDoc 1 + - documentIndex: *poolerDoc isKind: of: Pooler - documentIndex: *poolerDoc diff --git a/library/common-test/tests/pod/restart_policy_test.yaml b/library/common-test/tests/pod/restart_policy_test.yaml index 632ae37b..0df775a2 100644 --- a/library/common-test/tests/pod/restart_policy_test.yaml +++ b/library/common-test/tests/pod/restart_policy_test.yaml @@ -108,7 +108,7 @@ tests: podSpec: {} asserts: - failedTemplate: - errorMessage: Expected .amazonaws.com" + endpointURL: "" # Leave empty if using the default S3 endpoint + # Overrides the provider specific default path. Defaults to: + # S3: s3:// + # Azure: https://..core.windows.net/ + # Google: gs:// + destinationPath: "" + provider: s3 # One of s3, azure, google + s3: + region: "" + bucket: "" + path: "/" + accessKey: "" + secretKey: "" + azure: + path: "/" + connectionString: "" + storageAccount: "" + storageKey: "" + storageSasToken: "" + containerName: "" + serviceName: blob + inheritFromAzureAD: false + google: + path: "/" + bucket: "" + gkeEnvironment: false + applicationCredentials: "" + + # Database cluster backup configuration + backups: + enabled: false # You need to configure backups manually, so backups are disabled by default. + + # Overrides the provider specific default endpoint. Defaults to: + # S3: https://s3..amazonaws.com" + endpointURL: "" # Leave empty if using the default S3 endpoint + + # Overrides the provider specific default path. Defaults to: + # S3: s3:// + # Azure: https://..core.windows.net/ + # Google: gs:// + destinationPath: "" + + provider: s3 + s3: + region: "" + bucket: "" + path: "/" + accessKey: "" + secretKey: "" + azure: + path: "/" + connectionString: "" + storageAccount: "" + storageKey: "" + storageSasToken: "" + containerName: "" + serviceName: blob + inheritFromAzureAD: false + google: + path: "/" + bucket: "" + gkeEnvironment: false + applicationCredentials: "" + + scheduledBackups: [] + # - name: daily-backup # Daily at midnight + # schedule: "0 0 0 * * *" # Daily at midnight + # backupOwnerReference: self + # immediate: false + # suspend: false + + retentionPolicy: "30d" + + # - Manual list of backups + manualBackups: [] + # - name: today + # labels: {} + # annotations: {} + # - name: beforeUpgrade + # labels: {} + # annotations: {} + + # Database cluster PgBouncer configuration + pooler: + # -- enable to create extra pgbouncer for readonly access + createRO: false + poolMode: session + # -- Gets scaled to 0 if hibernation is true + instances: 2 + # parameters: + # max_client_conn: "1000" + # default_pool_size: "25" + labels: {} + annotations: {} + + # -- contains credentials and urls output by generator creds: {} - # -- contains postgresql settings - # ref: https://cloudnative-pg.io/documentation/1.19/postgresql_conf/#the-postgresql-section - postgresql: {} + # -- Redis dependency configuration # @default -- See below redis: enabled: false - # -- can be used to make an easy accessable note which URLS to use to access the DB. + # -- can be used to make an easy accessible note which URLS to use to access the DB. creds: {} manifestManager: enabled: false