1 package storage
2
3 import (
4 "fmt"
5 "testing"
6
7 devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
8 "github.com/devfile/api/v2/pkg/attributes"
9 "github.com/devfile/library/v2/pkg/devfile/generator"
10 devfileParser "github.com/devfile/library/v2/pkg/devfile/parser"
11 "github.com/devfile/library/v2/pkg/devfile/parser/data"
12 parsercommon "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
13 "github.com/golang/mock/gomock"
14 "github.com/google/go-cmp/cmp"
15 "github.com/redhat-developer/odo/pkg/configAutomount"
16 "github.com/redhat-developer/odo/pkg/testingutil"
17 corev1 "k8s.io/api/core/v1"
18 v1 "k8s.io/api/core/v1"
19 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20 "k8s.io/utils/pointer"
21 )
22
23 func TestGetPVC(t *testing.T) {
24
25 tests := []struct {
26 pvc string
27 volumeName string
28 }{
29 {
30 pvc: "mypvc",
31 volumeName: "myvolume",
32 },
33 }
34
35 for _, tt := range tests {
36 t.Run(tt.volumeName, func(t *testing.T) {
37 volume := getPVC(tt.volumeName, tt.pvc)
38
39 if volume.Name != tt.volumeName {
40 t.Errorf("TestGetPVC error: volume name does not match; expected %s got %s", tt.volumeName, volume.Name)
41 }
42
43 if volume.PersistentVolumeClaim.ClaimName != tt.pvc {
44 t.Errorf("TestGetPVC error: pvc name does not match; expected %s got %s", tt.pvc, volume.PersistentVolumeClaim.ClaimName)
45 }
46 })
47 }
48 }
49
50 func TestGetVolumeInfos(t *testing.T) {
51 tests := []struct {
52 name string
53 pvcs []corev1.PersistentVolumeClaim
54 wantOdoSourcePVCName string
55 wantInfos map[string]VolumeInfo
56 wantErr bool
57 }{
58 {
59 name: "odo-projects is not found",
60 pvcs: []corev1.PersistentVolumeClaim{
61 {
62 ObjectMeta: metav1.ObjectMeta{
63 Name: "pvc1",
64 Labels: map[string]string{
65 "app.kubernetes.io/storage-name": "a-name",
66 },
67 },
68 },
69 },
70 wantOdoSourcePVCName: "",
71 wantInfos: map[string]VolumeInfo{
72 "a-name": {
73 PVCName: "pvc1",
74 VolumeName: "pvc1-vol",
75 },
76 },
77 },
78 {
79 name: "odo-projects is found",
80 pvcs: []corev1.PersistentVolumeClaim{
81 {
82 ObjectMeta: metav1.ObjectMeta{
83 Name: "pvc1",
84 Labels: map[string]string{
85 "app.kubernetes.io/storage-name": "odo-projects",
86 },
87 },
88 },
89 },
90 wantOdoSourcePVCName: "pvc1",
91 wantInfos: map[string]VolumeInfo{},
92 },
93 {
94 name: "odo-projects is found and other pvcs",
95 pvcs: []corev1.PersistentVolumeClaim{
96 {
97 ObjectMeta: metav1.ObjectMeta{
98 Name: "pvc1",
99 Labels: map[string]string{
100 "app.kubernetes.io/storage-name": "odo-projects",
101 },
102 },
103 },
104 {
105 ObjectMeta: metav1.ObjectMeta{
106 Name: "pvc2",
107 Labels: map[string]string{
108 "app.kubernetes.io/storage-name": "name2",
109 },
110 },
111 },
112 {
113 ObjectMeta: metav1.ObjectMeta{
114 Name: "pvc3",
115 Labels: map[string]string{
116 "app.kubernetes.io/storage-name": "name3",
117 },
118 },
119 },
120 },
121 wantOdoSourcePVCName: "pvc1",
122 wantInfos: map[string]VolumeInfo{
123 "name2": {
124 PVCName: "pvc2",
125 VolumeName: "pvc2-vol",
126 },
127 "name3": {
128 PVCName: "pvc3",
129 VolumeName: "pvc3-vol",
130 },
131 },
132 },
133 }
134
135 for _, tt := range tests {
136 t.Run(tt.name, func(t *testing.T) {
137 odoSourcePVCName, infos, err := GetVolumeInfos(tt.pvcs)
138 if err != nil != tt.wantErr {
139 t.Errorf("Got error %v, expected %v", err, tt.wantErr)
140 return
141 }
142 if err != nil {
143 return
144 }
145 if diff := cmp.Diff(tt.wantOdoSourcePVCName, odoSourcePVCName); diff != "" {
146 t.Errorf("GetVolumeInfos() wantOdoSourcePVCName mismatch (-want +got):\n%s", diff)
147 }
148 if diff := cmp.Diff(tt.wantInfos, infos); diff != "" {
149 t.Errorf("GetVolumeInfos() wantInfos mismatch (-want +got):\n%s", diff)
150 }
151 })
152 }
153 }
154
155 func TestAddVolumeMountToContainers(t *testing.T) {
156
157 tests := []struct {
158 podName string
159 namespace string
160 serviceAccount string
161 pvc string
162 volumeName string
163 containerMountPathsMap map[string][]string
164 container v1.Container
165 labels map[string]string
166 wantErr bool
167 }{
168 {
169 podName: "podSpecTest",
170 namespace: "default",
171 serviceAccount: "default",
172 pvc: "mypvc",
173 volumeName: "myvolume",
174 containerMountPathsMap: map[string][]string{
175 "container1": {"/tmp/path1", "/tmp/path2"},
176 },
177 container: v1.Container{
178 Name: "container1",
179 Image: "image1",
180 ImagePullPolicy: v1.PullAlways,
181
182 Command: []string{"tail"},
183 Args: []string{"-f", "/dev/null"},
184 Env: []v1.EnvVar{},
185 },
186 labels: map[string]string{
187 "app": "app",
188 "component": "frontend",
189 },
190 wantErr: false,
191 },
192 {
193 podName: "podSpecTest",
194 namespace: "default",
195 serviceAccount: "default",
196 pvc: "mypvc",
197 volumeName: "myvolume",
198 containerMountPathsMap: map[string][]string{
199 "container1": {"/tmp/path1", "/tmp/path2"},
200 },
201 container: v1.Container{},
202 labels: map[string]string{
203 "app": "app",
204 "component": "frontend",
205 },
206 wantErr: true,
207 },
208 }
209
210 for _, tt := range tests {
211 t.Run(tt.podName, func(t *testing.T) {
212 containers := []v1.Container{tt.container}
213 initContainers := []v1.Container{}
214 addVolumeMountToContainers(containers, initContainers, tt.volumeName, tt.containerMountPathsMap)
215
216 mountPathCount := 0
217 for _, container := range containers {
218 if container.Name == tt.container.Name {
219 for _, volumeMount := range container.VolumeMounts {
220 if volumeMount.Name == tt.volumeName {
221 for _, mountPath := range tt.containerMountPathsMap[tt.container.Name] {
222 if volumeMount.MountPath == mountPath {
223 mountPathCount++
224 }
225 }
226 }
227 }
228 }
229 }
230
231 if mountPathCount != len(tt.containerMountPathsMap[tt.container.Name]) {
232 t.Errorf("Volume Mounts for %s have not been properly mounted to the container", tt.volumeName)
233 }
234 })
235 }
236 }
237
238 func TestGetVolumesAndVolumeMounts(t *testing.T) {
239
240 type testVolumeMountInfo struct {
241 mountPath string
242 volumeName string
243 }
244
245 tests := []struct {
246 name string
247 components []devfilev1.Component
248 volumeNameToVolInfo map[string]VolumeInfo
249 wantContainerToVol map[string][]testVolumeMountInfo
250 wantErr bool
251 }{
252 {
253 name: "One volume mounted",
254 components: []devfilev1.Component{testingutil.GetFakeContainerComponent("comp1"), testingutil.GetFakeContainerComponent("comp2")},
255 volumeNameToVolInfo: map[string]VolumeInfo{
256 "myvolume1": {
257 PVCName: "volume1-pvc",
258 VolumeName: "volume1-pvc-vol",
259 },
260 },
261 wantContainerToVol: map[string][]testVolumeMountInfo{
262 "comp1": {
263 {
264 mountPath: "/my/volume/mount/path1",
265 volumeName: "volume1-pvc-vol",
266 },
267 },
268 "comp2": {
269 {
270 mountPath: "/my/volume/mount/path1",
271 volumeName: "volume1-pvc-vol",
272 },
273 },
274 },
275 wantErr: false,
276 },
277 {
278 name: "One volume mounted at diff locations",
279 components: []devfilev1.Component{
280 {
281 Name: "container1",
282 ComponentUnion: devfilev1.ComponentUnion{
283 Container: &devfilev1.ContainerComponent{
284 Container: devfilev1.Container{
285 VolumeMounts: []devfilev1.VolumeMount{
286 {
287 Name: "volume1",
288 Path: "/path1",
289 },
290 {
291 Name: "volume1",
292 Path: "/path2",
293 },
294 },
295 },
296 },
297 },
298 },
299 },
300 volumeNameToVolInfo: map[string]VolumeInfo{
301 "volume1": {
302 PVCName: "volume1-pvc",
303 VolumeName: "volume1-pvc-vol",
304 },
305 },
306 wantContainerToVol: map[string][]testVolumeMountInfo{
307 "container1": {
308 {
309 mountPath: "/path1",
310 volumeName: "volume1-pvc-vol",
311 },
312 {
313 mountPath: "/path2",
314 volumeName: "volume1-pvc-vol",
315 },
316 },
317 },
318 wantErr: false,
319 },
320 {
321 name: "One volume mounted at diff container components",
322 components: []devfilev1.Component{
323 {
324 Name: "container1",
325 ComponentUnion: devfilev1.ComponentUnion{
326 Container: &devfilev1.ContainerComponent{
327 Container: devfilev1.Container{
328 VolumeMounts: []devfilev1.VolumeMount{
329 {
330 Name: "volume1",
331 Path: "/path1",
332 },
333 },
334 },
335 },
336 },
337 },
338 {
339 Name: "container2",
340 ComponentUnion: devfilev1.ComponentUnion{
341 Container: &devfilev1.ContainerComponent{
342 Container: devfilev1.Container{
343 VolumeMounts: []devfilev1.VolumeMount{
344 {
345 Name: "volume1",
346 Path: "/path2",
347 },
348 },
349 },
350 },
351 },
352 },
353 },
354 volumeNameToVolInfo: map[string]VolumeInfo{
355 "volume1": {
356 PVCName: "volume1-pvc",
357 VolumeName: "volume1-pvc-vol",
358 },
359 },
360 wantContainerToVol: map[string][]testVolumeMountInfo{
361 "container1": {
362 {
363 mountPath: "/path1",
364 volumeName: "volume1-pvc-vol",
365 },
366 },
367 "container2": {
368 {
369 mountPath: "/path2",
370 volumeName: "volume1-pvc-vol",
371 },
372 },
373 },
374 wantErr: false,
375 },
376 {
377 name: "Invalid case",
378 components: []devfilev1.Component{
379 {
380 Name: "container1",
381 Attributes: attributes.Attributes{}.FromStringMap(map[string]string{
382 "firstString": "firstStringValue",
383 }),
384 ComponentUnion: devfilev1.ComponentUnion{},
385 },
386 },
387 wantErr: true,
388 },
389 }
390
391 for _, tt := range tests {
392 t.Run(tt.name, func(t *testing.T) {
393
394 devObj := devfileParser.DevfileObj{
395 Data: func() data.DevfileData {
396 devfileData, err := data.NewDevfileData(string(data.APISchemaVersion200))
397 if err != nil {
398 t.Error(err)
399 }
400 err = devfileData.AddComponents(tt.components)
401 if err != nil {
402 t.Error(err)
403 }
404 return devfileData
405 }(),
406 }
407
408 podTemplateSpec, err := generator.GetPodTemplateSpec(devObj, generator.PodTemplateParams{})
409 if !tt.wantErr && err != nil {
410 t.Errorf("TestGetVolumesAndVolumeMounts error - %v", err)
411 return
412 }
413
414 if tt.wantErr && err != nil {
415 return
416 }
417
418 containers := podTemplateSpec.Spec.Containers
419
420 var options parsercommon.DevfileOptions
421 if tt.wantErr {
422 options = parsercommon.DevfileOptions{
423 Filter: map[string]interface{}{
424 "firstString": "firstStringValue",
425 },
426 }
427 }
428
429 initContainers := []v1.Container{}
430 pvcVols, err := GetPersistentVolumesAndVolumeMounts(devObj, containers, initContainers, tt.volumeNameToVolInfo, options)
431 if !tt.wantErr && err != nil {
432 t.Errorf("TestGetVolumesAndVolumeMounts unexpected error: %v", err)
433 return
434 } else if tt.wantErr && err != nil {
435 return
436 } else if tt.wantErr && err == nil {
437 t.Error("TestGetVolumesAndVolumeMounts expected error but got nil")
438 return
439 }
440
441
442 for _, volInfo := range tt.volumeNameToVolInfo {
443 matched := false
444 for _, pvcVol := range pvcVols {
445 if volInfo.VolumeName == pvcVol.Name && pvcVol.PersistentVolumeClaim != nil && volInfo.PVCName == pvcVol.PersistentVolumeClaim.ClaimName {
446 matched = true
447 }
448 }
449
450 if !matched {
451 t.Errorf("TestGetVolumesAndVolumeMounts error - could not find volume details %s in the actual result", volInfo.VolumeName)
452 }
453 }
454
455
456 for _, container := range containers {
457 if volMounts, ok := tt.wantContainerToVol[container.Name]; !ok {
458 t.Errorf("TestGetVolumesAndVolumeMounts error - did not find the expected container %s", container.Name)
459 return
460 } else {
461 for _, expectedVolMount := range volMounts {
462 matched := false
463 for _, actualVolMount := range container.VolumeMounts {
464 if expectedVolMount.volumeName == actualVolMount.Name && expectedVolMount.mountPath == actualVolMount.MountPath {
465 matched = true
466 }
467 }
468
469 if !matched {
470 t.Errorf("TestGetVolumesAndVolumeMounts error - could not find volume mount details for path %s in the actual result for container %s", expectedVolMount.mountPath, container.Name)
471 }
472 }
473 }
474 }
475 })
476 }
477 }
478
479 func TestGetAutomountVolumes(t *testing.T) {
480
481 container1 := corev1.Container{
482 Name: "container1",
483 Image: "image1",
484 }
485 container2 := corev1.Container{
486 Name: "container2",
487 Image: "image2",
488 }
489 initContainer1 := corev1.Container{
490 Name: "initContainer1",
491 Image: "image1",
492 }
493 initContainer2 := corev1.Container{
494 Name: "initContainer2",
495 Image: "image2",
496 }
497
498 type args struct {
499 configAutomountClient func(ctrl *gomock.Controller) configAutomount.Client
500 containers []corev1.Container
501 initContainers []corev1.Container
502 }
503 tests := []struct {
504 name string
505 args args
506 want []corev1.Volume
507 wantVolumeMounts []corev1.VolumeMount
508 wantEnvFroms []corev1.EnvFromSource
509 wantErr bool
510 }{
511 {
512 name: "No automounting volume",
513 args: args{
514 configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
515 client := configAutomount.NewMockClient(ctrl)
516 client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{}, nil)
517 return client
518 },
519 containers: []corev1.Container{container1, container2},
520 initContainers: []corev1.Container{initContainer1, initContainer2},
521 },
522 want: nil,
523 wantVolumeMounts: nil,
524 wantErr: false,
525 },
526 {
527 name: "One PVC",
528 args: args{
529 configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
530 info1 := configAutomount.AutomountInfo{
531 VolumeType: configAutomount.VolumeTypePVC,
532 VolumeName: "pvc1",
533 MountPath: "/path/to/mount1",
534 MountAs: configAutomount.MountAsFile,
535 }
536 client := configAutomount.NewMockClient(ctrl)
537 client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1}, nil)
538 return client
539 },
540 containers: []corev1.Container{container1, container2},
541 initContainers: []corev1.Container{initContainer1, initContainer2},
542 },
543 want: []v1.Volume{
544 {
545 Name: "auto-pvc-pvc1",
546 VolumeSource: v1.VolumeSource{
547 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
548 ClaimName: "pvc1",
549 },
550 },
551 },
552 },
553 wantVolumeMounts: []v1.VolumeMount{
554 {
555 Name: "auto-pvc-pvc1",
556 MountPath: "/path/to/mount1",
557 },
558 },
559 wantErr: false,
560 },
561 {
562 name: "One PVC and one secret",
563 args: args{
564 configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
565 info1 := configAutomount.AutomountInfo{
566 VolumeType: configAutomount.VolumeTypePVC,
567 VolumeName: "pvc1",
568 MountPath: "/path/to/mount1",
569 MountAs: configAutomount.MountAsFile,
570 }
571 info2 := configAutomount.AutomountInfo{
572 VolumeType: configAutomount.VolumeTypeSecret,
573 VolumeName: "secret2",
574 MountPath: "/path/to/mount2",
575 MountAs: configAutomount.MountAsFile,
576 }
577 client := configAutomount.NewMockClient(ctrl)
578 client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
579 return client
580 },
581 containers: []corev1.Container{container1, container2},
582 initContainers: []corev1.Container{initContainer1, initContainer2},
583 },
584 want: []v1.Volume{
585 {
586 Name: "auto-pvc-pvc1",
587 VolumeSource: v1.VolumeSource{
588 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
589 ClaimName: "pvc1",
590 },
591 },
592 },
593 {
594 Name: "auto-secret-secret2",
595 VolumeSource: v1.VolumeSource{
596 Secret: &v1.SecretVolumeSource{
597 SecretName: "secret2",
598 },
599 },
600 },
601 },
602 wantVolumeMounts: []v1.VolumeMount{
603 {
604 Name: "auto-pvc-pvc1",
605 MountPath: "/path/to/mount1",
606 },
607 {
608 Name: "auto-secret-secret2",
609 MountPath: "/path/to/mount2",
610 },
611 },
612 wantErr: false,
613 },
614 {
615 name: "One PVC, one secret and one configmap",
616 args: args{
617 configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
618 info1 := configAutomount.AutomountInfo{
619 VolumeType: configAutomount.VolumeTypePVC,
620 VolumeName: "pvc1",
621 MountPath: "/path/to/mount1",
622 MountAs: configAutomount.MountAsFile,
623 }
624 info2 := configAutomount.AutomountInfo{
625 VolumeType: configAutomount.VolumeTypeSecret,
626 VolumeName: "secret2",
627 MountPath: "/path/to/mount2",
628 MountAs: configAutomount.MountAsFile,
629 }
630 info3 := configAutomount.AutomountInfo{
631 VolumeType: configAutomount.VolumeTypeConfigmap,
632 VolumeName: "cm3",
633 MountPath: "/path/to/mount3",
634 MountAs: configAutomount.MountAsFile,
635 }
636 client := configAutomount.NewMockClient(ctrl)
637 client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2, info3}, nil)
638 return client
639 },
640 containers: []corev1.Container{container1, container2},
641 initContainers: []corev1.Container{initContainer1, initContainer2},
642 },
643 want: []v1.Volume{
644 {
645 Name: "auto-pvc-pvc1",
646 VolumeSource: v1.VolumeSource{
647 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
648 ClaimName: "pvc1",
649 },
650 },
651 },
652 {
653 Name: "auto-secret-secret2",
654 VolumeSource: v1.VolumeSource{
655 Secret: &v1.SecretVolumeSource{
656 SecretName: "secret2",
657 },
658 },
659 },
660 {
661 Name: "auto-cm-cm3",
662 VolumeSource: v1.VolumeSource{
663 ConfigMap: &v1.ConfigMapVolumeSource{
664 LocalObjectReference: v1.LocalObjectReference{
665 Name: "cm3",
666 },
667 },
668 },
669 },
670 },
671 wantVolumeMounts: []v1.VolumeMount{
672 {
673 Name: "auto-pvc-pvc1",
674 MountPath: "/path/to/mount1",
675 },
676 {
677 Name: "auto-secret-secret2",
678 MountPath: "/path/to/mount2",
679 },
680 {
681 Name: "auto-cm-cm3",
682 MountPath: "/path/to/mount3",
683 },
684 },
685 wantErr: false,
686 },
687 {
688 name: "One secret and one configmap mounted as Env",
689 args: args{
690 configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
691 info1 := configAutomount.AutomountInfo{
692 VolumeType: configAutomount.VolumeTypeSecret,
693 VolumeName: "secret1",
694 MountAs: configAutomount.MountAsEnv,
695 }
696 info2 := configAutomount.AutomountInfo{
697 VolumeType: configAutomount.VolumeTypeConfigmap,
698 VolumeName: "cm2",
699 MountAs: configAutomount.MountAsEnv,
700 }
701 client := configAutomount.NewMockClient(ctrl)
702 client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
703 return client
704 },
705 containers: []corev1.Container{container1, container2},
706 initContainers: []corev1.Container{initContainer1, initContainer2},
707 },
708 want: nil,
709 wantVolumeMounts: nil,
710 wantEnvFroms: []corev1.EnvFromSource{
711 {
712 SecretRef: &v1.SecretEnvSource{
713 LocalObjectReference: v1.LocalObjectReference{
714 Name: "secret1",
715 },
716 },
717 },
718 {
719 ConfigMapRef: &v1.ConfigMapEnvSource{
720 LocalObjectReference: v1.LocalObjectReference{
721 Name: "cm2",
722 },
723 },
724 },
725 },
726 wantErr: false,
727 },
728 {
729 name: "One secret and one configmap mounted as Subpath",
730 args: args{
731 configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
732 info1 := configAutomount.AutomountInfo{
733 VolumeType: configAutomount.VolumeTypeSecret,
734 VolumeName: "secret1",
735 MountPath: "/path/to/secret1",
736 MountAs: configAutomount.MountAsSubpath,
737 Keys: []string{"secretKey1", "secretKey2"},
738 }
739 info2 := configAutomount.AutomountInfo{
740 VolumeType: configAutomount.VolumeTypeConfigmap,
741 VolumeName: "cm2",
742 MountPath: "/path/to/cm2",
743 MountAs: configAutomount.MountAsSubpath,
744 Keys: []string{"cmKey1", "cmKey2"},
745 }
746 client := configAutomount.NewMockClient(ctrl)
747 client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
748 return client
749 },
750 containers: []corev1.Container{container1, container2},
751 initContainers: []corev1.Container{initContainer1, initContainer2},
752 },
753 want: []corev1.Volume{
754 {
755 Name: "auto-secret-secret1",
756 VolumeSource: v1.VolumeSource{
757 Secret: &v1.SecretVolumeSource{
758 SecretName: "secret1",
759 },
760 },
761 },
762 {
763 Name: "auto-cm-cm2",
764 VolumeSource: v1.VolumeSource{
765 ConfigMap: &v1.ConfigMapVolumeSource{
766 LocalObjectReference: v1.LocalObjectReference{
767 Name: "cm2",
768 },
769 },
770 },
771 },
772 },
773 wantVolumeMounts: []corev1.VolumeMount{
774 {
775 Name: "auto-secret-secret1",
776 MountPath: "/path/to/secret1/secretKey1",
777 SubPath: "secretKey1",
778 },
779 {
780 Name: "auto-secret-secret1",
781 MountPath: "/path/to/secret1/secretKey2",
782 SubPath: "secretKey2",
783 },
784 {
785 Name: "auto-cm-cm2",
786 MountPath: "/path/to/cm2/cmKey1",
787 SubPath: "cmKey1",
788 },
789 {
790 Name: "auto-cm-cm2",
791 MountPath: "/path/to/cm2/cmKey2",
792 SubPath: "cmKey2",
793 },
794 },
795 wantErr: false,
796 },
797 {
798 name: "One secret and one configmap mounted as file with access mode",
799 args: args{
800 configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
801 info1 := configAutomount.AutomountInfo{
802 VolumeType: configAutomount.VolumeTypeSecret,
803 VolumeName: "secret1",
804 MountPath: "/path/to/secret1",
805 MountAs: configAutomount.MountAsFile,
806 Keys: []string{"secretKey1", "secretKey2"},
807 MountAccessMode: pointer.Int32(0400),
808 }
809 info2 := configAutomount.AutomountInfo{
810 VolumeType: configAutomount.VolumeTypeConfigmap,
811 VolumeName: "cm2",
812 MountPath: "/path/to/cm2",
813 MountAs: configAutomount.MountAsFile,
814 Keys: []string{"cmKey1", "cmKey2"},
815 MountAccessMode: pointer.Int32(0444),
816 }
817 client := configAutomount.NewMockClient(ctrl)
818 client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
819 return client
820 },
821 containers: []corev1.Container{container1, container2},
822 initContainers: []corev1.Container{initContainer1, initContainer2},
823 },
824 want: []corev1.Volume{
825 {
826 Name: "auto-secret-secret1",
827 VolumeSource: v1.VolumeSource{
828 Secret: &v1.SecretVolumeSource{
829 DefaultMode: pointer.Int32(0400),
830 SecretName: "secret1",
831 },
832 },
833 },
834 {
835 Name: "auto-cm-cm2",
836 VolumeSource: v1.VolumeSource{
837 ConfigMap: &v1.ConfigMapVolumeSource{
838 DefaultMode: pointer.Int32(0444),
839 LocalObjectReference: v1.LocalObjectReference{
840 Name: "cm2",
841 },
842 },
843 },
844 },
845 },
846 wantVolumeMounts: []corev1.VolumeMount{
847 {
848 Name: "auto-secret-secret1",
849 MountPath: "/path/to/secret1",
850 },
851 {
852 Name: "auto-cm-cm2",
853 MountPath: "/path/to/cm2",
854 },
855 },
856 wantErr: false,
857 },
858 {
859 name: "One secret and one configmap mounted as Subpath with access mode",
860 args: args{
861 configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
862 info1 := configAutomount.AutomountInfo{
863 VolumeType: configAutomount.VolumeTypeSecret,
864 VolumeName: "secret1",
865 MountPath: "/path/to/secret1",
866 MountAs: configAutomount.MountAsSubpath,
867 Keys: []string{"secretKey1", "secretKey2"},
868 MountAccessMode: pointer.Int32(0400),
869 }
870 info2 := configAutomount.AutomountInfo{
871 VolumeType: configAutomount.VolumeTypeConfigmap,
872 VolumeName: "cm2",
873 MountPath: "/path/to/cm2",
874 MountAs: configAutomount.MountAsSubpath,
875 Keys: []string{"cmKey1", "cmKey2"},
876 MountAccessMode: pointer.Int32(0444),
877 }
878 client := configAutomount.NewMockClient(ctrl)
879 client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
880 return client
881 },
882 containers: []corev1.Container{container1, container2},
883 initContainers: []corev1.Container{initContainer1, initContainer2},
884 },
885 want: []corev1.Volume{
886 {
887 Name: "auto-secret-secret1",
888 VolumeSource: v1.VolumeSource{
889 Secret: &v1.SecretVolumeSource{
890 SecretName: "secret1",
891 DefaultMode: pointer.Int32(0400),
892 },
893 },
894 },
895 {
896 Name: "auto-cm-cm2",
897 VolumeSource: v1.VolumeSource{
898 ConfigMap: &v1.ConfigMapVolumeSource{
899 LocalObjectReference: v1.LocalObjectReference{
900 Name: "cm2",
901 },
902 DefaultMode: pointer.Int32(0444),
903 },
904 },
905 },
906 },
907 wantVolumeMounts: []corev1.VolumeMount{
908 {
909 Name: "auto-secret-secret1",
910 MountPath: "/path/to/secret1/secretKey1",
911 SubPath: "secretKey1",
912 },
913 {
914 Name: "auto-secret-secret1",
915 MountPath: "/path/to/secret1/secretKey2",
916 SubPath: "secretKey2",
917 },
918 {
919 Name: "auto-cm-cm2",
920 MountPath: "/path/to/cm2/cmKey1",
921 SubPath: "cmKey1",
922 },
923 {
924 Name: "auto-cm-cm2",
925 MountPath: "/path/to/cm2/cmKey2",
926 SubPath: "cmKey2",
927 },
928 },
929 wantErr: false,
930 },
931 }
932 for _, tt := range tests {
933 t.Run(tt.name, func(t *testing.T) {
934 ctrl := gomock.NewController(t)
935 got, err := GetAutomountVolumes(tt.args.configAutomountClient(ctrl), tt.args.containers, tt.args.initContainers)
936 if (err != nil) != tt.wantErr {
937 t.Errorf("GetAutomountVolumes() error = %v, wantErr %v", err, tt.wantErr)
938 return
939 }
940 if diff := cmp.Diff(tt.want, got); diff != "" {
941 t.Errorf("GetAutomountVolumes() mismatch (-want +got):\n%s", diff)
942 }
943
944 checkContainers := func(containers, initContainers []corev1.Container) error {
945 allContainers := containers
946 allContainers = append(allContainers, initContainers...)
947 for _, container := range allContainers {
948 if diff := cmp.Diff(tt.wantVolumeMounts, container.VolumeMounts); diff != "" {
949 return fmt.Errorf(diff)
950 }
951 if diff := cmp.Diff(tt.wantEnvFroms, container.EnvFrom); diff != "" {
952 return fmt.Errorf(diff)
953 }
954 }
955 return nil
956 }
957
958 if err := checkContainers(tt.args.containers, tt.args.initContainers); err != nil {
959 t.Errorf("GetAutomountVolumes() containers error: %v", err)
960 }
961 })
962 }
963 }
964
View as plain text