1
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 })
180
View as plain text