1
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
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)
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
137 framework.Logf("Attach should fail and the corresponding event should show up, error: %v", err)
138 }
139
140
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
175
176 err = e2evolume.WaitForVolumeAttachmentTerminated(ctx, attachmentName, m.cs, csiVolumeAttachmentTimeout)
177 framework.ExpectNoError(err, "Failed to delete VolumeAttachment: %v", err)
178 })
179 })
180 })
181
View as plain text