k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/e2e/storage/flexvolume_mounted_volume_resize.go (about) 1 /* 2 Copyright 2018 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 storage 18 19 import ( 20 "context" 21 "fmt" 22 "github.com/onsi/ginkgo/v2" 23 "github.com/onsi/gomega" 24 v1 "k8s.io/api/core/v1" 25 storagev1 "k8s.io/api/storage/v1" 26 "k8s.io/apimachinery/pkg/api/resource" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 utilerrors "k8s.io/apimachinery/pkg/util/errors" 29 clientset "k8s.io/client-go/kubernetes" 30 "k8s.io/kubernetes/test/e2e/feature" 31 "k8s.io/kubernetes/test/e2e/framework" 32 e2edeployment "k8s.io/kubernetes/test/e2e/framework/deployment" 33 e2enode "k8s.io/kubernetes/test/e2e/framework/node" 34 e2epod "k8s.io/kubernetes/test/e2e/framework/pod" 35 e2epv "k8s.io/kubernetes/test/e2e/framework/pv" 36 e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" 37 "k8s.io/kubernetes/test/e2e/storage/testsuites" 38 "k8s.io/kubernetes/test/e2e/storage/utils" 39 admissionapi "k8s.io/pod-security-admission/api" 40 "path" 41 ) 42 43 var _ = utils.SIGDescribe(feature.Flexvolumes, "Mounted flexvolume expand", framework.WithSlow(), func() { 44 var ( 45 c clientset.Interface 46 ns string 47 err error 48 pvc *v1.PersistentVolumeClaim 49 resizableSc *storagev1.StorageClass 50 node *v1.Node 51 nodeName string 52 nodeKeyValueLabel map[string]string 53 nodeLabelValue string 54 nodeKey string 55 ) 56 57 f := framework.NewDefaultFramework("mounted-flexvolume-expand") 58 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 59 ginkgo.BeforeEach(func(ctx context.Context) { 60 e2eskipper.SkipUnlessProviderIs("aws", "gce", "local") 61 e2eskipper.SkipUnlessMasterOSDistroIs("debian", "ubuntu", "gci", "custom") 62 e2eskipper.SkipUnlessNodeOSDistroIs("debian", "ubuntu", "gci", "custom") 63 e2eskipper.SkipUnlessSSHKeyPresent() 64 c = f.ClientSet 65 ns = f.Namespace.Name 66 framework.ExpectNoError(e2enode.WaitForAllNodesSchedulable(ctx, c, f.Timeouts.NodeSchedulable)) 67 68 node, err = e2enode.GetRandomReadySchedulableNode(ctx, f.ClientSet) 69 framework.ExpectNoError(err) 70 nodeName = node.Name 71 72 nodeKey = "mounted_flexvolume_expand_" + ns 73 nodeLabelValue = ns 74 nodeKeyValueLabel = map[string]string{nodeKey: nodeLabelValue} 75 e2enode.AddOrUpdateLabelOnNode(c, nodeName, nodeKey, nodeLabelValue) 76 ginkgo.DeferCleanup(e2enode.RemoveLabelOffNode, c, nodeName, nodeKey) 77 78 test := testsuites.StorageClassTest{ 79 Name: "flexvolume-resize", 80 Timeouts: f.Timeouts, 81 ClaimSize: "2Gi", 82 AllowVolumeExpansion: true, 83 Provisioner: "flex-expand", 84 } 85 86 resizableSc, err = c.StorageV1().StorageClasses().Create(ctx, newStorageClass(test, ns, "resizing"), metav1.CreateOptions{}) 87 if err != nil { 88 fmt.Printf("storage class creation error: %v\n", err) 89 } 90 framework.ExpectNoError(err, "Error creating resizable storage class") 91 if !*resizableSc.AllowVolumeExpansion { 92 framework.Failf("Class %s does not allow volume expansion", resizableSc.Name) 93 } 94 95 pvc = e2epv.MakePersistentVolumeClaim(e2epv.PersistentVolumeClaimConfig{ 96 StorageClassName: &(resizableSc.Name), 97 ClaimSize: "2Gi", 98 }, ns) 99 pvc, err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Create(ctx, pvc, metav1.CreateOptions{}) 100 framework.ExpectNoError(err, "Error creating pvc") 101 ginkgo.DeferCleanup(func(ctx context.Context) { 102 framework.Logf("AfterEach: Cleaning up resources for mounted volume resize") 103 if errs := e2epv.PVPVCCleanup(ctx, c, ns, nil, pvc); len(errs) > 0 { 104 framework.Failf("AfterEach: Failed to delete PVC and/or PV. Errors: %v", utilerrors.NewAggregate(errs)) 105 } 106 }) 107 }) 108 109 ginkgo.It("Should verify mounted flex volumes can be resized", func(ctx context.Context) { 110 driver := "dummy-attachable" 111 ginkgo.By(fmt.Sprintf("installing flexvolume %s on node %s as %s", path.Join(driverDir, driver), node.Name, driver)) 112 installFlex(ctx, c, node, "k8s", driver, path.Join(driverDir, driver)) 113 ginkgo.By(fmt.Sprintf("installing flexvolume %s on (master) node %s as %s", path.Join(driverDir, driver), node.Name, driver)) 114 installFlex(ctx, c, nil, "k8s", driver, path.Join(driverDir, driver)) 115 116 pv := e2epv.MakePersistentVolume(e2epv.PersistentVolumeConfig{ 117 PVSource: v1.PersistentVolumeSource{ 118 FlexVolume: &v1.FlexPersistentVolumeSource{ 119 Driver: "k8s/" + driver, 120 }}, 121 NamePrefix: "pv-", 122 StorageClassName: resizableSc.Name, 123 VolumeMode: pvc.Spec.VolumeMode, 124 }) 125 126 _, err = e2epv.CreatePV(ctx, c, f.Timeouts, pv) 127 framework.ExpectNoError(err, "Error creating pv %v", err) 128 129 ginkgo.By("Waiting for PVC to be in bound phase") 130 pvcClaims := []*v1.PersistentVolumeClaim{pvc} 131 var pvs []*v1.PersistentVolume 132 133 pvs, err = e2epv.WaitForPVClaimBoundPhase(ctx, c, pvcClaims, framework.ClaimProvisionTimeout) 134 framework.ExpectNoError(err, "Failed waiting for PVC to be bound %v", err) 135 gomega.Expect(pvs).To(gomega.HaveLen(1)) 136 137 ginkgo.By("Creating a deployment with the provisioned volume") 138 deployment, err := e2edeployment.CreateDeployment(ctx, c, int32(1), map[string]string{"test": "app"}, nodeKeyValueLabel, ns, pvcClaims, admissionapi.LevelRestricted, "") 139 framework.ExpectNoError(err, "Failed creating deployment %v", err) 140 ginkgo.DeferCleanup(c.AppsV1().Deployments(ns).Delete, deployment.Name, metav1.DeleteOptions{}) 141 142 ginkgo.By("Expanding current pvc") 143 newSize := resource.MustParse("6Gi") 144 newPVC, err := testsuites.ExpandPVCSize(ctx, pvc, newSize, c) 145 framework.ExpectNoError(err, "While updating pvc for more size") 146 pvc = newPVC 147 gomega.Expect(pvc).NotTo(gomega.BeNil()) 148 149 pvcSize := pvc.Spec.Resources.Requests[v1.ResourceStorage] 150 if pvcSize.Cmp(newSize) != 0 { 151 framework.Failf("error updating pvc size %q", pvc.Name) 152 } 153 154 ginkgo.By("Waiting for cloudprovider resize to finish") 155 err = testsuites.WaitForControllerVolumeResize(ctx, pvc, c, totalResizeWaitPeriod) 156 framework.ExpectNoError(err, "While waiting for pvc resize to finish") 157 158 ginkgo.By("Getting a pod from deployment") 159 podList, err := e2edeployment.GetPodsForDeployment(ctx, c, deployment) 160 framework.ExpectNoError(err, "While getting pods from deployment") 161 gomega.Expect(podList.Items).NotTo(gomega.BeEmpty()) 162 pod := podList.Items[0] 163 164 ginkgo.By("Deleting the pod from deployment") 165 err = e2epod.DeletePodWithWait(ctx, c, &pod) 166 framework.ExpectNoError(err, "while deleting pod for resizing") 167 168 ginkgo.By("Waiting for deployment to create new pod") 169 pod, err = waitForDeploymentToRecreatePod(ctx, c, deployment) 170 framework.ExpectNoError(err, "While waiting for pod to be recreated") 171 172 ginkgo.By("Waiting for file system resize to finish") 173 pvc, err = testsuites.WaitForFSResize(ctx, pvc, c) 174 framework.ExpectNoError(err, "while waiting for fs resize to finish") 175 176 pvcConditions := pvc.Status.Conditions 177 gomega.Expect(pvcConditions).To(gomega.BeEmpty(), "pvc should not have conditions") 178 }) 179 })