secrets_volume.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package common
  14. import (
  15. "fmt"
  16. "path"
  17. "k8s.io/api/core/v1"
  18. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  19. "k8s.io/apimachinery/pkg/util/uuid"
  20. "k8s.io/kubernetes/test/e2e/framework"
  21. imageutils "k8s.io/kubernetes/test/utils/image"
  22. . "github.com/onsi/ginkgo"
  23. . "github.com/onsi/gomega"
  24. )
  25. var _ = Describe("[sig-storage] Secrets", func() {
  26. f := framework.NewDefaultFramework("secrets")
  27. /*
  28. Release : v1.9
  29. Testname: Secrets Volume, default
  30. Description: Create a secret. Create a Pod with secret volume source configured into the container. Pod MUST be able to read the secret from the mounted volume from the container runtime and the file mode of the secret MUST be -rw-r--r-- by default.
  31. */
  32. framework.ConformanceIt("should be consumable from pods in volume [NodeConformance]", func() {
  33. doSecretE2EWithoutMapping(f, nil /* default mode */, "secret-test-"+string(uuid.NewUUID()), nil, nil)
  34. })
  35. /*
  36. Release : v1.9
  37. Testname: Secrets Volume, volume mode 0400
  38. Description: Create a secret. Create a Pod with secret volume source configured into the container with file mode set to 0x400. Pod MUST be able to read the secret from the mounted volume from the container runtime and the file mode of the secret MUST be -r——--—-—- by default.
  39. This test is marked LinuxOnly since Windows does not support setting specific file permissions.
  40. */
  41. framework.ConformanceIt("should be consumable from pods in volume with defaultMode set [LinuxOnly] [NodeConformance]", func() {
  42. defaultMode := int32(0400)
  43. doSecretE2EWithoutMapping(f, &defaultMode, "secret-test-"+string(uuid.NewUUID()), nil, nil)
  44. })
  45. /*
  46. Release : v1.9
  47. Testname: Secrets Volume, volume mode 0440, fsGroup 1001 and uid 1000
  48. Description: Create a secret. Create a Pod with secret volume source configured into the container with file mode set to 0x440 as a non-root user with uid 1000 and fsGroup id 1001. Pod MUST be able to read the secret from the mounted volume from the container runtime and the file mode of the secret MUST be -r——r-—-—- by default.
  49. This test is marked LinuxOnly since Windows does not support setting specific file permissions, or running as UID / GID.
  50. */
  51. framework.ConformanceIt("should be consumable from pods in volume as non-root with defaultMode and fsGroup set [LinuxOnly] [NodeConformance]", func() {
  52. defaultMode := int32(0440) /* setting fsGroup sets mode to at least 440 */
  53. fsGroup := int64(1001)
  54. uid := int64(1000)
  55. doSecretE2EWithoutMapping(f, &defaultMode, "secret-test-"+string(uuid.NewUUID()), &fsGroup, &uid)
  56. })
  57. /*
  58. Release : v1.9
  59. Testname: Secrets Volume, mapping
  60. Description: Create a secret. Create a Pod with secret volume source configured into the container with a custom path. Pod MUST be able to read the secret from the mounted volume from the specified custom path. The file mode of the secret MUST be -rw—r-—r—- by default.
  61. */
  62. framework.ConformanceIt("should be consumable from pods in volume with mappings [NodeConformance]", func() {
  63. doSecretE2EWithMapping(f, nil)
  64. })
  65. /*
  66. Release : v1.9
  67. Testname: Secrets Volume, mapping, volume mode 0400
  68. Description: Create a secret. Create a Pod with secret volume source configured into the container with a custom path and file mode set to 0x400. Pod MUST be able to read the secret from the mounted volume from the specified custom path. The file mode of the secret MUST be -r-—r-—r—-.
  69. This test is marked LinuxOnly since Windows does not support setting specific file permissions.
  70. */
  71. framework.ConformanceIt("should be consumable from pods in volume with mappings and Item Mode set [LinuxOnly] [NodeConformance]", func() {
  72. mode := int32(0400)
  73. doSecretE2EWithMapping(f, &mode)
  74. })
  75. /*
  76. Release : v1.12
  77. Testname: Secrets Volume, volume mode default, secret with same name in different namespace
  78. Description: Create a secret with same name in two namespaces. Create a Pod with secret volume source configured into the container. Pod MUST be able to read the secrets from the mounted volume from the container runtime and only secrets which are associated with namespace where pod is created. The file mode of the secret MUST be -rw-r--r-- by default.
  79. */
  80. framework.ConformanceIt("should be able to mount in a volume regardless of a different secret existing with same name in different namespace [NodeConformance]", func() {
  81. var (
  82. namespace2 *v1.Namespace
  83. err error
  84. secret2Name = "secret-test-" + string(uuid.NewUUID())
  85. )
  86. if namespace2, err = f.CreateNamespace("secret-namespace", nil); err != nil {
  87. framework.Failf("unable to create new namespace %s: %v", namespace2.Name, err)
  88. }
  89. secret2 := secretForTest(namespace2.Name, secret2Name)
  90. secret2.Data = map[string][]byte{
  91. "this_should_not_match_content_of_other_secret": []byte("similarly_this_should_not_match_content_of_other_secret\n"),
  92. }
  93. if secret2, err = f.ClientSet.CoreV1().Secrets(namespace2.Name).Create(secret2); err != nil {
  94. framework.Failf("unable to create test secret %s: %v", secret2.Name, err)
  95. }
  96. doSecretE2EWithoutMapping(f, nil /* default mode */, secret2.Name, nil, nil)
  97. })
  98. /*
  99. Release : v1.9
  100. Testname: Secrets Volume, mapping multiple volume paths
  101. Description: Create a secret. Create a Pod with two secret volume sources configured into the container in to two different custom paths. Pod MUST be able to read the secret from the both the mounted volumes from the two specified custom paths.
  102. */
  103. framework.ConformanceIt("should be consumable in multiple volumes in a pod [NodeConformance]", func() {
  104. // This test ensures that the same secret can be mounted in multiple
  105. // volumes in the same pod. This test case exists to prevent
  106. // regressions that break this use-case.
  107. var (
  108. name = "secret-test-" + string(uuid.NewUUID())
  109. volumeName = "secret-volume"
  110. volumeMountPath = "/etc/secret-volume"
  111. volumeName2 = "secret-volume-2"
  112. volumeMountPath2 = "/etc/secret-volume-2"
  113. secret = secretForTest(f.Namespace.Name, name)
  114. )
  115. By(fmt.Sprintf("Creating secret with name %s", secret.Name))
  116. var err error
  117. if secret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(secret); err != nil {
  118. framework.Failf("unable to create test secret %s: %v", secret.Name, err)
  119. }
  120. pod := &v1.Pod{
  121. ObjectMeta: metav1.ObjectMeta{
  122. Name: "pod-secrets-" + string(uuid.NewUUID()),
  123. },
  124. Spec: v1.PodSpec{
  125. Volumes: []v1.Volume{
  126. {
  127. Name: volumeName,
  128. VolumeSource: v1.VolumeSource{
  129. Secret: &v1.SecretVolumeSource{
  130. SecretName: name,
  131. },
  132. },
  133. },
  134. {
  135. Name: volumeName2,
  136. VolumeSource: v1.VolumeSource{
  137. Secret: &v1.SecretVolumeSource{
  138. SecretName: name,
  139. },
  140. },
  141. },
  142. },
  143. Containers: []v1.Container{
  144. {
  145. Name: "secret-volume-test",
  146. Image: imageutils.GetE2EImage(imageutils.Mounttest),
  147. Args: []string{
  148. "--file_content=/etc/secret-volume/data-1",
  149. "--file_mode=/etc/secret-volume/data-1"},
  150. VolumeMounts: []v1.VolumeMount{
  151. {
  152. Name: volumeName,
  153. MountPath: volumeMountPath,
  154. ReadOnly: true,
  155. },
  156. {
  157. Name: volumeName2,
  158. MountPath: volumeMountPath2,
  159. ReadOnly: true,
  160. },
  161. },
  162. },
  163. },
  164. RestartPolicy: v1.RestartPolicyNever,
  165. },
  166. }
  167. fileModeRegexp := framework.GetFileModeRegex("/etc/secret-volume/data-1", nil)
  168. f.TestContainerOutputRegexp("consume secrets", pod, 0, []string{
  169. "content of file \"/etc/secret-volume/data-1\": value-1",
  170. fileModeRegexp,
  171. })
  172. })
  173. /*
  174. Release : v1.9
  175. Testname: Secrets Volume, create, update and delete
  176. Description: Create a Pod with three containers with secrets volume sources namely a create, update and delete container. Create Container when started MUST not have secret, update and delete containers MUST be created with a secret value. Create a secret in the create container, the Pod MUST be able to read the secret from the create container. Update the secret in the update container, Pod MUST be able to read the updated secret value. Delete the secret in the delete container. Pod MUST fail to read the secret from the delete container.
  177. */
  178. framework.ConformanceIt("optional updates should be reflected in volume [NodeConformance]", func() {
  179. podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet)
  180. containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds()))
  181. trueVal := true
  182. volumeMountPath := "/etc/secret-volumes"
  183. deleteName := "s-test-opt-del-" + string(uuid.NewUUID())
  184. deleteContainerName := "dels-volume-test"
  185. deleteVolumeName := "deletes-volume"
  186. deleteSecret := &v1.Secret{
  187. ObjectMeta: metav1.ObjectMeta{
  188. Namespace: f.Namespace.Name,
  189. Name: deleteName,
  190. },
  191. Data: map[string][]byte{
  192. "data-1": []byte("value-1"),
  193. },
  194. }
  195. updateName := "s-test-opt-upd-" + string(uuid.NewUUID())
  196. updateContainerName := "upds-volume-test"
  197. updateVolumeName := "updates-volume"
  198. updateSecret := &v1.Secret{
  199. ObjectMeta: metav1.ObjectMeta{
  200. Namespace: f.Namespace.Name,
  201. Name: updateName,
  202. },
  203. Data: map[string][]byte{
  204. "data-1": []byte("value-1"),
  205. },
  206. }
  207. createName := "s-test-opt-create-" + string(uuid.NewUUID())
  208. createContainerName := "creates-volume-test"
  209. createVolumeName := "creates-volume"
  210. createSecret := &v1.Secret{
  211. ObjectMeta: metav1.ObjectMeta{
  212. Namespace: f.Namespace.Name,
  213. Name: createName,
  214. },
  215. Data: map[string][]byte{
  216. "data-1": []byte("value-1"),
  217. },
  218. }
  219. By(fmt.Sprintf("Creating secret with name %s", deleteSecret.Name))
  220. var err error
  221. if deleteSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(deleteSecret); err != nil {
  222. framework.Failf("unable to create test secret %s: %v", deleteSecret.Name, err)
  223. }
  224. By(fmt.Sprintf("Creating secret with name %s", updateSecret.Name))
  225. if updateSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(updateSecret); err != nil {
  226. framework.Failf("unable to create test secret %s: %v", updateSecret.Name, err)
  227. }
  228. pod := &v1.Pod{
  229. ObjectMeta: metav1.ObjectMeta{
  230. Name: "pod-secrets-" + string(uuid.NewUUID()),
  231. },
  232. Spec: v1.PodSpec{
  233. Volumes: []v1.Volume{
  234. {
  235. Name: deleteVolumeName,
  236. VolumeSource: v1.VolumeSource{
  237. Secret: &v1.SecretVolumeSource{
  238. SecretName: deleteName,
  239. Optional: &trueVal,
  240. },
  241. },
  242. },
  243. {
  244. Name: updateVolumeName,
  245. VolumeSource: v1.VolumeSource{
  246. Secret: &v1.SecretVolumeSource{
  247. SecretName: updateName,
  248. Optional: &trueVal,
  249. },
  250. },
  251. },
  252. {
  253. Name: createVolumeName,
  254. VolumeSource: v1.VolumeSource{
  255. Secret: &v1.SecretVolumeSource{
  256. SecretName: createName,
  257. Optional: &trueVal,
  258. },
  259. },
  260. },
  261. },
  262. Containers: []v1.Container{
  263. {
  264. Name: deleteContainerName,
  265. Image: imageutils.GetE2EImage(imageutils.Mounttest),
  266. Command: []string{"/mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/delete/data-1"},
  267. VolumeMounts: []v1.VolumeMount{
  268. {
  269. Name: deleteVolumeName,
  270. MountPath: path.Join(volumeMountPath, "delete"),
  271. ReadOnly: true,
  272. },
  273. },
  274. },
  275. {
  276. Name: updateContainerName,
  277. Image: imageutils.GetE2EImage(imageutils.Mounttest),
  278. Command: []string{"/mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/update/data-3"},
  279. VolumeMounts: []v1.VolumeMount{
  280. {
  281. Name: updateVolumeName,
  282. MountPath: path.Join(volumeMountPath, "update"),
  283. ReadOnly: true,
  284. },
  285. },
  286. },
  287. {
  288. Name: createContainerName,
  289. Image: imageutils.GetE2EImage(imageutils.Mounttest),
  290. Command: []string{"/mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/create/data-1"},
  291. VolumeMounts: []v1.VolumeMount{
  292. {
  293. Name: createVolumeName,
  294. MountPath: path.Join(volumeMountPath, "create"),
  295. ReadOnly: true,
  296. },
  297. },
  298. },
  299. },
  300. RestartPolicy: v1.RestartPolicyNever,
  301. },
  302. }
  303. By("Creating the pod")
  304. f.PodClient().CreateSync(pod)
  305. pollCreateLogs := func() (string, error) {
  306. return framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, createContainerName)
  307. }
  308. Eventually(pollCreateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/secret-volumes/create/data-1"))
  309. pollUpdateLogs := func() (string, error) {
  310. return framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, updateContainerName)
  311. }
  312. Eventually(pollUpdateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/secret-volumes/update/data-3"))
  313. pollDeleteLogs := func() (string, error) {
  314. return framework.GetPodLogs(f.ClientSet, f.Namespace.Name, pod.Name, deleteContainerName)
  315. }
  316. Eventually(pollDeleteLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-1"))
  317. By(fmt.Sprintf("Deleting secret %v", deleteSecret.Name))
  318. err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Delete(deleteSecret.Name, &metav1.DeleteOptions{})
  319. framework.ExpectNoError(err, "Failed to delete secret %q in namespace %q", deleteSecret.Name, f.Namespace.Name)
  320. By(fmt.Sprintf("Updating secret %v", updateSecret.Name))
  321. updateSecret.ResourceVersion = "" // to force update
  322. delete(updateSecret.Data, "data-1")
  323. updateSecret.Data["data-3"] = []byte("value-3")
  324. _, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Update(updateSecret)
  325. framework.ExpectNoError(err, "Failed to update secret %q in namespace %q", updateSecret.Name, f.Namespace.Name)
  326. By(fmt.Sprintf("Creating secret with name %s", createSecret.Name))
  327. if createSecret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(createSecret); err != nil {
  328. framework.Failf("unable to create test secret %s: %v", createSecret.Name, err)
  329. }
  330. By("waiting to observe update in volume")
  331. Eventually(pollCreateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-1"))
  332. Eventually(pollUpdateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-3"))
  333. Eventually(pollDeleteLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/secret-volumes/delete/data-1"))
  334. })
  335. //The secret is in pending during volume creation until the secret objects are available
  336. //or until mount the secret volume times out. There is no secret object defined for the pod, so it should return timout exception unless it is marked optional.
  337. //Slow (~5 mins)
  338. It("Should fail non-optional pod creation due to secret object does not exist [Slow]", func() {
  339. volumeMountPath := "/etc/secret-volumes"
  340. podName := "pod-secrets-" + string(uuid.NewUUID())
  341. err := createNonOptionalSecretPod(f, volumeMountPath, podName)
  342. framework.ExpectError(err, "created pod %q with non-optional secret in namespace %q", podName, f.Namespace.Name)
  343. })
  344. //Secret object defined for the pod, If a key is specified which is not present in the secret,
  345. // the volume setup will error unless it is marked optional, during the pod creation.
  346. //Slow (~5 mins)
  347. It("Should fail non-optional pod creation due to the key in the secret object does not exist [Slow]", func() {
  348. volumeMountPath := "/etc/secret-volumes"
  349. podName := "pod-secrets-" + string(uuid.NewUUID())
  350. err := createNonOptionalSecretPodWithSecret(f, volumeMountPath, podName)
  351. framework.ExpectError(err, "created pod %q with non-optional secret in namespace %q", podName, f.Namespace.Name)
  352. })
  353. })
  354. func secretForTest(namespace, name string) *v1.Secret {
  355. return &v1.Secret{
  356. ObjectMeta: metav1.ObjectMeta{
  357. Namespace: namespace,
  358. Name: name,
  359. },
  360. Data: map[string][]byte{
  361. "data-1": []byte("value-1\n"),
  362. "data-2": []byte("value-2\n"),
  363. "data-3": []byte("value-3\n"),
  364. },
  365. }
  366. }
  367. func doSecretE2EWithoutMapping(f *framework.Framework, defaultMode *int32, secretName string,
  368. fsGroup *int64, uid *int64) {
  369. var (
  370. volumeName = "secret-volume"
  371. volumeMountPath = "/etc/secret-volume"
  372. secret = secretForTest(f.Namespace.Name, secretName)
  373. )
  374. By(fmt.Sprintf("Creating secret with name %s", secret.Name))
  375. var err error
  376. if secret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(secret); err != nil {
  377. framework.Failf("unable to create test secret %s: %v", secret.Name, err)
  378. }
  379. pod := &v1.Pod{
  380. ObjectMeta: metav1.ObjectMeta{
  381. Name: "pod-secrets-" + string(uuid.NewUUID()),
  382. Namespace: f.Namespace.Name,
  383. },
  384. Spec: v1.PodSpec{
  385. Volumes: []v1.Volume{
  386. {
  387. Name: volumeName,
  388. VolumeSource: v1.VolumeSource{
  389. Secret: &v1.SecretVolumeSource{
  390. SecretName: secretName,
  391. },
  392. },
  393. },
  394. },
  395. Containers: []v1.Container{
  396. {
  397. Name: "secret-volume-test",
  398. Image: imageutils.GetE2EImage(imageutils.Mounttest),
  399. Args: []string{
  400. "--file_content=/etc/secret-volume/data-1",
  401. "--file_mode=/etc/secret-volume/data-1"},
  402. VolumeMounts: []v1.VolumeMount{
  403. {
  404. Name: volumeName,
  405. MountPath: volumeMountPath,
  406. },
  407. },
  408. },
  409. },
  410. RestartPolicy: v1.RestartPolicyNever,
  411. },
  412. }
  413. if defaultMode != nil {
  414. pod.Spec.Volumes[0].VolumeSource.Secret.DefaultMode = defaultMode
  415. }
  416. if fsGroup != nil || uid != nil {
  417. pod.Spec.SecurityContext = &v1.PodSecurityContext{
  418. FSGroup: fsGroup,
  419. RunAsUser: uid,
  420. }
  421. }
  422. fileModeRegexp := framework.GetFileModeRegex("/etc/secret-volume/data-1", defaultMode)
  423. expectedOutput := []string{
  424. "content of file \"/etc/secret-volume/data-1\": value-1",
  425. fileModeRegexp,
  426. }
  427. f.TestContainerOutputRegexp("consume secrets", pod, 0, expectedOutput)
  428. }
  429. func doSecretE2EWithMapping(f *framework.Framework, mode *int32) {
  430. var (
  431. name = "secret-test-map-" + string(uuid.NewUUID())
  432. volumeName = "secret-volume"
  433. volumeMountPath = "/etc/secret-volume"
  434. secret = secretForTest(f.Namespace.Name, name)
  435. )
  436. By(fmt.Sprintf("Creating secret with name %s", secret.Name))
  437. var err error
  438. if secret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(secret); err != nil {
  439. framework.Failf("unable to create test secret %s: %v", secret.Name, err)
  440. }
  441. pod := &v1.Pod{
  442. ObjectMeta: metav1.ObjectMeta{
  443. Name: "pod-secrets-" + string(uuid.NewUUID()),
  444. },
  445. Spec: v1.PodSpec{
  446. Volumes: []v1.Volume{
  447. {
  448. Name: volumeName,
  449. VolumeSource: v1.VolumeSource{
  450. Secret: &v1.SecretVolumeSource{
  451. SecretName: name,
  452. Items: []v1.KeyToPath{
  453. {
  454. Key: "data-1",
  455. Path: "new-path-data-1",
  456. },
  457. },
  458. },
  459. },
  460. },
  461. },
  462. Containers: []v1.Container{
  463. {
  464. Name: "secret-volume-test",
  465. Image: imageutils.GetE2EImage(imageutils.Mounttest),
  466. Args: []string{
  467. "--file_content=/etc/secret-volume/new-path-data-1",
  468. "--file_mode=/etc/secret-volume/new-path-data-1"},
  469. VolumeMounts: []v1.VolumeMount{
  470. {
  471. Name: volumeName,
  472. MountPath: volumeMountPath,
  473. },
  474. },
  475. },
  476. },
  477. RestartPolicy: v1.RestartPolicyNever,
  478. },
  479. }
  480. if mode != nil {
  481. pod.Spec.Volumes[0].VolumeSource.Secret.Items[0].Mode = mode
  482. }
  483. fileModeRegexp := framework.GetFileModeRegex("/etc/secret-volume/new-path-data-1", mode)
  484. expectedOutput := []string{
  485. "content of file \"/etc/secret-volume/new-path-data-1\": value-1",
  486. fileModeRegexp,
  487. }
  488. f.TestContainerOutputRegexp("consume secrets", pod, 0, expectedOutput)
  489. }
  490. func createNonOptionalSecretPod(f *framework.Framework, volumeMountPath, podName string) error {
  491. podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet)
  492. containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds()))
  493. falseValue := false
  494. createName := "s-test-opt-create-" + string(uuid.NewUUID())
  495. createContainerName := "creates-volume-test"
  496. createVolumeName := "creates-volume"
  497. //creating a pod without secret object created, by mentioning the secret volume source reference name
  498. pod := &v1.Pod{
  499. ObjectMeta: metav1.ObjectMeta{
  500. Name: podName,
  501. },
  502. Spec: v1.PodSpec{
  503. Volumes: []v1.Volume{
  504. {
  505. Name: createVolumeName,
  506. VolumeSource: v1.VolumeSource{
  507. Secret: &v1.SecretVolumeSource{
  508. SecretName: createName,
  509. Optional: &falseValue,
  510. },
  511. },
  512. },
  513. },
  514. Containers: []v1.Container{
  515. {
  516. Name: createContainerName,
  517. Image: imageutils.GetE2EImage(imageutils.Mounttest),
  518. Command: []string{"/mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/create/data-1"},
  519. VolumeMounts: []v1.VolumeMount{
  520. {
  521. Name: createVolumeName,
  522. MountPath: path.Join(volumeMountPath, "create"),
  523. ReadOnly: true,
  524. },
  525. },
  526. },
  527. },
  528. RestartPolicy: v1.RestartPolicyNever,
  529. },
  530. }
  531. By("Creating the pod")
  532. pod = f.PodClient().Create(pod)
  533. return f.WaitForPodRunning(pod.Name)
  534. }
  535. func createNonOptionalSecretPodWithSecret(f *framework.Framework, volumeMountPath, podName string) error {
  536. podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet)
  537. containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds()))
  538. falseValue := false
  539. createName := "s-test-opt-create-" + string(uuid.NewUUID())
  540. createContainerName := "creates-volume-test"
  541. createVolumeName := "creates-volume"
  542. secret := secretForTest(f.Namespace.Name, createName)
  543. By(fmt.Sprintf("Creating secret with name %s", secret.Name))
  544. var err error
  545. if secret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(secret); err != nil {
  546. framework.Failf("unable to create test secret %s: %v", secret.Name, err)
  547. }
  548. //creating a pod with secret object, with the key which is not present in secret object.
  549. pod := &v1.Pod{
  550. ObjectMeta: metav1.ObjectMeta{
  551. Name: podName,
  552. },
  553. Spec: v1.PodSpec{
  554. Volumes: []v1.Volume{
  555. {
  556. Name: createVolumeName,
  557. VolumeSource: v1.VolumeSource{
  558. Secret: &v1.SecretVolumeSource{
  559. SecretName: createName,
  560. Items: []v1.KeyToPath{
  561. {
  562. Key: "data_4",
  563. Path: "value-4\n",
  564. },
  565. },
  566. Optional: &falseValue,
  567. },
  568. },
  569. },
  570. },
  571. Containers: []v1.Container{
  572. {
  573. Name: createContainerName,
  574. Image: imageutils.GetE2EImage(imageutils.Mounttest),
  575. Command: []string{"/mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/create/data-1"},
  576. VolumeMounts: []v1.VolumeMount{
  577. {
  578. Name: createVolumeName,
  579. MountPath: path.Join(volumeMountPath, "create"),
  580. ReadOnly: true,
  581. },
  582. },
  583. },
  584. },
  585. RestartPolicy: v1.RestartPolicyNever,
  586. },
  587. }
  588. By("Creating the pod")
  589. pod = f.PodClient().Create(pod)
  590. return f.WaitForPodRunning(pod.Name)
  591. }