k8s.io/kubernetes@v1.29.3/test/e2e/storage/persistent_volumes-gce.go (about) 1 /* 2 Copyright 2017 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 22 "github.com/onsi/ginkgo/v2" 23 24 v1 "k8s.io/api/core/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/labels" 27 "k8s.io/apimachinery/pkg/types" 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 e2epod "k8s.io/kubernetes/test/e2e/framework/pod" 33 "k8s.io/kubernetes/test/e2e/framework/providers/gce" 34 e2epv "k8s.io/kubernetes/test/e2e/framework/pv" 35 e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" 36 "k8s.io/kubernetes/test/e2e/storage/utils" 37 admissionapi "k8s.io/pod-security-admission/api" 38 ) 39 40 // verifyGCEDiskAttached performs a sanity check to verify the PD attached to the node 41 func verifyGCEDiskAttached(diskName string, nodeName types.NodeName) bool { 42 gceCloud, err := gce.GetGCECloud() 43 framework.ExpectNoError(err) 44 isAttached, err := gceCloud.DiskIsAttached(diskName, nodeName) 45 framework.ExpectNoError(err) 46 return isAttached 47 } 48 49 // initializeGCETestSpec creates a PV, PVC, and ClientPod that will run until killed by test or clean up. 50 func initializeGCETestSpec(ctx context.Context, c clientset.Interface, t *framework.TimeoutContext, ns string, pvConfig e2epv.PersistentVolumeConfig, pvcConfig e2epv.PersistentVolumeClaimConfig, isPrebound bool) (*v1.Pod, *v1.PersistentVolume, *v1.PersistentVolumeClaim) { 51 ginkgo.By("Creating the PV and PVC") 52 pv, pvc, err := e2epv.CreatePVPVC(ctx, c, t, pvConfig, pvcConfig, ns, isPrebound) 53 framework.ExpectNoError(err) 54 framework.ExpectNoError(e2epv.WaitOnPVandPVC(ctx, c, t, ns, pv, pvc)) 55 56 ginkgo.By("Creating the Client Pod") 57 clientPod, err := e2epod.CreateClientPod(ctx, c, ns, pvc) 58 framework.ExpectNoError(err) 59 return clientPod, pv, pvc 60 } 61 62 // Testing configurations of single a PV/PVC pair attached to a GCE PD 63 var _ = utils.SIGDescribe("PersistentVolumes GCEPD", feature.StorageProvider, func() { 64 var ( 65 c clientset.Interface 66 diskName string 67 ns string 68 err error 69 pv *v1.PersistentVolume 70 pvc *v1.PersistentVolumeClaim 71 clientPod *v1.Pod 72 pvConfig e2epv.PersistentVolumeConfig 73 pvcConfig e2epv.PersistentVolumeClaimConfig 74 volLabel labels.Set 75 selector *metav1.LabelSelector 76 node types.NodeName 77 ) 78 79 f := framework.NewDefaultFramework("pv") 80 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 81 ginkgo.BeforeEach(func(ctx context.Context) { 82 c = f.ClientSet 83 ns = f.Namespace.Name 84 85 // Enforce binding only within test space via selector labels 86 volLabel = labels.Set{e2epv.VolumeSelectorKey: ns} 87 selector = metav1.SetAsLabelSelector(volLabel) 88 89 e2eskipper.SkipUnlessProviderIs("gce", "gke") 90 ginkgo.By("Initializing Test Spec") 91 diskName, err = e2epv.CreatePDWithRetry(ctx) 92 framework.ExpectNoError(err) 93 94 pvConfig = e2epv.PersistentVolumeConfig{ 95 NamePrefix: "gce-", 96 Labels: volLabel, 97 PVSource: v1.PersistentVolumeSource{ 98 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ 99 PDName: diskName, 100 FSType: e2epv.GetDefaultFSType(), 101 ReadOnly: false, 102 }, 103 }, 104 Prebind: nil, 105 } 106 emptyStorageClass := "" 107 pvcConfig = e2epv.PersistentVolumeClaimConfig{ 108 Selector: selector, 109 StorageClassName: &emptyStorageClass, 110 } 111 clientPod, pv, pvc = initializeGCETestSpec(ctx, c, f.Timeouts, ns, pvConfig, pvcConfig, false) 112 node = types.NodeName(clientPod.Spec.NodeName) 113 }) 114 115 ginkgo.AfterEach(func(ctx context.Context) { 116 framework.Logf("AfterEach: Cleaning up test resources") 117 if c != nil { 118 framework.ExpectNoError(e2epod.DeletePodWithWait(ctx, c, clientPod)) 119 if errs := e2epv.PVPVCCleanup(ctx, c, ns, pv, pvc); len(errs) > 0 { 120 framework.Failf("AfterEach: Failed to delete PVC and/or PV. Errors: %v", utilerrors.NewAggregate(errs)) 121 } 122 clientPod, pv, pvc, node = nil, nil, nil, "" 123 if diskName != "" { 124 framework.ExpectNoError(e2epv.DeletePDWithRetry(ctx, diskName)) 125 } 126 } 127 }) 128 129 // Attach a persistent disk to a pod using a PVC. 130 // Delete the PVC and then the pod. Expect the pod to succeed in unmounting and detaching PD on delete. 131 ginkgo.It("should test that deleting a PVC before the pod does not cause pod deletion to fail on PD detach", func(ctx context.Context) { 132 133 ginkgo.By("Deleting the Claim") 134 framework.ExpectNoError(e2epv.DeletePersistentVolumeClaim(ctx, c, pvc.Name, ns), "Unable to delete PVC ", pvc.Name) 135 if !verifyGCEDiskAttached(diskName, node) { 136 framework.Failf("Disk %s is not attached to node %s", diskName, node) 137 } 138 139 ginkgo.By("Deleting the Pod") 140 framework.ExpectNoError(e2epod.DeletePodWithWait(ctx, c, clientPod), "Failed to delete pod ", clientPod.Name) 141 142 ginkgo.By("Verifying Persistent Disk detach") 143 framework.ExpectNoError(waitForPDDetach(diskName, node), "PD ", diskName, " did not detach") 144 }) 145 146 // Attach a persistent disk to a pod using a PVC. 147 // Delete the PV and then the pod. Expect the pod to succeed in unmounting and detaching PD on delete. 148 ginkgo.It("should test that deleting the PV before the pod does not cause pod deletion to fail on PD detach", func(ctx context.Context) { 149 150 ginkgo.By("Deleting the Persistent Volume") 151 framework.ExpectNoError(e2epv.DeletePersistentVolume(ctx, c, pv.Name), "Failed to delete PV ", pv.Name) 152 if !verifyGCEDiskAttached(diskName, node) { 153 framework.Failf("Disk %s is not attached to node %s", diskName, node) 154 } 155 156 ginkgo.By("Deleting the client pod") 157 framework.ExpectNoError(e2epod.DeletePodWithWait(ctx, c, clientPod), "Failed to delete pod ", clientPod.Name) 158 159 ginkgo.By("Verifying Persistent Disk detaches") 160 framework.ExpectNoError(waitForPDDetach(diskName, node), "PD ", diskName, " did not detach") 161 }) 162 163 // Test that a Pod and PVC attached to a GCEPD successfully unmounts and detaches when the encompassing Namespace is deleted. 164 ginkgo.It("should test that deleting the Namespace of a PVC and Pod causes the successful detach of Persistent Disk", func(ctx context.Context) { 165 166 ginkgo.By("Deleting the Namespace") 167 err := c.CoreV1().Namespaces().Delete(ctx, ns, metav1.DeleteOptions{}) 168 framework.ExpectNoError(err) 169 170 // issue deletes for the client pod and claim, accelerating namespace controller actions 171 e2epod.DeletePodOrFail(ctx, c, clientPod.Namespace, clientPod.Name) 172 framework.ExpectNoError(e2epv.DeletePersistentVolumeClaim(ctx, c, pvc.Name, ns), "Unable to delete PVC ", pvc.Name) 173 174 ginkgo.By("Verifying Persistent Disk detaches") 175 framework.ExpectNoError(waitForPDDetach(diskName, node), "PD ", diskName, " did not detach") 176 }) 177 })