@@ -24,9 +24,12 @@ import (
24
24
v1 "k8s.io/api/core/v1"
25
25
storagev1 "k8s.io/api/storage/v1"
26
26
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27
+ "k8s.io/apimachinery/pkg/fields"
27
28
clientset "k8s.io/client-go/kubernetes"
29
+ "k8s.io/kubernetes/pkg/kubelet/events"
28
30
"k8s.io/kubernetes/test/e2e/framework"
29
31
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
32
+ e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
30
33
"k8s.io/kubernetes/test/e2e/storage/testpatterns"
31
34
)
32
35
@@ -94,6 +97,11 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
94
97
// Now do the more expensive test initialization.
95
98
l .config , l .testCleanup = driver .PrepareTest (f )
96
99
l .intreeOps , l .migratedOps = getMigrationVolumeOpCounts (f .ClientSet , dInfo .InTreePluginName )
100
+ }
101
+
102
+ // manualInit initializes l.genericVolumeTestResource without creating the PV & PVC objects.
103
+ manualInit := func () {
104
+ init ()
97
105
98
106
fsType := pattern .FsType
99
107
volBindMode := storagev1 .VolumeBindingImmediate
@@ -167,7 +175,7 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
167
175
case testpatterns .PreprovisionedPV :
168
176
if pattern .VolMode == v1 .PersistentVolumeBlock && ! isBlockSupported {
169
177
ginkgo .It ("should fail to create pod by failing to mount volume [Slow]" , func () {
170
- init ()
178
+ manualInit ()
171
179
defer cleanup ()
172
180
173
181
var err error
@@ -196,13 +204,12 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
196
204
}()
197
205
framework .ExpectError (err )
198
206
})
199
- // TODO(mkimuram): Add more tests
200
207
}
201
208
202
209
case testpatterns .DynamicPV :
203
210
if pattern .VolMode == v1 .PersistentVolumeBlock && ! isBlockSupported {
204
211
ginkgo .It ("should fail in binding dynamic provisioned PV to PVC [Slow]" , func () {
205
- init ()
212
+ manualInit ()
206
213
defer cleanup ()
207
214
208
215
var err error
@@ -218,12 +225,57 @@ func (t *volumeModeTestSuite) defineTests(driver TestDriver, pattern testpattern
218
225
err = framework .WaitForPersistentVolumeClaimPhase (v1 .ClaimBound , l .cs , l .pvc .Namespace , l .pvc .Name , framework .Poll , framework .ClaimProvisionTimeout )
219
226
framework .ExpectError (err )
220
227
})
221
- // TODO(mkimuram): Add more tests
222
228
}
223
229
default :
224
230
e2elog .Failf ("Volume mode test doesn't support volType: %v" , pattern .VolType )
225
231
}
226
232
233
+ ginkgo .It ("should fail to use a volume in a pod with mismatched mode [Slow]" , func () {
234
+ skipBlockTest (driver )
235
+ init ()
236
+ l .genericVolumeTestResource = * createGenericVolumeTestResource (driver , l .config , pattern )
237
+ defer cleanup ()
238
+
239
+ ginkgo .By ("Creating pod" )
240
+ var err error
241
+ pod := framework .MakeSecPod (l .ns .Name , []* v1.PersistentVolumeClaim {l .pvc }, nil , false , "" , false , false , framework .SELinuxLabel , nil )
242
+ // Change volumeMounts to volumeDevices and the other way around
243
+ pod = swapVolumeMode (pod )
244
+
245
+ // Run the pod
246
+ pod , err = l .cs .CoreV1 ().Pods (l .ns .Name ).Create (pod )
247
+ framework .ExpectNoError (err )
248
+ defer func () {
249
+ framework .ExpectNoError (framework .DeletePodWithWait (f , l .cs , pod ))
250
+ }()
251
+
252
+ ginkgo .By ("Waiting for pod to fail" )
253
+ // Wait for an event that the pod is invalid.
254
+ eventSelector := fields.Set {
255
+ "involvedObject.kind" : "Pod" ,
256
+ "involvedObject.name" : pod .Name ,
257
+ "involvedObject.namespace" : l .ns .Name ,
258
+ "reason" : events .FailedMountVolume ,
259
+ }.AsSelector ().String ()
260
+
261
+ var msg string
262
+ if pattern .VolMode == v1 .PersistentVolumeBlock {
263
+ msg = "has volumeMode Block, but is specified in volumeMounts"
264
+ } else {
265
+ msg = "has volumeMode Filesystem, but is specified in volumeDevices"
266
+ }
267
+ err = e2epod .WaitTimeoutForPodEvent (l .cs , pod .Name , l .ns .Name , eventSelector , msg , framework .PodStartTimeout )
268
+ // Events are unreliable, don't depend on them. They're used only to speed up the test.
269
+ if err != nil {
270
+ e2elog .Logf ("Warning: did not get event about mismatched volume use" )
271
+ }
272
+
273
+ // Check the pod is still not running
274
+ p , err := l .cs .CoreV1 ().Pods (l .ns .Name ).Get (pod .Name , metav1.GetOptions {})
275
+ framework .ExpectNoError (err , "could not re-read the pod after event (or timeout)" )
276
+ framework .ExpectEqual (p .Status .Phase , v1 .PodPending )
277
+ })
278
+
227
279
}
228
280
229
281
func generateConfigsForPreprovisionedPVTest (scName string , volBindMode storagev1.VolumeBindingMode ,
@@ -254,3 +306,29 @@ func generateConfigsForPreprovisionedPVTest(scName string, volBindMode storagev1
254
306
255
307
return scConfig , pvConfig , pvcConfig
256
308
}
309
+
310
+ // swapVolumeMode changes volumeMounts to volumeDevices and the other way around
311
+ func swapVolumeMode (podTemplate * v1.Pod ) * v1.Pod {
312
+ pod := podTemplate .DeepCopy ()
313
+ for c := range pod .Spec .Containers {
314
+ container := & pod .Spec .Containers [c ]
315
+ container .VolumeDevices = []v1.VolumeDevice {}
316
+ container .VolumeMounts = []v1.VolumeMount {}
317
+
318
+ // Change VolumeMounts to VolumeDevices
319
+ for _ , volumeMount := range podTemplate .Spec .Containers [c ].VolumeMounts {
320
+ container .VolumeDevices = append (container .VolumeDevices , v1.VolumeDevice {
321
+ Name : volumeMount .Name ,
322
+ DevicePath : volumeMount .MountPath ,
323
+ })
324
+ }
325
+ // Change VolumeDevices to VolumeMounts
326
+ for _ , volumeDevice := range podTemplate .Spec .Containers [c ].VolumeDevices {
327
+ container .VolumeMounts = append (container .VolumeMounts , v1.VolumeMount {
328
+ Name : volumeDevice .Name ,
329
+ MountPath : volumeDevice .DevicePath ,
330
+ })
331
+ }
332
+ }
333
+ return pod
334
+ }
0 commit comments