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