From 22e518cd98db563b9a4a3832e025c11c144858ee Mon Sep 17 00:00:00 2001 From: yerkennz Date: Tue, 4 Aug 2026 18:55:21 +0500 Subject: [PATCH 1/2] feat: [CPCAP-12366] add custom annotation for PVC in helm charts --- docs/public/installation.md | 2 ++ operator/api/common/v1/common_types.go | 15 ++++++++------- operator/api/common/v1/zz_generated.deepcopy.go | 7 +++++++ .../crds/netcracker.com_patronicores.yaml | 12 ++++++++++++ operator/charts/patroni-core/values.schema.json | 7 +++++++ operator/charts/patroni-core/values.yaml | 11 +++++++++++ .../crds/netcracker.com_patroniservices.yaml | 4 ++++ .../charts/patroni-services/values.schema.json | 7 +++++++ operator/charts/patroni-services/values.yaml | 7 +++++++ operator/pkg/storage/storage.go | 5 +++-- 10 files changed, 68 insertions(+), 9 deletions(-) diff --git a/docs/public/installation.md b/docs/public/installation.md index c84c7564..192d3eae 100644 --- a/docs/public/installation.md +++ b/docs/public/installation.md @@ -256,6 +256,7 @@ This sections describes all possible deploy parameters for Patroni component. | patroni.storage.nodes | []string | no | n/a | Specifies list of nodes to which Patroni pods will be scheduled. | | patroni.storage.selectors | []string | no | n/a | Specifies list of selector to choose PVCs. | | patroni.storage.volumes | []string | no | n/a | Specifies list of Persistence Volumes that will be used for PVCs. Should be specified only in case of `pv` storageClass. | +| patroni.storage.annotations | map[string]string | no | n/a | Specifies optional annotations to apply to PVCs. Use `argocd.argoproj.io/sync-options: Prune=false` to protect from ArgoCD pruning. | | patroni.pgWalStorage | Storage Group | no | n/a | Specifies set of storage parameters for separater volume for `pg_wal` directory. Parameters are the same as for `storage`. | | patroni.pgWalStorageAutoManage | bool | no | n/a | Specifies is pg_wal files have to be moved to separate volume `pg_wal` directory automatically. | | patroni.priorityClassName | string | no | n/a | Specifies [Priority Class](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass). | @@ -407,6 +408,7 @@ This sections describes all possible deploy parameters for PostgreSQL Backup Dae | backupDaemon.storage.selectors | []string | no | n/a | Specifies list of selector to choose PVCs. | | backupDaemon.storage.volumes | []string | no | n/a | Specifies list of Persistence Volumes that will be used for PVCs. Should be specified only in case of `pv` storageClass. | | backupDaemon.storage.accessMode | []string | no | n/a | Specifies list of [Access Modes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes) that will be used for PVCs. | +| backupDaemon.storage.annotations | map[string]string | no | n/a | Specifies optional annotations to apply to PVCs. Use `argocd.argoproj.io/sync-options: Prune=false` to protect from ArgoCD pruning. | | backupDaemon.s3Storage.url | string | no | n/a | Specifies url address to S3 storage. | | backupDaemon.s3Storage.accessKeyId | string | no | n/a | Specifies S3 accessKeyId credential. | | backupDaemon.s3Storage.secretAccessKey | string | no | n/a | Specifies S3 secretAccessKey credential. | diff --git a/operator/api/common/v1/common_types.go b/operator/api/common/v1/common_types.go index bf164e65..c4f9c95c 100644 --- a/operator/api/common/v1/common_types.go +++ b/operator/api/common/v1/common_types.go @@ -20,13 +20,14 @@ package v1 // Storage Describes Storage that will be used by patroni type Storage struct { // +kubebuilder:validation:Pattern=`^[0-9]+(m|Ki|Mi|Gi|Ti|Pi|Ei|k|M|G|T|P|E)$` - Size string `json:"size,omitempty"` - Type string `json:"type,omitempty"` - StorageClass string `json:"storageClass,omitempty"` - Volumes []string `json:"volumes,omitempty"` - Nodes []string `json:"nodes,omitempty"` - Selectors []string `json:"selectors,omitempty"` - AccessModes []string `json:"accessModes,omitempty"` + Size string `json:"size,omitempty"` + Type string `json:"type,omitempty"` + StorageClass string `json:"storageClass,omitempty"` + Volumes []string `json:"volumes,omitempty"` + Nodes []string `json:"nodes,omitempty"` + Selectors []string `json:"selectors,omitempty"` + AccessModes []string `json:"accessModes,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` } type CloudSql struct { Project string `json:"project,omitempty"` diff --git a/operator/api/common/v1/zz_generated.deepcopy.go b/operator/api/common/v1/zz_generated.deepcopy.go index a915d992..7aace796 100644 --- a/operator/api/common/v1/zz_generated.deepcopy.go +++ b/operator/api/common/v1/zz_generated.deepcopy.go @@ -27,6 +27,13 @@ func (in *Storage) DeepCopyInto(out *Storage) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Storage. diff --git a/operator/charts/patroni-core/crds/netcracker.com_patronicores.yaml b/operator/charts/patroni-core/crds/netcracker.com_patronicores.yaml index 491ebb0b..8d202d55 100644 --- a/operator/charts/patroni-core/crds/netcracker.com_patronicores.yaml +++ b/operator/charts/patroni-core/crds/netcracker.com_patronicores.yaml @@ -2113,6 +2113,10 @@ spec: items: type: string type: array + annotations: + additionalProperties: + type: string + type: object nodes: items: type: string @@ -2470,6 +2474,10 @@ spec: items: type: string type: array + annotations: + additionalProperties: + type: string + type: object nodes: items: type: string @@ -2603,6 +2611,10 @@ spec: items: type: string type: array + annotations: + additionalProperties: + type: string + type: object nodes: items: type: string diff --git a/operator/charts/patroni-core/values.schema.json b/operator/charts/patroni-core/values.schema.json index f4b62a79..6b3ee064 100644 --- a/operator/charts/patroni-core/values.schema.json +++ b/operator/charts/patroni-core/values.schema.json @@ -713,6 +713,13 @@ "items": { "type": "string" } + }, + "annotations": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Optional annotations to apply to PVCs created for this storage. Use this to protect PVCs from ArgoCD pruning or add custom metadata." } } }, diff --git a/operator/charts/patroni-core/values.yaml b/operator/charts/patroni-core/values.yaml index 5d38aa43..60d75610 100644 --- a/operator/charts/patroni-core/values.yaml +++ b/operator/charts/patroni-core/values.yaml @@ -185,6 +185,11 @@ patroni: type: pv # Size of the PVC that will be create for each of Patroni Pod as mount for data files size: 5Gi + # Optional annotations to apply to PVCs created for Patroni storage. + # Use this to protect PVCs from ArgoCD pruning or add custom metadata. + # Example: Prevent ArgoCD from deleting PVCs during sync: + # annotations: + # argocd.argoproj.io/sync-options: Prune=false # Parameter specifies the list of labels that is used to bind suitable # persistent volumes with the persistent volume claims # selectors: @@ -228,6 +233,10 @@ patroni: # type: provisioned # Size of the PVC that will be created for each of Patroni Pod as mount for data files # size: 10Gi + # Optional annotations to apply to PVCs created for WAL storage. + # Use this to protect PVCs from ArgoCD pruning or add custom metadata. + # annotations: + # argocd.argoproj.io/sync-options: Prune=false # Parameter specifies the list of labels that is used to bind suitable # persistent volumes with the persistent volume claims # selectors: @@ -260,6 +269,8 @@ patroni: # size: 3Gi # volumes: # - pg-backrest-backups-pv-1 +# annotations: +# argocd.argoproj.io/sync-options: Prune=false # s3: # bucket: "pgbackrest" # endpoint: "https://minio-service" diff --git a/operator/charts/patroni-services/crds/netcracker.com_patroniservices.yaml b/operator/charts/patroni-services/crds/netcracker.com_patroniservices.yaml index b631ca90..fb3416b0 100644 --- a/operator/charts/patroni-services/crds/netcracker.com_patroniservices.yaml +++ b/operator/charts/patroni-services/crds/netcracker.com_patroniservices.yaml @@ -1336,6 +1336,10 @@ spec: items: type: string type: array + annotations: + additionalProperties: + type: string + type: object nodes: items: type: string diff --git a/operator/charts/patroni-services/values.schema.json b/operator/charts/patroni-services/values.schema.json index 4559037b..c2e3ee6b 100644 --- a/operator/charts/patroni-services/values.schema.json +++ b/operator/charts/patroni-services/values.schema.json @@ -1266,6 +1266,13 @@ "items": { "type": "string" } + }, + "annotations": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Optional annotations to apply to PVCs created for this storage. Use this to protect PVCs from ArgoCD pruning or add custom metadata." } } }, diff --git a/operator/charts/patroni-services/values.yaml b/operator/charts/patroni-services/values.yaml index 6c882687..65caf328 100644 --- a/operator/charts/patroni-services/values.yaml +++ b/operator/charts/patroni-services/values.yaml @@ -213,6 +213,11 @@ backupDaemon: type: provisioned # Size of the PVC that will be create for each of Patroni Pod as mount for data files size: 1Gi + # Optional annotations to apply to PVCs created for backup daemon storage. + # Use this to protect PVCs from ArgoCD pruning or add custom metadata. + # Example: Prevent ArgoCD from deleting PVCs during sync: + # annotations: + # argocd.argoproj.io/sync-options: Prune=false # Parameter specifies the list of labels that is used to bind suitable # persistent volumes with the persistent volume claims # selectors: @@ -240,6 +245,8 @@ backupDaemon: # size: 3Gi # volumes: # - pg-backrest-backups-pv-1 +# annotations: +# argocd.argoproj.io/sync-options: Prune=false # s3: # bucket: "pgbackrest" # endpoint: "https://minio-service" diff --git a/operator/pkg/storage/storage.go b/operator/pkg/storage/storage.go index 6b6ab30b..c60ca6ff 100644 --- a/operator/pkg/storage/storage.go +++ b/operator/pkg/storage/storage.go @@ -69,8 +69,9 @@ func NewPvc(pvcName string, storageEntity *commonv1.Storage, idx int) *corev1.Pe pvc := &corev1.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ - Name: pvcName, - Namespace: util.GetNameSpace(), + Name: pvcName, + Namespace: util.GetNameSpace(), + Annotations: storageEntity.Annotations, }, Spec: pvcSpec, } From c37c56b8ed1b1abd19b1f9d27f187f8aa965a818 Mon Sep 17 00:00:00 2001 From: yerkennz Date: Wed, 5 Aug 2026 15:33:06 +0500 Subject: [PATCH 2/2] feat: add annotation in upgrade case --- operator/charts/patroni-core/templates/cr.yaml | 4 ++++ operator/charts/patroni-services/templates/cr.yaml | 4 ++++ operator/pkg/helper/resource_management.go | 11 ++++++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/operator/charts/patroni-core/templates/cr.yaml b/operator/charts/patroni-core/templates/cr.yaml index 025f2107..9054babf 100644 --- a/operator/charts/patroni-core/templates/cr.yaml +++ b/operator/charts/patroni-core/templates/cr.yaml @@ -124,6 +124,10 @@ spec: - {{ . }} {{- end }} {{ end }} + {{ if .Values.patroni.storage.annotations }} + annotations: + {{- toYaml .Values.patroni.storage.annotations | nindent 8 }} + {{ end }} {{ if .Values.patroni.standbyCluster }} standbyCluster: host: {{ .Values.patroni.standbyCluster.host }} diff --git a/operator/charts/patroni-services/templates/cr.yaml b/operator/charts/patroni-services/templates/cr.yaml index 73a0895b..f24afe67 100644 --- a/operator/charts/patroni-services/templates/cr.yaml +++ b/operator/charts/patroni-services/templates/cr.yaml @@ -98,6 +98,10 @@ spec: - {{ . }} {{- end }} {{ end }} + {{ if .Values.backupDaemon.storage.annotations }} + annotations: + {{- toYaml .Values.backupDaemon.storage.annotations | nindent 8 }} + {{ end }} {{ if .Values.backupDaemon.priorityClassName }} priorityClassName: {{ .Values.backupDaemon.priorityClassName }} {{ end }} diff --git a/operator/pkg/helper/resource_management.go b/operator/pkg/helper/resource_management.go index 2b2185c0..b335bac0 100644 --- a/operator/pkg/helper/resource_management.go +++ b/operator/pkg/helper/resource_management.go @@ -516,8 +516,17 @@ func (rm *ResourceManager) CreatePvcIfNotExists(pvc *corev1.PersistentVolumeClai return err } } else { - logger.Info(fmt.Sprintf("PVC %s exists, clearing owner reference...", pvc.Name)) + logger.Info(fmt.Sprintf("PVC %s exists, clearing owner reference and updating annotations...", pvc.Name)) foundPvc.OwnerReferences = nil + if pvc.Annotations != nil { + if foundPvc.Annotations == nil { + foundPvc.Annotations = make(map[string]string) + } + for key, value := range pvc.Annotations { + foundPvc.Annotations[key] = value + } + } + err := rm.kubeClient.Update(context.TODO(), foundPvc) if err != nil { logger.Error(fmt.Sprintf("Failed to clear Owner Reference for %s", pvc.Name), zap.Error(err))