k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/e2e/storage/csimock/csi_attach_volume.go (about) 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 csimock 18 19 import ( 20 "context" 21 "fmt" 22 "time" 23 24 "github.com/onsi/ginkgo/v2" 25 "github.com/onsi/gomega" 26 27 v1 "k8s.io/api/core/v1" 28 apierrors "k8s.io/apimachinery/pkg/api/errors" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/apimachinery/pkg/fields" 31 "k8s.io/kubernetes/pkg/kubelet/events" 32 "k8s.io/kubernetes/test/e2e/framework" 33 e2eevents "k8s.io/kubernetes/test/e2e/framework/events" 34 e2epod "k8s.io/kubernetes/test/e2e/framework/pod" 35 e2evolume "k8s.io/kubernetes/test/e2e/framework/volume" 36 storageframework "k8s.io/kubernetes/test/e2e/storage/framework" 37 "k8s.io/kubernetes/test/e2e/storage/utils" 38 admissionapi "k8s.io/pod-security-admission/api" 39 ) 40 41 var _ = utils.SIGDescribe("CSI Mock volume attach", func() { 42 // The CSIDriverRegistry feature gate is needed for this test in Kubernetes 1.12. 43 f := framework.NewDefaultFramework("csi-mock-volumes-attach") 44 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 45 m := newMockDriverSetup(f) 46 47 ginkgo.Context("CSI attach test using mock driver", func() { 48 tests := []struct { 49 name string 50 disableAttach bool 51 deployClusterRegistrar bool 52 volumeType volumeType 53 }{ 54 { 55 name: "should not require VolumeAttach for drivers without attachment", 56 disableAttach: true, 57 deployClusterRegistrar: true, 58 }, 59 { 60 name: "should require VolumeAttach for drivers with attachment", 61 deployClusterRegistrar: true, 62 }, 63 { 64 name: "should require VolumeAttach for ephemermal volume and drivers with attachment", 65 deployClusterRegistrar: true, 66 volumeType: genericEphemeral, 67 }, 68 { 69 name: "should preserve attachment policy when no CSIDriver present", 70 deployClusterRegistrar: false, 71 }, 72 } 73 for _, t := range tests { 74 test := t 75 ginkgo.It(t.name, func(ctx context.Context) { 76 var err error 77 m.init(ctx, testParameters{registerDriver: test.deployClusterRegistrar, disableAttach: test.disableAttach}) 78 ginkgo.DeferCleanup(m.cleanup) 79 80 volumeType := test.volumeType 81 if volumeType == "" { 82 volumeType = pvcReference 83 } 84 _, claim, pod := m.createPod(ctx, volumeType) 85 if pod == nil { 86 return 87 } 88 err = e2epod.WaitForPodNameRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace) 89 framework.ExpectNoError(err, "Failed to start pod: %v", err) 90 91 ginkgo.By("Checking if VolumeAttachment was created for the pod") 92 testConfig := storageframework.ConvertTestConfig(m.config) 93 attachmentName := e2evolume.GetVolumeAttachmentName(ctx, m.cs, testConfig, m.provisioner, claim.Name, claim.Namespace) 94 _, err = m.cs.StorageV1().VolumeAttachments().Get(context.TODO(), attachmentName, metav1.GetOptions{}) 95 if err != nil { 96 if apierrors.IsNotFound(err) { 97 if !test.disableAttach { 98 framework.ExpectNoError(err, "Expected VolumeAttachment but none was found") 99 } 100 } else { 101 framework.ExpectNoError(err, "Failed to find VolumeAttachment") 102 } 103 } 104 if test.disableAttach { 105 gomega.Expect(err).To(gomega.MatchError(apierrors.IsNotFound, "Unexpected VolumeAttachment found")) 106 } 107 }) 108 109 } 110 }) 111 112 ginkgo.Context("CSI CSIDriver deployment after pod creation using non-attachable mock driver", func() { 113 f.It("should bringup pod after deploying CSIDriver attach=false", f.WithSlow(), func(ctx context.Context) { 114 var err error 115 m.init(ctx, testParameters{registerDriver: false, disableAttach: true}) 116 ginkgo.DeferCleanup(m.cleanup) 117 118 _, claim, pod := m.createPod(ctx, pvcReference) // late binding as specified above 119 if pod == nil { 120 return 121 } 122 123 ginkgo.By("Checking if attaching failed and pod cannot start") 124 eventSelector := fields.Set{ 125 "involvedObject.kind": "Pod", 126 "involvedObject.name": pod.Name, 127 "involvedObject.namespace": pod.Namespace, 128 "reason": events.FailedAttachVolume, 129 }.AsSelector().String() 130 msg := "AttachVolume.Attach failed for volume" 131 132 err = e2eevents.WaitTimeoutForEvent(ctx, m.cs, pod.Namespace, eventSelector, msg, f.Timeouts.PodStart) 133 if err != nil { 134 getPod := e2epod.Get(m.cs, pod) 135 gomega.Consistently(ctx, getPod).WithTimeout(10*time.Second).Should(e2epod.BeInPhase(v1.PodPending), 136 "Pod should not be in running status because attaching should failed") 137 // Events are unreliable, don't depend on the event. It's used only to speed up the test. 138 framework.Logf("Attach should fail and the corresponding event should show up, error: %v", err) 139 } 140 141 // VolumeAttachment should be created because the default value for CSI attachable is true 142 ginkgo.By("Checking if VolumeAttachment was created for the pod") 143 testConfig := storageframework.ConvertTestConfig(m.config) 144 attachmentName := e2evolume.GetVolumeAttachmentName(ctx, m.cs, testConfig, m.provisioner, claim.Name, claim.Namespace) 145 _, err = m.cs.StorageV1().VolumeAttachments().Get(context.TODO(), attachmentName, metav1.GetOptions{}) 146 if err != nil { 147 if apierrors.IsNotFound(err) { 148 framework.ExpectNoError(err, "Expected VolumeAttachment but none was found") 149 } else { 150 framework.ExpectNoError(err, "Failed to find VolumeAttachment") 151 } 152 } 153 154 ginkgo.By("Deploy CSIDriver object with attachRequired=false") 155 driverNamespace := m.config.DriverNamespace 156 157 canAttach := false 158 o := utils.PatchCSIOptions{ 159 OldDriverName: "csi-mock", 160 NewDriverName: "csi-mock-" + f.UniqueName, 161 CanAttach: &canAttach, 162 } 163 err = utils.CreateFromManifests(ctx, f, driverNamespace, func(item interface{}) error { 164 return utils.PatchCSIDeployment(f, o, item) 165 }, "test/e2e/testing-manifests/storage-csi/mock/csi-mock-driverinfo.yaml") 166 if err != nil { 167 framework.Failf("fail to deploy CSIDriver object: %v", err) 168 } 169 170 ginkgo.By("Wait for the pod in running status") 171 err = e2epod.WaitForPodNameRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace) 172 framework.ExpectNoError(err, "Failed to start pod: %v", err) 173 174 ginkgo.By(fmt.Sprintf("Wait for the volumeattachment to be deleted up to %v", csiVolumeAttachmentTimeout)) 175 // This step can be slow because we have to wait either a NodeUpdate event happens or 176 // the detachment for this volume timeout so that we can do a force detach. 177 err = e2evolume.WaitForVolumeAttachmentTerminated(ctx, attachmentName, m.cs, csiVolumeAttachmentTimeout) 178 framework.ExpectNoError(err, "Failed to delete VolumeAttachment: %v", err) 179 }) 180 }) 181 })