1
16
17 package storage
18
19 import (
20 "context"
21 "fmt"
22 "path"
23
24 v1 "k8s.io/api/core/v1"
25 apierrors "k8s.io/apimachinery/pkg/api/errors"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/util/uuid"
28 "k8s.io/kubernetes/test/e2e/framework"
29 e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
30 e2epodoutput "k8s.io/kubernetes/test/e2e/framework/pod/output"
31 imageutils "k8s.io/kubernetes/test/utils/image"
32 admissionapi "k8s.io/pod-security-admission/api"
33
34 "github.com/onsi/ginkgo/v2"
35 "github.com/onsi/gomega"
36 )
37
38 var _ = SIGDescribe("Secrets", func() {
39 f := framework.NewDefaultFramework("secrets")
40 f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
41
42
47 framework.ConformanceIt("should be consumable from pods in volume", f.WithNodeConformance(), func(ctx context.Context) {
48 doSecretE2EWithoutMapping(ctx, f, nil , "secret-test-"+string(uuid.NewUUID()), nil, nil)
49 })
50
51
57 framework.ConformanceIt("should be consumable from pods in volume with defaultMode set [LinuxOnly]", f.WithNodeConformance(), func(ctx context.Context) {
58 defaultMode := int32(0400)
59 doSecretE2EWithoutMapping(ctx, f, &defaultMode, "secret-test-"+string(uuid.NewUUID()), nil, nil)
60 })
61
62
68 framework.ConformanceIt("should be consumable from pods in volume as non-root with defaultMode and fsGroup set [LinuxOnly]", f.WithNodeConformance(), func(ctx context.Context) {
69 defaultMode := int32(0440)
70 fsGroup := int64(1001)
71 doSecretE2EWithoutMapping(ctx, f, &defaultMode, "secret-test-"+string(uuid.NewUUID()), &fsGroup, &nonRootTestUserID)
72 })
73
74
79 framework.ConformanceIt("should be consumable from pods in volume with mappings", f.WithNodeConformance(), func(ctx context.Context) {
80 doSecretE2EWithMapping(ctx, f, nil)
81 })
82
83
89 framework.ConformanceIt("should be consumable from pods in volume with mappings and Item Mode set [LinuxOnly]", f.WithNodeConformance(), func(ctx context.Context) {
90 mode := int32(0400)
91 doSecretE2EWithMapping(ctx, f, &mode)
92 })
93
94
99 framework.ConformanceIt("should be able to mount in a volume regardless of a different secret existing with same name in different namespace", f.WithNodeConformance(), func(ctx context.Context) {
100 var (
101 namespace2 *v1.Namespace
102 err error
103 secret2Name = "secret-test-" + string(uuid.NewUUID())
104 )
105
106 if namespace2, err = f.CreateNamespace(ctx, "secret-namespace", nil); err != nil {
107 framework.Failf("unable to create new namespace %s: %v", namespace2.Name, err)
108 }
109
110 secret2 := secretForTest(namespace2.Name, secret2Name)
111 secret2.Data = map[string][]byte{
112 "this_should_not_match_content_of_other_secret": []byte("similarly_this_should_not_match_content_of_other_secret\n"),
113 }
114 if secret2, err = f.ClientSet.CoreV1().Secrets(namespace2.Name).Create(ctx, secret2, metav1.CreateOptions{}); err != nil {
115 framework.Failf("unable to create test secret %s: %v", secret2.Name, err)
116 }
117 doSecretE2EWithoutMapping(ctx, f, nil , secret2.Name, nil, nil)
118 })
119
120
125 framework.ConformanceIt("should be consumable in multiple volumes in a pod", f.WithNodeConformance(), func(ctx context.Context) {
126
127
128
129 var (
130 name = "secret-test-" + string(uuid.NewUUID())
131 volumeName = "secret-volume"
132 volumeMountPath = "/etc/secret-volume"
133 volumeName2 = "secret-volume-2"
134 volumeMountPath2 = "/etc/secret-volume-2"
135 secret = secretForTest(f.Namespace.Name, name)
136 )
137
138 ginkgo.By(fmt.Sprintf("Creating secret with name %s", secret.Name))
139 var err error
140 if secret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(ctx, secret, metav1.CreateOptions{}); err != nil {
141 framework.Failf("unable to create test secret %s: %v", secret.Name, err)
142 }
143
144 pod := &v1.Pod{
145 ObjectMeta: metav1.ObjectMeta{
146 Name: "pod-secrets-" + string(uuid.NewUUID()),
147 },
148 Spec: v1.PodSpec{
149 Volumes: []v1.Volume{
150 {
151 Name: volumeName,
152 VolumeSource: v1.VolumeSource{
153 Secret: &v1.SecretVolumeSource{
154 SecretName: name,
155 },
156 },
157 },
158 {
159 Name: volumeName2,
160 VolumeSource: v1.VolumeSource{
161 Secret: &v1.SecretVolumeSource{
162 SecretName: name,
163 },
164 },
165 },
166 },
167 Containers: []v1.Container{
168 {
169 Name: "secret-volume-test",
170 Image: imageutils.GetE2EImage(imageutils.Agnhost),
171 Args: []string{
172 "mounttest",
173 "--file_content=/etc/secret-volume/data-1",
174 "--file_mode=/etc/secret-volume/data-1"},
175 VolumeMounts: []v1.VolumeMount{
176 {
177 Name: volumeName,
178 MountPath: volumeMountPath,
179 ReadOnly: true,
180 },
181 {
182 Name: volumeName2,
183 MountPath: volumeMountPath2,
184 ReadOnly: true,
185 },
186 },
187 },
188 },
189 RestartPolicy: v1.RestartPolicyNever,
190 },
191 }
192
193 fileModeRegexp := getFileModeRegex("/etc/secret-volume/data-1", nil)
194 e2epodoutput.TestContainerOutputRegexp(ctx, f, "consume secrets", pod, 0, []string{
195 "content of file \"/etc/secret-volume/data-1\": value-1",
196 fileModeRegexp,
197 })
198 })
199
200
205 framework.ConformanceIt("optional updates should be reflected in volume", f.WithNodeConformance(), func(ctx context.Context) {
206 podLogTimeout := e2epod.GetPodSecretUpdateTimeout(ctx, f.ClientSet)
207 containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds()))
208 trueVal := true
209 volumeMountPath := "/etc/secret-volumes"
210
211 deleteName := "s-test-opt-del-" + string(uuid.NewUUID())
212 deleteContainerName := "dels-volume-test"
213 deleteVolumeName := "deletes-volume"
214 deleteSecret := &v1.Secret{
215 ObjectMeta: metav1.ObjectMeta{
216 Namespace: f.Namespace.Name,
217 Name: deleteName,
218 },
219 Data: map[string][]byte{
220 "data-1": []byte("value-1"),
221 },
222 }
223
224 updateName := "s-test-opt-upd-" + string(uuid.NewUUID())
225 updateContainerName := "upds-volume-test"
226 updateVolumeName := "updates-volume"
227 updateSecret := &v1.Secret{
228 ObjectMeta: metav1.ObjectMeta{
229 Namespace: f.Namespace.Name,
230 Name: updateName,
231 },
232 Data: map[string][]byte{
233 "data-1": []byte("value-1"),
234 },
235 }
236
237 createName := "s-test-opt-create-" + string(uuid.NewUUID())
238 createContainerName := "creates-volume-test"
239 createVolumeName := "creates-volume"
240 createSecret := &v1.Secret{
241 ObjectMeta: metav1.ObjectMeta{
242 Namespace: f.Namespace.Name,
243 Name: createName,
244 },
245 Data: map[string][]byte{
246 "data-1": []byte("value-1"),
247 },
248 }
249
250 ginkgo.By(fmt.Sprintf("Creating secret with name %s", deleteSecret.Name))
251 var err error
252 if deleteSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(ctx, deleteSecret, metav1.CreateOptions{}); err != nil {
253 framework.Failf("unable to create test secret %s: %v", deleteSecret.Name, err)
254 }
255
256 ginkgo.By(fmt.Sprintf("Creating secret with name %s", updateSecret.Name))
257 if updateSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(ctx, updateSecret, metav1.CreateOptions{}); err != nil {
258 framework.Failf("unable to create test secret %s: %v", updateSecret.Name, err)
259 }
260
261 pod := &v1.Pod{
262 ObjectMeta: metav1.ObjectMeta{
263 Name: "pod-secrets-" + string(uuid.NewUUID()),
264 },
265 Spec: v1.PodSpec{
266 Volumes: []v1.Volume{
267 {
268 Name: deleteVolumeName,
269 VolumeSource: v1.VolumeSource{
270 Secret: &v1.SecretVolumeSource{
271 SecretName: deleteName,
272 Optional: &trueVal,
273 },
274 },
275 },
276 {
277 Name: updateVolumeName,
278 VolumeSource: v1.VolumeSource{
279 Secret: &v1.SecretVolumeSource{
280 SecretName: updateName,
281 Optional: &trueVal,
282 },
283 },
284 },
285 {
286 Name: createVolumeName,
287 VolumeSource: v1.VolumeSource{
288 Secret: &v1.SecretVolumeSource{
289 SecretName: createName,
290 Optional: &trueVal,
291 },
292 },
293 },
294 },
295 Containers: []v1.Container{
296 {
297 Name: deleteContainerName,
298 Image: imageutils.GetE2EImage(imageutils.Agnhost),
299 Args: []string{"mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/delete/data-1"},
300 VolumeMounts: []v1.VolumeMount{
301 {
302 Name: deleteVolumeName,
303 MountPath: path.Join(volumeMountPath, "delete"),
304 ReadOnly: true,
305 },
306 },
307 },
308 {
309 Name: updateContainerName,
310 Image: imageutils.GetE2EImage(imageutils.Agnhost),
311 Args: []string{"mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/update/data-3"},
312 VolumeMounts: []v1.VolumeMount{
313 {
314 Name: updateVolumeName,
315 MountPath: path.Join(volumeMountPath, "update"),
316 ReadOnly: true,
317 },
318 },
319 },
320 {
321 Name: createContainerName,
322 Image: imageutils.GetE2EImage(imageutils.Agnhost),
323 Args: []string{"mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/create/data-1"},
324 VolumeMounts: []v1.VolumeMount{
325 {
326 Name: createVolumeName,
327 MountPath: path.Join(volumeMountPath, "create"),
328 ReadOnly: true,
329 },
330 },
331 },
332 },
333 RestartPolicy: v1.RestartPolicyNever,
334 },
335 }
336 ginkgo.By("Creating the pod")
337 e2epod.NewPodClient(f).CreateSync(ctx, pod)
338
339 pollCreateLogs := func() (string, error) {
340 return e2epod.GetPodLogs(ctx, f.ClientSet, f.Namespace.Name, pod.Name, createContainerName)
341 }
342 gomega.Eventually(ctx, pollCreateLogs, podLogTimeout, framework.Poll).Should(gomega.ContainSubstring("Error reading file /etc/secret-volumes/create/data-1"))
343
344 pollUpdateLogs := func() (string, error) {
345 return e2epod.GetPodLogs(ctx, f.ClientSet, f.Namespace.Name, pod.Name, updateContainerName)
346 }
347 gomega.Eventually(ctx, pollUpdateLogs, podLogTimeout, framework.Poll).Should(gomega.ContainSubstring("Error reading file /etc/secret-volumes/update/data-3"))
348
349 pollDeleteLogs := func() (string, error) {
350 return e2epod.GetPodLogs(ctx, f.ClientSet, f.Namespace.Name, pod.Name, deleteContainerName)
351 }
352 gomega.Eventually(ctx, pollDeleteLogs, podLogTimeout, framework.Poll).Should(gomega.ContainSubstring("value-1"))
353
354 ginkgo.By(fmt.Sprintf("Deleting secret %v", deleteSecret.Name))
355 err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Delete(ctx, deleteSecret.Name, metav1.DeleteOptions{})
356 framework.ExpectNoError(err, "Failed to delete secret %q in namespace %q", deleteSecret.Name, f.Namespace.Name)
357
358 ginkgo.By(fmt.Sprintf("Updating secret %v", updateSecret.Name))
359 updateSecret.ResourceVersion = ""
360 delete(updateSecret.Data, "data-1")
361 updateSecret.Data["data-3"] = []byte("value-3")
362 _, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Update(ctx, updateSecret, metav1.UpdateOptions{})
363 framework.ExpectNoError(err, "Failed to update secret %q in namespace %q", updateSecret.Name, f.Namespace.Name)
364
365 ginkgo.By(fmt.Sprintf("Creating secret with name %s", createSecret.Name))
366 if createSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(ctx, createSecret, metav1.CreateOptions{}); err != nil {
367 framework.Failf("unable to create test secret %s: %v", createSecret.Name, err)
368 }
369
370 ginkgo.By("waiting to observe update in volume")
371
372 gomega.Eventually(ctx, pollCreateLogs, podLogTimeout, framework.Poll).Should(gomega.ContainSubstring("value-1"))
373 gomega.Eventually(ctx, pollUpdateLogs, podLogTimeout, framework.Poll).Should(gomega.ContainSubstring("value-3"))
374 gomega.Eventually(ctx, pollDeleteLogs, podLogTimeout, framework.Poll).Should(gomega.ContainSubstring("Error reading file /etc/secret-volumes/delete/data-1"))
375 })
376
377
386 framework.ConformanceIt("should be immutable if `immutable` field is set", func(ctx context.Context) {
387 name := "immutable"
388 secret := secretForTest(f.Namespace.Name, name)
389
390 currentSecret, err := f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(ctx, secret, metav1.CreateOptions{})
391 framework.ExpectNoError(err, "Failed to create secret %q in namespace %q", secret.Name, secret.Namespace)
392
393 currentSecret.Data["data-4"] = []byte("value-4\n")
394 currentSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Update(ctx, currentSecret, metav1.UpdateOptions{})
395 framework.ExpectNoError(err, "Failed to update secret %q in namespace %q", secret.Name, secret.Namespace)
396
397
398 trueVal := true
399 currentSecret.Immutable = &trueVal
400 currentSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Update(ctx, currentSecret, metav1.UpdateOptions{})
401 framework.ExpectNoError(err, "Failed to mark secret %q in namespace %q as immutable", secret.Name, secret.Namespace)
402
403
404 currentSecret.Data["data-5"] = []byte("value-5\n")
405 _, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Update(ctx, currentSecret, metav1.UpdateOptions{})
406 if !apierrors.IsInvalid(err) {
407 framework.Failf("expected 'invalid' as error, got instead: %v", err)
408 }
409
410
411 currentSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Get(ctx, name, metav1.GetOptions{})
412 framework.ExpectNoError(err, "Failed to get secret %q in namespace %q", secret.Name, secret.Namespace)
413 if !*currentSecret.Immutable {
414 framework.Failf("currentSecret %s can be switched from immutable to mutable", currentSecret.Name)
415 }
416
417 falseVal := false
418 currentSecret.Immutable = &falseVal
419 _, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Update(ctx, currentSecret, metav1.UpdateOptions{})
420 if !apierrors.IsInvalid(err) {
421 framework.Failf("expected 'invalid' as error, got instead: %v", err)
422 }
423
424
425 currentSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Get(ctx, name, metav1.GetOptions{})
426 framework.ExpectNoError(err, "Failed to get secret %q in namespace %q", secret.Name, secret.Namespace)
427 currentSecret.Labels = map[string]string{"label1": "value1"}
428 _, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Update(ctx, currentSecret, metav1.UpdateOptions{})
429 framework.ExpectNoError(err, "Failed to update secret %q in namespace %q", secret.Name, secret.Namespace)
430
431
432 err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Delete(ctx, name, metav1.DeleteOptions{})
433 framework.ExpectNoError(err, "Failed to delete secret %q in namespace %q", secret.Name, secret.Namespace)
434 })
435
436
437
438
439 f.It("Should fail non-optional pod creation due to secret object does not exist", f.WithSlow(), func(ctx context.Context) {
440 volumeMountPath := "/etc/secret-volumes"
441 podName := "pod-secrets-" + string(uuid.NewUUID())
442 pod := createNonOptionalSecretPod(ctx, f, volumeMountPath, podName)
443 getPod := e2epod.Get(f.ClientSet, pod)
444 gomega.Consistently(ctx, getPod).WithTimeout(f.Timeouts.PodStart).Should(e2epod.BeInPhase(v1.PodPending))
445 })
446
447
448
449
450 f.It("Should fail non-optional pod creation due to the key in the secret object does not exist", f.WithSlow(), func(ctx context.Context) {
451 volumeMountPath := "/etc/secret-volumes"
452 podName := "pod-secrets-" + string(uuid.NewUUID())
453 pod := createNonOptionalSecretPodWithSecret(ctx, f, volumeMountPath, podName)
454 getPod := e2epod.Get(f.ClientSet, pod)
455 gomega.Consistently(ctx, getPod).WithTimeout(f.Timeouts.PodStart).Should(e2epod.BeInPhase(v1.PodPending))
456 })
457 })
458
459 func secretForTest(namespace, name string) *v1.Secret {
460 return &v1.Secret{
461 ObjectMeta: metav1.ObjectMeta{
462 Namespace: namespace,
463 Name: name,
464 },
465 Data: map[string][]byte{
466 "data-1": []byte("value-1\n"),
467 "data-2": []byte("value-2\n"),
468 "data-3": []byte("value-3\n"),
469 },
470 }
471 }
472
473 func doSecretE2EWithoutMapping(ctx context.Context, f *framework.Framework, defaultMode *int32, secretName string,
474 fsGroup *int64, uid *int64) {
475 var (
476 volumeName = "secret-volume"
477 volumeMountPath = "/etc/secret-volume"
478 secret = secretForTest(f.Namespace.Name, secretName)
479 )
480
481 ginkgo.By(fmt.Sprintf("Creating secret with name %s", secret.Name))
482 var err error
483 if secret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(ctx, secret, metav1.CreateOptions{}); err != nil {
484 framework.Failf("unable to create test secret %s: %v", secret.Name, err)
485 }
486
487 pod := &v1.Pod{
488 ObjectMeta: metav1.ObjectMeta{
489 Name: "pod-secrets-" + string(uuid.NewUUID()),
490 Namespace: f.Namespace.Name,
491 },
492 Spec: v1.PodSpec{
493 Volumes: []v1.Volume{
494 {
495 Name: volumeName,
496 VolumeSource: v1.VolumeSource{
497 Secret: &v1.SecretVolumeSource{
498 SecretName: secretName,
499 },
500 },
501 },
502 },
503 Containers: []v1.Container{
504 {
505 Name: "secret-volume-test",
506 Image: imageutils.GetE2EImage(imageutils.Agnhost),
507 Args: []string{
508 "mounttest",
509 "--file_content=/etc/secret-volume/data-1",
510 "--file_mode=/etc/secret-volume/data-1"},
511 VolumeMounts: []v1.VolumeMount{
512 {
513 Name: volumeName,
514 MountPath: volumeMountPath,
515 },
516 },
517 },
518 },
519 RestartPolicy: v1.RestartPolicyNever,
520 },
521 }
522
523 if defaultMode != nil {
524 pod.Spec.Volumes[0].VolumeSource.Secret.DefaultMode = defaultMode
525 }
526
527 if fsGroup != nil || uid != nil {
528 pod.Spec.SecurityContext = &v1.PodSecurityContext{
529 FSGroup: fsGroup,
530 RunAsUser: uid,
531 }
532 }
533
534 fileModeRegexp := getFileModeRegex("/etc/secret-volume/data-1", defaultMode)
535 expectedOutput := []string{
536 "content of file \"/etc/secret-volume/data-1\": value-1",
537 fileModeRegexp,
538 }
539
540 e2epodoutput.TestContainerOutputRegexp(ctx, f, "consume secrets", pod, 0, expectedOutput)
541 }
542
543 func doSecretE2EWithMapping(ctx context.Context, f *framework.Framework, mode *int32) {
544 var (
545 name = "secret-test-map-" + string(uuid.NewUUID())
546 volumeName = "secret-volume"
547 volumeMountPath = "/etc/secret-volume"
548 secret = secretForTest(f.Namespace.Name, name)
549 )
550
551 ginkgo.By(fmt.Sprintf("Creating secret with name %s", secret.Name))
552 var err error
553 if secret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(ctx, secret, metav1.CreateOptions{}); err != nil {
554 framework.Failf("unable to create test secret %s: %v", secret.Name, err)
555 }
556
557 pod := &v1.Pod{
558 ObjectMeta: metav1.ObjectMeta{
559 Name: "pod-secrets-" + string(uuid.NewUUID()),
560 },
561 Spec: v1.PodSpec{
562 Volumes: []v1.Volume{
563 {
564 Name: volumeName,
565 VolumeSource: v1.VolumeSource{
566 Secret: &v1.SecretVolumeSource{
567 SecretName: name,
568 Items: []v1.KeyToPath{
569 {
570 Key: "data-1",
571 Path: "new-path-data-1",
572 },
573 },
574 },
575 },
576 },
577 },
578 Containers: []v1.Container{
579 {
580 Name: "secret-volume-test",
581 Image: imageutils.GetE2EImage(imageutils.Agnhost),
582 Args: []string{
583 "mounttest",
584 "--file_content=/etc/secret-volume/new-path-data-1",
585 "--file_mode=/etc/secret-volume/new-path-data-1"},
586 VolumeMounts: []v1.VolumeMount{
587 {
588 Name: volumeName,
589 MountPath: volumeMountPath,
590 },
591 },
592 },
593 },
594 RestartPolicy: v1.RestartPolicyNever,
595 },
596 }
597
598 if mode != nil {
599 pod.Spec.Volumes[0].VolumeSource.Secret.Items[0].Mode = mode
600 }
601
602 fileModeRegexp := getFileModeRegex("/etc/secret-volume/new-path-data-1", mode)
603 expectedOutput := []string{
604 "content of file \"/etc/secret-volume/new-path-data-1\": value-1",
605 fileModeRegexp,
606 }
607
608 e2epodoutput.TestContainerOutputRegexp(ctx, f, "consume secrets", pod, 0, expectedOutput)
609 }
610
611 func createNonOptionalSecretPod(ctx context.Context, f *framework.Framework, volumeMountPath, podName string) *v1.Pod {
612 podLogTimeout := e2epod.GetPodSecretUpdateTimeout(ctx, f.ClientSet)
613 containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds()))
614 falseValue := false
615
616 createName := "s-test-opt-create-" + string(uuid.NewUUID())
617 createContainerName := "creates-volume-test"
618 createVolumeName := "creates-volume"
619
620
621 pod := &v1.Pod{
622 ObjectMeta: metav1.ObjectMeta{
623 Name: podName,
624 },
625 Spec: v1.PodSpec{
626 Volumes: []v1.Volume{
627 {
628 Name: createVolumeName,
629 VolumeSource: v1.VolumeSource{
630 Secret: &v1.SecretVolumeSource{
631 SecretName: createName,
632 Optional: &falseValue,
633 },
634 },
635 },
636 },
637 Containers: []v1.Container{
638 {
639 Name: createContainerName,
640 Image: imageutils.GetE2EImage(imageutils.Agnhost),
641 Args: []string{"mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/create/data-1"},
642 VolumeMounts: []v1.VolumeMount{
643 {
644 Name: createVolumeName,
645 MountPath: path.Join(volumeMountPath, "create"),
646 ReadOnly: true,
647 },
648 },
649 },
650 },
651 RestartPolicy: v1.RestartPolicyNever,
652 },
653 }
654 ginkgo.By("Creating the pod")
655 pod = e2epod.NewPodClient(f).Create(ctx, pod)
656 return pod
657 }
658
659 func createNonOptionalSecretPodWithSecret(ctx context.Context, f *framework.Framework, volumeMountPath, podName string) *v1.Pod {
660 podLogTimeout := e2epod.GetPodSecretUpdateTimeout(ctx, f.ClientSet)
661 containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds()))
662 falseValue := false
663
664 createName := "s-test-opt-create-" + string(uuid.NewUUID())
665 createContainerName := "creates-volume-test"
666 createVolumeName := "creates-volume"
667
668 secret := secretForTest(f.Namespace.Name, createName)
669
670 ginkgo.By(fmt.Sprintf("Creating secret with name %s", secret.Name))
671 var err error
672 if secret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(ctx, secret, metav1.CreateOptions{}); err != nil {
673 framework.Failf("unable to create test secret %s: %v", secret.Name, err)
674 }
675
676 pod := &v1.Pod{
677 ObjectMeta: metav1.ObjectMeta{
678 Name: podName,
679 },
680 Spec: v1.PodSpec{
681 Volumes: []v1.Volume{
682 {
683 Name: createVolumeName,
684 VolumeSource: v1.VolumeSource{
685 Secret: &v1.SecretVolumeSource{
686 SecretName: createName,
687 Items: []v1.KeyToPath{
688 {
689 Key: "data_4",
690 Path: "value-4\n",
691 },
692 },
693 Optional: &falseValue,
694 },
695 },
696 },
697 },
698 Containers: []v1.Container{
699 {
700 Name: createContainerName,
701 Image: imageutils.GetE2EImage(imageutils.Agnhost),
702 Args: []string{"mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/create/data-1"},
703 VolumeMounts: []v1.VolumeMount{
704 {
705 Name: createVolumeName,
706 MountPath: path.Join(volumeMountPath, "create"),
707 ReadOnly: true,
708 },
709 },
710 },
711 },
712 RestartPolicy: v1.RestartPolicyNever,
713 },
714 }
715 ginkgo.By("Creating the pod")
716 pod = e2epod.NewPodClient(f).Create(ctx, pod)
717 return pod
718 }
719
View as plain text