From 53f0356754796ae918f3a6f128a6a448ef63b667 Mon Sep 17 00:00:00 2001 From: Nicolas Blondiau Date: Fri, 19 Jun 2026 19:15:52 +0200 Subject: [PATCH] feat(cnpg): add PostgreSQL 17 and 18 support - Add '17' and '18' to valid pgVersions in _validation.tpl - Add '17' and '18' to the pgVersion enum in schemas/cnpg/cnpg.json and regenerate docs/cnpg/index.md (the supported-version gate for consumers) - Reject type 'vectors' + pgVersion '18' with a clear message (pgvecto.rs has no PG18 build; superseded by VectorChord) instead of a cryptic image error - Add postgres17Image/postgres18Image (cloudnative-pg/postgresql 17.10, 18.4) - Add postgresPostgis17Image (postgis 17-3.5) and postgresPostgis18Image (postgis 18-3.6-standard-bookworm; plain 18-3.x tags are not published) - Add postgresVectors17Image (pgvecto.rs 17.5-v0.4.0) - Add postgresVectorchord17Image/18Image (vectorchord 17.9-1.1.1, 18.3-1.1.1) - Add unit tests for the new image selectors and the vectors/18 guard - Add cnpg-pg17, cnpg-pg18 and cnpg-pg18-postgis install fixtures + CI matrix entries - Update cluster_validation_test.yaml for the new valid versions - Bump common library chart version 30.0.0 -> 30.1.0 pgvecto.rs publishes no PG18 image (superseded by VectorChord), so postgresVectors18Image is intentionally omitted. All image digests were verified against the ghcr.io registry. --- .github/workflows/common-tests.yaml | 3 + .../common-test/ci/cnpg-pg17-values.yaml | 51 +++++++ .../ci/cnpg-pg18-postgis-values.yaml | 52 +++++++ .../common-test/ci/cnpg-pg18-values.yaml | 51 +++++++ .../tests/cnpg/cluster_spec_test.yaml | 131 ++++++++++++++++++ .../tests/cnpg/cluster_validation_test.yaml | 16 ++- charts/library/common/Chart.yaml | 2 +- charts/library/common/docs/cnpg/index.md | 2 +- charts/library/common/schemas/cnpg/cnpg.json | 4 +- .../lib/cnpg/cluster/_validation.tpl | 7 +- charts/library/common/values.yaml | 37 +++++ 11 files changed, 351 insertions(+), 5 deletions(-) create mode 100644 charts/library/common-test/ci/cnpg-pg17-values.yaml create mode 100644 charts/library/common-test/ci/cnpg-pg18-postgis-values.yaml create mode 100644 charts/library/common-test/ci/cnpg-pg18-values.yaml diff --git a/.github/workflows/common-tests.yaml b/.github/workflows/common-tests.yaml index 03c85493cfbb7..f359ff899de43 100644 --- a/.github/workflows/common-tests.yaml +++ b/.github/workflows/common-tests.yaml @@ -214,6 +214,9 @@ jobs: - metrics-values.yaml - cnpg-values.yaml - cnpg-multi-values.yaml + - cnpg-pg17-values.yaml + - cnpg-pg18-values.yaml + - cnpg-pg18-postgis-values.yaml - register-operator-values.yaml ## TODO: reenable when we've some credentials ready to rock for testing # - volsync-dest-values.yaml diff --git a/charts/library/common-test/ci/cnpg-pg17-values.yaml b/charts/library/common-test/ci/cnpg-pg17-values.yaml new file mode 100644 index 0000000000000..315cc5cff54eb --- /dev/null +++ b/charts/library/common-test/ci/cnpg-pg17-values.yaml @@ -0,0 +1,51 @@ +service: + main: + enabled: true + ports: + main: + enabled: true + port: 8080 + +workload: + main: + enabled: true + podSpec: + containers: + main: + enabled: true + args: + - --port + - "8080" + probes: + liveness: + enabled: true + readiness: + enabled: true + startup: + enabled: true + +cnpg: + main: + enabled: true + # -- exercise PostgreSQL 17 (postgres17Image) + pgVersion: 17 + # -- number of instances for both postgres and pgbouncer + instances: 2 + database: "app" + user: "app" + password: test-password + # -- change to supervised to disable unsupervised updates + primaryUpdateStrategy: unsupervised + # -- storage size for the two pvc's per instance + storage: + size: "256Gi" + walsize: "256Gi" + pooler: + # -- enable to create extra pgbouncer for readonly access + createRO: false + instances: 2 + # -- set to enable prometheus metrics + monitoring: + enablePodMonitor: false + # -- contains credentials and urls output by generator + creds: {} diff --git a/charts/library/common-test/ci/cnpg-pg18-postgis-values.yaml b/charts/library/common-test/ci/cnpg-pg18-postgis-values.yaml new file mode 100644 index 0000000000000..e5c26474c16db --- /dev/null +++ b/charts/library/common-test/ci/cnpg-pg18-postgis-values.yaml @@ -0,0 +1,52 @@ +service: + main: + enabled: true + ports: + main: + enabled: true + port: 8080 + +workload: + main: + enabled: true + podSpec: + containers: + main: + enabled: true + args: + - --port + - "8080" + probes: + liveness: + enabled: true + readiness: + enabled: true + startup: + enabled: true + +cnpg: + main: + enabled: true + # -- exercise PostGIS on PostgreSQL 18 (postgresPostgis18Image) + type: postgis + pgVersion: 18 + # -- number of instances for both postgres and pgbouncer + instances: 2 + database: "app" + user: "app" + password: test-password + # -- change to supervised to disable unsupervised updates + primaryUpdateStrategy: unsupervised + # -- storage size for the two pvc's per instance + storage: + size: "256Gi" + walsize: "256Gi" + pooler: + # -- enable to create extra pgbouncer for readonly access + createRO: false + instances: 2 + # -- set to enable prometheus metrics + monitoring: + enablePodMonitor: false + # -- contains credentials and urls output by generator + creds: {} diff --git a/charts/library/common-test/ci/cnpg-pg18-values.yaml b/charts/library/common-test/ci/cnpg-pg18-values.yaml new file mode 100644 index 0000000000000..ddf41cfa17640 --- /dev/null +++ b/charts/library/common-test/ci/cnpg-pg18-values.yaml @@ -0,0 +1,51 @@ +service: + main: + enabled: true + ports: + main: + enabled: true + port: 8080 + +workload: + main: + enabled: true + podSpec: + containers: + main: + enabled: true + args: + - --port + - "8080" + probes: + liveness: + enabled: true + readiness: + enabled: true + startup: + enabled: true + +cnpg: + main: + enabled: true + # -- exercise PostgreSQL 18 (postgres18Image) + pgVersion: 18 + # -- number of instances for both postgres and pgbouncer + instances: 2 + database: "app" + user: "app" + password: test-password + # -- change to supervised to disable unsupervised updates + primaryUpdateStrategy: unsupervised + # -- storage size for the two pvc's per instance + storage: + size: "256Gi" + walsize: "256Gi" + pooler: + # -- enable to create extra pgbouncer for readonly access + createRO: false + instances: 2 + # -- set to enable prometheus metrics + monitoring: + enablePodMonitor: false + # -- contains credentials and urls output by generator + creds: {} diff --git a/charts/library/common-test/tests/cnpg/cluster_spec_test.yaml b/charts/library/common-test/tests/cnpg/cluster_spec_test.yaml index ccdf08f233e50..d250ca1dfc73f 100644 --- a/charts/library/common-test/tests/cnpg/cluster_spec_test.yaml +++ b/charts/library/common-test/tests/cnpg/cluster_spec_test.yaml @@ -248,6 +248,137 @@ tests: path: spec.imageName value: ghcr.io/cloudnative-pg/postgresql:15.6 + - it: should generate correct imageName for postgres pgVersion 17 + set: + postgres17Image: + repository: ghcr.io/cloudnative-pg/postgresql + tag: "17.10" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + password: test-password + pgVersion: 17 + asserts: + - documentIndex: *clusterDoc + equal: + path: spec.imageName + value: ghcr.io/cloudnative-pg/postgresql:17.10 + + - it: should generate correct imageName for postgres pgVersion 18 + set: + postgres18Image: + repository: ghcr.io/cloudnative-pg/postgresql + tag: "18.4" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + password: test-password + pgVersion: 18 + asserts: + - documentIndex: *clusterDoc + equal: + path: spec.imageName + value: ghcr.io/cloudnative-pg/postgresql:18.4 + + - it: should generate correct imageName for postgis pgVersion 17 + set: + postgresPostgis17Image: + repository: ghcr.io/cloudnative-pg/postgis + tag: "17-3.5" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + password: test-password + type: postgis + pgVersion: 17 + asserts: + - documentIndex: *clusterDoc + equal: + path: spec.imageName + value: ghcr.io/cloudnative-pg/postgis:17-3.5 + + - it: should generate correct imageName for postgis pgVersion 18 + set: + postgresPostgis18Image: + repository: ghcr.io/cloudnative-pg/postgis + tag: "18-3.6-standard-bookworm" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + password: test-password + type: postgis + pgVersion: 18 + asserts: + - documentIndex: *clusterDoc + equal: + path: spec.imageName + value: ghcr.io/cloudnative-pg/postgis:18-3.6-standard-bookworm + + - it: should generate correct imageName for vectors pgVersion 17 + set: + postgresVectors17Image: + repository: ghcr.io/tensorchord/cloudnative-pgvecto.rs + tag: "17.5-v0.4.0" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + password: test-password + type: vectors + pgVersion: 17 + asserts: + - documentIndex: *clusterDoc + equal: + path: spec.imageName + value: ghcr.io/tensorchord/cloudnative-pgvecto.rs:17.5-v0.4.0 + + - it: should generate correct imageName for vectorchord pgVersion 17 + set: + postgresVectorchord17Image: + repository: ghcr.io/tensorchord/cloudnative-vectorchord + tag: "17.9-1.1.1" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + password: test-password + type: vectorchord + pgVersion: 17 + asserts: + - documentIndex: *clusterDoc + equal: + path: spec.imageName + value: ghcr.io/tensorchord/cloudnative-vectorchord:17.9-1.1.1 + + - it: should generate correct imageName for vectorchord pgVersion 18 + set: + postgresVectorchord18Image: + repository: ghcr.io/tensorchord/cloudnative-vectorchord + tag: "18.3-1.1.1" + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + password: test-password + type: vectorchord + pgVersion: 18 + asserts: + - documentIndex: *clusterDoc + equal: + path: spec.imageName + value: ghcr.io/tensorchord/cloudnative-vectorchord:18.3-1.1.1 + - it: should override options set: ext1: some-extension diff --git a/charts/library/common-test/tests/cnpg/cluster_validation_test.yaml b/charts/library/common-test/tests/cnpg/cluster_validation_test.yaml index 8b648777b8824..bc7c5222c4515 100644 --- a/charts/library/common-test/tests/cnpg/cluster_validation_test.yaml +++ b/charts/library/common-test/tests/cnpg/cluster_validation_test.yaml @@ -49,7 +49,21 @@ tests: pgVersion: invalid asserts: - failedTemplate: - errorMessage: CNPG - Expected [pgVersion] to be one of [15, 16], but got [invalid] + errorMessage: CNPG - Expected [pgVersion] to be one of [15, 16, 17, 18], but got [invalid] + + - it: should fail with vectors on pgVersion 18 + set: + cnpg: + my-pg: + enabled: true + user: test-user + database: test-db + password: test-password + type: vectors + pgVersion: 18 + asserts: + - failedTemplate: + errorMessage: CNPG Cluster - type [vectors] is not available for pgVersion [18]; pgvecto.rs has been superseded by VectorChord, use type [vectorchord] instead - it: should fail with hibernate not a bool set: diff --git a/charts/library/common/Chart.yaml b/charts/library/common/Chart.yaml index 2e0445e2f4916..f532dd814d9e2 100644 --- a/charts/library/common/Chart.yaml +++ b/charts/library/common/Chart.yaml @@ -47,4 +47,4 @@ sources: - https://github.com/trueforge-org/truecharts/tree/master/charts/library/common - https://hub.docker.com/_/ type: library -version: 30.0.0 +version: 30.1.0 diff --git a/charts/library/common/docs/cnpg/index.md b/charts/library/common/docs/cnpg/index.md index 18b29128e88f1..79692df5f4343 100644 --- a/charts/library/common/docs/cnpg/index.md +++ b/charts/library/common/docs/cnpg/index.md @@ -255,7 +255,7 @@ Define a CNPG cluster | Required | ❌ | | Helm `tpl` | ❌ | | Default | `16` | -| Enum | `15`, `16` | +| Enum | `15`, `16`, `17`, `18` | Example diff --git a/charts/library/common/schemas/cnpg/cnpg.json b/charts/library/common/schemas/cnpg/cnpg.json index 16f9679d221ea..405c94a2c160b 100644 --- a/charts/library/common/schemas/cnpg/cnpg.json +++ b/charts/library/common/schemas/cnpg/cnpg.json @@ -76,7 +76,9 @@ "type": "integer", "enum": [ 15, - 16 + 16, + 17, + 18 ], "description": "Define a CNPG cluster", "default": 16 diff --git a/charts/library/common/templates/lib/cnpg/cluster/_validation.tpl b/charts/library/common/templates/lib/cnpg/cluster/_validation.tpl index eac1e3342dc9d..615bd3251f46f 100644 --- a/charts/library/common/templates/lib/cnpg/cluster/_validation.tpl +++ b/charts/library/common/templates/lib/cnpg/cluster/_validation.tpl @@ -14,7 +14,7 @@ {{- fail (printf "CNPG - Expected [pgVersion] to be a string, but got [%s]" (kindOf $objectData.pgVersion)) -}} {{- end -}} - {{- $validVersions := (list "15" "16") -}} + {{- $validVersions := (list "15" "16" "17" "18") -}} {{- if not (mustHas $objectData.pgVersion $validVersions) -}} {{- fail (printf "CNPG - Expected [pgVersion] to be one of [%s], but got [%s]" (join ", " $validVersions) $objectData.pgVersion) -}} {{- end -}} @@ -45,6 +45,11 @@ {{- end -}} {{- end -}} + {{/* pgvecto.rs (type vectors) publishes no PostgreSQL 18 image; it is superseded by VectorChord */}} + {{- if and (eq ($objectData.type | default "postgres") "vectors") (eq ($objectData.pgVersion | toString) "18") -}} + {{- fail "CNPG Cluster - type [vectors] is not available for pgVersion [18]; pgvecto.rs has been superseded by VectorChord, use type [vectorchord] instead" -}} + {{- end -}} + {{- if (hasKey $objectData "cluster") -}} {{- if (hasKey $objectData.cluster "logLevel") -}} {{- $validLevels := (list "error" "warning" "info" "debug" "trace") -}} diff --git a/charts/library/common/values.yaml b/charts/library/common/values.yaml index fb810977e6a24..814085b9dec91 100644 --- a/charts/library/common/values.yaml +++ b/charts/library/common/values.yaml @@ -674,6 +674,16 @@ postgres16Image: tag: "16.13@sha256:2bc26604d2f0650f9b98668a51a95679c02024860d512ace92e7fcf69da7d611" pullPolicy: IfNotPresent +postgres17Image: + repository: ghcr.io/cloudnative-pg/postgresql + tag: "17.10@sha256:e62489a417c64e6d679baffae21a129d196ba44f1362bb109ae84e304396e6ac" + pullPolicy: IfNotPresent + +postgres18Image: + repository: ghcr.io/cloudnative-pg/postgresql + tag: "18.4@sha256:c4d03ff9119154edbdae8879313cdf0aa5143a26e7ae400ca3ebe22dfc680a73" + pullPolicy: IfNotPresent + postgresPostgis15Image: repository: ghcr.io/cloudnative-pg/postgis tag: "15-3.4@sha256:4596b193991cd2463a07d40e3d3d62c59f046a7dece8f163ad1aba15925a38e4" @@ -684,6 +694,18 @@ postgresPostgis16Image: tag: "16-3.4@sha256:bb5a8590a8c934767482e34e1d103253f412aec703b77bbc52ad9044bf6e56f9" pullPolicy: IfNotPresent +postgresPostgis17Image: + repository: ghcr.io/cloudnative-pg/postgis + tag: "17-3.5@sha256:4db9bca5c2ce024ccf297ce3ce879d1d93a936149badae045c1fd77c7c9adc08" + pullPolicy: IfNotPresent + +# PostGIS 18 is only published under the new "---" tag scheme; +# no plain "18-3.x" tag exists upstream (unlike the 15-17 entries above). +postgresPostgis18Image: + repository: ghcr.io/cloudnative-pg/postgis + tag: "18-3.6-standard-bookworm@sha256:18dc2130a6f9350fa3bdc9e6d31bfa9b5b4d6aad0fc18c6125ec351ce5a1baee" + pullPolicy: IfNotPresent + postgresVectors15Image: repository: ghcr.io/tensorchord/cloudnative-pgvecto.rs tag: "15.7-v0.2.1@sha256:dbdeddf0d635f76df41f745407816c87c7468df35e3b7b0665ca4e0500ff3048" @@ -694,6 +716,11 @@ postgresVectors16Image: tag: "16.3-v0.2.1@sha256:f1a19d4fc4073b0671a72ad34ef012aa20d21b3ddf5b4b0c9077d54450db679a" pullPolicy: IfNotPresent +postgresVectors17Image: + repository: ghcr.io/tensorchord/cloudnative-pgvecto.rs + tag: "17.5-v0.4.0@sha256:cfa59ddef46bf642e3f6be9ad1878317ae5d4015707d02349bf1569d76b564e0" + pullPolicy: IfNotPresent + postgresVectorchord15Image: repository: ghcr.io/tensorchord/cloudnative-vectorchord tag: "15.14-0.5.3@sha256:1978732dc1e7e9ef94b9e806a094fcb123afab1e50a7e878e2d29de8b849cf47" @@ -704,6 +731,16 @@ postgresVectorchord16Image: tag: "16.10-0.5.3@sha256:a0776b514bb23858d8aa59b08587223f8b449bba1b278ffbcf85e097d6504eb0" pullPolicy: IfNotPresent +postgresVectorchord17Image: + repository: ghcr.io/tensorchord/cloudnative-vectorchord + tag: "17.9-1.1.1@sha256:82f9b46c9149681f2897bd221772a3b22a74784256f1154c91eb10c6785800d5" + pullPolicy: IfNotPresent + +postgresVectorchord18Image: + repository: ghcr.io/tensorchord/cloudnative-vectorchord + tag: "18.3-1.1.1@sha256:392b53675b403d6a2c72b673cc488a7c272514755dd818c622fb9ce4665193c4" + pullPolicy: IfNotPresent + # -- Configure the ingresses for the chart here. # Additional ingresses can be added by adding a dictionary key similar to the 'main' ingress. # @default -- See below