diff --git a/pkg/controller/deployment/deployment_controller_test.go b/pkg/controller/deployment/deployment_controller_test.go index f1081681..17819f23 100644 --- a/pkg/controller/deployment/deployment_controller_test.go +++ b/pkg/controller/deployment/deployment_controller_test.go @@ -214,6 +214,7 @@ var _ = Describe("Deployment controller Suite", func() { m.UpdateWithFunc(deployment, removeContainer2).Should(Succeed()) waitForDeploymentReconciled(deployment) + waitForDeploymentReconciled(deployment) // Get the updated Deployment m.Get(deployment, timeout).Should(Succeed()) diff --git a/pkg/core/children.go b/pkg/core/children.go index 21e34ea1..f239ea4a 100644 --- a/pkg/core/children.go +++ b/pkg/core/children.go @@ -105,10 +105,10 @@ func getChildNamesByType(obj podController) (map[string]configMetadata, map[stri // and Secrets for _, vol := range obj.GetPodTemplate().Spec.Volumes { if cm := vol.VolumeSource.ConfigMap; cm != nil { - configMaps[cm.Name] = configMetadata{required: true, allKeys: true} + configMaps[cm.Name] = configMetadata{required: isRequired(cm.Optional), allKeys: true} } if s := vol.VolumeSource.Secret; s != nil { - secrets[s.SecretName] = configMetadata{required: true, allKeys: true} + secrets[s.SecretName] = configMetadata{required: isRequired(s.Optional), allKeys: true} } } @@ -117,10 +117,10 @@ func getChildNamesByType(obj podController) (map[string]configMetadata, map[stri for _, container := range obj.GetPodTemplate().Spec.Containers { for _, env := range container.EnvFrom { if cm := env.ConfigMapRef; cm != nil { - configMaps[cm.Name] = configMetadata{required: true, allKeys: true} + configMaps[cm.Name] = configMetadata{required: isRequired(cm.Optional), allKeys: true} } if s := env.SecretRef; s != nil { - secrets[s.Name] = configMetadata{required: true, allKeys: true} + secrets[s.Name] = configMetadata{required: isRequired(s.Optional), allKeys: true} } } } @@ -142,6 +142,10 @@ func getChildNamesByType(obj podController) (map[string]configMetadata, map[stri return configMaps, secrets } +func isRequired(b *bool) bool { + return b == nil || !*b +} + // parseConfigMapKeyRef updates the metadata for a ConfigMap to include the keys specified in this ConfigMapKeySelector func parseConfigMapKeyRef(metadata configMetadata, cm *corev1.ConfigMapKeySelector) configMetadata { if !metadata.allKeys { diff --git a/pkg/core/children_test.go b/pkg/core/children_test.go index a178bf4e..d02987de 100644 --- a/pkg/core/children_test.go +++ b/pkg/core/children_test.go @@ -216,10 +216,22 @@ var _ = Describe("Wave children Suite", func() { Expect(configMaps).To(HaveKeyWithValue(cm1.GetName(), configMetadata{required: true, allKeys: true})) }) + It("optional ConfigMaps referenced in Volumes are returned as optional", func() { + Expect(configMaps).To(HaveKeyWithValue("volume-optional", configMetadata{required: false, allKeys: true})) + }) + + It("optional Secrets referenced in Volumes are returned as optional", func() { + Expect(secrets).To(HaveKeyWithValue("volume-optional", configMetadata{required: false, allKeys: true})) + }) + It("returns ConfigMaps referenced in EnvFrom", func() { Expect(configMaps).To(HaveKeyWithValue(cm2.GetName(), configMetadata{required: true, allKeys: true})) }) + It("optional ConfigMaps referenced in EnvFrom are returned as optional", func() { + Expect(configMaps).To(HaveKeyWithValue("envfrom-optional", configMetadata{required: false, allKeys: true})) + }) + It("returns ConfigMaps referenced in Env", func() { Expect(configMaps).To(HaveKeyWithValue(cm3.GetName(), configMetadata{ required: true, @@ -232,6 +244,16 @@ var _ = Describe("Wave children Suite", func() { })) }) + It("returns ConfigMaps referenced in Env as optional correctly", func() { + Expect(configMaps).To(HaveKeyWithValue("env-optional", configMetadata{ + required: false, + allKeys: false, + keys: map[string]struct{}{ + "key2": {}, + }, + })) + }) + It("returns Secrets referenced in Volumes", func() { Expect(secrets).To(HaveKeyWithValue(s1.GetName(), configMetadata{required: true, allKeys: true})) }) @@ -240,8 +262,12 @@ var _ = Describe("Wave children Suite", func() { Expect(secrets).To(HaveKeyWithValue(s2.GetName(), configMetadata{required: true, allKeys: true})) }) + It("optional Secrets referenced in EnvFrom are returned as optional", func() { + Expect(secrets).To(HaveKeyWithValue("envfrom-optional", configMetadata{required: false, allKeys: true})) + }) + It("returns Secrets referenced in Env", func() { - Expect(configMaps).To(HaveKeyWithValue(s3.GetName(), configMetadata{ + Expect(secrets).To(HaveKeyWithValue(s3.GetName(), configMetadata{ required: true, allKeys: false, keys: map[string]struct{}{ @@ -252,9 +278,19 @@ var _ = Describe("Wave children Suite", func() { })) }) + It("returns secrets referenced in Env as optional correctly", func() { + Expect(secrets).To(HaveKeyWithValue("env-optional", configMetadata{ + required: false, + allKeys: false, + keys: map[string]struct{}{ + "key2": {}, + }, + })) + }) + It("does not return extra children", func() { - Expect(configMaps).To(HaveLen(4)) - Expect(secrets).To(HaveLen(4)) + Expect(configMaps).To(HaveLen(7)) + Expect(secrets).To(HaveLen(7)) }) }) diff --git a/test/utils/test_objects.go b/test/utils/test_objects.go index b5195cc1..865d2da1 100644 --- a/test/utils/test_objects.go +++ b/test/utils/test_objects.go @@ -53,6 +53,15 @@ var ExampleDeployment = &appsv1.Deployment{ }, }, }, + { + Name: "secret-optional", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "volume-optional", + Optional: &trueValue, + }, + }, + }, { Name: "configmap1", VolumeSource: corev1.VolumeSource{ @@ -63,6 +72,17 @@ var ExampleDeployment = &appsv1.Deployment{ }, }, }, + { + Name: "configmap-optional", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "volume-optional", + }, + Optional: &trueValue, + }, + }, + }, }, Containers: []corev1.Container{ { @@ -181,6 +201,14 @@ var ExampleDeployment = &appsv1.Deployment{ }, }, }, + { + ConfigMapRef: &corev1.ConfigMapEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "envfrom-optional", + }, + Optional: &trueValue, + }, + }, { SecretRef: &corev1.SecretEnvSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -188,12 +216,32 @@ var ExampleDeployment = &appsv1.Deployment{ }, }, }, + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "envfrom-optional", + }, + Optional: &trueValue, + }, + }, }, }, { Name: "container2", Image: "container2", Env: []corev1.EnvVar{ + { + Name: "env_optional_key2", + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-optional", + }, + Key: "key2", + Optional: &trueValue, + }, + }, + }, { Name: "example3_key2", ValueFrom: &corev1.EnvVarSource{ @@ -216,6 +264,18 @@ var ExampleDeployment = &appsv1.Deployment{ }, }, }, + { + Name: "env_optional_secret_key2", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-optional", + }, + Key: "key2", + Optional: &trueValue, + }, + }, + }, }, EnvFrom: []corev1.EnvFromSource{ {