1
16
17 package cache
18
19 import (
20 "testing"
21
22 v1 "k8s.io/api/core/v1"
23 "k8s.io/apimachinery/pkg/api/resource"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 utilfeature "k8s.io/apiserver/pkg/util/feature"
26 featuregatetesting "k8s.io/component-base/featuregate/testing"
27 "k8s.io/kubernetes/pkg/features"
28 "k8s.io/kubernetes/pkg/volume"
29 volumetesting "k8s.io/kubernetes/pkg/volume/testing"
30 "k8s.io/kubernetes/pkg/volume/util"
31 volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
32 )
33
34
35
36
37 func Test_AddPodToVolume_Positive_NewPodNewVolume(t *testing.T) {
38
39 volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
40 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
41 dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
42 pod := &v1.Pod{
43 ObjectMeta: metav1.ObjectMeta{
44 Name: "pod3",
45 UID: "pod3uid",
46 },
47 Spec: v1.PodSpec{
48 Volumes: []v1.Volume{
49 {
50 Name: "volume-name",
51 VolumeSource: v1.VolumeSource{
52 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
53 PDName: "fake-device1",
54 },
55 },
56 },
57 },
58 },
59 }
60
61 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
62 podName := util.GetUniquePodName(pod)
63
64
65 generatedVolumeName, err := dsw.AddPodToVolume(
66 podName, pod, volumeSpec, volumeSpec.Name(), "" , nil )
67
68
69 if err != nil {
70 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
71 }
72
73 verifyVolumeExistsDsw(t, generatedVolumeName, "" , dsw)
74 verifyVolumeExistsInVolumesToMount(
75 t, generatedVolumeName, false , dsw)
76 verifyPodExistsInVolumeDsw(t, podName, generatedVolumeName, "" , dsw)
77 verifyVolumeExistsWithSpecNameInVolumeDsw(t, podName, volumeSpec.Name(), dsw)
78 }
79
80
81
82
83 func Test_AddPodToVolume_Positive_ExistingPodExistingVolume(t *testing.T) {
84
85 volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
86 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
87 dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
88 pod := &v1.Pod{
89 ObjectMeta: metav1.ObjectMeta{
90 Name: "pod3",
91 UID: "pod3uid",
92 },
93 Spec: v1.PodSpec{
94 Volumes: []v1.Volume{
95 {
96 Name: "volume-name",
97 VolumeSource: v1.VolumeSource{
98 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
99 PDName: "fake-device1",
100 },
101 },
102 },
103 },
104 },
105 }
106
107 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
108 podName := util.GetUniquePodName(pod)
109
110
111 generatedVolumeName, err := dsw.AddPodToVolume(
112 podName, pod, volumeSpec, volumeSpec.Name(), "" , nil )
113
114
115 if err != nil {
116 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
117 }
118
119 verifyVolumeExistsDsw(t, generatedVolumeName, "" , dsw)
120 verifyVolumeExistsInVolumesToMount(
121 t, generatedVolumeName, false , dsw)
122 verifyPodExistsInVolumeDsw(t, podName, generatedVolumeName, "" , dsw)
123 verifyVolumeExistsWithSpecNameInVolumeDsw(t, podName, volumeSpec.Name(), dsw)
124 }
125
126
127
128
129 func Test_AddPodToVolume_Positive_NamesForDifferentPodsAndDifferentVolumes(t *testing.T) {
130
131 fakeVolumeHost := volumetesting.NewFakeVolumeHost(t,
132 "",
133 nil,
134 nil,
135 )
136 plugins := []volume.VolumePlugin{
137 &volumetesting.FakeBasicVolumePlugin{
138 Plugin: volumetesting.FakeVolumePlugin{
139 PluginName: "basic",
140 },
141 },
142 &volumetesting.FakeDeviceMountableVolumePlugin{
143 FakeBasicVolumePlugin: volumetesting.FakeBasicVolumePlugin{
144 Plugin: volumetesting.FakeVolumePlugin{
145 PluginName: "device-mountable",
146 },
147 },
148 },
149 &volumetesting.FakeAttachableVolumePlugin{
150 FakeDeviceMountableVolumePlugin: volumetesting.FakeDeviceMountableVolumePlugin{
151 FakeBasicVolumePlugin: volumetesting.FakeBasicVolumePlugin{
152 Plugin: volumetesting.FakeVolumePlugin{
153 PluginName: "attachable",
154 },
155 },
156 },
157 },
158 }
159 volumePluginMgr := volume.VolumePluginMgr{}
160 volumePluginMgr.InitPlugins(plugins, nil , fakeVolumeHost)
161 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
162 dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)
163
164 testcases := map[string]struct {
165 pod1 *v1.Pod
166 pod2 *v1.Pod
167 same bool
168 }{
169 "basic": {
170 &v1.Pod{
171 ObjectMeta: metav1.ObjectMeta{
172 Name: "pod1",
173 UID: "pod1uid",
174 },
175 Spec: v1.PodSpec{
176 Volumes: []v1.Volume{
177 {
178 Name: "basic",
179 VolumeSource: v1.VolumeSource{},
180 },
181 },
182 },
183 },
184 &v1.Pod{
185 ObjectMeta: metav1.ObjectMeta{
186 Name: "pod2",
187 UID: "pod2uid",
188 },
189 Spec: v1.PodSpec{
190 Volumes: []v1.Volume{
191 {
192 Name: "basic",
193 VolumeSource: v1.VolumeSource{},
194 },
195 },
196 },
197 },
198 false,
199 },
200 "device-mountable": {
201 &v1.Pod{
202 ObjectMeta: metav1.ObjectMeta{
203 Name: "pod1",
204 UID: "pod1uid",
205 },
206 Spec: v1.PodSpec{
207 Volumes: []v1.Volume{
208 {
209 Name: "device-mountable",
210 VolumeSource: v1.VolumeSource{},
211 },
212 },
213 },
214 },
215 &v1.Pod{
216 ObjectMeta: metav1.ObjectMeta{
217 Name: "pod2",
218 UID: "pod2uid",
219 },
220 Spec: v1.PodSpec{
221 Volumes: []v1.Volume{
222 {
223 Name: "device-mountable",
224 VolumeSource: v1.VolumeSource{},
225 },
226 },
227 },
228 },
229 true,
230 },
231 "attachable": {
232 &v1.Pod{
233 ObjectMeta: metav1.ObjectMeta{
234 Name: "pod1",
235 UID: "pod1uid",
236 },
237 Spec: v1.PodSpec{
238 Volumes: []v1.Volume{
239 {
240 Name: "attachable",
241 VolumeSource: v1.VolumeSource{},
242 },
243 },
244 },
245 },
246 &v1.Pod{
247 ObjectMeta: metav1.ObjectMeta{
248 Name: "pod2",
249 UID: "pod2uid",
250 },
251 Spec: v1.PodSpec{
252 Volumes: []v1.Volume{
253 {
254 Name: "attachable",
255 VolumeSource: v1.VolumeSource{},
256 },
257 },
258 },
259 },
260 true,
261 },
262 }
263
264
265 for name, v := range testcases {
266 volumeSpec1 := &volume.Spec{Volume: &v.pod1.Spec.Volumes[0]}
267 volumeSpec2 := &volume.Spec{Volume: &v.pod2.Spec.Volumes[0]}
268 generatedVolumeName1, err1 := dsw.AddPodToVolume(util.GetUniquePodName(v.pod1), v.pod1, volumeSpec1, volumeSpec1.Name(), "", nil)
269 generatedVolumeName2, err2 := dsw.AddPodToVolume(util.GetUniquePodName(v.pod2), v.pod2, volumeSpec2, volumeSpec2.Name(), "", nil)
270 if err1 != nil {
271 t.Fatalf("test %q: AddPodToVolume failed. Expected: <no error> Actual: <%v>", name, err1)
272 }
273 if err2 != nil {
274 t.Fatalf("test %q: AddPodToVolume failed. Expected: <no error> Actual: <%v>", name, err2)
275 }
276 if v.same {
277 if generatedVolumeName1 != generatedVolumeName2 {
278 t.Fatalf("test %q: AddPodToVolume should generate same names, but got %q != %q", name, generatedVolumeName1, generatedVolumeName2)
279 }
280 } else {
281 if generatedVolumeName1 == generatedVolumeName2 {
282 t.Fatalf("test %q: AddPodToVolume should generate different names, but got %q == %q", name, generatedVolumeName1, generatedVolumeName2)
283 }
284 }
285 }
286
287 }
288
289
290
291
292 func Test_DeletePodFromVolume_Positive_PodExistsVolumeExists(t *testing.T) {
293
294 volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
295 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
296 dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
297 pod := &v1.Pod{
298 ObjectMeta: metav1.ObjectMeta{
299 Name: "pod3",
300 UID: "pod3uid",
301 },
302 Spec: v1.PodSpec{
303 Volumes: []v1.Volume{
304 {
305 Name: "volume-name",
306 VolumeSource: v1.VolumeSource{
307 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
308 PDName: "fake-device1",
309 },
310 },
311 },
312 },
313 },
314 }
315
316 volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
317 podName := util.GetUniquePodName(pod)
318 generatedVolumeName, err := dsw.AddPodToVolume(
319 podName, pod, volumeSpec, volumeSpec.Name(), "" , nil )
320 if err != nil {
321 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
322 }
323 verifyVolumeExistsDsw(t, generatedVolumeName, "" , dsw)
324 verifyVolumeExistsInVolumesToMount(
325 t, generatedVolumeName, false , dsw)
326 verifyPodExistsInVolumeDsw(t, podName, generatedVolumeName, "" , dsw)
327
328
329 dsw.DeletePodFromVolume(podName, generatedVolumeName)
330
331
332 verifyVolumeDoesntExist(t, generatedVolumeName, "" , dsw)
333 verifyVolumeDoesntExistInVolumesToMount(t, generatedVolumeName, dsw)
334 verifyPodDoesntExistInVolumeDsw(t, podName, generatedVolumeName, "" , dsw)
335 verifyVolumeDoesntExistWithSpecNameInVolumeDsw(t, podName, volumeSpec.Name(), dsw)
336 }
337
338
339
340
341
342
343
344
345 func Test_MarkVolumesReportedInUse_Positive_NewPodNewVolume(t *testing.T) {
346
347 volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
348 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
349 dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
350
351 pod1 := &v1.Pod{
352 ObjectMeta: metav1.ObjectMeta{
353 Name: "pod1",
354 UID: "pod1uid",
355 },
356 Spec: v1.PodSpec{
357 Volumes: []v1.Volume{
358 {
359 Name: "volume1-name",
360 VolumeSource: v1.VolumeSource{
361 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
362 PDName: "fake-device1",
363 },
364 },
365 },
366 },
367 },
368 }
369
370 volume1Spec := &volume.Spec{Volume: &pod1.Spec.Volumes[0]}
371 pod1Name := util.GetUniquePodName(pod1)
372
373 pod2 := &v1.Pod{
374 ObjectMeta: metav1.ObjectMeta{
375 Name: "pod2",
376 UID: "pod2uid",
377 },
378 Spec: v1.PodSpec{
379 Volumes: []v1.Volume{
380 {
381 Name: "volume2-name",
382 VolumeSource: v1.VolumeSource{
383 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
384 PDName: "fake-device2",
385 },
386 },
387 },
388 },
389 },
390 }
391
392 volume2Spec := &volume.Spec{Volume: &pod2.Spec.Volumes[0]}
393 pod2Name := util.GetUniquePodName(pod2)
394
395 pod3 := &v1.Pod{
396 ObjectMeta: metav1.ObjectMeta{
397 Name: "pod3",
398 UID: "pod3uid",
399 },
400 Spec: v1.PodSpec{
401 Volumes: []v1.Volume{
402 {
403 Name: "volume3-name",
404 VolumeSource: v1.VolumeSource{
405 GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
406 PDName: "fake-device3",
407 },
408 },
409 },
410 },
411 },
412 }
413
414 volume3Spec := &volume.Spec{Volume: &pod3.Spec.Volumes[0]}
415 pod3Name := util.GetUniquePodName(pod3)
416
417 generatedVolume1Name, err := dsw.AddPodToVolume(
418 pod1Name, pod1, volume1Spec, volume1Spec.Name(), "" , nil )
419 if err != nil {
420 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
421 }
422
423 generatedVolume2Name, err := dsw.AddPodToVolume(
424 pod2Name, pod2, volume2Spec, volume2Spec.Name(), "" , nil )
425 if err != nil {
426 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
427 }
428
429 generatedVolume3Name, err := dsw.AddPodToVolume(
430 pod3Name, pod3, volume3Spec, volume3Spec.Name(), "" , nil )
431 if err != nil {
432 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
433 }
434
435
436 volumesReportedInUse := []v1.UniqueVolumeName{generatedVolume2Name}
437 dsw.MarkVolumesReportedInUse(volumesReportedInUse)
438
439
440 verifyVolumeExistsDsw(t, generatedVolume1Name, "" , dsw)
441 verifyVolumeExistsInVolumesToMount(
442 t, generatedVolume1Name, false , dsw)
443 verifyPodExistsInVolumeDsw(t, pod1Name, generatedVolume1Name, "" , dsw)
444 verifyVolumeExistsDsw(t, generatedVolume2Name, "" , dsw)
445 verifyVolumeExistsInVolumesToMount(
446 t, generatedVolume2Name, true , dsw)
447 verifyPodExistsInVolumeDsw(t, pod2Name, generatedVolume2Name, "" , dsw)
448 verifyVolumeExistsDsw(t, generatedVolume3Name, "" , dsw)
449 verifyVolumeExistsInVolumesToMount(
450 t, generatedVolume3Name, false , dsw)
451 verifyPodExistsInVolumeDsw(t, pod3Name, generatedVolume3Name, "" , dsw)
452
453
454 volumesReportedInUse = []v1.UniqueVolumeName{generatedVolume3Name}
455 dsw.MarkVolumesReportedInUse(volumesReportedInUse)
456
457
458 verifyVolumeExistsDsw(t, generatedVolume1Name, "" , dsw)
459 verifyVolumeExistsInVolumesToMount(
460 t, generatedVolume1Name, false , dsw)
461 verifyPodExistsInVolumeDsw(t, pod1Name, generatedVolume1Name, "" , dsw)
462 verifyVolumeExistsDsw(t, generatedVolume2Name, "" , dsw)
463 verifyVolumeExistsInVolumesToMount(
464 t, generatedVolume2Name, false , dsw)
465 verifyPodExistsInVolumeDsw(t, pod2Name, generatedVolume2Name, "" , dsw)
466 verifyVolumeExistsDsw(t, generatedVolume3Name, "" , dsw)
467 verifyVolumeExistsInVolumesToMount(
468 t, generatedVolume3Name, true , dsw)
469 verifyPodExistsInVolumeDsw(t, pod3Name, generatedVolume3Name, "" , dsw)
470 }
471
472 func Test_AddPodToVolume_WithEmptyDirSizeLimit(t *testing.T) {
473 volumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
474 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
475 dsw := NewDesiredStateOfWorld(volumePluginMgr, seLinuxTranslator)
476 quantity1Gi := resource.MustParse("1Gi")
477 quantity2Gi := resource.MustParse("2Gi")
478 quantity3Gi := resource.MustParse("3Gi")
479
480 pod1 := &v1.Pod{
481 ObjectMeta: metav1.ObjectMeta{
482 Name: "pod1",
483 UID: "pod1uid",
484 },
485 Spec: v1.PodSpec{
486 Containers: []v1.Container{
487 {
488 Resources: v1.ResourceRequirements{
489 Limits: v1.ResourceList{
490 v1.ResourceEphemeralStorage: quantity1Gi,
491 },
492 },
493 },
494 {
495 Resources: v1.ResourceRequirements{
496 Limits: v1.ResourceList{
497 v1.ResourceEphemeralStorage: quantity1Gi,
498 },
499 },
500 },
501 },
502 Volumes: []v1.Volume{
503 {
504 Name: "emptyDir1",
505 VolumeSource: v1.VolumeSource{
506 EmptyDir: &v1.EmptyDirVolumeSource{
507 SizeLimit: &quantity1Gi,
508 },
509 },
510 },
511 {
512 Name: "emptyDir2",
513 VolumeSource: v1.VolumeSource{
514 EmptyDir: &v1.EmptyDirVolumeSource{
515 SizeLimit: &quantity2Gi,
516 },
517 },
518 },
519 {
520 Name: "emptyDir3",
521 VolumeSource: v1.VolumeSource{
522 EmptyDir: &v1.EmptyDirVolumeSource{
523 SizeLimit: &quantity3Gi,
524 },
525 },
526 },
527 {
528 Name: "emptyDir4",
529 VolumeSource: v1.VolumeSource{
530 EmptyDir: &v1.EmptyDirVolumeSource{},
531 },
532 },
533 },
534 },
535 }
536 pod1Name := util.GetUniquePodName(pod1)
537 pod1DesiredSizeLimitMap := map[string]*resource.Quantity{
538 "emptyDir1": &quantity1Gi,
539 "emptyDir2": &quantity2Gi,
540 "emptyDir3": &quantity2Gi,
541 "emptyDir4": &quantity2Gi,
542 }
543 pod2 := &v1.Pod{
544 ObjectMeta: metav1.ObjectMeta{
545 Name: "pod2",
546 UID: "pod2uid",
547 },
548 Spec: v1.PodSpec{
549 Volumes: []v1.Volume{
550 {
551 Name: "emptyDir5",
552 VolumeSource: v1.VolumeSource{
553 EmptyDir: &v1.EmptyDirVolumeSource{
554 SizeLimit: &quantity1Gi,
555 },
556 },
557 },
558 {
559 Name: "emptyDir6",
560 VolumeSource: v1.VolumeSource{
561 EmptyDir: &v1.EmptyDirVolumeSource{
562 SizeLimit: &quantity2Gi,
563 },
564 },
565 },
566 {
567 Name: "emptyDir7",
568 VolumeSource: v1.VolumeSource{
569 EmptyDir: &v1.EmptyDirVolumeSource{
570 SizeLimit: &quantity3Gi,
571 },
572 },
573 },
574 {
575 Name: "emptyDir8",
576 VolumeSource: v1.VolumeSource{
577 EmptyDir: &v1.EmptyDirVolumeSource{},
578 },
579 },
580 },
581 },
582 }
583 pod2Name := util.GetUniquePodName(pod2)
584 pod2DesiredSizeLimitMap := map[string]*resource.Quantity{
585 "emptyDir5": &quantity1Gi,
586 "emptyDir6": &quantity2Gi,
587 "emptyDir7": &quantity3Gi,
588 "emptyDir8": resource.NewQuantity(0, resource.BinarySI),
589 }
590 for i := range pod1.Spec.Volumes {
591 volumeSpec := &volume.Spec{Volume: &pod1.Spec.Volumes[i]}
592 _, err := dsw.AddPodToVolume(pod1Name, pod1, volumeSpec, volumeSpec.Name(), "", nil )
593 if err != nil {
594 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
595 }
596 }
597 for i := range pod2.Spec.Volumes {
598 volumeSpec := &volume.Spec{Volume: &pod2.Spec.Volumes[i]}
599 _, err := dsw.AddPodToVolume(pod2Name, pod2, volumeSpec, volumeSpec.Name(), "", nil )
600 if err != nil {
601 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
602 }
603 }
604 verifyDesiredSizeLimitInVolumeDsw(t, pod1Name, pod1DesiredSizeLimitMap, dsw)
605 verifyDesiredSizeLimitInVolumeDsw(t, pod2Name, pod2DesiredSizeLimitMap, dsw)
606 }
607
608
609
610
611 func Test_AddPodToVolume_Positive_SELinuxNoRWOP(t *testing.T) {
612 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
613
614 plugins := []volume.VolumePlugin{
615 &volumetesting.FakeDeviceMountableVolumePlugin{
616 FakeBasicVolumePlugin: volumetesting.FakeBasicVolumePlugin{
617 Plugin: volumetesting.FakeVolumePlugin{
618 PluginName: "basic",
619 SupportsSELinux: true,
620 },
621 },
622 },
623 }
624 volumePluginMgr := volume.VolumePluginMgr{}
625 fakeVolumeHost := volumetesting.NewFakeVolumeHost(t,
626 "",
627 nil,
628 nil,
629 )
630 volumePluginMgr.InitPlugins(plugins, nil , fakeVolumeHost)
631 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
632 dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)
633 seLinux := v1.SELinuxOptions{
634 User: "system_u",
635 Role: "object_r",
636 Type: "container_t",
637 Level: "s0:c1,c2",
638 }
639 pod := &v1.Pod{
640 ObjectMeta: metav1.ObjectMeta{
641 Name: "pod1",
642 UID: "pod1uid",
643 },
644 Spec: v1.PodSpec{
645 SecurityContext: &v1.PodSecurityContext{
646 SELinuxOptions: &seLinux,
647 },
648 Volumes: []v1.Volume{
649 {
650 Name: "volume-name",
651 VolumeSource: v1.VolumeSource{
652 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
653 ClaimName: "myClaim",
654 },
655 },
656 },
657 },
658 },
659 }
660
661 volumeSpec := &volume.Spec{
662 PersistentVolume: &v1.PersistentVolume{
663 ObjectMeta: metav1.ObjectMeta{
664 Name: "basicPV",
665 },
666 Spec: v1.PersistentVolumeSpec{
667 AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany},
668 },
669 },
670 }
671 podName := util.GetUniquePodName(pod)
672 seLinuxContainerContexts := []*v1.SELinuxOptions{&seLinux}
673
674
675 generatedVolumeName, err := dsw.AddPodToVolume(
676 podName, pod, volumeSpec, volumeSpec.Name(), "" , seLinuxContainerContexts)
677
678
679 if err != nil {
680 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
681 }
682
683 verifyVolumeExistsDsw(t, generatedVolumeName, "" , dsw)
684 verifyVolumeExistsInVolumesToMount(
685 t, generatedVolumeName, false , dsw)
686 verifyPodExistsInVolumeDsw(t, podName, generatedVolumeName, "" , dsw)
687 verifyVolumeExistsWithSpecNameInVolumeDsw(t, podName, volumeSpec.Name(), dsw)
688 }
689
690
691
692
693 func Test_AddPodToVolume_Positive_NoSELinuxPlugin(t *testing.T) {
694 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
695
696 plugins := []volume.VolumePlugin{
697 &volumetesting.FakeDeviceMountableVolumePlugin{
698 FakeBasicVolumePlugin: volumetesting.FakeBasicVolumePlugin{
699 Plugin: volumetesting.FakeVolumePlugin{
700 PluginName: "basic",
701 SupportsSELinux: false,
702 },
703 },
704 },
705 }
706 volumePluginMgr := volume.VolumePluginMgr{}
707 fakeVolumeHost := volumetesting.NewFakeVolumeHost(t,
708 "",
709 nil,
710 nil,
711 )
712 volumePluginMgr.InitPlugins(plugins, nil , fakeVolumeHost)
713 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
714 dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)
715 seLinux := v1.SELinuxOptions{
716 User: "system_u",
717 Role: "object_r",
718 Type: "container_t",
719 Level: "s0:c1,c2",
720 }
721 pod := &v1.Pod{
722 ObjectMeta: metav1.ObjectMeta{
723 Name: "pod1",
724 UID: "pod1uid",
725 },
726 Spec: v1.PodSpec{
727 SecurityContext: &v1.PodSecurityContext{
728 SELinuxOptions: &seLinux,
729 },
730 Volumes: []v1.Volume{
731 {
732 Name: "volume-name",
733 VolumeSource: v1.VolumeSource{
734 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
735 ClaimName: "myClaim",
736 },
737 },
738 },
739 },
740 },
741 }
742
743 volumeSpec := &volume.Spec{
744 PersistentVolume: &v1.PersistentVolume{
745 ObjectMeta: metav1.ObjectMeta{
746 Name: "basicPV",
747 },
748 Spec: v1.PersistentVolumeSpec{
749 AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod},
750 },
751 },
752 }
753 podName := util.GetUniquePodName(pod)
754 seLinuxContainerContexts := []*v1.SELinuxOptions{&seLinux}
755
756
757 generatedVolumeName, err := dsw.AddPodToVolume(
758 podName, pod, volumeSpec, volumeSpec.Name(), "" , seLinuxContainerContexts)
759
760
761 if err != nil {
762 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
763 }
764
765 verifyVolumeExistsDsw(t, generatedVolumeName, "" , dsw)
766 verifyVolumeExistsInVolumesToMount(
767 t, generatedVolumeName, false , dsw)
768 verifyPodExistsInVolumeDsw(t, podName, generatedVolumeName, "" , dsw)
769 verifyVolumeExistsWithSpecNameInVolumeDsw(t, podName, volumeSpec.Name(), dsw)
770 }
771
772
773
774
775
776 func Test_AddPodToVolume_Positive_ExistingPodSameSELinuxRWOP(t *testing.T) {
777 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
778
779 plugins := []volume.VolumePlugin{
780 &volumetesting.FakeDeviceMountableVolumePlugin{
781 FakeBasicVolumePlugin: volumetesting.FakeBasicVolumePlugin{
782 Plugin: volumetesting.FakeVolumePlugin{
783 PluginName: "basic",
784 SupportsSELinux: true,
785 },
786 },
787 },
788 }
789 volumePluginMgr := volume.VolumePluginMgr{}
790 fakeVolumeHost := volumetesting.NewFakeVolumeHost(t,
791 "",
792 nil,
793 nil,
794 )
795 volumePluginMgr.InitPlugins(plugins, nil , fakeVolumeHost)
796 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
797 dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)
798 seLinux := v1.SELinuxOptions{
799 User: "system_u",
800 Role: "object_r",
801 Type: "container_t",
802 Level: "s0:c1,c2",
803 }
804 pod := &v1.Pod{
805 ObjectMeta: metav1.ObjectMeta{
806 Name: "pod1",
807 UID: "pod1uid",
808 },
809 Spec: v1.PodSpec{
810 SecurityContext: &v1.PodSecurityContext{
811 SELinuxOptions: &seLinux,
812 },
813 Volumes: []v1.Volume{
814 {
815 Name: "volume-name",
816 VolumeSource: v1.VolumeSource{
817 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
818 ClaimName: "myClaim",
819 },
820 },
821 },
822 },
823 },
824 }
825
826 volumeSpec := &volume.Spec{
827 PersistentVolume: &v1.PersistentVolume{
828 ObjectMeta: metav1.ObjectMeta{
829 Name: "basicPV",
830 },
831 Spec: v1.PersistentVolumeSpec{
832 AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod},
833 },
834 },
835 }
836 podName := util.GetUniquePodName(pod)
837 seLinuxContainerContexts := []*v1.SELinuxOptions{&seLinux}
838
839
840 generatedVolumeName, err := dsw.AddPodToVolume(
841 podName, pod, volumeSpec, volumeSpec.Name(), "" , seLinuxContainerContexts)
842
843
844 if err != nil {
845 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
846 }
847
848 verifyVolumeExistsDsw(t, generatedVolumeName, "system_u:object_r:container_file_t:s0:c1,c2", dsw)
849 verifyVolumeExistsInVolumesToMount(
850 t, generatedVolumeName, false , dsw)
851 verifyPodExistsInVolumeDsw(t, podName, generatedVolumeName, "system_u:object_r:container_file_t:s0:c1,c2", dsw)
852 verifyVolumeExistsWithSpecNameInVolumeDsw(t, podName, volumeSpec.Name(), dsw)
853
854
855 pod2 := pod.DeepCopy()
856 pod2.Name = "pod2"
857 pod2.UID = "pod2uid"
858 pod2Name := util.GetUniquePodName(pod)
859
860
861 generatedVolumeName2, err := dsw.AddPodToVolume(
862 pod2Name, pod2, volumeSpec, volumeSpec.Name(), "" , seLinuxContainerContexts)
863
864 if err != nil {
865 t.Fatalf("Second AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
866 }
867 if generatedVolumeName2 != generatedVolumeName {
868 t.Errorf("Expected second generatedVolumeName %s, got %s", generatedVolumeName, generatedVolumeName2)
869 }
870
871 verifyPodExistsInVolumeDsw(t, pod2Name, generatedVolumeName, "system_u:object_r:container_file_t:s0:c1,c2", dsw)
872 }
873
874
875
876
877
878 func Test_AddPodToVolume_Negative_ExistingPodDifferentSELinuxRWOP(t *testing.T) {
879 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
880
881 plugins := []volume.VolumePlugin{
882 &volumetesting.FakeDeviceMountableVolumePlugin{
883 FakeBasicVolumePlugin: volumetesting.FakeBasicVolumePlugin{
884 Plugin: volumetesting.FakeVolumePlugin{
885 PluginName: "basic",
886 SupportsSELinux: true,
887 },
888 },
889 },
890 }
891 volumePluginMgr := volume.VolumePluginMgr{}
892 fakeVolumeHost := volumetesting.NewFakeVolumeHost(t,
893 "",
894 nil,
895 nil,
896 )
897 volumePluginMgr.InitPlugins(plugins, nil , fakeVolumeHost)
898 seLinuxTranslator := util.NewFakeSELinuxLabelTranslator()
899 dsw := NewDesiredStateOfWorld(&volumePluginMgr, seLinuxTranslator)
900 seLinux1 := v1.SELinuxOptions{
901 User: "system_u",
902 Role: "object_r",
903 Type: "container_t",
904 Level: "s0:c1,c2",
905 }
906 pod := &v1.Pod{
907 ObjectMeta: metav1.ObjectMeta{
908 Name: "pod1",
909 UID: "pod1uid",
910 },
911 Spec: v1.PodSpec{
912 SecurityContext: &v1.PodSecurityContext{
913 SELinuxOptions: &seLinux1,
914 },
915 Volumes: []v1.Volume{
916 {
917 Name: "volume-name",
918 VolumeSource: v1.VolumeSource{
919 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
920 ClaimName: "myClaim",
921 },
922 },
923 },
924 },
925 },
926 }
927
928 volumeSpec := &volume.Spec{
929 PersistentVolume: &v1.PersistentVolume{
930 ObjectMeta: metav1.ObjectMeta{
931 Name: "basicPV",
932 },
933 Spec: v1.PersistentVolumeSpec{
934 AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod},
935 },
936 },
937 }
938 podName := util.GetUniquePodName(pod)
939 seLinuxContainerContexts := []*v1.SELinuxOptions{&seLinux1}
940
941
942 generatedVolumeName, err := dsw.AddPodToVolume(
943 podName, pod, volumeSpec, volumeSpec.Name(), "" , seLinuxContainerContexts)
944
945
946 if err != nil {
947 t.Fatalf("AddPodToVolume failed. Expected: <no error> Actual: <%v>", err)
948 }
949
950 verifyVolumeExistsDsw(t, generatedVolumeName, "system_u:object_r:container_file_t:s0:c1,c2", dsw)
951 verifyVolumeExistsInVolumesToMount(
952 t, generatedVolumeName, false , dsw)
953 verifyPodExistsInVolumeDsw(t, podName, generatedVolumeName, "system_u:object_r:container_file_t:s0:c1,c2", dsw)
954 verifyVolumeExistsWithSpecNameInVolumeDsw(t, podName, volumeSpec.Name(), dsw)
955
956
957 seLinux2 := v1.SELinuxOptions{
958 User: "system_u",
959 Role: "object_r",
960 Type: "container_t",
961 Level: "s0:c3,c4",
962 }
963 seLinuxContainerContexts2 := []*v1.SELinuxOptions{&seLinux2}
964 pod2 := pod.DeepCopy()
965 pod2.Name = "pod2"
966 pod2.UID = "pod2uid"
967 pod2.Spec.SecurityContext.SELinuxOptions = &seLinux2
968 pod2Name := util.GetUniquePodName(pod2)
969
970
971 _, err = dsw.AddPodToVolume(
972 pod2Name, pod2, volumeSpec, volumeSpec.Name(), "" , seLinuxContainerContexts2)
973
974 if err == nil {
975 t.Fatalf("Second AddPodToVolume succeeded, expected a failure")
976 }
977
978 verifyPodExistsInVolumeDsw(t, podName, generatedVolumeName, "system_u:object_r:container_file_t:s0:c1,c2", dsw)
979 }
980
981 func verifyVolumeExistsDsw(
982 t *testing.T, expectedVolumeName v1.UniqueVolumeName, expectedSELinuxContext string, dsw DesiredStateOfWorld) {
983 volumeExists := dsw.VolumeExists(expectedVolumeName, expectedSELinuxContext)
984 if !volumeExists {
985 t.Fatalf(
986 "VolumeExists(%q) failed. Expected: <true> Actual: <%v>",
987 expectedVolumeName,
988 volumeExists)
989 }
990 }
991
992 func verifyVolumeDoesntExist(
993 t *testing.T, expectedVolumeName v1.UniqueVolumeName, expectedSELinuxContext string, dsw DesiredStateOfWorld) {
994 volumeExists := dsw.VolumeExists(expectedVolumeName, expectedSELinuxContext)
995 if volumeExists {
996 t.Fatalf(
997 "VolumeExists(%q) returned incorrect value. Expected: <false> Actual: <%v>",
998 expectedVolumeName,
999 volumeExists)
1000 }
1001 }
1002
1003 func verifyVolumeExistsInVolumesToMount(
1004 t *testing.T,
1005 expectedVolumeName v1.UniqueVolumeName,
1006 expectReportedInUse bool,
1007 dsw DesiredStateOfWorld) {
1008 volumesToMount := dsw.GetVolumesToMount()
1009 for _, volume := range volumesToMount {
1010 if volume.VolumeName == expectedVolumeName {
1011 if volume.ReportedInUse != expectReportedInUse {
1012 t.Fatalf(
1013 "Found volume %v in the list of VolumesToMount, but ReportedInUse incorrect. Expected: <%v> Actual: <%v>",
1014 expectedVolumeName,
1015 expectReportedInUse,
1016 volume.ReportedInUse)
1017 }
1018
1019 return
1020 }
1021 }
1022
1023 t.Fatalf(
1024 "Could not find volume %v in the list of desired state of world volumes to mount %+v",
1025 expectedVolumeName,
1026 volumesToMount)
1027 }
1028
1029 func verifyVolumeDoesntExistInVolumesToMount(
1030 t *testing.T, volumeToCheck v1.UniqueVolumeName, dsw DesiredStateOfWorld) {
1031 volumesToMount := dsw.GetVolumesToMount()
1032 for _, volume := range volumesToMount {
1033 if volume.VolumeName == volumeToCheck {
1034 t.Fatalf(
1035 "Found volume %v in the list of desired state of world volumes to mount. Expected it not to exist.",
1036 volumeToCheck)
1037 }
1038 }
1039 }
1040
1041 func verifyPodExistsInVolumeDsw(
1042 t *testing.T,
1043 expectedPodName volumetypes.UniquePodName,
1044 expectedVolumeName v1.UniqueVolumeName,
1045 expectedSeLinuxContext string,
1046 dsw DesiredStateOfWorld) {
1047 if podExistsInVolume := dsw.PodExistsInVolume(
1048 expectedPodName, expectedVolumeName, expectedSeLinuxContext); !podExistsInVolume {
1049 t.Fatalf(
1050 "DSW PodExistsInVolume returned incorrect value. Expected: <true> Actual: <%v>",
1051 podExistsInVolume)
1052 }
1053 }
1054
1055 func verifyPodDoesntExistInVolumeDsw(
1056 t *testing.T,
1057 expectedPodName volumetypes.UniquePodName,
1058 expectedVolumeName v1.UniqueVolumeName,
1059 expectedSeLinuxContext string,
1060 dsw DesiredStateOfWorld) {
1061 if podExistsInVolume := dsw.PodExistsInVolume(
1062 expectedPodName, expectedVolumeName, expectedSeLinuxContext); podExistsInVolume {
1063 t.Fatalf(
1064 "DSW PodExistsInVolume returned incorrect value. Expected: <true> Actual: <%v>",
1065 podExistsInVolume)
1066 }
1067 }
1068
1069 func verifyVolumeExistsWithSpecNameInVolumeDsw(
1070 t *testing.T,
1071 expectedPodName volumetypes.UniquePodName,
1072 expectedVolumeSpecName string,
1073 dsw DesiredStateOfWorld) {
1074 if podExistsInVolume := dsw.VolumeExistsWithSpecName(
1075 expectedPodName, expectedVolumeSpecName); !podExistsInVolume {
1076 t.Fatalf(
1077 "DSW VolumeExistsWithSpecNam returned incorrect value. Expected: <true> Actual: <%v>",
1078 podExistsInVolume)
1079 }
1080 }
1081
1082 func verifyVolumeDoesntExistWithSpecNameInVolumeDsw(
1083 t *testing.T,
1084 expectedPodName volumetypes.UniquePodName,
1085 expectedVolumeSpecName string,
1086 dsw DesiredStateOfWorld) {
1087 if podExistsInVolume := dsw.VolumeExistsWithSpecName(
1088 expectedPodName, expectedVolumeSpecName); podExistsInVolume {
1089 t.Fatalf(
1090 "DSW VolumeExistsWithSpecNam returned incorrect value. Expected: <true> Actual: <%v>",
1091 podExistsInVolume)
1092 }
1093 }
1094
1095 func verifyDesiredSizeLimitInVolumeDsw(
1096 t *testing.T,
1097 expectedPodName volumetypes.UniquePodName,
1098 expectedDesiredSizeMap map[string]*resource.Quantity,
1099 dsw DesiredStateOfWorld) {
1100 volumesToMount := dsw.GetVolumesToMount()
1101 for volumeName, expectedDesiredSize := range expectedDesiredSizeMap {
1102 if podExistsInVolume := dsw.VolumeExistsWithSpecName(
1103 expectedPodName, volumeName); !podExistsInVolume {
1104 t.Fatalf(
1105 "DSW VolumeExistsWithSpecName returned incorrect value. Expected: <true> Actual: <%v>",
1106 podExistsInVolume)
1107 }
1108 for _, v := range volumesToMount {
1109 if v.VolumeSpec.Name() == volumeName && v.PodName == expectedPodName {
1110 if v.DesiredSizeLimit == nil || v.DesiredSizeLimit.Value() != expectedDesiredSize.Value() {
1111 t.Fatalf(
1112 "Found volume %v in the list of VolumesToMount, but DesiredSizeLimit incorrect. Expected: <%v> Actual: <%v>",
1113 volumeName,
1114 expectedDesiredSize,
1115 v.DesiredSizeLimit)
1116
1117 }
1118 }
1119 }
1120 }
1121 }
1122
View as plain text