diff --git a/test/e2e/common/configmap.go b/test/e2e/common/configmap.go index 5eda31a4840..c6479f32d98 100644 --- a/test/e2e/common/configmap.go +++ b/test/e2e/common/configmap.go @@ -20,6 +20,7 @@ import ( "fmt" . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" @@ -122,6 +123,11 @@ var _ = Describe("[sig-node] ConfigMap", func() { "p_data_1=value-1", "p_data_2=value-2", "p_data_3=value-3", }) }) + + It("should fail to create configMap in volume due to empty configmap key", func() { + configMap, err := newConfigMapWithEmptyKey(f) + Expect(err).To(HaveOccurred(), "created configMap %q with empty key in namespace %q", configMap.Name, f.Namespace.Name) + }) }) func newEnvFromConfigMap(f *framework.Framework, name string) *v1.ConfigMap { @@ -137,3 +143,19 @@ func newEnvFromConfigMap(f *framework.Framework, name string) *v1.ConfigMap { }, } } + +func newConfigMapWithEmptyKey(f *framework.Framework) (*v1.ConfigMap, error) { + name := "configmap-test-emptyKey-" + string(uuid.NewUUID()) + configMap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: f.Namespace.Name, + Name: name, + }, + Data: map[string]string{ + "": "value-1", + }, + } + + By(fmt.Sprintf("Creating configMap that has name %s", configMap.Name)) + return f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(configMap) +} diff --git a/test/e2e/common/configmap_volume.go b/test/e2e/common/configmap_volume.go index 32e42a23166..40cdcd5044c 100644 --- a/test/e2e/common/configmap_volume.go +++ b/test/e2e/common/configmap_volume.go @@ -540,6 +540,26 @@ var _ = Describe("[sig-storage] ConfigMap", func() { }) }) + + //The pod is in pending during volume creation until the configMap objects are available + //or until mount the configMap volume times out. There is no configMap object defined for the pod, so it should return timout exception unless it is marked optional. + //Slow (~5 mins) + It("Should fail non-optional pod creation due to configMap object does not exist [Slow]", func() { + volumeMountPath := "/etc/configmap-volumes" + podName := "pod-configmaps-" + string(uuid.NewUUID()) + err := createNonOptionalConfigMapPod(f, volumeMountPath, podName) + Expect(err).To(HaveOccurred(), "created pod %q with non-optional configMap in namespace %q", podName, f.Namespace.Name) + }) + + //ConfigMap object defined for the pod, If a key is specified which is not present in the ConfigMap, + // the volume setup will error unless it is marked optional, during the pod creation. + //Slow (~5 mins) + It("Should fail non-optional pod creation due to the key in the configMap object does not exist [Slow]", func() { + volumeMountPath := "/etc/configmap-volumes" + podName := "pod-configmaps-" + string(uuid.NewUUID()) + err := createNonOptionalConfigMapPodWithConfig(f, volumeMountPath, podName) + Expect(err).To(HaveOccurred(), "created pod %q with non-optional configMap in namespace %q", podName, f.Namespace.Name) + }) }) func newConfigMap(f *framework.Framework, name string) *v1.ConfigMap { @@ -724,3 +744,115 @@ func doConfigMapE2EWithMappings(f *framework.Framework, uid, fsGroup int64, item } f.TestContainerOutput("consume configMaps", pod, 0, output) } + +func createNonOptionalConfigMapPod(f *framework.Framework, volumeMountPath, podName string) error { + podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) + containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) + falseValue := false + + createName := "cm-test-opt-create-" + string(uuid.NewUUID()) + createContainerName := "createcm-volume-test" + createVolumeName := "createcm-volume" + + //creating a pod without configMap object created, by mentioning the configMap volume source's local reference name + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: createVolumeName, + VolumeSource: v1.VolumeSource{ + ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: createName, + }, + Optional: &falseValue, + }, + }, + }, + }, + Containers: []v1.Container{ + { + Name: createContainerName, + Image: imageutils.GetE2EImage(imageutils.Mounttest), + Command: []string{"/mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/configmap-volumes/create/data-1"}, + VolumeMounts: []v1.VolumeMount{ + { + Name: createVolumeName, + MountPath: path.Join(volumeMountPath, "create"), + ReadOnly: true, + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + }, + } + By("Creating the pod") + pod = f.PodClient().Create(pod) + return f.WaitForPodRunning(pod.Name) +} + +func createNonOptionalConfigMapPodWithConfig(f *framework.Framework, volumeMountPath, podName string) error { + podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) + containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) + falseValue := false + + createName := "cm-test-opt-create-" + string(uuid.NewUUID()) + createContainerName := "createcm-volume-test" + createVolumeName := "createcm-volume" + configMap := newConfigMap(f, createName) + + By(fmt.Sprintf("Creating configMap with name %s", configMap.Name)) + var err error + if configMap, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(configMap); err != nil { + framework.Failf("unable to create test configMap %s: %v", configMap.Name, err) + } + //creating a pod with configMap object, but with different key which is not present in configMap object. + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: createVolumeName, + VolumeSource: v1.VolumeSource{ + ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: createName, + }, + Items: []v1.KeyToPath{ + { + Key: "data-4", + Path: "path/to/data-4", + }, + }, + Optional: &falseValue, + }, + }, + }, + }, + Containers: []v1.Container{ + { + Name: createContainerName, + Image: imageutils.GetE2EImage(imageutils.Mounttest), + Command: []string{"/mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/configmap-volumes/create/data-1"}, + VolumeMounts: []v1.VolumeMount{ + { + Name: createVolumeName, + MountPath: path.Join(volumeMountPath, "create"), + ReadOnly: true, + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + }, + } + By("Creating the pod") + pod = f.PodClient().Create(pod) + return f.WaitForPodRunning(pod.Name) +} diff --git a/test/e2e/common/projected_configmap.go b/test/e2e/common/projected_configmap.go index 5a8fda22966..2616189d42b 100644 --- a/test/e2e/common/projected_configmap.go +++ b/test/e2e/common/projected_configmap.go @@ -481,6 +481,26 @@ var _ = Describe("[sig-storage] Projected configMap", func() { }) }) + + //The pod is in pending during volume creation until the configMap objects are available + //or until mount the configMap volume times out. There is no configMap object defined for the pod, so it should return timout exception unless it is marked optional. + //Slow (~5 mins) + It("Should fail non-optional pod creation due to configMap object does not exist [Slow]", func() { + volumeMountPath := "/etc/projected-configmap-volumes" + podName := "pod-projected-configmaps-" + string(uuid.NewUUID()) + err := createNonOptionalConfigMapPod(f, volumeMountPath, podName) + Expect(err).To(HaveOccurred(), "created pod %q with non-optional configMap in namespace %q", podName, f.Namespace.Name) + }) + + //ConfigMap object defined for the pod, If a key is specified which is not present in the ConfigMap, + // the volume setup will error unless it is marked optional, during the pod creation. + //Slow (~5 mins) + It("Should fail non-optional pod creation due to the key in the configMap object does not exist [Slow]", func() { + volumeMountPath := "/etc/configmap-volumes" + podName := "pod-configmaps-" + string(uuid.NewUUID()) + err := createNonOptionalConfigMapPodWithConfig(f, volumeMountPath, podName) + Expect(err).To(HaveOccurred(), "created pod %q with non-optional configMap in namespace %q", podName, f.Namespace.Name) + }) }) func doProjectedConfigMapE2EWithoutMappings(f *framework.Framework, uid, fsGroup int64, defaultMode *int32) { diff --git a/test/e2e/common/projected_secret.go b/test/e2e/common/projected_secret.go index 9b0bb49ec80..4f88da9f3e0 100644 --- a/test/e2e/common/projected_secret.go +++ b/test/e2e/common/projected_secret.go @@ -399,6 +399,26 @@ var _ = Describe("[sig-storage] Projected secret", func() { Eventually(pollUpdateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-3")) Eventually(pollDeleteLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/projected-secret-volumes/delete/data-1")) }) + + //The secret is in pending during volume creation until the secret objects are available + //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. + //Slow (~5 mins) + It("Should fail non-optional pod creation due to secret object does not exist [Slow]", func() { + volumeMountPath := "/etc/projected-secret-volumes" + podName := "pod-secrets-" + string(uuid.NewUUID()) + err := createNonOptionalSecretPod(f, volumeMountPath, podName) + Expect(err).To(HaveOccurred(), "created pod %q with non-optional secret in namespace %q", podName, f.Namespace.Name) + }) + + //Secret object defined for the pod, If a key is specified which is not present in the secret, + // the volume setup will error unless it is marked optional, during the pod creation. + //Slow (~5 mins) + It("Should fail non-optional pod creation due to the key in the secret object does not exist [Slow]", func() { + volumeMountPath := "/etc/secret-volumes" + podName := "pod-secrets-" + string(uuid.NewUUID()) + err := createNonOptionalSecretPodWithSecret(f, volumeMountPath, podName) + Expect(err).To(HaveOccurred(), "created pod %q with non-optional secret in namespace %q", podName, f.Namespace.Name) + }) }) func doProjectedSecretE2EWithoutMapping(f *framework.Framework, defaultMode *int32, diff --git a/test/e2e/common/secrets.go b/test/e2e/common/secrets.go index 4da60718fd6..ce771c22ebd 100644 --- a/test/e2e/common/secrets.go +++ b/test/e2e/common/secrets.go @@ -26,6 +26,7 @@ import ( imageutils "k8s.io/kubernetes/test/utils/image" . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) var _ = Describe("[sig-api-machinery] Secrets", func() { @@ -124,6 +125,11 @@ var _ = Describe("[sig-api-machinery] Secrets", func() { "p_data_1=value-1", "p_data_2=value-2", "p_data_3=value-3", }) }) + + It("should fail to create secret in volume due to empty secret key", func() { + secret, err := createEmptyKeySecretForTest(f) + Expect(err).To(HaveOccurred(), "created secret %q with empty key in namespace %q", secret.Name, f.Namespace.Name) + }) }) func newEnvFromSecret(namespace, name string) *v1.Secret { @@ -139,3 +145,18 @@ func newEnvFromSecret(namespace, name string) *v1.Secret { }, } } + +func createEmptyKeySecretForTest(f *framework.Framework) (*v1.Secret, error) { + secretName := "secret-emptyKey-test-" + string(uuid.NewUUID()) + secret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: f.Namespace.Name, + Name: secretName, + }, + Data: map[string][]byte{ + "": []byte("value-1\n"), + }, + } + By(fmt.Sprintf("Creating projection with secret that has name %s", secret.Name)) + return f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(secret) +} diff --git a/test/e2e/common/secrets_volume.go b/test/e2e/common/secrets_volume.go index 432cd21afd5..e700c699e80 100644 --- a/test/e2e/common/secrets_volume.go +++ b/test/e2e/common/secrets_volume.go @@ -364,6 +364,26 @@ var _ = Describe("[sig-storage] Secrets", func() { Eventually(pollUpdateLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("value-3")) Eventually(pollDeleteLogs, podLogTimeout, framework.Poll).Should(ContainSubstring("Error reading file /etc/secret-volumes/delete/data-1")) }) + + //The secret is in pending during volume creation until the secret objects are available + //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. + //Slow (~5 mins) + It("Should fail non-optional pod creation due to secret object does not exist [Slow]", func() { + volumeMountPath := "/etc/secret-volumes" + podName := "pod-secrets-" + string(uuid.NewUUID()) + err := createNonOptionalSecretPod(f, volumeMountPath, podName) + Expect(err).To(HaveOccurred(), "created pod %q with non-optional secret in namespace %q", podName, f.Namespace.Name) + }) + + //Secret object defined for the pod, If a key is specified which is not present in the secret, + // the volume setup will error unless it is marked optional, during the pod creation. + //Slow (~5 mins) + It("Should fail non-optional pod creation due to the key in the secret object does not exist [Slow]", func() { + volumeMountPath := "/etc/secret-volumes" + podName := "pod-secrets-" + string(uuid.NewUUID()) + err := createNonOptionalSecretPodWithSecret(f, volumeMountPath, podName) + Expect(err).To(HaveOccurred(), "created pod %q with non-optional secret in namespace %q", podName, f.Namespace.Name) + }) }) func secretForTest(namespace, name string) *v1.Secret { @@ -521,3 +541,112 @@ func doSecretE2EWithMapping(f *framework.Framework, mode *int32) { f.TestContainerOutput("consume secrets", pod, 0, expectedOutput) } + +func createNonOptionalSecretPod(f *framework.Framework, volumeMountPath, podName string) error { + podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) + containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) + falseValue := false + + createName := "s-test-opt-create-" + string(uuid.NewUUID()) + createContainerName := "creates-volume-test" + createVolumeName := "creates-volume" + + //creating a pod without secret object created, by mentioning the secret volume source reference name + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: createVolumeName, + VolumeSource: v1.VolumeSource{ + Secret: &v1.SecretVolumeSource{ + SecretName: createName, + Optional: &falseValue, + }, + }, + }, + }, + Containers: []v1.Container{ + { + Name: createContainerName, + Image: imageutils.GetE2EImage(imageutils.Mounttest), + Command: []string{"/mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/create/data-1"}, + VolumeMounts: []v1.VolumeMount{ + { + Name: createVolumeName, + MountPath: path.Join(volumeMountPath, "create"), + ReadOnly: true, + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + }, + } + By("Creating the pod") + pod = f.PodClient().Create(pod) + return f.WaitForPodRunning(pod.Name) +} + +func createNonOptionalSecretPodWithSecret(f *framework.Framework, volumeMountPath, podName string) error { + podLogTimeout := framework.GetPodSecretUpdateTimeout(f.ClientSet) + containerTimeoutArg := fmt.Sprintf("--retry_time=%v", int(podLogTimeout.Seconds())) + falseValue := false + + createName := "s-test-opt-create-" + string(uuid.NewUUID()) + createContainerName := "creates-volume-test" + createVolumeName := "creates-volume" + + secret := secretForTest(f.Namespace.Name, createName) + + By(fmt.Sprintf("Creating secret with name %s", secret.Name)) + var err error + if secret, err = f.ClientSet.CoreV1().Secrets(f.Namespace.Name).Create(secret); err != nil { + framework.Failf("unable to create test secret %s: %v", secret.Name, err) + } + //creating a pod with secret object, with the key which is not present in secret object. + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: createVolumeName, + VolumeSource: v1.VolumeSource{ + Secret: &v1.SecretVolumeSource{ + SecretName: createName, + Items: []v1.KeyToPath{ + { + Key: "data_4", + Path: "value-4\n", + }, + }, + Optional: &falseValue, + }, + }, + }, + }, + Containers: []v1.Container{ + { + Name: createContainerName, + Image: imageutils.GetE2EImage(imageutils.Mounttest), + Command: []string{"/mounttest", "--break_on_expected_content=false", containerTimeoutArg, "--file_content_in_loop=/etc/secret-volumes/create/data-1"}, + VolumeMounts: []v1.VolumeMount{ + { + Name: createVolumeName, + MountPath: path.Join(volumeMountPath, "create"), + ReadOnly: true, + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + }, + } + By("Creating the pod") + pod = f.PodClient().Create(pod) + return f.WaitForPodRunning(pod.Name) +}