k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/e2e/storage/csimock/csi_fsgroup_policy.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package csimock 18 19 import ( 20 "context" 21 "fmt" 22 "math/rand" 23 "strconv" 24 25 "github.com/onsi/ginkgo/v2" 26 "github.com/onsi/gomega" 27 storagev1 "k8s.io/api/storage/v1" 28 "k8s.io/kubernetes/test/e2e/framework" 29 e2epod "k8s.io/kubernetes/test/e2e/framework/pod" 30 e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" 31 e2evolume "k8s.io/kubernetes/test/e2e/framework/volume" 32 "k8s.io/kubernetes/test/e2e/storage/utils" 33 admissionapi "k8s.io/pod-security-admission/api" 34 ) 35 36 var _ = utils.SIGDescribe("CSI Mock volume fsgroup policies", func() { 37 f := framework.NewDefaultFramework("csi-mock-volumes-fsgroup-policy") 38 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 39 m := newMockDriverSetup(f) 40 41 // These tests *only* work on a cluster which has the CSIVolumeFSGroupPolicy feature enabled. 42 ginkgo.Context("CSI FSGroupPolicy [LinuxOnly]", func() { 43 tests := []struct { 44 name string 45 fsGroupPolicy storagev1.FSGroupPolicy 46 modified bool 47 }{ 48 { 49 name: "should modify fsGroup if fsGroupPolicy=default", 50 fsGroupPolicy: storagev1.ReadWriteOnceWithFSTypeFSGroupPolicy, 51 modified: true, 52 }, 53 { 54 name: "should modify fsGroup if fsGroupPolicy=File", 55 fsGroupPolicy: storagev1.FileFSGroupPolicy, 56 modified: true, 57 }, 58 { 59 name: "should not modify fsGroup if fsGroupPolicy=None", 60 fsGroupPolicy: storagev1.NoneFSGroupPolicy, 61 modified: false, 62 }, 63 } 64 for _, t := range tests { 65 test := t 66 ginkgo.It(test.name, func(ctx context.Context) { 67 if framework.NodeOSDistroIs("windows") { 68 e2eskipper.Skipf("FSGroupPolicy is only applied on linux nodes -- skipping") 69 } 70 m.init(ctx, testParameters{ 71 disableAttach: true, 72 registerDriver: true, 73 fsGroupPolicy: &test.fsGroupPolicy, 74 }) 75 ginkgo.DeferCleanup(m.cleanup) 76 77 waitUtilFSGroupInPod(ctx, m, test.modified) 78 79 // The created resources will be removed by the cleanup() function, 80 // so need to delete anything here. 81 }) 82 } 83 }) 84 85 ginkgo.Context("CSI FSGroupPolicy Update [LinuxOnly]", func() { 86 tests := []struct { 87 name string 88 oldFSGroupPolicy storagev1.FSGroupPolicy 89 newFSGroupPolicy storagev1.FSGroupPolicy 90 }{ 91 { 92 name: "should update fsGroup if update from None to File", 93 oldFSGroupPolicy: storagev1.NoneFSGroupPolicy, 94 newFSGroupPolicy: storagev1.FileFSGroupPolicy, 95 }, 96 { 97 name: "should update fsGroup if update from None to default", 98 oldFSGroupPolicy: storagev1.NoneFSGroupPolicy, 99 newFSGroupPolicy: storagev1.ReadWriteOnceWithFSTypeFSGroupPolicy, 100 }, 101 { 102 name: "should not update fsGroup if update from File to None", 103 oldFSGroupPolicy: storagev1.FileFSGroupPolicy, 104 newFSGroupPolicy: storagev1.NoneFSGroupPolicy, 105 }, 106 { 107 name: "should update fsGroup if update from File to default", 108 oldFSGroupPolicy: storagev1.FileFSGroupPolicy, 109 newFSGroupPolicy: storagev1.ReadWriteOnceWithFSTypeFSGroupPolicy, 110 }, 111 { 112 name: "should not update fsGroup if update from detault to None", 113 oldFSGroupPolicy: storagev1.ReadWriteOnceWithFSTypeFSGroupPolicy, 114 newFSGroupPolicy: storagev1.NoneFSGroupPolicy, 115 }, 116 { 117 name: "should update fsGroup if update from detault to File", 118 oldFSGroupPolicy: storagev1.ReadWriteOnceWithFSTypeFSGroupPolicy, 119 newFSGroupPolicy: storagev1.FileFSGroupPolicy, 120 }, 121 } 122 for _, t := range tests { 123 test := t 124 ginkgo.It(test.name, func(ctx context.Context) { 125 if framework.NodeOSDistroIs("windows") { 126 e2eskipper.Skipf("FSGroupPolicy is only applied on linux nodes -- skipping") 127 } 128 m.init(ctx, testParameters{ 129 disableAttach: true, 130 registerDriver: true, 131 fsGroupPolicy: &test.oldFSGroupPolicy, 132 }) 133 ginkgo.DeferCleanup(m.cleanup) 134 135 waitUtilFSGroupInPod(ctx, m, test.oldFSGroupPolicy != storagev1.NoneFSGroupPolicy) 136 m.update(utils.PatchCSIOptions{FSGroupPolicy: &test.newFSGroupPolicy}) 137 waitUtilFSGroupInPod(ctx, m, test.newFSGroupPolicy != storagev1.NoneFSGroupPolicy) 138 139 // The created resources will be removed by the cleanup() function, 140 // so need to delete anything here. 141 }) 142 } 143 }) 144 }) 145 146 func waitUtilFSGroupInPod(ctx context.Context, m *mockDriverSetup, modified bool) { 147 var err error 148 149 utils.WaitUntil(framework.Poll, framework.PodStartTimeout, func() bool { 150 err = gomega.InterceptGomegaFailure(func() { 151 fsGroupVal := int64(rand.Int63n(20000) + 1024) 152 fsGroup := &fsGroupVal 153 154 _, _, pod := m.createPodWithFSGroup(ctx, fsGroup) /* persistent volume */ 155 defer func() { 156 err = e2epod.DeletePodWithWait(context.TODO(), m.f.ClientSet, pod) 157 framework.ExpectNoError(err, "failed: deleting the pod: %s", err) 158 }() 159 160 mountPath := pod.Spec.Containers[0].VolumeMounts[0].MountPath 161 dirName := mountPath + "/" + m.f.UniqueName 162 fileName := dirName + "/" + m.f.UniqueName 163 164 err = e2epod.WaitForPodNameRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace) 165 framework.ExpectNoError(err, "failed to start pod") 166 167 // Create the subdirectory to ensure that fsGroup propagates 168 createDirectory := fmt.Sprintf("mkdir %s", dirName) 169 _, _, err = e2evolume.PodExec(m.f, pod, createDirectory) 170 framework.ExpectNoError(err, "failed: creating the directory: %s", err) 171 172 // Inject the contents onto the mount 173 createFile := fmt.Sprintf("echo '%s' > '%s'; sync", "filecontents", fileName) 174 _, _, err = e2evolume.PodExec(m.f, pod, createFile) 175 framework.ExpectNoError(err, "failed: writing the contents: %s", err) 176 177 // Delete the created file. This step is mandatory, as the mock driver 178 // won't clean up the contents automatically. 179 defer func() { 180 deleteDir := fmt.Sprintf("rm -fr %s", dirName) 181 _, _, err = e2evolume.PodExec(m.f, pod, deleteDir) 182 framework.ExpectNoError(err, "failed: deleting the directory: %s", err) 183 }() 184 185 // Ensure that the fsGroup matches what we expect 186 if modified { 187 utils.VerifyFSGroupInPod(m.f, fileName, strconv.FormatInt(*fsGroup, 10), pod) 188 } else { 189 utils.VerifyFSGroupInPod(m.f, fileName, "root", pod) 190 } 191 }) 192 193 return err == nil 194 }) 195 196 framework.ExpectNoError(err, "failed: verifing fsgroup in pod: %s", err) 197 }