1
16
17 package cache
18
19 import (
20 "fmt"
21 "testing"
22
23 "k8s.io/apimachinery/pkg/api/resource"
24 "k8s.io/apimachinery/pkg/types"
25 utilfeature "k8s.io/apiserver/pkg/util/feature"
26 featuregatetesting "k8s.io/component-base/featuregate/testing"
27
28 "github.com/stretchr/testify/require"
29 v1 "k8s.io/api/core/v1"
30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31 "k8s.io/klog/v2/ktesting"
32 "k8s.io/kubernetes/pkg/features"
33 "k8s.io/kubernetes/pkg/volume"
34 volumetesting "k8s.io/kubernetes/pkg/volume/testing"
35 "k8s.io/kubernetes/pkg/volume/util"
36 "k8s.io/kubernetes/pkg/volume/util/operationexecutor"
37 volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
38 )
39
40 var emptyVolumeName = v1.UniqueVolumeName("")
41
42
43
44
45 func Test_MarkVolumeAsAttached_Positive_NewVolume(t *testing.T) {
46
47 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
48 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
49 pod := &v1.Pod{
50 ObjectMeta: metav1.ObjectMeta{
51 Name: "pod1",
52 UID: "pod1uid",
53 },
54 Spec: v1.PodSpec{
55 Volumes: []v1.Volume{
56 {
57 Name: "volume-name",
58 VolumeSource: v1.VolumeSource{
59 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
60 PDName: "fake-device1",
61 },
62 },
63 },
64 },
65 },
66 }
67 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
68 devicePath := "fake/device/path"
69 generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
70 if err != nil {
71 t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: <no error> Actual: <%v>", err)
72 }
73
74
75 logger, _ := ktesting.NewTestContext(t)
76 err = asw.MarkVolumeAsAttached(logger, emptyVolumeName, volumeSpec, "" , devicePath)
77
78
79 if err != nil {
80 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
81 }
82
83 verifyVolumeExistsAsw(t, generatedVolumeName, true , asw)
84 verifyVolumeExistsInUnmountedVolumes(t, generatedVolumeName, asw)
85 verifyVolumeDoesntExistInGloballyMountedVolumes(t, generatedVolumeName, asw)
86 }
87
88
89
90
91
92
93 func Test_MarkVolumeAsAttached_SuppliedVolumeName_Positive_NewVolume(t *testing.T) {
94
95 volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
96 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
97 pod := &v1.Pod{
98 ObjectMeta: metav1.ObjectMeta{
99 Name: "pod1",
100 UID: "pod1uid",
101 },
102 Spec: v1.PodSpec{
103 Volumes: []v1.Volume{
104 {
105 Name: "volume-name",
106 VolumeSource: v1.VolumeSource{
107 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
108 PDName: "fake-device1",
109 },
110 },
111 },
112 },
113 },
114 }
115 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
116 devicePath := "fake/device/path"
117 volumeName := v1.UniqueVolumeName("this-would-never-be-a-volume-name")
118
119
120 logger, _ := ktesting.NewTestContext(t)
121 err := asw.MarkVolumeAsAttached(logger, volumeName, volumeSpec, "" , devicePath)
122
123
124 if err != nil {
125 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
126 }
127
128 verifyVolumeExistsAsw(t, volumeName, true , asw)
129 verifyVolumeExistsInUnmountedVolumes(t, volumeName, asw)
130 verifyVolumeDoesntExistInGloballyMountedVolumes(t, volumeName, asw)
131 }
132
133
134
135
136
137 func Test_MarkVolumeAsAttached_Positive_ExistingVolume(t *testing.T) {
138
139 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
140 devicePath := "fake/device/path"
141 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
142 pod := &v1.Pod{
143 ObjectMeta: metav1.ObjectMeta{
144 Name: "pod1",
145 UID: "pod1uid",
146 },
147 Spec: v1.PodSpec{
148 Volumes: []v1.Volume{
149 {
150 Name: "volume-name",
151 VolumeSource: v1.VolumeSource{
152 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
153 PDName: "fake-device1",
154 },
155 },
156 },
157 },
158 },
159 }
160 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
161 generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
162 if err != nil {
163 t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: <no error> Actual: <%v>", err)
164 }
165 logger, _ := ktesting.NewTestContext(t)
166 err = asw.MarkVolumeAsAttached(logger, emptyVolumeName, volumeSpec, "" , devicePath)
167 if err != nil {
168 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
169 }
170
171
172 err = asw.MarkVolumeAsAttached(logger, emptyVolumeName, volumeSpec, "" , devicePath)
173
174
175 if err != nil {
176 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
177 }
178
179 verifyVolumeExistsAsw(t, generatedVolumeName, true , asw)
180 verifyVolumeExistsInUnmountedVolumes(t, generatedVolumeName, asw)
181 verifyVolumeDoesntExistInGloballyMountedVolumes(t, generatedVolumeName, asw)
182 }
183
184
185
186
187 func Test_AddPodToVolume_Positive_ExistingVolumeNewNode(t *testing.T) {
188
189 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
190 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
191 devicePath := "fake/device/path"
192
193 pod := &v1.Pod{
194 ObjectMeta: metav1.ObjectMeta{
195 Name: "pod1",
196 UID: "pod1uid",
197 },
198 Spec: v1.PodSpec{
199 Volumes: []v1.Volume{
200 {
201 Name: "volume-name",
202 VolumeSource: v1.VolumeSource{
203 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
204 PDName: "fake-device1",
205 },
206 },
207 },
208 },
209 },
210 }
211 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
212 generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
213 if err != nil {
214 t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: <no error> Actual: <%v>", err)
215 }
216 logger, _ := ktesting.NewTestContext(t)
217 err = asw.MarkVolumeAsAttached(logger, emptyVolumeName, volumeSpec, "" , devicePath)
218 if err != nil {
219 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
220 }
221 podName := util.GetUniquePodName(pod)
222
223 mounter, err := plugin.NewMounter(volumeSpec, pod, volume.VolumeOptions{})
224 if err != nil {
225 t.Fatalf("NewMounter failed. Expected: <no error> Actual: <%v>", err)
226 }
227
228 mapper, err := plugin.NewBlockVolumeMapper(volumeSpec, pod, volume.VolumeOptions{})
229 if err != nil {
230 t.Fatalf("NewBlockVolumeMapper failed. Expected: <no error> Actual: <%v>", err)
231 }
232
233
234 markVolumeOpts := operationexecutor.MarkVolumeOpts{
235 PodName: podName,
236 PodUID: pod.UID,
237 VolumeName: generatedVolumeName,
238 Mounter: mounter,
239 BlockVolumeMapper: mapper,
240 OuterVolumeSpecName: volumeSpec.Name(),
241 VolumeSpec: volumeSpec,
242 }
243 err = asw.AddPodToVolume(markVolumeOpts)
244
245 if err != nil {
246 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
247 }
248
249 verifyVolumeExistsAsw(t, generatedVolumeName, true , asw)
250 verifyVolumeDoesntExistInUnmountedVolumes(t, generatedVolumeName, asw)
251 verifyVolumeDoesntExistInGloballyMountedVolumes(t, generatedVolumeName, asw)
252 verifyPodExistsInVolumeAsw(t, podName, generatedVolumeName, "fake/device/path" , asw)
253 verifyVolumeExistsWithSpecNameInVolumeAsw(t, podName, volumeSpec.Name(), asw)
254 verifyVolumeMountedElsewhere(t, podName, generatedVolumeName, false , asw)
255 }
256
257
258
259
260
261 func Test_AddPodToVolume_Positive_ExistingVolumeExistingNode(t *testing.T) {
262
263 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
264 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
265 devicePath := "fake/device/path"
266
267 pod := &v1.Pod{
268 ObjectMeta: metav1.ObjectMeta{
269 Name: "pod1",
270 UID: "pod1uid",
271 },
272 Spec: v1.PodSpec{
273 Volumes: []v1.Volume{
274 {
275 Name: "volume-name",
276 VolumeSource: v1.VolumeSource{
277 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
278 PDName: "fake-device1",
279 },
280 },
281 },
282 },
283 },
284 }
285
286 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
287 generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(
288 plugin, volumeSpec)
289 if err != nil {
290 t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: <no error> Actual: <%v>", err)
291 }
292 logger, _ := ktesting.NewTestContext(t)
293 err = asw.MarkVolumeAsAttached(logger, emptyVolumeName, volumeSpec, "" , devicePath)
294 if err != nil {
295 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
296 }
297 podName := util.GetUniquePodName(pod)
298
299 mounter, err := plugin.NewMounter(volumeSpec, pod, volume.VolumeOptions{})
300 if err != nil {
301 t.Fatalf("NewMounter failed. Expected: <no error> Actual: <%v>", err)
302 }
303
304 mapper, err := plugin.NewBlockVolumeMapper(volumeSpec, pod, volume.VolumeOptions{})
305 if err != nil {
306 t.Fatalf("NewBlockVolumeMapper failed. Expected: <no error> Actual: <%v>", err)
307 }
308
309 markVolumeOpts := operationexecutor.MarkVolumeOpts{
310 PodName: podName,
311 PodUID: pod.UID,
312 VolumeName: generatedVolumeName,
313 Mounter: mounter,
314 BlockVolumeMapper: mapper,
315 OuterVolumeSpecName: volumeSpec.Name(),
316 VolumeSpec: volumeSpec,
317 }
318 err = asw.AddPodToVolume(markVolumeOpts)
319 if err != nil {
320 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
321 }
322
323
324 err = asw.AddPodToVolume(markVolumeOpts)
325
326 if err != nil {
327 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
328 }
329
330 verifyVolumeExistsAsw(t, generatedVolumeName, true , asw)
331 verifyVolumeDoesntExistInUnmountedVolumes(t, generatedVolumeName, asw)
332 verifyVolumeDoesntExistInGloballyMountedVolumes(t, generatedVolumeName, asw)
333 verifyPodExistsInVolumeAsw(t, podName, generatedVolumeName, "fake/device/path" , asw)
334 verifyVolumeExistsWithSpecNameInVolumeAsw(t, podName, volumeSpec.Name(), asw)
335 verifyVolumeMountedElsewhere(t, podName, generatedVolumeName, false , asw)
336 }
337
338
339
340
341
342 func Test_AddTwoPodsToVolume_Positive(t *testing.T) {
343
344 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
345 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
346 devicePath := "fake/device/path"
347
348 pod1 := &v1.Pod{
349 ObjectMeta: metav1.ObjectMeta{
350 Name: "pod1",
351 UID: "pod1uid",
352 },
353 Spec: v1.PodSpec{
354 Volumes: []v1.Volume{
355 {
356 Name: "volume-name-1",
357 VolumeSource: v1.VolumeSource{
358 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
359 PDName: "fake-device1",
360 },
361 },
362 },
363 },
364 },
365 }
366
367 pod2 := &v1.Pod{
368 ObjectMeta: metav1.ObjectMeta{
369 Name: "pod2",
370 UID: "pod2uid",
371 },
372 Spec: v1.PodSpec{
373 Volumes: []v1.Volume{
374 {
375 Name: "volume-name-2",
376 VolumeSource: v1.VolumeSource{
377 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
378 PDName: "fake-device1",
379 },
380 },
381 },
382 },
383 },
384 }
385 volumeSpec1 := &volume.Spec{Volume: &pod1.Spec.Volumes[0]}
386 volumeSpec2 := &volume.Spec{Volume: &pod2.Spec.Volumes[0]}
387 generatedVolumeName1, err := util.GetUniqueVolumeNameFromSpec(
388 plugin, volumeSpec1)
389 require.NoError(t, err)
390 generatedVolumeName2, err := util.GetUniqueVolumeNameFromSpec(
391 plugin, volumeSpec2)
392 require.NoError(t, err)
393
394 if generatedVolumeName1 != generatedVolumeName2 {
395 t.Fatalf(
396 "Unique volume names should be the same. unique volume name 1: <%q> unique volume name 2: <%q>, spec1 %v, spec2 %v",
397 generatedVolumeName1,
398 generatedVolumeName2, volumeSpec1, volumeSpec2)
399 }
400 logger, _ := ktesting.NewTestContext(t)
401 err = asw.MarkVolumeAsAttached(logger, generatedVolumeName1, volumeSpec1, "" , devicePath)
402 if err != nil {
403 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
404 }
405 podName1 := util.GetUniquePodName(pod1)
406
407 mounter1, err := plugin.NewMounter(volumeSpec1, pod1, volume.VolumeOptions{})
408 if err != nil {
409 t.Fatalf("NewMounter failed. Expected: <no error> Actual: <%v>", err)
410 }
411
412 mapper1, err := plugin.NewBlockVolumeMapper(volumeSpec1, pod1, volume.VolumeOptions{})
413 if err != nil {
414 t.Fatalf("NewBlockVolumeMapper failed. Expected: <no error> Actual: <%v>", err)
415 }
416
417 markVolumeOpts1 := operationexecutor.MarkVolumeOpts{
418 PodName: podName1,
419 PodUID: pod1.UID,
420 VolumeName: generatedVolumeName1,
421 Mounter: mounter1,
422 BlockVolumeMapper: mapper1,
423 OuterVolumeSpecName: volumeSpec1.Name(),
424 VolumeSpec: volumeSpec1,
425 }
426 err = asw.AddPodToVolume(markVolumeOpts1)
427 if err != nil {
428 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
429 }
430
431 podName2 := util.GetUniquePodName(pod2)
432
433 mounter2, err := plugin.NewMounter(volumeSpec2, pod2, volume.VolumeOptions{})
434 if err != nil {
435 t.Fatalf("NewMounter failed. Expected: <no error> Actual: <%v>", err)
436 }
437
438 mapper2, err := plugin.NewBlockVolumeMapper(volumeSpec2, pod2, volume.VolumeOptions{})
439 if err != nil {
440 t.Fatalf("NewBlockVolumeMapper failed. Expected: <no error> Actual: <%v>", err)
441 }
442
443 markVolumeOpts2 := operationexecutor.MarkVolumeOpts{
444 PodName: podName2,
445 PodUID: pod2.UID,
446 VolumeName: generatedVolumeName1,
447 Mounter: mounter2,
448 BlockVolumeMapper: mapper2,
449 OuterVolumeSpecName: volumeSpec2.Name(),
450 VolumeSpec: volumeSpec2,
451 }
452 err = asw.AddPodToVolume(markVolumeOpts2)
453 if err != nil {
454 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
455 }
456
457 verifyVolumeExistsAsw(t, generatedVolumeName1, true , asw)
458 verifyVolumeDoesntExistInUnmountedVolumes(t, generatedVolumeName1, asw)
459 verifyVolumeDoesntExistInGloballyMountedVolumes(t, generatedVolumeName1, asw)
460 verifyPodExistsInVolumeAsw(t, podName1, generatedVolumeName1, "fake/device/path" , asw)
461 verifyVolumeExistsWithSpecNameInVolumeAsw(t, podName1, volumeSpec1.Name(), asw)
462 verifyPodExistsInVolumeAsw(t, podName2, generatedVolumeName2, "fake/device/path" , asw)
463 verifyVolumeExistsWithSpecNameInVolumeAsw(t, podName2, volumeSpec2.Name(), asw)
464 verifyVolumeSpecNameInVolumeAsw(t, podName1, []*volume.Spec{volumeSpec1}, asw)
465 verifyVolumeSpecNameInVolumeAsw(t, podName2, []*volume.Spec{volumeSpec2}, asw)
466 verifyVolumeMountedElsewhere(t, podName1, generatedVolumeName1, true , asw)
467 verifyVolumeMountedElsewhere(t, podName2, generatedVolumeName2, true , asw)
468 }
469
470
471
472 func TestActualStateOfWorld_FoundDuringReconstruction(t *testing.T) {
473 tests := []struct {
474 name string
475 opCallback func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error
476 verifyCallback func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error
477 }{
478 {
479 name: "marking volume mounted should remove volume from found during reconstruction",
480 opCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
481 volumeOpts.VolumeMountState = operationexecutor.VolumeMounted
482 return asw.MarkVolumeAsMounted(volumeOpts)
483 },
484 verifyCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
485 ok := asw.IsVolumeReconstructed(volumeOpts.VolumeName, volumeOpts.PodName)
486 if ok {
487 return fmt.Errorf("found unexpected volume in reconstructed volume list")
488 }
489 return nil
490 },
491 },
492 {
493 name: "removing volume from pod should remove volume from found during reconstruction",
494 opCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
495 return asw.MarkVolumeAsUnmounted(volumeOpts.PodName, volumeOpts.VolumeName)
496 },
497 verifyCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
498 ok := asw.IsVolumeReconstructed(volumeOpts.VolumeName, volumeOpts.PodName)
499 if ok {
500 return fmt.Errorf("found unexpected volume in reconstructed volume list")
501 }
502 return nil
503 },
504 },
505 {
506 name: "removing volume entirely from ASOW should remove volume from found during reconstruction",
507 opCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
508 err := asw.MarkVolumeAsUnmounted(volumeOpts.PodName, volumeOpts.VolumeName)
509 if err != nil {
510 return err
511 }
512 asw.MarkVolumeAsDetached(volumeOpts.VolumeName, "")
513 return nil
514 },
515 verifyCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
516 ok := asw.IsVolumeReconstructed(volumeOpts.VolumeName, volumeOpts.PodName)
517 if ok {
518 return fmt.Errorf("found unexpected volume in reconstructed volume list")
519 }
520 aswInstance, _ := asw.(*actualStateOfWorld)
521 _, found := aswInstance.foundDuringReconstruction[volumeOpts.VolumeName]
522 if found {
523 return fmt.Errorf("found unexpected volume in reconstructed map")
524 }
525 return nil
526 },
527 },
528 {
529 name: "uncertain attachability is resolved to attachable",
530 opCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
531 asw.UpdateReconstructedVolumeAttachability(volumeOpts.VolumeName, true)
532 return nil
533 },
534 verifyCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
535 verifyVolumeAttachability(t, volumeOpts.VolumeName, asw, volumeAttachabilityTrue)
536 return nil
537 },
538 },
539 {
540 name: "uncertain attachability is resolved to non-attachable",
541 opCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
542 asw.UpdateReconstructedVolumeAttachability(volumeOpts.VolumeName, false)
543 return nil
544 },
545 verifyCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
546 verifyVolumeAttachability(t, volumeOpts.VolumeName, asw, volumeAttachabilityFalse)
547 return nil
548 },
549 },
550 {
551 name: "certain (false) attachability cannot be changed",
552 opCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
553 asw.UpdateReconstructedVolumeAttachability(volumeOpts.VolumeName, false)
554
555 asw.UpdateReconstructedVolumeAttachability(volumeOpts.VolumeName, true)
556 return nil
557 },
558 verifyCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
559 verifyVolumeAttachability(t, volumeOpts.VolumeName, asw, volumeAttachabilityFalse)
560 return nil
561 },
562 },
563 {
564 name: "certain (true) attachability cannot be changed",
565 opCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
566 asw.UpdateReconstructedVolumeAttachability(volumeOpts.VolumeName, true)
567
568 asw.UpdateReconstructedVolumeAttachability(volumeOpts.VolumeName, false)
569 return nil
570 },
571 verifyCallback: func(asw ActualStateOfWorld, volumeOpts operationexecutor.MarkVolumeOpts) error {
572 verifyVolumeAttachability(t, volumeOpts.VolumeName, asw, volumeAttachabilityTrue)
573 return nil
574 },
575 },
576 }
577 for _, tc := range tests {
578 t.Run(tc.name, func(t *testing.T) {
579 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
580 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
581 devicePath := "fake/device/path"
582
583 pod1 := getTestPod("pod1", "pod1uid", "volume-name-1", "fake-device1")
584 volumeSpec1 := &volume.Spec{Volume: &pod1.Spec.Volumes[0]}
585 generatedVolumeName1, err := util.GetUniqueVolumeNameFromSpec(
586 plugin, volumeSpec1)
587 require.NoError(t, err)
588 err = asw.AddAttachUncertainReconstructedVolume(generatedVolumeName1, volumeSpec1, "" , devicePath)
589 if err != nil {
590 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
591 }
592 podName1 := util.GetUniquePodName(pod1)
593
594 mounter1, err := plugin.NewMounter(volumeSpec1, pod1, volume.VolumeOptions{})
595 if err != nil {
596 t.Fatalf("NewMounter failed. Expected: <no error> Actual: <%v>", err)
597 }
598
599 mapper1, err := plugin.NewBlockVolumeMapper(volumeSpec1, pod1, volume.VolumeOptions{})
600 if err != nil {
601 t.Fatalf("NewBlockVolumeMapper failed. Expected: <no error> Actual: <%v>", err)
602 }
603
604 markVolumeOpts1 := operationexecutor.MarkVolumeOpts{
605 PodName: podName1,
606 PodUID: pod1.UID,
607 VolumeName: generatedVolumeName1,
608 Mounter: mounter1,
609 BlockVolumeMapper: mapper1,
610 OuterVolumeSpecName: volumeSpec1.Name(),
611 VolumeSpec: volumeSpec1,
612 VolumeMountState: operationexecutor.VolumeMountUncertain,
613 }
614 _, err = asw.CheckAndMarkVolumeAsUncertainViaReconstruction(markVolumeOpts1)
615 if err != nil {
616 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
617 }
618
619 verifyVolumeExistsAsw(t, generatedVolumeName1, true , asw)
620 verifyVolumeDoesntExistInUnmountedVolumes(t, generatedVolumeName1, asw)
621 verifyVolumeDoesntExistInGloballyMountedVolumes(t, generatedVolumeName1, asw)
622 verifyVolumeExistsWithSpecNameInVolumeAsw(t, podName1, volumeSpec1.Name(), asw)
623 verifyVolumeSpecNameInVolumeAsw(t, podName1, []*volume.Spec{volumeSpec1}, asw)
624 verifyVolumeFoundInReconstruction(t, podName1, generatedVolumeName1, asw)
625 verifyVolumeAttachability(t, generatedVolumeName1, asw, volumeAttachabilityUncertain)
626
627 if tc.opCallback != nil {
628 err = tc.opCallback(asw, markVolumeOpts1)
629 if err != nil {
630 t.Fatalf("for test %s: %v", tc.name, err)
631 }
632 }
633 err = tc.verifyCallback(asw, markVolumeOpts1)
634 if err != nil {
635 t.Fatalf("for test %s verification failed: %v", tc.name, err)
636 }
637 })
638 }
639 }
640
641
642 func Test_MarkVolumeAsDetached_Negative_PodInVolume(t *testing.T) {
643
644 volumePluginMgr, plugin := volumetesting.GetTestVolumePluginMgr(t)
645 devicePath := "fake/device/path"
646 asw := NewActualStateOfWorld("mynode", volumePluginMgr)
647 pod := &v1.Pod{
648 ObjectMeta: metav1.ObjectMeta{
649 Name: "pod1",
650 UID: "pod1uid",
651 },
652 Spec: v1.PodSpec{
653 Volumes: []v1.Volume{
654 {
655 Name: "volume-name",
656 VolumeSource: v1.VolumeSource{
657 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
658 PDName: "fake-device1",
659 },
660 },
661 },
662 },
663 },
664 }
665 logger, _ := ktesting.NewTestContext(t)
666 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
667 err := asw.MarkVolumeAsAttached(logger, emptyVolumeName, volumeSpec, "" , devicePath)
668 if err != nil {
669 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
670 }
671
672 generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
673 if err != nil {
674 t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: <no error> Actual: <%v>", err)
675 }
676
677 podName := util.GetUniquePodName(pod)
678 mounter, err := plugin.NewMounter(volumeSpec, pod, volume.VolumeOptions{})
679 if err != nil {
680 t.Fatalf("NewMounter failed. Expected: <no error> Actual: <%v>", err)
681 }
682
683 mapper, err := plugin.NewBlockVolumeMapper(volumeSpec, pod, volume.VolumeOptions{})
684 if err != nil {
685 t.Fatalf("NewBlockVolumeMapper failed. Expected: <no error> Actual: <%v>", err)
686 }
687
688 markVolumeOpts := operationexecutor.MarkVolumeOpts{
689 PodName: podName,
690 PodUID: pod.UID,
691 VolumeName: generatedVolumeName,
692 Mounter: mounter,
693 BlockVolumeMapper: mapper,
694 OuterVolumeSpecName: volumeSpec.Name(),
695 VolumeSpec: volumeSpec,
696 }
697 err = asw.AddPodToVolume(markVolumeOpts)
698 if err != nil {
699 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
700 }
701
702
703 asw.MarkVolumeAsDetached(generatedVolumeName, "" )
704
705
706 verifyPodExistsInVolumeAsw(t, podName, generatedVolumeName, "fake/device/path" , asw)
707 }
708
709 func getTestPod(podName, podUID, outerVolumeName, pdName string) *v1.Pod {
710 pod := &v1.Pod{
711 ObjectMeta: metav1.ObjectMeta{
712 Name: podName,
713 UID: types.UID(podUID),
714 },
715 Spec: v1.PodSpec{
716 Volumes: []v1.Volume{
717 {
718 Name: outerVolumeName,
719 VolumeSource: v1.VolumeSource{
720 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
721 PDName: pdName,
722 },
723 },
724 },
725 },
726 },
727 }
728 return pod
729 }
730
731
732
733 func Test_AddPodToVolume_Negative_VolumeDoesntExist(t *testing.T) {
734
735 volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
736 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
737
738 pod := &v1.Pod{
739 ObjectMeta: metav1.ObjectMeta{
740 Name: "pod1",
741 UID: "pod1uid",
742 },
743 Spec: v1.PodSpec{
744 Volumes: []v1.Volume{
745 {
746 Name: "volume-name",
747 VolumeSource: v1.VolumeSource{
748 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
749 PDName: "fake-device1",
750 },
751 },
752 },
753 },
754 },
755 }
756
757 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
758 plugin, err := volumePluginMgr.FindPluginBySpec(volumeSpec)
759 if err != nil {
760 t.Fatalf(
761 "volumePluginMgr.FindPluginBySpec failed to find volume plugin for %#v with: %v",
762 volumeSpec,
763 err)
764 }
765
766 generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(
767 plugin, volumeSpec)
768 require.NoError(t, err)
769
770 blockplugin, err := volumePluginMgr.FindMapperPluginBySpec(volumeSpec)
771 if err != nil {
772 t.Fatalf(
773 "volumePluginMgr.FindMapperPluginBySpec failed to find volume plugin for %#v with: %v",
774 volumeSpec,
775 err)
776 }
777
778 volumeName, err := util.GetUniqueVolumeNameFromSpec(
779 plugin, volumeSpec)
780 require.NoError(t, err)
781
782 podName := util.GetUniquePodName(pod)
783
784 mounter, err := plugin.NewMounter(volumeSpec, pod, volume.VolumeOptions{})
785 if err != nil {
786 t.Fatalf("NewMounter failed. Expected: <no error> Actual: <%v>", err)
787 }
788
789 mapper, err := blockplugin.NewBlockVolumeMapper(volumeSpec, pod, volume.VolumeOptions{})
790 if err != nil {
791 t.Fatalf("NewBlockVolumeMapper failed. Expected: <no error> Actual: <%v>", err)
792 }
793
794
795 markVolumeOpts := operationexecutor.MarkVolumeOpts{
796 PodName: podName,
797 PodUID: pod.UID,
798 VolumeName: volumeName,
799 Mounter: mounter,
800 BlockVolumeMapper: mapper,
801 OuterVolumeSpecName: volumeSpec.Name(),
802 VolumeSpec: volumeSpec,
803 }
804 err = asw.AddPodToVolume(markVolumeOpts)
805
806 if err == nil {
807 t.Fatalf("AddPodToVolume did not fail. Expected: <\"no volume with the name ... exists in the list of attached volumes\"> Actual: <no error>")
808 }
809
810 verifyVolumeExistsAsw(t, volumeName, false , asw)
811 verifyVolumeDoesntExistInUnmountedVolumes(t, volumeName, asw)
812 verifyVolumeDoesntExistInGloballyMountedVolumes(t, volumeName, asw)
813 verifyPodDoesntExistInVolumeAsw(
814 t,
815 podName,
816 volumeName,
817 false,
818 asw)
819 verifyVolumeDoesntExistWithSpecNameInVolumeAsw(t, podName, volumeSpec.Name(), asw)
820 verifyVolumeMountedElsewhere(t, podName, generatedVolumeName, false , asw)
821 }
822
823
824
825
826
827 func Test_MarkDeviceAsMounted_Positive_NewVolume(t *testing.T) {
828
829 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
830 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
831 pod := &v1.Pod{
832 ObjectMeta: metav1.ObjectMeta{
833 Name: "pod1",
834 UID: "pod1uid",
835 },
836 Spec: v1.PodSpec{
837 Volumes: []v1.Volume{
838 {
839 Name: "volume-name",
840 VolumeSource: v1.VolumeSource{
841 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
842 PDName: "fake-device1",
843 },
844 },
845 },
846 },
847 },
848 }
849 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
850 devicePath := "fake/device/path"
851 deviceMountPath := "fake/device/mount/path"
852 generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
853 if err != nil {
854 t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: <no error> Actual: <%v>", err)
855 }
856 logger, _ := ktesting.NewTestContext(t)
857 err = asw.MarkVolumeAsAttached(logger, emptyVolumeName, volumeSpec, "" , devicePath)
858 if err != nil {
859 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
860 }
861
862
863 err = asw.MarkDeviceAsMounted(generatedVolumeName, devicePath, deviceMountPath, "")
864
865
866 if err != nil {
867 t.Fatalf("MarkDeviceAsMounted failed. Expected: <no error> Actual: <%v>", err)
868 }
869
870 verifyVolumeExistsAsw(t, generatedVolumeName, true , asw)
871 verifyVolumeExistsInUnmountedVolumes(t, generatedVolumeName, asw)
872 verifyVolumeExistsInGloballyMountedVolumes(t, generatedVolumeName, asw)
873 }
874
875
876
877
878 func Test_AddPodToVolume_Positive_SELinux(t *testing.T) {
879
880 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
881 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
882 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
883 devicePath := "fake/device/path"
884
885 pod := &v1.Pod{
886 ObjectMeta: metav1.ObjectMeta{
887 Name: "pod1",
888 UID: "pod1uid",
889 },
890 Spec: v1.PodSpec{
891 Volumes: []v1.Volume{
892 {
893 Name: "volume-name",
894 VolumeSource: v1.VolumeSource{
895 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
896 PDName: "fake-device1",
897 },
898 },
899 },
900 },
901 },
902 }
903 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
904 generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
905 if err != nil {
906 t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: <no error> Actual: <%v>", err)
907 }
908 logger, _ := ktesting.NewTestContext(t)
909 err = asw.MarkVolumeAsAttached(logger, emptyVolumeName, volumeSpec, "" , devicePath)
910 if err != nil {
911 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
912 }
913 podName := util.GetUniquePodName(pod)
914
915 mounter, err := plugin.NewMounter(volumeSpec, pod, volume.VolumeOptions{})
916 if err != nil {
917 t.Fatalf("NewMounter failed. Expected: <no error> Actual: <%v>", err)
918 }
919
920 mapper, err := plugin.NewBlockVolumeMapper(volumeSpec, pod, volume.VolumeOptions{})
921 if err != nil {
922 t.Fatalf("NewBlockVolumeMapper failed. Expected: <no error> Actual: <%v>", err)
923 }
924
925
926 markVolumeOpts := operationexecutor.MarkVolumeOpts{
927 PodName: podName,
928 PodUID: pod.UID,
929 VolumeName: generatedVolumeName,
930 Mounter: mounter,
931 BlockVolumeMapper: mapper,
932 OuterVolumeSpecName: volumeSpec.Name(),
933 VolumeSpec: volumeSpec,
934 SELinuxMountContext: "system_u:object_r:container_file_t:s0:c0,c1",
935 VolumeMountState: operationexecutor.VolumeMounted,
936 }
937 err = asw.AddPodToVolume(markVolumeOpts)
938
939 if err != nil {
940 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
941 }
942
943 verifyVolumeExistsAswWithSELinux(t, generatedVolumeName, "system_u:object_r:container_file_t:s0:c0,c1", asw)
944 verifyVolumeDoesntExistInUnmountedVolumes(t, generatedVolumeName, asw)
945 verifyVolumeDoesntExistInGloballyMountedVolumes(t, generatedVolumeName, asw)
946 verifyPodExistsInVolumeAswWithSELinux(t, podName, generatedVolumeName, "fake/device/path" , "system_u:object_r:container_file_t:s0:c0,c1", asw)
947 verifyPodExistsInVolumeSELinuxMismatch(t, podName, generatedVolumeName, "" , asw)
948 verifyVolumeExistsWithSpecNameInVolumeAsw(t, podName, volumeSpec.Name(), asw)
949 verifyVolumeMountedElsewhere(t, podName, generatedVolumeName, false , asw)
950 }
951
952
953
954
955
956 func Test_MarkDeviceAsMounted_Positive_SELinux(t *testing.T) {
957
958 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
959 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
960 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
961 pod := &v1.Pod{
962 ObjectMeta: metav1.ObjectMeta{
963 Name: "pod1",
964 UID: "pod1uid",
965 },
966 Spec: v1.PodSpec{
967 Volumes: []v1.Volume{
968 {
969 Name: "volume-name",
970 VolumeSource: v1.VolumeSource{
971 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
972 PDName: "fake-device1",
973 },
974 },
975 },
976 },
977 },
978 }
979 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
980 devicePath := "fake/device/path"
981 deviceMountPath := "fake/device/mount/path"
982 generatedVolumeName, err := util.GetUniqueVolumeNameFromSpec(plugin, volumeSpec)
983 if err != nil {
984 t.Fatalf("GetUniqueVolumeNameFromSpec failed. Expected: <no error> Actual: <%v>", err)
985 }
986 logger, _ := ktesting.NewTestContext(t)
987 err = asw.MarkVolumeAsAttached(logger, emptyVolumeName, volumeSpec, "" , devicePath)
988 if err != nil {
989 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
990 }
991
992
993 err = asw.MarkDeviceAsMounted(generatedVolumeName, devicePath, deviceMountPath, "system_u:system_r:container_t:s0:c0,c1")
994
995
996 if err != nil {
997 t.Fatalf("MarkDeviceAsMounted failed. Expected: <no error> Actual: <%v>", err)
998 }
999
1000 verifyVolumeExistsAsw(t, generatedVolumeName, true , asw)
1001 verifyVolumeExistsInUnmountedVolumes(t, generatedVolumeName, asw)
1002 verifyVolumeExistsInGloballyMountedVolumesWithSELinux(t, generatedVolumeName, "system_u:system_r:container_t:s0:c0,c1", asw)
1003 }
1004
1005 func TestUncertainVolumeMounts(t *testing.T) {
1006
1007 volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
1008 asw := NewActualStateOfWorld("mynode" , volumePluginMgr)
1009 devicePath := "fake/device/path"
1010
1011 pod1 := &v1.Pod{
1012 ObjectMeta: metav1.ObjectMeta{
1013 Name: "pod1",
1014 UID: "pod1uid",
1015 },
1016 Spec: v1.PodSpec{
1017 Volumes: []v1.Volume{
1018 {
1019 Name: "volume-name-1",
1020 VolumeSource: v1.VolumeSource{
1021 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
1022 PDName: "fake-device1",
1023 },
1024 },
1025 },
1026 },
1027 },
1028 }
1029 volumeSpec1 := &volume.Spec{Volume: &pod1.Spec.Volumes[0]}
1030 generatedVolumeName1, err := util.GetUniqueVolumeNameFromSpec(
1031 plugin, volumeSpec1)
1032 require.NoError(t, err)
1033 logger, _ := ktesting.NewTestContext(t)
1034 err = asw.MarkVolumeAsAttached(logger, generatedVolumeName1, volumeSpec1, "" , devicePath)
1035 if err != nil {
1036 t.Fatalf("MarkVolumeAsAttached failed. Expected: <no error> Actual: <%v>", err)
1037 }
1038 podName1 := util.GetUniquePodName(pod1)
1039
1040 mounter1, err := plugin.NewMounter(volumeSpec1, pod1, volume.VolumeOptions{})
1041 if err != nil {
1042 t.Fatalf("NewMounter failed. Expected: <no error> Actual: <%v>", err)
1043 }
1044
1045 markVolumeOpts1 := operationexecutor.MarkVolumeOpts{
1046 PodName: podName1,
1047 PodUID: pod1.UID,
1048 VolumeName: generatedVolumeName1,
1049 Mounter: mounter1,
1050 OuterVolumeSpecName: volumeSpec1.Name(),
1051 VolumeSpec: volumeSpec1,
1052 VolumeMountState: operationexecutor.VolumeMountUncertain,
1053 }
1054 err = asw.AddPodToVolume(markVolumeOpts1)
1055 if err != nil {
1056 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
1057 }
1058 mountedVolumes := asw.GetMountedVolumesForPod(podName1)
1059 volumeFound := false
1060 for _, volume := range mountedVolumes {
1061 if volume.InnerVolumeSpecName == volumeSpec1.Name() {
1062 volumeFound = true
1063 }
1064 }
1065 if volumeFound {
1066 t.Fatalf("expected volume %s to be not found in asw.GetMountedVolumesForPod", volumeSpec1.Name())
1067 }
1068
1069 possiblyMountedVolumes := asw.GetPossiblyMountedVolumesForPod(podName1)
1070 volumeFound = false
1071 for _, volume := range possiblyMountedVolumes {
1072 if volume.InnerVolumeSpecName == volumeSpec1.Name() {
1073 volumeFound = true
1074 }
1075 }
1076 if !volumeFound {
1077 t.Fatalf("expected volume %s to be found in aws.GetPossiblyMountedVolumesForPod", volumeSpec1.Name())
1078 }
1079
1080 volExists, _, _ := asw.PodExistsInVolume(podName1, generatedVolumeName1, resource.Quantity{}, "")
1081 if volExists {
1082 t.Fatalf("expected volume %s to not exist in asw", generatedVolumeName1)
1083 }
1084 removed := asw.PodRemovedFromVolume(podName1, generatedVolumeName1)
1085 if removed {
1086 t.Fatalf("expected volume %s not to be removed in asw", generatedVolumeName1)
1087 }
1088 }
1089
1090 func verifyVolumeExistsInGloballyMountedVolumes(
1091 t *testing.T, expectedVolumeName v1.UniqueVolumeName, asw ActualStateOfWorld) {
1092 globallyMountedVolumes := asw.GetGloballyMountedVolumes()
1093 for _, volume := range globallyMountedVolumes {
1094 if volume.VolumeName == expectedVolumeName {
1095 return
1096 }
1097 }
1098
1099 t.Fatalf(
1100 "Could not find volume %v in the list of GloballyMountedVolumes for actual state of world %+v",
1101 expectedVolumeName,
1102 globallyMountedVolumes)
1103 }
1104
1105 func verifyVolumeExistsInGloballyMountedVolumesWithSELinux(
1106 t *testing.T, expectedVolumeName v1.UniqueVolumeName, expectedSELinuxContext string, asw ActualStateOfWorld) {
1107 globallyMountedVolumes := asw.GetGloballyMountedVolumes()
1108 for _, volume := range globallyMountedVolumes {
1109 if volume.VolumeName == expectedVolumeName {
1110 if volume.SELinuxMountContext == expectedSELinuxContext {
1111 return
1112 }
1113 t.Errorf(
1114 "Volume %q has wrong SELinux context. Expected %q, got %q",
1115 expectedVolumeName,
1116 expectedSELinuxContext,
1117 volume.SELinuxMountContext)
1118 }
1119 }
1120
1121 t.Fatalf(
1122 "Could not find volume %v in the list of GloballyMountedVolumes for actual state of world %+v",
1123 expectedVolumeName,
1124 globallyMountedVolumes)
1125 }
1126
1127 func verifyVolumeDoesntExistInGloballyMountedVolumes(
1128 t *testing.T, volumeToCheck v1.UniqueVolumeName, asw ActualStateOfWorld) {
1129 globallyMountedVolumes := asw.GetGloballyMountedVolumes()
1130 for _, volume := range globallyMountedVolumes {
1131 if volume.VolumeName == volumeToCheck {
1132 t.Fatalf(
1133 "Found volume %v in the list of GloballyMountedVolumes. Expected it not to exist.",
1134 volumeToCheck)
1135 }
1136 }
1137 }
1138
1139 func verifyVolumeExistsAsw(
1140 t *testing.T,
1141 expectedVolumeName v1.UniqueVolumeName,
1142 shouldExist bool,
1143 asw ActualStateOfWorld) {
1144 volumeExists := asw.VolumeExists(expectedVolumeName)
1145 if shouldExist != volumeExists {
1146 t.Fatalf(
1147 "VolumeExists(%q) response incorrect. Expected: <%v> Actual: <%v>",
1148 expectedVolumeName,
1149 shouldExist,
1150 volumeExists)
1151 }
1152 }
1153
1154 func verifyVolumeExistsAswWithSELinux(
1155 t *testing.T,
1156 expectedVolumeName v1.UniqueVolumeName,
1157 expectedSELinuxContext string,
1158 asw ActualStateOfWorld) {
1159 volumes := asw.GetMountedVolumes()
1160 for _, vol := range volumes {
1161 if vol.VolumeName == expectedVolumeName {
1162 if vol.SELinuxMountContext == expectedSELinuxContext {
1163 return
1164 }
1165 t.Errorf(
1166 "Volume %q has wrong SELinux context, expected %q, got %q",
1167 expectedVolumeName,
1168 expectedSELinuxContext,
1169 vol.SELinuxMountContext)
1170 }
1171 }
1172 t.Errorf("Volume %q not found in ASW", expectedVolumeName)
1173 }
1174
1175 func verifyVolumeExistsInUnmountedVolumes(
1176 t *testing.T, expectedVolumeName v1.UniqueVolumeName, asw ActualStateOfWorld) {
1177 unmountedVolumes := asw.GetUnmountedVolumes()
1178 for _, volume := range unmountedVolumes {
1179 if volume.VolumeName == expectedVolumeName {
1180 return
1181 }
1182 }
1183
1184 t.Fatalf(
1185 "Could not find volume %v in the list of UnmountedVolumes for actual state of world %+v",
1186 expectedVolumeName,
1187 unmountedVolumes)
1188 }
1189
1190 func verifyVolumeDoesntExistInUnmountedVolumes(
1191 t *testing.T, volumeToCheck v1.UniqueVolumeName, asw ActualStateOfWorld) {
1192 unmountedVolumes := asw.GetUnmountedVolumes()
1193 for _, volume := range unmountedVolumes {
1194 if volume.VolumeName == volumeToCheck {
1195 t.Fatalf(
1196 "Found volume %v in the list of UnmountedVolumes. Expected it not to exist.",
1197 volumeToCheck)
1198 }
1199 }
1200 }
1201
1202 func verifyPodExistsInVolumeAsw(
1203 t *testing.T,
1204 expectedPodName volumetypes.UniquePodName,
1205 expectedVolumeName v1.UniqueVolumeName,
1206 expectedDevicePath string,
1207 asw ActualStateOfWorld) {
1208 verifyPodExistsInVolumeAswWithSELinux(t, expectedPodName, expectedVolumeName, expectedDevicePath, "", asw)
1209 }
1210
1211 func verifyPodExistsInVolumeAswWithSELinux(
1212 t *testing.T,
1213 expectedPodName volumetypes.UniquePodName,
1214 expectedVolumeName v1.UniqueVolumeName,
1215 expectedDevicePath string,
1216 expectedSELinuxLabel string,
1217 asw ActualStateOfWorld) {
1218 podExistsInVolume, devicePath, err :=
1219 asw.PodExistsInVolume(expectedPodName, expectedVolumeName, resource.Quantity{}, expectedSELinuxLabel)
1220 if err != nil {
1221 t.Fatalf(
1222 "ASW PodExistsInVolume failed. Expected: <no error> Actual: <%v>", err)
1223 }
1224
1225 if !podExistsInVolume {
1226 t.Fatalf(
1227 "ASW PodExistsInVolume result invalid. Expected: <true> Actual: <%v>",
1228 podExistsInVolume)
1229 }
1230
1231 if devicePath != expectedDevicePath {
1232 t.Fatalf(
1233 "Invalid devicePath. Expected: <%q> Actual: <%q> ",
1234 expectedDevicePath,
1235 devicePath)
1236 }
1237 }
1238
1239 func verifyVolumeMountedElsewhere(
1240 t *testing.T,
1241 expectedPodName volumetypes.UniquePodName,
1242 expectedVolumeName v1.UniqueVolumeName,
1243 expectedMountedElsewhere bool,
1244 asw ActualStateOfWorld) {
1245 mountedElsewhere := asw.IsVolumeMountedElsewhere(expectedVolumeName, expectedPodName)
1246 if mountedElsewhere != expectedMountedElsewhere {
1247 t.Fatalf(
1248 "IsVolumeMountedElsewhere assertion failure. Expected : <%t> Actual: <%t>",
1249 expectedMountedElsewhere,
1250 mountedElsewhere)
1251 }
1252 }
1253
1254 func verifyPodDoesntExistInVolumeAsw(
1255 t *testing.T,
1256 podToCheck volumetypes.UniquePodName,
1257 volumeToCheck v1.UniqueVolumeName,
1258 expectVolumeToExist bool,
1259 asw ActualStateOfWorld) {
1260 podExistsInVolume, devicePath, err :=
1261 asw.PodExistsInVolume(podToCheck, volumeToCheck, resource.Quantity{}, "")
1262 if !expectVolumeToExist && err == nil {
1263 t.Fatalf(
1264 "ASW PodExistsInVolume did not return error. Expected: <error indicating volume does not exist> Actual: <%v>", err)
1265 }
1266
1267 if expectVolumeToExist && err != nil {
1268 t.Fatalf(
1269 "ASW PodExistsInVolume failed. Expected: <no error> Actual: <%v>", err)
1270 }
1271
1272 if podExistsInVolume {
1273 t.Fatalf(
1274 "ASW PodExistsInVolume result invalid. Expected: <false> Actual: <%v>",
1275 podExistsInVolume)
1276 }
1277
1278 if devicePath != "" {
1279 t.Fatalf(
1280 "Invalid devicePath. Expected: <\"\"> Actual: <%q> ",
1281 devicePath)
1282 }
1283 }
1284
1285 func verifyPodExistsInVolumeSELinuxMismatch(
1286 t *testing.T,
1287 podToCheck volumetypes.UniquePodName,
1288 volumeToCheck v1.UniqueVolumeName,
1289 unexpectedSELinuxLabel string,
1290 asw ActualStateOfWorld) {
1291
1292 podExistsInVolume, _, err := asw.PodExistsInVolume(podToCheck, volumeToCheck, resource.Quantity{}, unexpectedSELinuxLabel)
1293 if podExistsInVolume {
1294 t.Errorf("expected Pod %s not to exists, but it does", podToCheck)
1295 }
1296 if err == nil {
1297 t.Error("expected PodExistsInVolume to return error, but it returned nil")
1298 }
1299
1300 if !IsSELinuxMountMismatchError(err) {
1301 t.Errorf("expected PodExistsInVolume to return SELinuxMountMismatchError, got %s", err)
1302 }
1303 }
1304
1305 func verifyVolumeExistsWithSpecNameInVolumeAsw(
1306 t *testing.T,
1307 expectedPodName volumetypes.UniquePodName,
1308 expectedVolumeName string,
1309 asw ActualStateOfWorld) {
1310 podExistsInVolume :=
1311 asw.VolumeExistsWithSpecName(expectedPodName, expectedVolumeName)
1312
1313 if !podExistsInVolume {
1314 t.Fatalf(
1315 "ASW VolumeExistsWithSpecName result invalid. Expected: <true> Actual: <%v>",
1316 podExistsInVolume)
1317 }
1318 }
1319
1320 func verifyVolumeDoesntExistWithSpecNameInVolumeAsw(
1321 t *testing.T,
1322 podToCheck volumetypes.UniquePodName,
1323 volumeToCheck string,
1324 asw ActualStateOfWorld) {
1325 podExistsInVolume :=
1326 asw.VolumeExistsWithSpecName(podToCheck, volumeToCheck)
1327
1328 if podExistsInVolume {
1329 t.Fatalf(
1330 "ASW VolumeExistsWithSpecName result invalid. Expected: <false> Actual: <%v>",
1331 podExistsInVolume)
1332 }
1333 }
1334
1335 func verifyVolumeSpecNameInVolumeAsw(
1336 t *testing.T,
1337 podToCheck volumetypes.UniquePodName,
1338 volumeSpecs []*volume.Spec,
1339 asw ActualStateOfWorld) {
1340 mountedVolumes :=
1341 asw.GetMountedVolumesForPod(podToCheck)
1342
1343 for i, volume := range mountedVolumes {
1344 if volume.InnerVolumeSpecName != volumeSpecs[i].Name() {
1345 t.Fatalf("Volume spec name does not match Expected: <%q> Actual: <%q>", volumeSpecs[i].Name(), volume.InnerVolumeSpecName)
1346 }
1347 }
1348 }
1349
1350 func verifyVolumeFoundInReconstruction(t *testing.T, podToCheck volumetypes.UniquePodName, volumeToCheck v1.UniqueVolumeName, asw ActualStateOfWorld) {
1351 isRecontructed := asw.IsVolumeReconstructed(volumeToCheck, podToCheck)
1352 if !isRecontructed {
1353 t.Fatalf("ASW IsVolumeReconstructed result invalid. expected <true> Actual <false>")
1354 }
1355 }
1356
1357 func verifyVolumeAttachability(t *testing.T, volumeToCheck v1.UniqueVolumeName, asw ActualStateOfWorld, expected volumeAttachability) {
1358 attached := asw.GetAttachedVolumes()
1359 attachable := false
1360
1361 for _, volume := range attached {
1362 if volume.VolumeName == volumeToCheck {
1363 attachable = volume.PluginIsAttachable
1364 break
1365 }
1366 }
1367
1368 switch expected {
1369 case volumeAttachabilityTrue:
1370 if !attachable {
1371 t.Errorf("ASW reports %s as not-attachable, when %s was expected", volumeToCheck, expected)
1372 }
1373
1374
1375 case volumeAttachabilityUncertain, volumeAttachabilityFalse:
1376 if attachable {
1377 t.Errorf("ASW reports %s as attachable, when %s was expected", volumeToCheck, expected)
1378 }
1379 }
1380 }
1381
View as plain text