1 package configAutomount
2
3 import (
4 "testing"
5
6 "github.com/golang/mock/gomock"
7 "github.com/google/go-cmp/cmp"
8 "github.com/redhat-developer/odo/pkg/kclient"
9 corev1 "k8s.io/api/core/v1"
10 "k8s.io/utils/pointer"
11 )
12
13 func TestKubernetesClient_GetAutomountingVolumes(t *testing.T) {
14
15 defaultPVC1 := corev1.PersistentVolumeClaim{}
16 defaultPVC1.SetName("defaultPVC1")
17 defaultPVC1.SetLabels(map[string]string{
18 labelMountName: labelMountValue,
19 })
20
21 defaultPVC2 := corev1.PersistentVolumeClaim{}
22 defaultPVC2.SetName("defaultPVC2")
23 defaultPVC2.SetLabels(map[string]string{
24 labelMountName: labelMountValue,
25 })
26
27 pvcMountPath := corev1.PersistentVolumeClaim{}
28 pvcMountPath.SetName("pvcMountPath")
29 pvcMountPath.SetLabels(map[string]string{
30 labelMountName: labelMountValue,
31 })
32 pvcMountPath.SetAnnotations(map[string]string{
33 annotationMountPathName: "/specific/pvc/mount/path",
34 })
35
36 roPVC := corev1.PersistentVolumeClaim{}
37 roPVC.SetName("roPVC")
38 roPVC.SetLabels(map[string]string{
39 labelMountName: labelMountValue,
40 })
41 roPVC.SetAnnotations(map[string]string{
42 annotationReadOnlyName: "true",
43 })
44
45 defaultSecret1 := corev1.Secret{}
46 defaultSecret1.SetName("defaultSecret1")
47 defaultSecret1.SetLabels(map[string]string{
48 labelMountName: labelMountValue,
49 })
50
51 defaultSecret2 := corev1.Secret{}
52 defaultSecret2.SetName("defaultSecret2")
53 defaultSecret2.SetLabels(map[string]string{
54 labelMountName: labelMountValue,
55 })
56
57 secretMountPath := corev1.Secret{}
58 secretMountPath.SetName("secretMountPath")
59 secretMountPath.SetLabels(map[string]string{
60 labelMountName: labelMountValue,
61 })
62 secretMountPath.SetAnnotations(map[string]string{
63 annotationMountPathName: "/specific/secret/mount/path",
64 })
65
66 secretMountAsSubpath := corev1.Secret{}
67 secretMountAsSubpath.Data = map[string][]byte{
68 "secretKey1": []byte(""),
69 "secretKey2": []byte(""),
70 }
71 secretMountAsSubpath.SetName("secretMountAsSubpath")
72 secretMountAsSubpath.SetLabels(map[string]string{
73 labelMountName: labelMountValue,
74 })
75 secretMountAsSubpath.SetAnnotations(map[string]string{
76 annotationMountAsName: "subpath",
77 })
78
79 secretMountAsEnv := corev1.Secret{}
80 secretMountAsEnv.SetName("secretMountAsEnv")
81 secretMountAsEnv.SetLabels(map[string]string{
82 labelMountName: labelMountValue,
83 })
84 secretMountAsEnv.SetAnnotations(map[string]string{
85 annotationMountAsName: "env",
86 })
87
88 roSecret := corev1.Secret{}
89 roSecret.SetName("roSecret")
90 roSecret.SetLabels(map[string]string{
91 labelMountName: labelMountValue,
92 })
93 roSecret.SetAnnotations(map[string]string{
94 annotationReadOnlyName: "true",
95 })
96
97 secretMountAccessMode := corev1.Secret{}
98 secretMountAccessMode.SetName("secretMountAccessMode")
99 secretMountAccessMode.SetLabels(map[string]string{
100 labelMountName: labelMountValue,
101 })
102 secretMountAccessMode.SetAnnotations(map[string]string{
103 annotationMountAccessMode: "0400",
104 })
105
106 secretMountAccessModeInvalid := corev1.Secret{}
107 secretMountAccessModeInvalid.SetName("secretMountAccessModeInvalid")
108 secretMountAccessModeInvalid.SetLabels(map[string]string{
109 labelMountName: labelMountValue,
110 })
111 secretMountAccessModeInvalid.SetAnnotations(map[string]string{
112 annotationMountAccessMode: "01444",
113 })
114
115 defaultCM1 := corev1.ConfigMap{}
116 defaultCM1.SetName("defaultCM1")
117 defaultCM1.SetLabels(map[string]string{
118 labelMountName: labelMountValue,
119 })
120
121 defaultCM2 := corev1.ConfigMap{}
122 defaultCM2.SetName("defaultCM2")
123 defaultCM2.SetLabels(map[string]string{
124 labelMountName: labelMountValue,
125 })
126
127 cmMountPath := corev1.ConfigMap{}
128 cmMountPath.SetName("cmMountPath")
129 cmMountPath.SetLabels(map[string]string{
130 labelMountName: labelMountValue,
131 })
132 cmMountPath.SetAnnotations(map[string]string{
133 annotationMountPathName: "/specific/configmap/mount/path",
134 })
135
136 cmMountAsSubpath := corev1.ConfigMap{}
137 cmMountAsSubpath.Data = map[string]string{
138 "cmKey1": "",
139 "cmKey2": "",
140 }
141 cmMountAsSubpath.SetName("cmMountAsSubpath")
142 cmMountAsSubpath.SetLabels(map[string]string{
143 labelMountName: labelMountValue,
144 })
145 cmMountAsSubpath.SetAnnotations(map[string]string{
146 annotationMountAsName: "subpath",
147 })
148
149 cmMountAsEnv := corev1.ConfigMap{}
150 cmMountAsEnv.SetName("cmMountAsEnv")
151 cmMountAsEnv.SetLabels(map[string]string{
152 labelMountName: labelMountValue,
153 })
154 cmMountAsEnv.SetAnnotations(map[string]string{
155 annotationMountAsName: "env",
156 })
157
158 roCM := corev1.ConfigMap{}
159 roCM.SetName("roCM")
160 roCM.SetLabels(map[string]string{
161 labelMountName: labelMountValue,
162 })
163 roCM.SetAnnotations(map[string]string{
164 annotationReadOnlyName: "true",
165 })
166
167 cmMountAccessMode := corev1.ConfigMap{}
168 cmMountAccessMode.SetName("cmMountAccessMode")
169 cmMountAccessMode.SetLabels(map[string]string{
170 labelMountName: labelMountValue,
171 })
172 cmMountAccessMode.SetAnnotations(map[string]string{
173 annotationMountAccessMode: "0444",
174 })
175
176 cmMountAccessModeInvalid := corev1.ConfigMap{}
177 cmMountAccessModeInvalid.SetName("cmMountAccessModeInvalid")
178 cmMountAccessModeInvalid.SetLabels(map[string]string{
179 labelMountName: labelMountValue,
180 })
181 cmMountAccessModeInvalid.SetAnnotations(map[string]string{
182 annotationMountAccessMode: "01444",
183 })
184
185 type fields struct {
186 kubeClient func(ctrl *gomock.Controller) kclient.ClientInterface
187 }
188 tests := []struct {
189 name string
190 fields fields
191 want []AutomountInfo
192 wantErr bool
193 }{
194 {
195 name: "Single default PVC",
196 fields: fields{
197 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
198 client := kclient.NewMockClientInterface(ctrl)
199 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{defaultPVC1}, nil).AnyTimes()
200 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{}, nil).AnyTimes()
201 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{}, nil).AnyTimes()
202 return client
203 },
204 },
205 want: []AutomountInfo{
206 {
207 VolumeType: VolumeTypePVC,
208 VolumeName: "defaultPVC1",
209 MountPath: "/tmp/defaultPVC1",
210 MountAs: MountAsFile,
211 },
212 },
213 wantErr: false,
214 },
215 {
216 name: "Two default PVCs",
217 fields: fields{
218 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
219 client := kclient.NewMockClientInterface(ctrl)
220 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{defaultPVC1, defaultPVC2}, nil).AnyTimes()
221 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{}, nil).AnyTimes()
222 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{}, nil).AnyTimes()
223 return client
224 },
225 },
226 want: []AutomountInfo{
227 {
228 VolumeType: VolumeTypePVC,
229 VolumeName: "defaultPVC1",
230 MountPath: "/tmp/defaultPVC1",
231 MountAs: MountAsFile,
232 },
233 {
234 VolumeType: VolumeTypePVC,
235 VolumeName: "defaultPVC2",
236 MountPath: "/tmp/defaultPVC2",
237 MountAs: MountAsFile,
238 },
239 },
240 wantErr: false,
241 },
242 {
243 name: "Two default secrets",
244 fields: fields{
245 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
246 client := kclient.NewMockClientInterface(ctrl)
247 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{}, nil).AnyTimes()
248 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{defaultSecret1, defaultSecret2}, nil).AnyTimes()
249 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{}, nil).AnyTimes()
250 return client
251 },
252 },
253 want: []AutomountInfo{
254 {
255 VolumeType: VolumeTypeSecret,
256 VolumeName: "defaultSecret1",
257 MountPath: "/etc/secret/defaultSecret1",
258 MountAs: MountAsFile,
259 },
260 {
261 VolumeType: VolumeTypeSecret,
262 VolumeName: "defaultSecret2",
263 MountPath: "/etc/secret/defaultSecret2",
264 MountAs: MountAsFile,
265 },
266 },
267 wantErr: false,
268 },
269 {
270 name: "Two default configmaps",
271 fields: fields{
272 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
273 client := kclient.NewMockClientInterface(ctrl)
274 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{}, nil).AnyTimes()
275 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{}, nil).AnyTimes()
276 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{defaultCM1, defaultCM2}, nil).AnyTimes()
277 return client
278 },
279 },
280 want: []AutomountInfo{
281 {
282 VolumeType: VolumeTypeConfigmap,
283 VolumeName: "defaultCM1",
284 MountPath: "/etc/config/defaultCM1",
285 MountAs: MountAsFile,
286 },
287 {
288 VolumeType: VolumeTypeConfigmap,
289 VolumeName: "defaultCM2",
290 MountPath: "/etc/config/defaultCM2",
291 MountAs: MountAsFile,
292 },
293 },
294 wantErr: false,
295 },
296 {
297 name: "PVC, Secret and ConfigMap with non default mount paths",
298 fields: fields{
299 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
300 client := kclient.NewMockClientInterface(ctrl)
301 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{pvcMountPath}, nil).AnyTimes()
302 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{secretMountPath}, nil).AnyTimes()
303 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{cmMountPath}, nil).AnyTimes()
304 return client
305 },
306 },
307 want: []AutomountInfo{
308 {
309 VolumeType: VolumeTypePVC,
310 VolumeName: "pvcMountPath",
311 MountPath: "/specific/pvc/mount/path",
312 MountAs: MountAsFile,
313 },
314 {
315 VolumeType: VolumeTypeSecret,
316 VolumeName: "secretMountPath",
317 MountPath: "/specific/secret/mount/path",
318 MountAs: MountAsFile,
319 },
320 {
321 VolumeType: VolumeTypeConfigmap,
322 VolumeName: "cmMountPath",
323 MountPath: "/specific/configmap/mount/path",
324 MountAs: MountAsFile,
325 },
326 },
327 wantErr: false,
328 },
329 {
330 name: "Secret and ConfigMap with mount-as annotations",
331 fields: fields{
332 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
333 client := kclient.NewMockClientInterface(ctrl)
334 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{}, nil).AnyTimes()
335 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{secretMountAsSubpath, secretMountAsEnv}, nil).AnyTimes()
336 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{cmMountAsSubpath, cmMountAsEnv}, nil).AnyTimes()
337 return client
338 },
339 },
340 want: []AutomountInfo{
341 {
342 VolumeType: VolumeTypeSecret,
343 VolumeName: "secretMountAsSubpath",
344 MountPath: "/etc/secret/secretMountAsSubpath",
345 MountAs: MountAsSubpath,
346 Keys: []string{"secretKey1", "secretKey2"},
347 },
348 {
349 VolumeType: VolumeTypeSecret,
350 VolumeName: "secretMountAsEnv",
351 MountPath: "",
352 MountAs: MountAsEnv,
353 },
354 {
355 VolumeType: VolumeTypeConfigmap,
356 VolumeName: "cmMountAsSubpath",
357 MountPath: "/etc/config/cmMountAsSubpath",
358 MountAs: MountAsSubpath,
359 Keys: []string{"cmKey1", "cmKey2"},
360 },
361 {
362 VolumeType: VolumeTypeConfigmap,
363 VolumeName: "cmMountAsEnv",
364 MountPath: "",
365 MountAs: MountAsEnv,
366 },
367 },
368 wantErr: false,
369 },
370 {
371 name: "Secret and ConfigMap with mount-access-mode annotations",
372 fields: fields{
373 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
374 client := kclient.NewMockClientInterface(ctrl)
375 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{}, nil).AnyTimes()
376 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{secretMountAccessMode}, nil).AnyTimes()
377 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{cmMountAccessMode}, nil).AnyTimes()
378 return client
379 },
380 },
381 want: []AutomountInfo{
382 {
383 VolumeType: VolumeTypeSecret,
384 VolumeName: "secretMountAccessMode",
385 MountPath: "/etc/secret/secretMountAccessMode",
386 MountAs: MountAsFile,
387 MountAccessMode: pointer.Int32(0400),
388 },
389 {
390 VolumeType: VolumeTypeConfigmap,
391 VolumeName: "cmMountAccessMode",
392 MountPath: "/etc/config/cmMountAccessMode",
393 MountAs: MountAsFile,
394 MountAccessMode: pointer.Int32(0444),
395 },
396 },
397 wantErr: false,
398 },
399 {
400 name: "Secret with invalid mount-access-mode annotation",
401 fields: fields{
402 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
403 client := kclient.NewMockClientInterface(ctrl)
404 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{}, nil).AnyTimes()
405 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{secretMountAccessModeInvalid}, nil).AnyTimes()
406 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{}, nil).AnyTimes()
407 return client
408 },
409 },
410 want: nil,
411 wantErr: true,
412 },
413 {
414 name: "Configmap with invalid mount-access-mode annotation",
415 fields: fields{
416 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
417 client := kclient.NewMockClientInterface(ctrl)
418 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{}, nil).AnyTimes()
419 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{}, nil).AnyTimes()
420 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{cmMountAccessModeInvalid}, nil).AnyTimes()
421 return client
422 },
423 },
424 want: nil,
425 wantErr: true,
426 },
427 {
428 name: "PVC, Secret and ConfigMap read-only",
429 fields: fields{
430 kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
431 client := kclient.NewMockClientInterface(ctrl)
432 client.EXPECT().ListPVCs(gomock.Any()).Return([]corev1.PersistentVolumeClaim{roPVC}, nil).AnyTimes()
433 client.EXPECT().ListSecrets(gomock.Any()).Return([]corev1.Secret{roSecret}, nil).AnyTimes()
434 client.EXPECT().ListConfigMaps(gomock.Any()).Return([]corev1.ConfigMap{roCM}, nil).AnyTimes()
435 return client
436 },
437 },
438 want: []AutomountInfo{
439 {
440 VolumeType: VolumeTypePVC,
441 VolumeName: "roPVC",
442 MountPath: "/tmp/roPVC",
443 MountAs: MountAsFile,
444 ReadOnly: true,
445 },
446 {
447 VolumeType: VolumeTypeSecret,
448 VolumeName: "roSecret",
449 MountPath: "/etc/secret/roSecret",
450 MountAs: MountAsFile,
451 ReadOnly: true,
452 },
453 {
454 VolumeType: VolumeTypeConfigmap,
455 VolumeName: "roCM",
456 MountPath: "/etc/config/roCM",
457 MountAs: MountAsFile,
458 ReadOnly: true,
459 },
460 },
461 wantErr: false,
462 }}
463 for _, tt := range tests {
464 t.Run(tt.name, func(t *testing.T) {
465 ctrl := gomock.NewController(t)
466 o := KubernetesClient{
467 kubeClient: tt.fields.kubeClient(ctrl),
468 }
469 got, err := o.GetAutomountingVolumes()
470 if (err != nil) != tt.wantErr {
471 t.Errorf("KubernetesClient.GetAutomountingVolumes() error = %v, wantErr %v", err, tt.wantErr)
472 return
473 }
474
475 if diff := cmp.Diff(tt.want, got); diff != "" {
476 t.Errorf("KubernetesClient.GetAutomountingVolumes() mismatch (-want +got):\n%s", diff)
477 }
478 })
479 }
480 }
481
View as plain text