mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-09 22:13:18 +09:00
helm-unittest coverage for the S3 request-checksum fix (was mutation-negative before): assert spec.instanceSidecarConfiguration.env pins AWS_REQUEST_CHECKSUM_CALCULATION=when_required on all rendered barman-cloud ObjectStores — postgres backup + bootstrap-recovery (packages/apps/postgres/tests/backup_storage_test.yaml) and the Keycloak DB (new packages/system/keycloak/tests/db_backup_test.yaml). Verified by mutation: reverting the template change now fails these assertions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Andrey Kolkov <andrey.kolkov@aenix.io>
291 lines
9.8 KiB
YAML
291 lines
9.8 KiB
YAML
suite: backup storage flow (barman-cloud plugin gating, chart Secret, bootstrap guards)
|
|
|
|
# Locks in the conditional rendering on the cnpg.io Cluster, the barman-cloud
|
|
# ObjectStore CR, and the chart-managed <release>-s3-creds Secret:
|
|
# - the legacy flow wires spec.plugins + renders the ObjectStore + the Secret
|
|
# only when real S3 coordinates are present;
|
|
# - the platform useSystemBucket flow leaves them out (the CNPG backup
|
|
# driver SSA-patches spec.plugins + the ObjectStore at first BackupJob time);
|
|
# - bootstrap.recovery fails fast at render time when it would otherwise
|
|
# emit a dangling s3Credentials reference (useSystemBucket, or no creds).
|
|
# These are template-rendering contracts, so helm-unittest is the right tool.
|
|
|
|
templates:
|
|
- templates/db.yaml
|
|
- templates/backup-secret.yaml
|
|
|
|
release:
|
|
name: pg-test
|
|
namespace: tenant-test
|
|
|
|
set:
|
|
_cluster:
|
|
scheduling: {}
|
|
|
|
tests:
|
|
- it: "useSystemBucket=true: chart skips spec.plugins, ObjectStore and <release>-s3-creds"
|
|
set:
|
|
backup:
|
|
enabled: true
|
|
useSystemBucket: true
|
|
asserts:
|
|
- notExists:
|
|
path: spec.plugins
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
# No chart-rendered ObjectStore in the platform flow (the driver owns it):
|
|
# db.yaml emits only Cluster + WorkloadMonitor.
|
|
- hasDocuments:
|
|
count: 2
|
|
template: templates/db.yaml
|
|
- hasDocuments:
|
|
count: 0
|
|
template: templates/backup-secret.yaml
|
|
|
|
- it: "legacy backup with inline creds: wires spec.plugins + ObjectStore + <release>-s3-creds"
|
|
set:
|
|
backup:
|
|
enabled: true
|
|
useSystemBucket: false
|
|
s3AccessKey: AKIAEXAMPLE
|
|
s3SecretKey: s3cr3t
|
|
asserts:
|
|
# The Cluster references the barman-cloud plugin, not native barmanObjectStore.
|
|
- notExists:
|
|
path: spec.backup.barmanObjectStore
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
- equal:
|
|
path: spec.plugins[0].name
|
|
value: barman-cloud.cloudnative-pg.io
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
- equal:
|
|
path: spec.plugins[0].parameters.barmanObjectName
|
|
value: pg-test
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
# The WAL-archive S3 prefix is pinned explicitly to the release name and
|
|
# must never change on a live cluster (the driver preserves it).
|
|
- equal:
|
|
path: spec.plugins[0].parameters.serverName
|
|
value: pg-test
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
# The ObjectStore carries the S3 credentials reference.
|
|
- equal:
|
|
path: metadata.name
|
|
value: pg-test
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: ObjectStore
|
|
- equal:
|
|
path: spec.configuration.s3Credentials.accessKeyId.name
|
|
value: pg-test-s3-creds
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: ObjectStore
|
|
# The barman-cloud sidecar's S3 request checksum is pinned to when_required
|
|
# (non-AWS S3 gateways reject the botocore default flexible checksum).
|
|
- equal:
|
|
path: spec.instanceSidecarConfiguration.env[0].name
|
|
value: AWS_REQUEST_CHECKSUM_CALCULATION
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: ObjectStore
|
|
- equal:
|
|
path: spec.instanceSidecarConfiguration.env[0].value
|
|
value: when_required
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: ObjectStore
|
|
- hasDocuments:
|
|
count: 1
|
|
template: templates/backup-secret.yaml
|
|
- equal:
|
|
path: metadata.name
|
|
value: pg-test-s3-creds
|
|
template: templates/backup-secret.yaml
|
|
|
|
- it: "empty retentionPolicy is omitted from the ObjectStore (plugin CRD rejects \"\")"
|
|
# The barman-cloud ObjectStore CRD validates retentionPolicy against
|
|
# ^[1-9][0-9]*[dwm]$, so an explicit empty value must be omitted rather than
|
|
# rendered as retentionPolicy: "" (which the API server rejects).
|
|
set:
|
|
backup:
|
|
enabled: true
|
|
useSystemBucket: false
|
|
s3AccessKey: AKIAEXAMPLE
|
|
s3SecretKey: s3cr3t
|
|
retentionPolicy: ""
|
|
asserts:
|
|
- notExists:
|
|
path: spec.retentionPolicy
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: ObjectStore
|
|
|
|
- it: "backup enabled, no creds, useSystemBucket=false: plugin + ObjectStore not rendered"
|
|
set:
|
|
backup:
|
|
enabled: true
|
|
useSystemBucket: false
|
|
s3AccessKey: ""
|
|
s3SecretKey: ""
|
|
asserts:
|
|
- notExists:
|
|
path: spec.plugins
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
# No ObjectStore rendered: db.yaml emits only Cluster + WorkloadMonitor.
|
|
- hasDocuments:
|
|
count: 2
|
|
template: templates/db.yaml
|
|
- hasDocuments:
|
|
count: 0
|
|
template: templates/backup-secret.yaml
|
|
|
|
- it: "bootstrap recovery: externalClusters[].plugin + a -recovery ObjectStore (serverName on the plugin param, not the ObjectStore)"
|
|
set:
|
|
backup:
|
|
enabled: true
|
|
useSystemBucket: false
|
|
s3AccessKey: AKIAEXAMPLE
|
|
s3SecretKey: s3cr3t
|
|
destinationPath: s3://bucket/pg-test/
|
|
endpointURL: https://s3.example:9000
|
|
bootstrap:
|
|
enabled: true
|
|
oldName: old-pg
|
|
serverName: old-server
|
|
asserts:
|
|
# Recovery uses the barman-cloud plugin, not the removed externalClusters[].barmanObjectStore.
|
|
- notExists:
|
|
path: spec.externalClusters[0].barmanObjectStore
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
- equal:
|
|
path: spec.externalClusters[0].plugin.name
|
|
value: barman-cloud.cloudnative-pg.io
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
- equal:
|
|
path: spec.externalClusters[0].plugin.parameters.barmanObjectName
|
|
value: pg-test-recovery
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
# serverName rides on the plugin parameter...
|
|
- equal:
|
|
path: spec.externalClusters[0].plugin.parameters.serverName
|
|
value: old-server
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
# ...and the -recovery ObjectStore carries the source S3 config but MUST NOT set
|
|
# serverName inside spec.configuration (the plugin forbids it there).
|
|
- equal:
|
|
path: spec.configuration.destinationPath
|
|
value: s3://bucket/pg-test/
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: metadata.name
|
|
value: pg-test-recovery
|
|
- notExists:
|
|
path: spec.configuration.serverName
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: metadata.name
|
|
value: pg-test-recovery
|
|
# The non-AWS S3 request-checksum pin is applied to the recovery ObjectStore too.
|
|
- equal:
|
|
path: spec.instanceSidecarConfiguration.env[0].name
|
|
value: AWS_REQUEST_CHECKSUM_CALCULATION
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: metadata.name
|
|
value: pg-test-recovery
|
|
- equal:
|
|
path: spec.instanceSidecarConfiguration.env[0].value
|
|
value: when_required
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: metadata.name
|
|
value: pg-test-recovery
|
|
|
|
- it: "bootstrap recovery without serverName: plugin serverName defaults to oldName (native parity)"
|
|
# Native CNPG defaulted an absent serverName to the externalClusters entry
|
|
# name (= oldName); the barman-cloud plugin defaults it to the NEW cluster's
|
|
# name, which would read the wrong S3 prefix. The chart must therefore
|
|
# always emit serverName, defaulting to oldName.
|
|
set:
|
|
backup:
|
|
enabled: true
|
|
useSystemBucket: false
|
|
s3AccessKey: AKIAEXAMPLE
|
|
s3SecretKey: s3cr3t
|
|
destinationPath: s3://bucket/pg-test/
|
|
endpointURL: https://s3.example:9000
|
|
bootstrap:
|
|
enabled: true
|
|
oldName: old-pg
|
|
serverName: ""
|
|
asserts:
|
|
- equal:
|
|
path: spec.externalClusters[0].plugin.parameters.serverName
|
|
value: old-pg
|
|
template: templates/db.yaml
|
|
documentSelector:
|
|
path: kind
|
|
value: Cluster
|
|
|
|
- it: "bootstrap + useSystemBucket: render fails fast (lock in existing guard)"
|
|
template: templates/db.yaml
|
|
set:
|
|
backup:
|
|
useSystemBucket: true
|
|
bootstrap:
|
|
enabled: true
|
|
oldName: old
|
|
asserts:
|
|
- failedTemplate:
|
|
errorMessage: "postgres: bootstrap.enabled=true is incompatible with backup.useSystemBucket=true. Use a backups.cozystack.io/RestoreJob against the cozy-default BackupClass to restore from the system bucket; see docs/operations/backup-classes.md."
|
|
|
|
- it: "bootstrap without credentials: render fails fast"
|
|
template: templates/db.yaml
|
|
set:
|
|
backup:
|
|
enabled: false
|
|
useSystemBucket: false
|
|
s3AccessKey: ""
|
|
s3SecretKey: ""
|
|
bootstrap:
|
|
enabled: true
|
|
oldName: old
|
|
asserts:
|
|
- failedTemplate:
|
|
errorMessage: "postgres: bootstrap.enabled=true requires S3 credentials: set backup.s3AccessKey+backup.s3SecretKey, backup.s3CredentialsSecret.name, or backup.useSystemBucket=true (with a backups.cozystack.io/RestoreJob)."
|