From 3118f67a36568bf26ffbf05bc049047e2a0f71c7 Mon Sep 17 00:00:00 2001 From: Philipp Hamann <84906475+pha91@users.noreply.github.com> Date: Tue, 7 Oct 2025 11:28:00 +0200 Subject: [PATCH 1/4] feat(plugins): add pluging including backup logic for barman cloud plugin Signed-off-by: Philipp Hamann <84906475+pha91@users.noreply.github.com> --- charts/cluster/README.md | 1 + charts/cluster/templates/_backup.tpl | 2 ++ charts/cluster/templates/_helpers.tpl | 16 ++++++++++++++ charts/cluster/templates/cluster.yaml | 4 ++++ charts/cluster/templates/objectStore.yaml | 22 +++++++++++++++++++ .../cluster/templates/scheduled-backups.yaml | 8 ++++++- ..._default_configuration_cluster-assert.yaml | 8 ++++++- .../01-non_default_configuration_cluster.yaml | 6 +++++ charts/cluster/values.schema.json | 21 ++++++++++++++++++ charts/cluster/values.yaml | 7 ++++++ 10 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 charts/cluster/templates/objectStore.yaml diff --git a/charts/cluster/README.md b/charts/cluster/README.md index 9af61a4475..260f82f99d 100644 --- a/charts/cluster/README.md +++ b/charts/cluster/README.md @@ -173,6 +173,7 @@ refer to the [CloudNativePG Documentation](https://cloudnative-pg.io/documentat | cluster.monitoring.podMonitor.relabelings | list | `[]` | The list of relabelings for the PodMonitor. Applied to samples before scraping. | | cluster.monitoring.prometheusRule.enabled | bool | `true` | Whether to enable the PrometheusRule automated alerts | | cluster.monitoring.prometheusRule.excludeRules | list | `[]` | Exclude specified rules | +| cluster.plugins | list | `[]` | The plugins configuration, containing any plugin to be loaded with the corresponding configuration | | cluster.postgresGID | int | `-1` | The GID of the postgres user inside the image, defaults to 26 | | cluster.postgresUID | int | `-1` | The UID of the postgres user inside the image, defaults to 26 | | cluster.postgresql.ldap | object | `{}` | PostgreSQL LDAP configuration (see https://cloudnative-pg.io/documentation/current/postgresql_conf/#ldap-configuration) | diff --git a/charts/cluster/templates/_backup.tpl b/charts/cluster/templates/_backup.tpl index 60270ea699..c690800417 100644 --- a/charts/cluster/templates/_backup.tpl +++ b/charts/cluster/templates/_backup.tpl @@ -2,6 +2,7 @@ {{- if .Values.backups.enabled }} backup: target: "prefer-standby" + {{ if (eq (include "cluster.useBarmanCloudPlugin" .) "false") }} retentionPolicy: {{ .Values.backups.retentionPolicy }} barmanObjectStore: wal: @@ -19,5 +20,6 @@ backup: {{- $d := dict "chartFullname" (include "cluster.fullname" .) "scope" .Values.backups "secretPrefix" "backup" }} {{- include "cluster.barmanObjectStoreConfig" $d | nindent 2 }} + {{- end}} {{- end }} {{- end }} diff --git a/charts/cluster/templates/_helpers.tpl b/charts/cluster/templates/_helpers.tpl index 2bae419493..23e923067c 100644 --- a/charts/cluster/templates/_helpers.tpl +++ b/charts/cluster/templates/_helpers.tpl @@ -144,3 +144,19 @@ Postgres GID {{- 26 -}} {{- end -}} {{- end -}} + + +{{/* +Check if barman-cloud plugin exists and is enabled +*/}} +{{- define "cluster.useBarmanCloudPlugin" -}} +{{- $hasPlugin := false }} +{{- if .Values.cluster.plugins }} + {{- range .Values.cluster.plugins }} + {{- if and (eq .name "barman-cloud.cloudnative-pg.io") .enabled }} + {{- $hasPlugin = true }} + {{- end }} + {{- end }} +{{- end }} +{{- $hasPlugin }} +{{- end }} diff --git a/charts/cluster/templates/cluster.yaml b/charts/cluster/templates/cluster.yaml index bb9ea770cc..a879584557 100644 --- a/charts/cluster/templates/cluster.yaml +++ b/charts/cluster/templates/cluster.yaml @@ -67,6 +67,10 @@ spec: name: {{ . }} {{ end }} enablePDB: {{ .Values.cluster.enablePDB }} + {{- with .Values.cluster.plugins }} + plugins: + {{- toYaml . | nindent 4}} + {{- end }} postgresql: {{- if or (eq .Values.type "timescaledb") (not (empty .Values.cluster.postgresql.shared_preload_libraries)) }} shared_preload_libraries: diff --git a/charts/cluster/templates/objectStore.yaml b/charts/cluster/templates/objectStore.yaml new file mode 100644 index 0000000000..4735215260 --- /dev/null +++ b/charts/cluster/templates/objectStore.yaml @@ -0,0 +1,22 @@ +{{ if and (eq (include "cluster.useBarmanCloudPlugin" .) "true") .Values.backups.enabled }} +apiVersion: barmancloud.cnpg.io/v1 +kind: ObjectStore +metadata: + name: {{ include "cluster.fullname" $ }}-object-store +spec: + configuration: + wal: + compression: {{ .Values.backups.wal.compression }} + {{- if .Values.backups.wal.encryption }} + encryption: {{ .Values.backups.wal.encryption }} + {{- end }} + maxParallel: {{ .Values.backups.wal.maxParallel }} + data: + compression: {{ .Values.backups.data.compression }} + {{- if .Values.backups.data.encryption }} + encryption: {{ .Values.backups.data.encryption }} + {{- end }} + jobs: {{ .Values.backups.data.jobs }} + {{- $d := dict "chartFullname" (include "cluster.fullname" .) "scope" .Values.backups "secretPrefix" "backup" -}} + {{- include "cluster.barmanObjectStoreConfig" $d | indent 2 }} +{{- end }} diff --git a/charts/cluster/templates/scheduled-backups.yaml b/charts/cluster/templates/scheduled-backups.yaml index 47a0717d69..ffaff03b95 100644 --- a/charts/cluster/templates/scheduled-backups.yaml +++ b/charts/cluster/templates/scheduled-backups.yaml @@ -11,9 +11,15 @@ metadata: spec: immediate: true schedule: {{ .schedule | quote }} - method: {{ .method }} backupOwnerReference: {{ .backupOwnerReference }} cluster: name: {{ include "cluster.fullname" $context }} +{{- if (eq (include "cluster.useBarmanCloudPlugin" $context ) "true") }} + pluginConfiguration: + name: barman-cloud.cloudnative-pg.io + method: plugin +{{ else }} + method: {{ .method }} +{{- end }} {{ end -}} {{ end }} diff --git a/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster-assert.yaml b/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster-assert.yaml index bc5cce7d10..e761847716 100644 --- a/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster-assert.yaml +++ b/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster-assert.yaml @@ -101,7 +101,13 @@ spec: memory: 256Mi limits: cpu: 100m - memory: 256Mi + memory: 256Mi + plugins: + - name: cnpg-i-plugin-example.my-org.io + enabled: true + parameters: + key1: value1 + key2: value2 priorityClassName: mega-high primaryUpdateStrategy: supervised primaryUpdateMethod: restart diff --git a/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster.yaml b/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster.yaml index 90f1a68b78..b052e7e29d 100644 --- a/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster.yaml +++ b/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster.yaml @@ -87,6 +87,12 @@ cluster: inRoles: - pg_monitor - pg_signal_backend + plugins: + - name: cnpg-i-plugin-example.my-org.io + enabled: true + parameters: + key1: value1 + key2: value2 postgresql: ldap: server: 'openldap.default.svc.cluster.local' diff --git a/charts/cluster/values.schema.json b/charts/cluster/values.schema.json index 8890226868..e5d01ac42e 100644 --- a/charts/cluster/values.schema.json +++ b/charts/cluster/values.schema.json @@ -262,6 +262,27 @@ } } }, + "plugins": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "isWALArchiver": { + "type": "boolean" + }, + "parameters": { + "type": "object" + } + }, + "required": ["name"] + } + }, "postgresGID": { "type": "integer" }, diff --git a/charts/cluster/values.yaml b/charts/cluster/values.yaml index 3d5f11dc1a..45045b7d0f 100644 --- a/charts/cluster/values.yaml +++ b/charts/cluster/values.yaml @@ -343,6 +343,13 @@ cluster: # - name: custom-queries-secret # key: custom-queries + plugins: [] + # - name: cnpg-i-plugin-example.my-org.io + # enabled: true + # parameters: + # key1: value1 + # key2: value2 + postgresql: # -- PostgreSQL configuration options (postgresql.conf) parameters: {} From 7782a6594e8d8490ce2ba20e7dd06abff7f10bd8 Mon Sep 17 00:00:00 2001 From: Philipp Hamann <84906475+pha91@users.noreply.github.com> Date: Wed, 8 Oct 2025 07:42:42 +0200 Subject: [PATCH 2/4] fix(test): remove trailing spaces Signed-off-by: Philipp Hamann <84906475+pha91@users.noreply.github.com> --- .../01-non_default_configuration_cluster-assert.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster-assert.yaml b/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster-assert.yaml index e761847716..929b33be02 100644 --- a/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster-assert.yaml +++ b/charts/cluster/test/postgresql-cluster-configuration/01-non_default_configuration_cluster-assert.yaml @@ -101,7 +101,7 @@ spec: memory: 256Mi limits: cpu: 100m - memory: 256Mi + memory: 256Mi plugins: - name: cnpg-i-plugin-example.my-org.io enabled: true From b24dec1938f70c4e9161bccafec07b95ac056663 Mon Sep 17 00:00:00 2001 From: Philipp Hamann <84906475+pha91@users.noreply.github.com> Date: Wed, 8 Oct 2025 09:04:59 +0200 Subject: [PATCH 3/4] feat(recovery): use plugin to recover cluster when plugin is enabled Signed-off-by: Philipp Hamann <84906475+pha91@users.noreply.github.com> --- charts/cluster/templates/_bootstrap.tpl | 20 +++++++++++++++----- charts/cluster/templates/objectStore.yaml | 11 ++++++++--- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/charts/cluster/templates/_bootstrap.tpl b/charts/cluster/templates/_bootstrap.tpl index 95bedd214f..bf6fe8efa7 100644 --- a/charts/cluster/templates/_bootstrap.tpl +++ b/charts/cluster/templates/_bootstrap.tpl @@ -86,16 +86,16 @@ externalClusters: recoveryTarget: targetTime: {{ . }} {{- end }} - {{ with .Values.recovery.database }} + {{- with .Values.recovery.database }} database: {{ . }} {{- end }} - {{ with .Values.recovery.owner }} + {{- with .Values.recovery.owner }} owner: {{ . }} {{- end }} {{- if eq .Values.recovery.method "backup" }} backup: name: {{ .Values.recovery.backupName }} - {{- else if eq .Values.recovery.method "object_store" }} + {{- else if and (eq .Values.recovery.method "object_store") (eq (include "cluster.useBarmanCloudPlugin" .) "false") }} source: objectStoreRecoveryCluster externalClusters: @@ -103,8 +103,18 @@ externalClusters: barmanObjectStore: serverName: {{ .Values.recovery.clusterName }} {{- $d := dict "chartFullname" (include "cluster.fullname" .) "scope" .Values.recovery "secretPrefix" "recovery" -}} - {{- include "cluster.barmanObjectStoreConfig" $d | nindent 4 }} - {{- end }} + {{- include "cluster.barmanObjectStoreConfig" $d | indent 4 }} + {{- else if and (eq .Values.recovery.method "object_store") (eq (include "cluster.useBarmanCloudPlugin" .) "true") }} + source: origin + +externalClusters: + - name: origin + plugin: + name: barman-cloud.cloudnative-pg.io + parameters: + barmanObjectName: {{ include "cluster.fullname" $ }}-object-store + serverName: {{ .Values.recovery.clusterName | default (include "cluster.fullname" .) }} +{{- end }} {{- end }} {{- else }} {{ fail "Invalid cluster mode!" }} diff --git a/charts/cluster/templates/objectStore.yaml b/charts/cluster/templates/objectStore.yaml index 4735215260..98f7455d63 100644 --- a/charts/cluster/templates/objectStore.yaml +++ b/charts/cluster/templates/objectStore.yaml @@ -1,10 +1,14 @@ -{{ if and (eq (include "cluster.useBarmanCloudPlugin" .) "true") .Values.backups.enabled }} +{{ if eq (include "cluster.useBarmanCloudPlugin" .) "true" }} apiVersion: barmancloud.cnpg.io/v1 kind: ObjectStore metadata: name: {{ include "cluster.fullname" $ }}-object-store spec: configuration: + {{- if and (eq .Values.mode "recovery") (eq .Values.recovery.method "object_store") -}} + {{- $d := dict "chartFullname" (include "cluster.fullname" .) "scope" .Values.recovery "secretPrefix" "recovery" -}} + {{- include "cluster.barmanObjectStoreConfig" $d | indent 2 }} + {{- else }} wal: compression: {{ .Values.backups.wal.compression }} {{- if .Values.backups.wal.encryption }} @@ -17,6 +21,7 @@ spec: encryption: {{ .Values.backups.data.encryption }} {{- end }} jobs: {{ .Values.backups.data.jobs }} - {{- $d := dict "chartFullname" (include "cluster.fullname" .) "scope" .Values.backups "secretPrefix" "backup" -}} - {{- include "cluster.barmanObjectStoreConfig" $d | indent 2 }} + {{- $d := dict "chartFullname" (include "cluster.fullname" .) "scope" .Values.backups "secretPrefix" "backup" -}} + {{- include "cluster.barmanObjectStoreConfig" $d | indent 2 }} + {{- end }} {{- end }} From 0289e16316aabc8a7e878832a03b1034df548fef Mon Sep 17 00:00:00 2001 From: Philipp Hamann <84906475+pha91@users.noreply.github.com> Date: Fri, 17 Oct 2025 09:35:48 +0200 Subject: [PATCH 4/4] featue(objectStore): add retentionPolicy to ObjectStore Signed-off-by: Philipp Hamann <84906475+pha91@users.noreply.github.com> --- charts/cluster/templates/objectStore.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/charts/cluster/templates/objectStore.yaml b/charts/cluster/templates/objectStore.yaml index 98f7455d63..ae0ef4171e 100644 --- a/charts/cluster/templates/objectStore.yaml +++ b/charts/cluster/templates/objectStore.yaml @@ -4,6 +4,9 @@ kind: ObjectStore metadata: name: {{ include "cluster.fullname" $ }}-object-store spec: + {{- with .Values.backups.retentionPolicy }} + retentionPolicy: {{ . }} + {{- end }} configuration: {{- if and (eq .Values.mode "recovery") (eq .Values.recovery.method "object_store") -}} {{- $d := dict "chartFullname" (include "cluster.fullname" .) "scope" .Values.recovery "secretPrefix" "recovery" -}}