k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/e2e/storage/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 "github.com/onsi/ginkgo/v2" 22 "github.com/onsi/gomega" 23 v1 "k8s.io/api/core/v1" 24 storagev1 "k8s.io/api/storage/v1" 25 "k8s.io/apimachinery/pkg/api/resource" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 admissionapi "k8s.io/pod-security-admission/api" 28 29 utilerrors "k8s.io/apimachinery/pkg/util/errors" 30 clientset "k8s.io/client-go/kubernetes" 31 "k8s.io/kubernetes/test/e2e/feature" 32 "k8s.io/kubernetes/test/e2e/framework" 33 e2edeployment "k8s.io/kubernetes/test/e2e/framework/deployment" 34 e2enode "k8s.io/kubernetes/test/e2e/framework/node" 35 e2epod "k8s.io/kubernetes/test/e2e/framework/pod" 36 e2epv "k8s.io/kubernetes/test/e2e/framework/pv" 37 e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" 38 "k8s.io/kubernetes/test/e2e/storage/testsuites" 39 "k8s.io/kubernetes/test/e2e/storage/utils" 40 ) 41 42 var _ = utils.SIGDescribe("Mounted volume expand", feature.StorageProvider, func() { 43 var ( 44 c clientset.Interface 45 ns string 46 pvc *v1.PersistentVolumeClaim 47 sc *storagev1.StorageClass 48 nodeName string 49 nodeKeyValueLabel map[string]string 50 nodeLabelValue string 51 nodeKey string 52 ) 53 54 f := framework.NewDefaultFramework("mounted-volume-expand") 55 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 56 ginkgo.BeforeEach(func(ctx context.Context) { 57 e2eskipper.SkipUnlessProviderIs("aws", "gce") 58 c = f.ClientSet 59 ns = f.Namespace.Name 60 framework.ExpectNoError(e2enode.WaitForAllNodesSchedulable(ctx, c, f.Timeouts.NodeSchedulable)) 61 62 node, err := e2enode.GetRandomReadySchedulableNode(ctx, f.ClientSet) 63 framework.ExpectNoError(err) 64 nodeName = node.Name 65 66 nodeKey = "mounted_volume_expand_" + ns 67 nodeLabelValue = ns 68 nodeKeyValueLabel = map[string]string{nodeKey: nodeLabelValue} 69 e2enode.AddOrUpdateLabelOnNode(c, nodeName, nodeKey, nodeLabelValue) 70 ginkgo.DeferCleanup(e2enode.RemoveLabelOffNode, c, nodeName, nodeKey) 71 72 test := testsuites.StorageClassTest{ 73 Name: "default", 74 Timeouts: f.Timeouts, 75 ClaimSize: "2Gi", 76 AllowVolumeExpansion: true, 77 DelayBinding: true, 78 Parameters: make(map[string]string), 79 } 80 81 sc = testsuites.SetupStorageClass(ctx, c, newStorageClass(test, ns, "resizing")) 82 if !*sc.AllowVolumeExpansion { 83 framework.Failf("Class %s does not allow volume expansion", sc.Name) 84 } 85 86 pvc = e2epv.MakePersistentVolumeClaim(e2epv.PersistentVolumeClaimConfig{ 87 ClaimSize: test.ClaimSize, 88 StorageClassName: &(sc.Name), 89 VolumeMode: &test.VolumeMode, 90 }, ns) 91 pvc, err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Create(ctx, pvc, metav1.CreateOptions{}) 92 framework.ExpectNoError(err, "Error creating pvc") 93 ginkgo.DeferCleanup(func(ctx context.Context) { 94 framework.Logf("AfterEach: Cleaning up resources for mounted volume resize") 95 96 if errs := e2epv.PVPVCCleanup(ctx, c, ns, nil, pvc); len(errs) > 0 { 97 framework.Failf("AfterEach: Failed to delete PVC and/or PV. Errors: %v", utilerrors.NewAggregate(errs)) 98 } 99 }) 100 }) 101 102 ginkgo.It("Should verify mounted devices can be resized", func(ctx context.Context) { 103 pvcClaims := []*v1.PersistentVolumeClaim{pvc} 104 105 // The reason we use a node selector is because we do not want pod to move to different node when pod is deleted. 106 // Keeping pod on same node reproduces the scenario that volume might already be mounted when resize is attempted. 107 // We should consider adding a unit test that exercises this better. 108 ginkgo.By("Creating a deployment with selected PVC") 109 deployment, err := e2edeployment.CreateDeployment(ctx, c, int32(1), map[string]string{"test": "app"}, nodeKeyValueLabel, ns, pvcClaims, admissionapi.LevelRestricted, "") 110 framework.ExpectNoError(err, "Failed creating deployment %v", err) 111 ginkgo.DeferCleanup(c.AppsV1().Deployments(ns).Delete, deployment.Name, metav1.DeleteOptions{}) 112 113 // PVC should be bound at this point 114 ginkgo.By("Checking for bound PVC") 115 pvs, err := e2epv.WaitForPVClaimBoundPhase(ctx, c, pvcClaims, framework.ClaimProvisionTimeout) 116 framework.ExpectNoError(err, "Failed waiting for PVC to be bound %v", err) 117 gomega.Expect(pvs).To(gomega.HaveLen(1)) 118 119 ginkgo.By("Wait for a pod from deployment to be running") 120 podList, err := e2edeployment.GetPodsForDeployment(ctx, c, deployment) 121 framework.ExpectNoError(err, "While getting pods from deployment") 122 gomega.Expect(podList.Items).NotTo(gomega.BeEmpty()) 123 pod := podList.Items[0] 124 err = e2epod.WaitTimeoutForPodRunningInNamespace(ctx, c, pod.Name, pod.Namespace, f.Timeouts.PodStart) 125 framework.ExpectNoError(err, "While waiting for pods to be ready") 126 127 ginkgo.By("Expanding current pvc") 128 newSize := resource.MustParse("6Gi") 129 newPVC, err := testsuites.ExpandPVCSize(ctx, pvc, newSize, c) 130 framework.ExpectNoError(err, "While updating pvc for more size") 131 pvc = newPVC 132 gomega.Expect(pvc).NotTo(gomega.BeNil()) 133 134 pvcSize := pvc.Spec.Resources.Requests[v1.ResourceStorage] 135 if pvcSize.Cmp(newSize) != 0 { 136 framework.Failf("error updating pvc size %q", pvc.Name) 137 } 138 139 ginkgo.By("Waiting for cloudprovider resize to finish") 140 err = testsuites.WaitForControllerVolumeResize(ctx, pvc, c, totalResizeWaitPeriod) 141 framework.ExpectNoError(err, "While waiting for pvc resize to finish") 142 143 ginkgo.By("Getting a pod from deployment") 144 podList, err = e2edeployment.GetPodsForDeployment(ctx, c, deployment) 145 framework.ExpectNoError(err, "While getting pods from deployment") 146 gomega.Expect(podList.Items).NotTo(gomega.BeEmpty()) 147 pod = podList.Items[0] 148 149 ginkgo.By("Deleting the pod from deployment") 150 err = e2epod.DeletePodWithWait(ctx, c, &pod) 151 framework.ExpectNoError(err, "while deleting pod for resizing") 152 153 ginkgo.By("Waiting for deployment to create new pod") 154 pod, err = waitForDeploymentToRecreatePod(ctx, c, deployment) 155 framework.ExpectNoError(err, "While waiting for pod to be recreated") 156 157 ginkgo.By("Waiting for file system resize to finish") 158 pvc, err = testsuites.WaitForFSResize(ctx, pvc, c) 159 framework.ExpectNoError(err, "while waiting for fs resize to finish") 160 161 pvcConditions := pvc.Status.Conditions 162 gomega.Expect(pvcConditions).To(gomega.BeEmpty(), "pvc should not have conditions") 163 }) 164 })