@@ -48,6 +48,7 @@ import (
48
48
"k8s.io/kubernetes/test/e2e/storage/utils"
49
49
"k8s.io/kubernetes/test/utils/format"
50
50
imageutils "k8s.io/kubernetes/test/utils/image"
51
+ "k8s.io/utils/ptr"
51
52
)
52
53
53
54
const (
@@ -101,14 +102,17 @@ type testParameters struct {
101
102
fsGroupPolicy * storagev1.FSGroupPolicy
102
103
enableSELinuxMount * bool
103
104
enableRecoverExpansionFailure bool
105
+ enableHonorPVReclaimPolicy bool
104
106
enableCSINodeExpandSecret bool
107
+ reclaimPolicy * v1.PersistentVolumeReclaimPolicy
105
108
}
106
109
107
110
type mockDriverSetup struct {
108
111
cs clientset.Interface
109
112
config * storageframework.PerTestConfig
110
113
pods []* v1.Pod
111
114
pvcs []* v1.PersistentVolumeClaim
115
+ pvs []* v1.PersistentVolume
112
116
sc map [string ]* storagev1.StorageClass
113
117
vsc map [string ]* unstructured.Unstructured
114
118
driver drivers.MockCSITestDriver
@@ -171,6 +175,7 @@ func (m *mockDriverSetup) init(ctx context.Context, tp testParameters) {
171
175
FSGroupPolicy : tp .fsGroupPolicy ,
172
176
EnableSELinuxMount : tp .enableSELinuxMount ,
173
177
EnableRecoverExpansionFailure : tp .enableRecoverExpansionFailure ,
178
+ EnableHonorPVReclaimPolicy : tp .enableHonorPVReclaimPolicy ,
174
179
}
175
180
176
181
// At the moment, only tests which need hooks are
@@ -235,6 +240,11 @@ func (m *mockDriverSetup) cleanup(ctx context.Context) {
235
240
}
236
241
}
237
242
243
+ for _ , pv := range m .pvs {
244
+ ginkgo .By (fmt .Sprintf ("Deleting pv %s" , pv .Name ))
245
+ errs = append (errs , e2epv .DeletePersistentVolume (ctx , cs , pv .Name ))
246
+ }
247
+
238
248
for _ , sc := range m .sc {
239
249
ginkgo .By (fmt .Sprintf ("Deleting storageclass %s" , sc .Name ))
240
250
cs .StorageV1 ().StorageClasses ().Delete (context .TODO (), sc .Name , metav1.DeleteOptions {})
@@ -286,6 +296,7 @@ func (m *mockDriverSetup) createPod(ctx context.Context, withVolume volumeType)
286
296
ExpectedSize : "1Gi" ,
287
297
DelayBinding : m .tp .lateBinding ,
288
298
AllowVolumeExpansion : m .tp .enableResizing ,
299
+ ReclaimPolicy : m .tp .reclaimPolicy ,
289
300
}
290
301
291
302
// The mock driver only works when everything runs on a single node.
@@ -319,6 +330,92 @@ func (m *mockDriverSetup) createPod(ctx context.Context, withVolume volumeType)
319
330
return // result variables set above
320
331
}
321
332
333
+ func (m * mockDriverSetup ) createPVC (ctx context.Context ) (class * storagev1.StorageClass , claim * v1.PersistentVolumeClaim ) {
334
+ ginkgo .By ("Creating pvc" )
335
+ f := m .f
336
+
337
+ sc := m .driver .GetDynamicProvisionStorageClass (ctx , m .config , "" )
338
+ if m .tp .enableCSINodeExpandSecret {
339
+ if sc .Parameters == nil {
340
+ parameters := map [string ]string {
341
+ csiNodeExpandSecretKey : "test-secret" ,
342
+ csiNodeExpandSecretNamespaceKey : f .Namespace .Name ,
343
+ }
344
+ sc .Parameters = parameters
345
+ } else {
346
+ sc .Parameters [csiNodeExpandSecretKey ] = "test-secret"
347
+ sc .Parameters [csiNodeExpandSecretNamespaceKey ] = f .Namespace .Name
348
+ }
349
+ }
350
+ scTest := testsuites.StorageClassTest {
351
+ Name : m .driver .GetDriverInfo ().Name ,
352
+ Timeouts : f .Timeouts ,
353
+ Provisioner : sc .Provisioner ,
354
+ Parameters : sc .Parameters ,
355
+ ClaimSize : "1Gi" ,
356
+ ExpectedSize : "1Gi" ,
357
+ DelayBinding : m .tp .lateBinding ,
358
+ AllowVolumeExpansion : m .tp .enableResizing ,
359
+ ReclaimPolicy : m .tp .reclaimPolicy ,
360
+ }
361
+
362
+ // The mock driver only works when everything runs on a single node.
363
+ nodeSelection := m .config .ClientNodeSelection
364
+ class , claim = createClaim (ctx , f .ClientSet , scTest , nodeSelection , m .tp .scName , f .Namespace .Name , nil )
365
+ if class != nil {
366
+ m .sc [class .Name ] = class
367
+ }
368
+ if claim != nil {
369
+ m .pvcs = append (m .pvcs , claim )
370
+ }
371
+
372
+ return class , claim
373
+ }
374
+
375
+ func (m * mockDriverSetup ) createPVPVC (ctx context.Context ) (class * storagev1.StorageClass , volume * v1.PersistentVolume , claim * v1.PersistentVolumeClaim ) {
376
+ ginkgo .By ("Creating the PV and PVC manually" )
377
+ f := m .f
378
+
379
+ sc := m .driver .GetDynamicProvisionStorageClass (ctx , m .config , "" )
380
+ if m .tp .enableCSINodeExpandSecret {
381
+ if sc .Parameters == nil {
382
+ parameters := map [string ]string {
383
+ csiNodeExpandSecretKey : "test-secret" ,
384
+ csiNodeExpandSecretNamespaceKey : f .Namespace .Name ,
385
+ }
386
+ sc .Parameters = parameters
387
+ } else {
388
+ sc .Parameters [csiNodeExpandSecretKey ] = "test-secret"
389
+ sc .Parameters [csiNodeExpandSecretNamespaceKey ] = f .Namespace .Name
390
+ }
391
+ }
392
+ scTest := testsuites.StorageClassTest {
393
+ Name : m .driver .GetDriverInfo ().Name ,
394
+ Timeouts : f .Timeouts ,
395
+ Provisioner : sc .Provisioner ,
396
+ Parameters : sc .Parameters ,
397
+ ClaimSize : "1Gi" ,
398
+ ExpectedSize : "1Gi" ,
399
+ DelayBinding : m .tp .lateBinding ,
400
+ AllowVolumeExpansion : m .tp .enableResizing ,
401
+ ReclaimPolicy : m .tp .reclaimPolicy ,
402
+ }
403
+
404
+ // The mock driver only works when everything runs on a single node.
405
+ nodeSelection := m .config .ClientNodeSelection
406
+ class , volume , claim = createVolumeAndClaim (ctx , f .ClientSet , scTest , nodeSelection , m .tp .scName , f .Namespace .Name , nil )
407
+ if class != nil {
408
+ m .sc [class .Name ] = class
409
+ }
410
+ if volume != nil {
411
+ m .pvs = append (m .pvs , volume )
412
+ }
413
+ if claim != nil {
414
+ m .pvcs = append (m .pvcs , claim )
415
+ }
416
+ return class , volume , claim
417
+ }
418
+
322
419
func (m * mockDriverSetup ) createPodWithPVC (pvc * v1.PersistentVolumeClaim ) (* v1.Pod , error ) {
323
420
f := m .f
324
421
@@ -344,6 +441,7 @@ func (m *mockDriverSetup) createPodWithFSGroup(ctx context.Context, fsGroup *int
344
441
ExpectedSize : "1Gi" ,
345
442
DelayBinding : m .tp .lateBinding ,
346
443
AllowVolumeExpansion : m .tp .enableResizing ,
444
+ ReclaimPolicy : m .tp .reclaimPolicy ,
347
445
}
348
446
class , claim , pod := startBusyBoxPod (ctx , f .ClientSet , scTest , nodeSelection , m .tp .scName , f .Namespace .Name , fsGroup )
349
447
@@ -375,6 +473,7 @@ func (m *mockDriverSetup) createPodWithSELinux(ctx context.Context, accessModes
375
473
DelayBinding : m .tp .lateBinding ,
376
474
AllowVolumeExpansion : m .tp .enableResizing ,
377
475
MountOptions : mountOptions ,
476
+ ReclaimPolicy : m .tp .reclaimPolicy ,
378
477
}
379
478
class , claim := createClaim (ctx , f .ClientSet , scTest , nodeSelection , m .tp .scName , f .Namespace .Name , accessModes )
380
479
pod , err := startPausePodWithSELinuxOptions (f .ClientSet , claim , nodeSelection , f .Namespace .Name , seLinuxOpts )
@@ -441,7 +540,7 @@ func newStorageClass(t testsuites.StorageClassTest, ns string, prefix string) *s
441
540
}
442
541
}
443
542
444
- sc := getStorageClass (pluginName , t .Parameters , & bindingMode , t .MountOptions , ns , prefix )
543
+ sc := getStorageClass (pluginName , t .Parameters , & bindingMode , t .MountOptions , t . ReclaimPolicy , ns , prefix )
445
544
if t .AllowVolumeExpansion {
446
545
sc .AllowVolumeExpansion = & t .AllowVolumeExpansion
447
546
}
@@ -453,6 +552,7 @@ func getStorageClass(
453
552
parameters map [string ]string ,
454
553
bindingMode * storagev1.VolumeBindingMode ,
455
554
mountOptions []string ,
555
+ reclaimPolicy * v1.PersistentVolumeReclaimPolicy ,
456
556
ns string ,
457
557
prefix string ,
458
558
) * storagev1.StorageClass {
@@ -472,6 +572,7 @@ func getStorageClass(
472
572
Parameters : parameters ,
473
573
VolumeBindingMode : bindingMode ,
474
574
MountOptions : mountOptions ,
575
+ ReclaimPolicy : reclaimPolicy ,
475
576
}
476
577
}
477
578
@@ -523,6 +624,44 @@ func createClaim(ctx context.Context, cs clientset.Interface, t testsuites.Stora
523
624
return class , claim
524
625
}
525
626
627
+ func createVolumeAndClaim (ctx context.Context , cs clientset.Interface , t testsuites.StorageClassTest , node e2epod.NodeSelection , scName , ns string , accessModes []v1.PersistentVolumeAccessMode ) (* storagev1.StorageClass , * v1.PersistentVolume , * v1.PersistentVolumeClaim ) {
628
+ class := createSC (cs , t , scName , ns )
629
+
630
+ volumeMode := v1 .PersistentVolumeFilesystem
631
+ if t .VolumeMode != "" {
632
+ volumeMode = t .VolumeMode
633
+ }
634
+
635
+ pvConfig := e2epv.PersistentVolumeConfig {
636
+ Capacity : t .ClaimSize ,
637
+ StorageClassName : class .Name ,
638
+ VolumeMode : & volumeMode ,
639
+ AccessModes : accessModes ,
640
+ ReclaimPolicy : ptr .Deref (class .ReclaimPolicy , v1 .PersistentVolumeReclaimDelete ),
641
+ PVSource : v1.PersistentVolumeSource {
642
+ CSI : & v1.CSIPersistentVolumeSource {
643
+ Driver : class .Provisioner ,
644
+ VolumeHandle : "test-volume-handle" ,
645
+ },
646
+ },
647
+ }
648
+
649
+ pvcConfig := e2epv.PersistentVolumeClaimConfig {
650
+ ClaimSize : t .ClaimSize ,
651
+ StorageClassName : & (class .Name ),
652
+ VolumeMode : & volumeMode ,
653
+ AccessModes : accessModes ,
654
+ }
655
+
656
+ volume , claim , err := e2epv .CreatePVPVC (ctx , cs , t .Timeouts , pvConfig , pvcConfig , ns , true )
657
+ framework .ExpectNoError (err , "Failed to create PV and PVC" )
658
+
659
+ err = e2epv .WaitOnPVandPVC (ctx , cs , t .Timeouts , ns , volume , claim )
660
+ framework .ExpectNoError (err , "Failed waiting for PV and PVC to be bound each other" )
661
+
662
+ return class , volume , claim
663
+ }
664
+
526
665
func startPausePod (ctx context.Context , cs clientset.Interface , t testsuites.StorageClassTest , node e2epod.NodeSelection , scName , ns string ) (* storagev1.StorageClass , * v1.PersistentVolumeClaim , * v1.Pod ) {
527
666
class , claim := createClaim (ctx , cs , t , node , scName , ns , nil )
528
667
0 commit comments