@@ -3,12 +3,15 @@ package e2e
33import (
44 "context"
55 "fmt"
6+ e2epv "k8s.io/kubernetes/test/e2e/framework/pv"
7+ e2evolume "k8s.io/kubernetes/test/e2e/framework/volume"
68 "os"
79 "strconv"
810 "strings"
911 "time"
1012
1113 ginkgo "github.com/onsi/ginkgo/v2"
14+ "k8s.io/apimachinery/pkg/labels"
1215 "k8s.io/apimachinery/pkg/util/rand"
1316 "k8s.io/kubernetes/test/e2e/framework/kubectl"
1417
@@ -416,6 +419,98 @@ var _ = ginkgo.Describe("[efs-csi] EFS CSI", func() {
416419 }
417420 })
418421
422+ createProvisionedDirectory := func (f * framework.Framework , basePath string , pvcName string ) (* v1.PersistentVolumeClaim , * storagev1.StorageClass ) {
423+ immediateBinding := storagev1 .VolumeBindingImmediate
424+ sc := storageframework .GetStorageClass ("efs.csi.aws.com" , map [string ]string {
425+ "provisioningMode" : "efs-dir" ,
426+ "fileSystemId" : FileSystemId ,
427+ "basePath" : basePath ,
428+ }, & immediateBinding , f .Namespace .Name )
429+ sc , err := f .ClientSet .StorageV1 ().StorageClasses ().Create (context .TODO (), sc , metav1.CreateOptions {})
430+ framework .Logf ("Created StorageClass %s" , sc .Name )
431+ framework .ExpectNoError (err , "creating dynamic provisioning storage class" )
432+ pvc := makeEFSPVC (f .Namespace .Name , pvcName , sc .Name )
433+ pvc , err = f .ClientSet .CoreV1 ().PersistentVolumeClaims (f .Namespace .Name ).Create (context .TODO (), pvc , metav1.CreateOptions {})
434+ err = e2epv .WaitForPersistentVolumeClaimPhase (v1 .ClaimBound , f .ClientSet , f .Namespace .Name , pvc .Name ,
435+ time .Second * 5 , time .Minute )
436+ framework .ExpectNoError (err , "waiting for pv to be provisioned and bound" )
437+ pvc , err = f .ClientSet .CoreV1 ().PersistentVolumeClaims (f .Namespace .Name ).Get (context .TODO (), pvc .Name , metav1.GetOptions {})
438+
439+ framework .Logf ("Created PVC %s, bound to PV %s by dynamic provisioning" , sc .Name , pvc .Name , pvc .Spec .VolumeName )
440+ return pvc , sc
441+ }
442+
443+ ginkgo .It ("should create a directory with the correct permissions when in directory provisioning mode" , func () {
444+ basePath := "dynamic_provisioning"
445+ dynamicPvc , sc := createProvisionedDirectory (f , basePath , "directory-pvc-1" )
446+ defer func () {
447+ err := f .ClientSet .StorageV1 ().StorageClasses ().Delete (context .TODO (), sc .Name , metav1.DeleteOptions {})
448+ framework .ExpectNoError (err , "removing provisioned StorageClass" )
449+ framework .Logf ("Deleted StorageClass %s" , sc .Name )
450+ }()
451+
452+ pvc , pv , err := createEFSPVCPV (f .ClientSet , f .Namespace .Name , "root-dir-pvc-create" , "/" , map [string ]string {})
453+ defer func () {
454+ _ = f .ClientSet .CoreV1 ().PersistentVolumeClaims (f .Namespace .Name ).Delete (context .TODO (), pvc .Name , metav1.DeleteOptions {})
455+ _ = f .ClientSet .CoreV1 ().PersistentVolumes ().Delete (context .TODO (), pv .Name , metav1.DeleteOptions {})
456+ }()
457+ framework .ExpectNoError (err , "creating root mounted pv, pvc to check" )
458+
459+ podSpec := e2epod .MakePod (f .Namespace .Name , nil , []* v1.PersistentVolumeClaim {pvc }, false , "" )
460+ podSpec .Spec .RestartPolicy = v1 .RestartPolicyNever
461+ pod , err := f .ClientSet .CoreV1 ().Pods (f .Namespace .Name ).Create (context .TODO (), podSpec , metav1.CreateOptions {})
462+ framework .ExpectNoError (err , "creating pod" )
463+ err = e2epod .WaitForPodRunningInNamespace (f .ClientSet , pod )
464+ framework .ExpectNoError (err , "pod started running successfully" )
465+
466+ provisionedPath := fmt .Sprintf ("/mnt/volume1/%s/%s" , basePath , dynamicPvc .Spec .VolumeName )
467+
468+ perms , _ , err := e2evolume .PodExec (f , pod , "stat -c \" %a\" " + provisionedPath )
469+ framework .ExpectNoError (err , "ran stat command in /mnt/volume1 to get folder permissions" )
470+ framework .Logf ("Perms Output: %s" , perms )
471+ framework .ExpectEqual (perms , fmt .Sprintf ("%d" , 777 ), "Checking File Permissions of mounted folder" )
472+
473+ _ = f .ClientSet .CoreV1 ().Pods (f .Namespace .Name ).Delete (context .TODO (), pod .Name , metav1.DeleteOptions {})
474+ err = e2epod .WaitForPodToDisappear (f .ClientSet , f .Namespace .Name , pod .Name , labels .Everything (), time .Second * 5 , time .Second * 60 )
475+ framework .ExpectNoError (err , "Cleaning up no longer required pod" )
476+ })
477+
478+ ginkgo .It ("should delete a directory provisioned in directory provisioning mode" , func () {
479+ basePath := "dynamic_provisioning_delete"
480+ pvc , sc := createProvisionedDirectory (f , basePath , "directory-pvc-2" )
481+ defer func () {
482+ err := f .ClientSet .StorageV1 ().StorageClasses ().Delete (context .TODO (), sc .Name , metav1.DeleteOptions {})
483+ framework .ExpectNoError (err , "removing provisioned StorageClass" )
484+ framework .Logf ("Deleted StorageClass %s" , sc .Name )
485+ }()
486+ volumeName := pvc .Spec .VolumeName
487+
488+ err := f .ClientSet .CoreV1 ().PersistentVolumeClaims (f .Namespace .Name ).Delete (context .TODO (), pvc .Name ,
489+ metav1.DeleteOptions {})
490+ framework .ExpectNoError (err , "deleting pvc" )
491+
492+ pvc , pv , err := createEFSPVCPV (f .ClientSet , f .Namespace .Name , "root-dir-pvc-delete" , "/" , map [string ]string {})
493+ defer func () {
494+ _ = f .ClientSet .CoreV1 ().PersistentVolumeClaims (f .Namespace .Name ).Delete (context .TODO (), pvc .Name , metav1.DeleteOptions {})
495+ _ = f .ClientSet .CoreV1 ().PersistentVolumes ().Delete (context .TODO (), pv .Name , metav1.DeleteOptions {})
496+ }()
497+ framework .ExpectNoError (err , "creating root mounted pv, pvc to check" )
498+
499+ podSpec := e2epod .MakePod (f .Namespace .Name , nil , []* v1.PersistentVolumeClaim {pvc }, false , "" )
500+ podSpec .Spec .RestartPolicy = v1 .RestartPolicyNever
501+ pod , err := f .ClientSet .CoreV1 ().Pods (f .Namespace .Name ).Create (context .TODO (), podSpec , metav1.CreateOptions {})
502+ framework .ExpectNoError (err , "creating pod" )
503+ err = e2epod .WaitForPodRunningInNamespace (f .ClientSet , pod )
504+ framework .ExpectNoError (err , "pod started running successfully" )
505+
506+ e2evolume .VerifyExecInPodFail (f , pod , "test -d " + "/mnt/volume1/" + basePath + "/" + volumeName , 1 )
507+
508+ _ = f .ClientSet .CoreV1 ().Pods (f .Namespace .Name ).Delete (context .TODO (), pod .Name , metav1.DeleteOptions {})
509+ err = e2epod .WaitForPodToDisappear (f .ClientSet , f .Namespace .Name , pod .Name , labels .Everything (), time .Second * 5 , time .Second * 60 )
510+ framework .ExpectNoError (err , "Cleaning up no longer required pod" )
511+
512+ })
513+
419514 })
420515})
421516
@@ -476,7 +571,7 @@ func createEFSPVCPV(c clientset.Interface, namespace, name, path string, volumeA
476571}
477572
478573func makeEFSPVCPV (namespace , name , path string , volumeAttributes map [string ]string ) (* v1.PersistentVolumeClaim , * v1.PersistentVolume ) {
479- pvc := makeEFSPVC (namespace , name )
574+ pvc := makeEFSPVC (namespace , name , "" )
480575 pv := makeEFSPV (name , path , volumeAttributes )
481576 pvc .Spec .VolumeName = pv .Name
482577 pv .Spec .ClaimRef = & v1.ObjectReference {
@@ -486,8 +581,7 @@ func makeEFSPVCPV(namespace, name, path string, volumeAttributes map[string]stri
486581 return pvc , pv
487582}
488583
489- func makeEFSPVC (namespace , name string ) * v1.PersistentVolumeClaim {
490- storageClassName := ""
584+ func makeEFSPVC (namespace , name string , storageClassName string ) * v1.PersistentVolumeClaim {
491585 return & v1.PersistentVolumeClaim {
492586 ObjectMeta : metav1.ObjectMeta {
493587 Name : name ,
0 commit comments