Files
e892b37565 feat(common): Add support for setting extra env to CNPG pods (#40673)
**Description**
<!--
Please include a summary of the change and which issue is fixed. Please
also include relevant motivation and context. List any dependencies that
are required for this change.
-->

This PR adds the ability to set extra environment variables to CNPG
pods.

I need this, as I need to set the `HTTP_PROXY`, `HTTPS_PROXY` and
`NO_PROXY` envs to the CNPG pods, so that backup/restore goes through my
Gluetun proxy.

This PR only adds support for CNPG, as with Volsync, this can be done by
setting environment variables on the Volsync controller itself (see
[release
notes](https://github.com/backube/volsync/blob/main/CHANGELOG.md#061)
for more info).

This PR, along with the other PRs I opened recently (#40000 , #40385,
#40523 , #40668) should be the last piece of the puzzle needed for
enabling backup/restore of clusters using a remote self-hosted S3
server.

⚒️ Fixes  # <!--(issue)-->

**⚙️ Type of change**

- [X] ⚙️ Feature/App addition
- [ ] 🪛 Bugfix
- [ ] ⚠️ Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] 🔃 Refactor of current code
- [ ] 📜 Documentation Changes

**🧪 How Has This Been Tested?**
<!--
Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration
-->

What I have tested:

- Rendered a chart with various combinations of CNPG envs set and looked
ad produced output
- Tested along with the other PRs (#40523, #40668) to verify backup up
to my S3 server works though the Gluetun proxy

**📃 Notes:**
<!-- Please enter any other relevant information here -->

Note that these changes should not affect any work related towards the
migration to the CNPG's new plugin-based barman. As per the [migration
guide](https://cloudnative-pg.io/plugin-barman-cloud/docs/migration/),
the required changes are primarily to export the keys under the
`barmanObjectStore` to a new CRD called `ObjectStore`. The `env` and
`envFrom` keys added in this PR are outside this dictionary; thus, they
should not require any changes when adding support for the new
plugin-based barman.

---

- [CNPG CRD for env and
envFrom](https://github.com/cloudnative-pg/cloudnative-pg/blob/main/config/crd/bases/postgresql.cnpg.io_clusters.yaml#L2161-L2368)

**✔️ Checklist:**

- [X] ⚖️ My code follows the style guidelines of this project
- [X] 👀 I have performed a self-review of my own code
- [X] #️⃣ I have commented my code, particularly in hard-to-understand
areas
- [ ] 📄 I have made changes to the documentation
- [X] 🧪 I have added tests to this description that prove my fix is
effective or that my feature works
- [X] ⬆️ I increased versions for any altered app according to semantic
versioning
- [X] I made sure the title starts with `feat(chart-name):`,
`fix(chart-name):`, `chore(chart-name):`, `docs(chart-name):` or
`fix(docs):`

** App addition**

If this PR is an app addition please make sure you have done the
following.

- [ ] 🖼️ 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._

---------

Signed-off-by: Kjeld Schouten <info@kjeldschouten.nl>
Co-authored-by: Kjeld Schouten <info@kjeldschouten.nl>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-18 00:05:25 +02:00

819 lines
24 KiB
YAML

suite: cnpg cluster spec test
templates:
- common.yaml
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should generate correct spec
set:
postgres16Image:
repository: ghcr.io/cloudnative-pg/postgresql
tag: "16.3"
pullPolicy: IfNotPresent
cnpg:
my-pg:
enabled: true
user: test-user
database: test-db
password: test-password
asserts:
- documentIndex: &clusterDoc 0
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
imageName: ghcr.io/cloudnative-pg/postgresql:16.3
primaryUpdateStrategy: unsupervised
primaryUpdateMethod: switchover
postgresUID: 26
postgresGID: 26
logLevel: info
instances: 2
nodeMaintenanceWindow:
reusePVC: true
inProgress: false
resources:
limits:
cpu: 1500m
memory: 2400Mi
requests:
cpu: 75m
memory: 200Mi
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: true
- it: should work with custom UID/GID
set:
postgres16Image:
repository: ghcr.io/cloudnative-pg/postgresql
tag: "16.3"
pullPolicy: IfNotPresent
cnpg:
my-pg:
enabled: true
user: test-user
database: test-db
password: test-password
cluster:
postgresUID: 666
postgresGID: 666
asserts:
- documentIndex: &clusterDoc 0
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
imageName: ghcr.io/cloudnative-pg/postgresql:16.3
postgresUID: 666
postgresGID: 666
primaryUpdateStrategy: unsupervised
primaryUpdateMethod: switchover
logLevel: info
instances: 2
nodeMaintenanceWindow:
reusePVC: true
inProgress: false
resources:
limits:
cpu: 1500m
memory: 2400Mi
requests:
cpu: 75m
memory: 200Mi
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: true
- it: should respect changed fallbackDefaults
set:
postgres15Image:
repository: ghcr.io/cloudnative-pg/postgresql
tag: "15.6"
global:
fallbackDefaults:
cnpg:
pgVersion: 15
vctAccessModes:
- ReadWriteMany
- ReadWriteOnce
cnpg:
my-pg:
enabled: true
user: test-user
database: test-db
password: test-password
asserts:
- documentIndex: *clusterDoc
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:
imageName: ghcr.io/cloudnative-pg/postgresql:15.6
storage:
pvcTemplate:
accessModes:
- ReadWriteMany
- ReadWriteOnce
resources:
requests:
storage: 100Gi
walStorage:
pvcTemplate:
accessModes:
- ReadWriteMany
- ReadWriteOnce
resources:
requests:
storage: 100Gi
- it: should generate correct imageName with changed type and pgVersion
set:
postgresVectors15Image:
repository: ghcr.io/tensorchord/cloudnative-pgvecto.rs
tag: "15.6-v0.2.1"
cnpg:
my-pg:
enabled: true
user: test-user
database: test-db
password: test-password
pgVersion: 15
type: vectors
asserts:
- documentIndex: *clusterDoc
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.imageName
value: ghcr.io/tensorchord/cloudnative-pgvecto.rs:15.6-v0.2.1
- it: should generate correct imageName with changed pgVersion
set:
postgres15Image:
repository: ghcr.io/cloudnative-pg/postgresql
tag: "15.6"
cnpg:
my-pg:
enabled: true
user: test-user
database: test-db
password: test-password
pgVersion: 15
asserts:
- documentIndex: *clusterDoc
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.imageName
value: ghcr.io/cloudnative-pg/postgresql:15.6
- it: should override options
set:
ext1: some-extension
ext2: some-other-extension
cnpg:
my-pg:
enabled: true
user: test-user
database: test-db
password: test-password
cluster:
enableSuperuserAccess: false
imageName: some-image
primaryUpdateStrategy: supervised
primaryUpdateMethod: restart
postgresUID: 26
postgresGID: 26
logLevel: debug
instances: 3
initdb:
dataChecksums: false
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
imageName: some-image
primaryUpdateStrategy: supervised
primaryUpdateMethod: restart
postgresUID: 26
postgresGID: 26
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: false
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:
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 20m
memory: 100Mi
cnpg:
my-pg:
enabled: true
user: test-user
database: test-db
password: test-password
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:
cnpg:
my-pg:
enabled: true
user: app
database: app
password: test-password
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:
postgresTimescaledb16Image:
repository: docker.io/timescale/timescaledb
tag: "some-tag"
cnpg:
my-pg:
enabled: true
user: app
database: app
password: test-password
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: true
postInitApplicationSQL:
- CREATE EXTENSION IF NOT EXISTS timescaledb;
- CREATE EXTENSION IF NOT EXISTS some-extension;
- it: should pass with postgis
set:
postgresPostgis16Image:
repository: docker.io/postgis/postgisdb
tag: "some-tag"
cnpg:
my-pg:
enabled: true
user: app
database: app
password: test-password
type: postgis
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
bootstrap:
initdb:
secret:
name: test-release-name-common-test-cnpg-my-pg-user
database: app
owner: app
dataChecksums: true
postInitApplicationSQL:
- CREATE EXTENSION IF NOT EXISTS postgis;
- CREATE EXTENSION IF NOT EXISTS postgis_topology;
- CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;
- CREATE EXTENSION IF NOT EXISTS postgis_tiger_geocoder;
- CREATE EXTENSION IF NOT EXISTS some-extension;
- it: should pass with vectors
set:
postgresVectors16Image:
repository: docker.io/vectors/vectors
tag: "some-tag"
cnpg:
my-pg:
enabled: true
user: app
database: app
password: test-password
type: vectors
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
- vectors.so
bootstrap:
initdb:
secret:
name: test-release-name-common-test-cnpg-my-pg-user
database: app
owner: app
dataChecksums: true
postInitApplicationSQL:
- CREATE EXTENSION IF NOT EXISTS vectors;
- CREATE EXTENSION IF NOT EXISTS some-extension;
- it: should pass with vectorchord
set:
postgresVectorchord16Image:
repository: docker.io/vectorchord/vectorchord
tag: "some-tag"
cnpg:
my-pg:
enabled: true
user: app
database: app
password: test-password
type: vectorchord
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
- vchord.so
bootstrap:
initdb:
secret:
name: test-release-name-common-test-cnpg-my-pg-user
database: app
owner: app
dataChecksums: true
postInitApplicationSQL:
- CREATE EXTENSION IF NOT EXISTS vchord CASCADE;
- CREATE EXTENSION IF NOT EXISTS some-extension;
- it: should pass with enabled monitoring
set:
postgresTimescaledb16Image:
repository: docker.io/timescale/timescaledb
tag: "some-tag"
cnpg:
my-pg:
enabled: true
user: app
database: app
password: test-password
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:
postgresTimescaledb16Image:
repository: docker.io/timescale/timescaledb
tag: "some-tag"
cnpg:
my-pg:
enabled: true
user: app
database: app
password: test-password
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
- it: should create the correct env with env key
set:
configmap:
configmap-name:
enabled: true
data:
key1: value1
key2: value2
secret:
secret-name:
enabled: true
data:
key1: value1
key2: value2
postgres16Image:
repository: ghcr.io/cloudnative-pg/postgresql
tag: "16.3"
pullPolicy: IfNotPresent
cnpg:
my-pg:
enabled: true
user: test-user
database: test-db
password: test-password
cluster:
env:
VAR1: some-value
VAR2:
configMapKeyRef:
name: configmap-name
key: key1
VAR3:
secretKeyRef:
name: secret-name
key: key2
asserts:
- documentIndex: *clusterDoc
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:
env:
- name: VAR1
value: some-value
- name: VAR2
valueFrom:
configMapKeyRef:
key: key1
name: test-release-name-common-test-configmap-name
- name: VAR3
valueFrom:
secretKeyRef:
key: key2
name: test-release-name-common-test-secret-name
- it: should create the correct env with envFrom key
set:
configmap:
configmap-name:
enabled: true
data:
key1: value1
key2: value2
secret:
secret-name:
enabled: true
data:
key3: value3
key4: value4
postgres16Image:
repository: ghcr.io/cloudnative-pg/postgresql
tag: "16.3"
pullPolicy: IfNotPresent
cnpg:
my-pg:
enabled: true
user: test-user
database: test-db
password: test-password
cluster:
envFrom:
- configMapRef:
name: configmap-name
- secretRef:
name: secret-name
asserts:
- documentIndex: *clusterDoc
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:
envFrom:
- configMapRef:
name: test-release-name-common-test-configmap-name
- secretRef:
name: test-release-name-common-test-secret-name