From 248a8409182b20a5ac51be15b9280017aea135b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Nussbaumer?= Date: Tue, 5 Aug 2025 16:26:16 +0200 Subject: [PATCH] feat: Permit specifying annotations for the BackupPVC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Clément Nussbaumer --- changelogs/unreleased/9173-clementnuss | 1 + pkg/exposer/csi_snapshot.go | 14 ++++++++++---- pkg/exposer/csi_snapshot_test.go | 2 +- pkg/types/node_agent.go | 3 +++ .../main/data-movement-backup-pvc-configuration.md | 10 ++++++++-- 5 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 changelogs/unreleased/9173-clementnuss diff --git a/changelogs/unreleased/9173-clementnuss b/changelogs/unreleased/9173-clementnuss new file mode 100644 index 000000000..c7dece117 --- /dev/null +++ b/changelogs/unreleased/9173-clementnuss @@ -0,0 +1 @@ +feat: Permit specifying annotations for the BackupPVC diff --git a/pkg/exposer/csi_snapshot.go b/pkg/exposer/csi_snapshot.go index a886c60c3..531330f62 100644 --- a/pkg/exposer/csi_snapshot.go +++ b/pkg/exposer/csi_snapshot.go @@ -188,6 +188,7 @@ func (e *csiSnapshotExposer) Expose(ctx context.Context, ownerObject corev1api.O backupPVCStorageClass := csiExposeParam.StorageClass backupPVCReadOnly := false spcNoRelabeling := false + backupPVCAnnotations := map[string]string{} if value, exists := csiExposeParam.BackupPVCConfig[csiExposeParam.StorageClass]; exists { if value.StorageClass != "" { backupPVCStorageClass = value.StorageClass @@ -201,9 +202,13 @@ func (e *csiSnapshotExposer) Expose(ctx context.Context, ownerObject corev1api.O curLog.WithField("vs name", volumeSnapshot.Name).Warn("Ignoring spcNoRelabling for read-write volume") } } + + if len(value.Annotations) > 0 { + backupPVCAnnotations = value.Annotations + } } - backupPVC, err := e.createBackupPVC(ctx, ownerObject, backupVS.Name, backupPVCStorageClass, csiExposeParam.AccessMode, volumeSize, backupPVCReadOnly) + backupPVC, err := e.createBackupPVC(ctx, ownerObject, backupVS.Name, backupPVCStorageClass, csiExposeParam.AccessMode, volumeSize, backupPVCReadOnly, backupPVCAnnotations) if err != nil { return errors.Wrap(err, "error to create backup pvc") } @@ -485,7 +490,7 @@ func (e *csiSnapshotExposer) createBackupVSC(ctx context.Context, ownerObject co return e.csiSnapshotClient.VolumeSnapshotContents().Create(ctx, vsc, metav1.CreateOptions{}) } -func (e *csiSnapshotExposer) createBackupPVC(ctx context.Context, ownerObject corev1api.ObjectReference, backupVS, storageClass, accessMode string, resource resource.Quantity, readOnly bool) (*corev1api.PersistentVolumeClaim, error) { +func (e *csiSnapshotExposer) createBackupPVC(ctx context.Context, ownerObject corev1api.ObjectReference, backupVS, storageClass, accessMode string, resource resource.Quantity, readOnly bool, annotations map[string]string) (*corev1api.PersistentVolumeClaim, error) { backupPVCName := ownerObject.Name volumeMode, err := getVolumeModeByAccessMode(accessMode) @@ -507,8 +512,9 @@ func (e *csiSnapshotExposer) createBackupPVC(ctx context.Context, ownerObject co pvc := &corev1api.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ - Namespace: ownerObject.Namespace, - Name: backupPVCName, + Namespace: ownerObject.Namespace, + Name: backupPVCName, + Annotations: annotations, OwnerReferences: []metav1.OwnerReference{ { APIVersion: ownerObject.APIVersion, diff --git a/pkg/exposer/csi_snapshot_test.go b/pkg/exposer/csi_snapshot_test.go index 5dd745065..a6d74d9fe 100644 --- a/pkg/exposer/csi_snapshot_test.go +++ b/pkg/exposer/csi_snapshot_test.go @@ -1114,7 +1114,7 @@ func Test_csiSnapshotExposer_createBackupPVC(t *testing.T) { APIVersion: tt.ownerBackup.APIVersion, } } - got, err := e.createBackupPVC(t.Context(), ownerObject, tt.backupVS, tt.storageClass, tt.accessMode, tt.resource, tt.readOnly) + got, err := e.createBackupPVC(t.Context(), ownerObject, tt.backupVS, tt.storageClass, tt.accessMode, tt.resource, tt.readOnly, map[string]string{}) if !tt.wantErr(t, err, fmt.Sprintf("createBackupPVC(%v, %v, %v, %v, %v, %v)", ownerObject, tt.backupVS, tt.storageClass, tt.accessMode, tt.resource, tt.readOnly)) { return } diff --git a/pkg/types/node_agent.go b/pkg/types/node_agent.go index d0696dc95..778aefcf1 100644 --- a/pkg/types/node_agent.go +++ b/pkg/types/node_agent.go @@ -56,6 +56,9 @@ type BackupPVC struct { // SPCNoRelabeling sets Spec.SecurityContext.SELinux.Type to "spc_t" for the pod mounting the backupPVC // ignored if ReadOnly is false SPCNoRelabeling bool `json:"spcNoRelabeling,omitempty"` + + // Annotations permits setting annotations for the backupPVC + Annotations map[string]string `json:"annotations,omitempty"` } type RestorePVC struct { diff --git a/site/content/docs/main/data-movement-backup-pvc-configuration.md b/site/content/docs/main/data-movement-backup-pvc-configuration.md index 11f6d6bc7..1dc290820 100644 --- a/site/content/docs/main/data-movement-backup-pvc-configuration.md +++ b/site/content/docs/main/data-movement-backup-pvc-configuration.md @@ -37,6 +37,9 @@ default the source PVC's storage class will be used. The users can specify the ConfigMap name during velero installation by CLI: `velero install --node-agent-configmap=` +- `annotations`: permits to set annotations on the backupPVC itself. typically useful for some CSI provider which cannot mount + a VolumeSnapshot without a custom annotation. + A sample of `backupPVC` config as part of the ConfigMap would look like: ```json { @@ -49,8 +52,11 @@ A sample of `backupPVC` config as part of the ConfigMap would look like: "storageClass": "backupPVC-storage-class" }, "storage-class-3": { - "readOnly": true - } + "readOnly": true, + "annotations": { + "some-csi.provider.io/readOnlyClone": true + } + }, "storage-class-4": { "readOnly": true, "spcNoRelabeling": true