@@ -2946,29 +2946,32 @@ func TestProvisionFromSnapshot(t *testing.T) {
29462946 }
29472947
29482948 type testcase struct {
2949- volOpts controller.ProvisionOptions
2950- restoredVolSizeSmall bool
2951- wrongDataSource bool
2952- snapshotStatusReady bool
2953- expectedPVSpec * pvSpec
2954- expectErr bool
2955- expectCSICall bool
2956- notPopulated bool
2957- misBoundSnapshotContentUID bool
2958- misBoundSnapshotContentNamespace bool
2959- misBoundSnapshotContentName bool
2960- nilBoundVolumeSnapshotContentName bool
2961- nilSnapshotStatus bool
2962- nilReadyToUse bool
2963- nilContentStatus bool
2964- nilSnapshotHandle bool
2965- allowVolumeModeChange bool
2966- xnsEnabled bool // set to use CrossNamespaceVolumeDataSource feature, default false
2967- snapNamespace string
2968- withreferenceGrants bool // set to use ReferenceGrant, default false
2969- refGrantsrcNamespace string
2970- referenceGrantFrom []gatewayv1beta1.ReferenceGrantFrom
2971- referenceGrantTo []gatewayv1beta1.ReferenceGrantTo
2949+ volOpts controller.ProvisionOptions
2950+ restoredVolSizeSmall bool
2951+ wrongDataSource bool
2952+ snapshotStatusReady bool
2953+ expectedPVSpec * pvSpec
2954+ expectErr bool
2955+ expectCSICall bool
2956+ notPopulated bool
2957+ misBoundSnapshotContentUID bool
2958+ misBoundSnapshotContentNamespace bool
2959+ misBoundSnapshotContentName bool
2960+ nilBoundVolumeSnapshotContentName bool
2961+ nilSnapshotStatus bool
2962+ nilReadyToUse bool
2963+ nilContentStatus bool
2964+ nilSnapshotHandle bool
2965+ allowVolumeModeChange bool
2966+ snapshotBeingDeleted bool // set DeletionTimestamp on snapshot
2967+ snapshotWithoutSourceProtectionFinalizer bool // simulate snapshot being deleted without the volumesnapshot-as-source-protection finalizer
2968+ snapshotWithDifferentFinalizer bool // simulate snapshot with a different finalizer (not the source protection one)
2969+ xnsEnabled bool // set to use CrossNamespaceVolumeDataSource feature, default false
2970+ snapNamespace string
2971+ withreferenceGrants bool // set to use ReferenceGrant, default false
2972+ refGrantsrcNamespace string
2973+ referenceGrantFrom []gatewayv1beta1.ReferenceGrantFrom
2974+ referenceGrantTo []gatewayv1beta1.ReferenceGrantTo
29722975 }
29732976 testcases := map [string ]testcase {
29742977 "provision with volume snapshot data source" : {
@@ -4486,6 +4489,123 @@ func TestProvisionFromSnapshot(t *testing.T) {
44864489 referenceGrantFrom : []gatewayv1beta1.ReferenceGrantFrom {},
44874490 referenceGrantTo : []gatewayv1beta1.ReferenceGrantTo {},
44884491 },
4492+ "provision with snapshot being deleted without source-protection-finalizer should fail" : {
4493+ volOpts : controller.ProvisionOptions {
4494+ StorageClass : & storagev1.StorageClass {
4495+ ReclaimPolicy : & deletePolicy ,
4496+ Parameters : map [string ]string {},
4497+ Provisioner : "test-driver" ,
4498+ },
4499+ PVName : "test-name" ,
4500+ PVC : & v1.PersistentVolumeClaim {
4501+ ObjectMeta : metav1.ObjectMeta {
4502+ UID : "testid" ,
4503+ Annotations : driverNameAnnotation ,
4504+ },
4505+ Spec : v1.PersistentVolumeClaimSpec {
4506+ StorageClassName : & snapClassName ,
4507+ Resources : v1.VolumeResourceRequirements {
4508+ Requests : v1.ResourceList {
4509+ v1 .ResourceName (v1 .ResourceStorage ): resource .MustParse (strconv .FormatInt (requestedBytes , 10 )),
4510+ },
4511+ },
4512+ AccessModes : []v1.PersistentVolumeAccessMode {v1 .ReadWriteOnce },
4513+ DataSource : & v1.TypedLocalObjectReference {
4514+ Name : snapName ,
4515+ Kind : "VolumeSnapshot" ,
4516+ APIGroup : & apiGrp ,
4517+ },
4518+ },
4519+ },
4520+ },
4521+ snapshotStatusReady : true ,
4522+ snapshotBeingDeleted : true ,
4523+ snapshotWithoutSourceProtectionFinalizer : true ,
4524+ expectErr : true ,
4525+ },
4526+ "provision with snapshot being deleted with different finalizer (not source-protection) should fail" : {
4527+ volOpts : controller.ProvisionOptions {
4528+ StorageClass : & storagev1.StorageClass {
4529+ ReclaimPolicy : & deletePolicy ,
4530+ Parameters : map [string ]string {},
4531+ Provisioner : "test-driver" ,
4532+ },
4533+ PVName : "test-name" ,
4534+ PVC : & v1.PersistentVolumeClaim {
4535+ ObjectMeta : metav1.ObjectMeta {
4536+ UID : "testid" ,
4537+ Annotations : driverNameAnnotation ,
4538+ },
4539+ Spec : v1.PersistentVolumeClaimSpec {
4540+ StorageClassName : & snapClassName ,
4541+ Resources : v1.VolumeResourceRequirements {
4542+ Requests : v1.ResourceList {
4543+ v1 .ResourceName (v1 .ResourceStorage ): resource .MustParse (strconv .FormatInt (requestedBytes , 10 )),
4544+ },
4545+ },
4546+ AccessModes : []v1.PersistentVolumeAccessMode {v1 .ReadWriteOnce },
4547+ DataSource : & v1.TypedLocalObjectReference {
4548+ Name : snapName ,
4549+ Kind : "VolumeSnapshot" ,
4550+ APIGroup : & apiGrp ,
4551+ },
4552+ },
4553+ },
4554+ },
4555+ snapshotStatusReady : true ,
4556+ snapshotBeingDeleted : true ,
4557+ snapshotWithDifferentFinalizer : true ,
4558+ expectErr : true ,
4559+ },
4560+ "provision with snapshot being deleted with source-protection-finalizer should proceed for cleanup" : {
4561+ volOpts : controller.ProvisionOptions {
4562+ StorageClass : & storagev1.StorageClass {
4563+ ReclaimPolicy : & deletePolicy ,
4564+ Parameters : map [string ]string {},
4565+ Provisioner : "test-driver" ,
4566+ },
4567+ PVName : "test-name" ,
4568+ PVC : & v1.PersistentVolumeClaim {
4569+ ObjectMeta : metav1.ObjectMeta {
4570+ UID : "testid" ,
4571+ Annotations : driverNameAnnotation ,
4572+ },
4573+ Spec : v1.PersistentVolumeClaimSpec {
4574+ StorageClassName : & snapClassName ,
4575+ Resources : v1.VolumeResourceRequirements {
4576+ Requests : v1.ResourceList {
4577+ v1 .ResourceName (v1 .ResourceStorage ): resource .MustParse (strconv .FormatInt (requestedBytes , 10 )),
4578+ },
4579+ },
4580+ AccessModes : []v1.PersistentVolumeAccessMode {v1 .ReadWriteOnce },
4581+ DataSource : & v1.TypedLocalObjectReference {
4582+ Name : snapName ,
4583+ Kind : "VolumeSnapshot" ,
4584+ APIGroup : & apiGrp ,
4585+ },
4586+ },
4587+ },
4588+ },
4589+ snapshotStatusReady : true ,
4590+ snapshotBeingDeleted : true ,
4591+ expectedPVSpec : & pvSpec {
4592+ Name : "test-testi" ,
4593+ ReclaimPolicy : v1 .PersistentVolumeReclaimDelete ,
4594+ AccessModes : []v1.PersistentVolumeAccessMode {v1 .ReadWriteOnce },
4595+ Capacity : v1.ResourceList {
4596+ v1 .ResourceName (v1 .ResourceStorage ): bytesToQuantity (requestedBytes ),
4597+ },
4598+ CSIPVS : & v1.CSIPersistentVolumeSource {
4599+ Driver : "test-driver" ,
4600+ VolumeHandle : "test-volume-id" ,
4601+ FSType : "ext4" ,
4602+ VolumeAttributes : map [string ]string {
4603+ "storage.kubernetes.io/csiProvisionerIdentity" : "test-provisioner" ,
4604+ },
4605+ },
4606+ },
4607+ expectCSICall : true ,
4608+ },
44894609 }
44904610
44914611 tmpdir := tempDir (t )
@@ -4516,6 +4636,19 @@ func TestProvisionFromSnapshot(t *testing.T) {
45164636 if tc .nilReadyToUse {
45174637 snap .Status .ReadyToUse = nil
45184638 }
4639+ if tc .snapshotBeingDeleted {
4640+ deletionTime := metav1 .Now ()
4641+ snap .ObjectMeta .DeletionTimestamp = & deletionTime
4642+ // Set up finalizers based on what the test is checking:
4643+ // - snapshotWithDifferentFinalizer: add a different finalizer to verify we check for the specific source-protection one
4644+ // - snapshotWithoutSourceProtectionFinalizer: don't add any finalizers (simulates new provisioning attempt)
4645+ // - default: add the volumesnapshot-as-source-protection finalizer (simulates in-flight provisioning)
4646+ if tc .snapshotWithDifferentFinalizer {
4647+ snap .ObjectMeta .Finalizers = []string {"some-other-finalizer" }
4648+ } else if ! tc .snapshotWithoutSourceProtectionFinalizer {
4649+ snap .ObjectMeta .Finalizers = []string {"snapshot.storage.kubernetes.io/volumesnapshot-as-source-protection" }
4650+ }
4651+ }
45194652 return true , snap , nil
45204653 })
45214654
0 commit comments