...

Source file src/k8s.io/kubernetes/test/e2e/storage/csi_mock/csi_fsgroup_policy.go

Documentation: k8s.io/kubernetes/test/e2e/storage/csi_mock

     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 csi_mock
    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  }
   198  

View as plain text