From 63cfddd18de1204c801febab72c8fa24cf3ab845 Mon Sep 17 00:00:00 2001 From: Adam Zhang Date: Tue, 28 Jul 2026 16:06:04 +0800 Subject: [PATCH] add tests to cover pvc and vsc ria Signed-off-by: Adam Zhang --- pkg/restore/actions/csi/pvc_action_test.go | 27 +++++++++++++++- .../actions/csi/volumesnapshot_action.go | 3 ++ .../actions/csi/volumesnapshot_action_test.go | 32 +++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/pkg/restore/actions/csi/pvc_action_test.go b/pkg/restore/actions/csi/pvc_action_test.go index 4ad8cd636..0e10144f6 100644 --- a/pkg/restore/actions/csi/pvc_action_test.go +++ b/pkg/restore/actions/csi/pvc_action_test.go @@ -371,6 +371,7 @@ func TestExecute(t *testing.T) { backup *velerov1api.Backup restore *velerov1api.Restore pvc *corev1api.PersistentVolumeClaim + pvcFromBackup *corev1api.PersistentVolumeClaim vs *snapshotv1api.VolumeSnapshot dataUploadResult *corev1api.ConfigMap expectedErr string @@ -407,6 +408,24 @@ func TestExecute(t *testing.T) { velerov1api.MustIncludeAdditionalItemRestoreAnnotation, "true", )).Result(), }, + { + name: "Restore from VolumeSnapshot with nil PVC annotations", + backup: builder.ForBackup("velero", "testBackup").Result(), + restore: builder.ForRestore("velero", "testRestore").ObjectMeta(builder.WithUID("restoreUID")).Backup("testBackup").Result(), + pvc: &corev1api.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testPVC", + Namespace: "velero", + }, + }, + pvcFromBackup: builder.ForPersistentVolumeClaim("velero", "testPVC").ObjectMeta(builder.WithAnnotations(velerov1api.VolumeSnapshotLabel, "vsName")).Result(), + vs: builder.ForVolumeSnapshot("velero", vsName).ObjectMeta( + builder.WithAnnotations(velerov1api.VolumeSnapshotRestoreSize, "10Gi"), + ).Result(), + expectedPVC: builder.ForPersistentVolumeClaim("velero", "testPVC").ObjectMeta(builder.WithAnnotations( + velerov1api.MustIncludeAdditionalItemRestoreAnnotation, "true", + )).Result(), + }, { name: "Restore from VolumeSnapshot without volume-snapshot-name annotation", backup: builder.ForBackup("velero", "testBackup").Result(), @@ -487,7 +506,13 @@ func TestExecute(t *testing.T) { require.NoError(t, err) input.Item = &unstructured.Unstructured{Object: pvcMap} - input.ItemFromBackup = &unstructured.Unstructured{Object: pvcMap} + if tc.pvcFromBackup != nil { + pvcFromBackupMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tc.pvcFromBackup) + require.NoError(t, err) + input.ItemFromBackup = &unstructured.Unstructured{Object: pvcFromBackupMap} + } else { + input.ItemFromBackup = &unstructured.Unstructured{Object: pvcMap} + } input.Restore = tc.restore } if tc.preCreatePVC { diff --git a/pkg/restore/actions/csi/volumesnapshot_action.go b/pkg/restore/actions/csi/volumesnapshot_action.go index ec0f1912b..13b7cb246 100644 --- a/pkg/restore/actions/csi/volumesnapshot_action.go +++ b/pkg/restore/actions/csi/volumesnapshot_action.go @@ -66,6 +66,9 @@ func resetVolumeSnapshotSpecForRestore(vs *snapshotv1api.VolumeSnapshot, vscName } func resetVolumeSnapshotAnnotation(vs *snapshotv1api.VolumeSnapshot) { + if vs.ObjectMeta.Annotations == nil { + vs.ObjectMeta.Annotations = make(map[string]string) + } vs.ObjectMeta.Annotations[velerov1api.VSCDeletionPolicyAnnotation] = string(snapshotv1api.VolumeSnapshotContentRetain) } diff --git a/pkg/restore/actions/csi/volumesnapshot_action_test.go b/pkg/restore/actions/csi/volumesnapshot_action_test.go index d1b42b91c..9d72971d0 100644 --- a/pkg/restore/actions/csi/volumesnapshot_action_test.go +++ b/pkg/restore/actions/csi/volumesnapshot_action_test.go @@ -103,6 +103,26 @@ func TestResetVolumeSnapshotSpecForRestore(t *testing.T) { } } +func TestResetVolumeSnapshotAnnotation(t *testing.T) { + t.Run("should set deletion policy annotation when annotations is nil", func(t *testing.T) { + vs := snapshotv1api.VolumeSnapshot{} + resetVolumeSnapshotAnnotation(&vs) + assert.NotNil(t, vs.ObjectMeta.Annotations) + assert.Equal(t, string(snapshotv1api.VolumeSnapshotContentRetain), vs.ObjectMeta.Annotations[velerov1api.VSCDeletionPolicyAnnotation]) + }) + + t.Run("should preserve existing annotations and set deletion policy annotation", func(t *testing.T) { + vs := snapshotv1api.VolumeSnapshot{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{"foo": "bar"}, + }, + } + resetVolumeSnapshotAnnotation(&vs) + assert.Equal(t, "bar", vs.ObjectMeta.Annotations["foo"]) + assert.Equal(t, string(snapshotv1api.VolumeSnapshotContentRetain), vs.ObjectMeta.Annotations[velerov1api.VSCDeletionPolicyAnnotation]) + }) +} + func TestVSExecute(t *testing.T) { newVscName := util.GenerateSha256FromRestoreUIDAndVsName("restoreUID", "vsName") tests := []struct { @@ -145,6 +165,18 @@ func TestVSExecute(t *testing.T) { expectErr: false, expectedVS: builder.ForVolumeSnapshot("ns", "test").SourceVolumeSnapshotContentName(newVscName).Result(), }, + { + name: "Normal case with nil VS annotations, VSC should be created", + vs: builder.ForVolumeSnapshot("ns", "vsName"). + SourceVolumeSnapshotContentName(newVscName). + VolumeSnapshotClass("vscClass"). + Status(). + BoundVolumeSnapshotContentName("vscName"). + Result(), + restore: builder.ForRestore("velero", "restore").ObjectMeta(builder.WithUID("restoreUID")).Result(), + expectErr: false, + expectedVS: builder.ForVolumeSnapshot("ns", "test").SourceVolumeSnapshotContentName(newVscName).Result(), + }, } for _, test := range tests {