diff --git a/pkg/controller/deployment/deployment_controller_test.go b/pkg/controller/deployment/deployment_controller_test.go index 36bd0b51..8d4dbea3 100644 --- a/pkg/controller/deployment/deployment_controller_test.go +++ b/pkg/controller/deployment/deployment_controller_test.go @@ -54,9 +54,15 @@ var _ = Describe("Deployment controller Suite", func() { var cm1 *corev1.ConfigMap var cm2 *corev1.ConfigMap var cm3 *corev1.ConfigMap + var cm4 *corev1.ConfigMap + var cm5 *corev1.ConfigMap + var cm6 *corev1.ConfigMap var s1 *corev1.Secret var s2 *corev1.Secret var s3 *corev1.Secret + var s4 *corev1.Secret + var s5 *corev1.Secret + var s6 *corev1.Secret const modified = "modified" @@ -97,22 +103,40 @@ var _ = Describe("Deployment controller Suite", func() { cm1 = utils.ExampleConfigMap1.DeepCopy() cm2 = utils.ExampleConfigMap2.DeepCopy() cm3 = utils.ExampleConfigMap3.DeepCopy() + cm4 = utils.ExampleConfigMap4.DeepCopy() + cm5 = utils.ExampleConfigMap5.DeepCopy() + cm6 = utils.ExampleConfigMap6.DeepCopy() s1 = utils.ExampleSecret1.DeepCopy() s2 = utils.ExampleSecret2.DeepCopy() s3 = utils.ExampleSecret3.DeepCopy() + s4 = utils.ExampleSecret4.DeepCopy() + s5 = utils.ExampleSecret5.DeepCopy() + s6 = utils.ExampleSecret6.DeepCopy() m.Create(cm1).Should(Succeed()) m.Create(cm2).Should(Succeed()) m.Create(cm3).Should(Succeed()) + m.Create(cm4).Should(Succeed()) + m.Create(cm5).Should(Succeed()) + m.Create(cm6).Should(Succeed()) m.Create(s1).Should(Succeed()) m.Create(s2).Should(Succeed()) m.Create(s3).Should(Succeed()) + m.Create(s4).Should(Succeed()) + m.Create(s5).Should(Succeed()) + m.Create(s6).Should(Succeed()) m.Get(cm1, timeout).Should(Succeed()) m.Get(cm2, timeout).Should(Succeed()) m.Get(cm3, timeout).Should(Succeed()) + m.Get(cm4, timeout).Should(Succeed()) + m.Get(cm5, timeout).Should(Succeed()) + m.Get(cm6, timeout).Should(Succeed()) m.Get(s1, timeout).Should(Succeed()) m.Get(s2, timeout).Should(Succeed()) m.Get(s3, timeout).Should(Succeed()) + m.Get(s4, timeout).Should(Succeed()) + m.Get(s5, timeout).Should(Succeed()) + m.Get(s6, timeout).Should(Succeed()) deployment = utils.ExampleDeployment.DeepCopy() @@ -204,7 +228,7 @@ var _ = Describe("Deployment controller Suite", func() { eventMessage := func(event *corev1.Event) string { return event.Message } - hashMessage := "Configuration hash updated to bd786f47ef9b79841ddba1059752f95c4fe21906df5e2964786b4658e02758d5" + hashMessage := "Configuration hash updated to 421778c325761f51dbf7a23a20eb9c1bc516ffd4aa7362ebec03175d427d7557" Eventually(func() *corev1.EventList { events := &corev1.EventList{} m.Client.List(context.TODO(), events) diff --git a/pkg/core/children.go b/pkg/core/children.go index a0dfcc87..9b109979 100644 --- a/pkg/core/children.go +++ b/pkg/core/children.go @@ -110,6 +110,33 @@ func getChildNamesByType(obj podController) (map[string]configMetadata, map[stri if s := vol.VolumeSource.Secret; s != nil { secrets[s.SecretName] = configMetadata{required: isRequired(s.Optional), allKeys: true} } + + if projection := vol.VolumeSource.Projected; projection != nil { + for _, source := range projection.Sources { + if cm := source.ConfigMap; cm != nil { + if cm.Items == nil { + configMaps[cm.Name] = configMetadata{required: isRequired(cm.Optional), allKeys: true} + } else { + keys := make(map[string]struct{}) + for _, item := range cm.Items { + keys[item.Key] = struct{}{} + } + configMaps[cm.Name] = configMetadata{required: isRequired(cm.Optional), allKeys: false, keys: keys} + } + } + if s := source.Secret; s != nil { + if s.Items == nil { + secrets[s.Name] = configMetadata{required: isRequired(s.Optional), allKeys: true} + } else { + keys := make(map[string]struct{}) + for _, item := range s.Items { + keys[item.Key] = struct{}{} + } + secrets[s.Name] = configMetadata{required: isRequired(s.Optional), allKeys: false, keys: keys} + } + } + } + } } // Range through all Containers and their respective EnvFrom, diff --git a/pkg/core/children_test.go b/pkg/core/children_test.go index e73f4d20..7672ea2c 100644 --- a/pkg/core/children_test.go +++ b/pkg/core/children_test.go @@ -17,10 +17,11 @@ limitations under the License. package core import ( - metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sync" "time" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/wave-k8s/wave/test/utils" @@ -38,7 +39,6 @@ var _ = Describe("Wave children Suite", func() { var m utils.Matcher var deploymentObject *appsv1.Deployment var podControllerDeployment podController - var existingChildren []Object var currentChildren []configObject var mgrStopped *sync.WaitGroup var stopMgr chan struct{} @@ -49,10 +49,14 @@ var _ = Describe("Wave children Suite", func() { var cm2 *corev1.ConfigMap var cm3 *corev1.ConfigMap var cm4 *corev1.ConfigMap + var cm5 *corev1.ConfigMap + var cm6 *corev1.ConfigMap var s1 *corev1.Secret var s2 *corev1.Secret var s3 *corev1.Secret var s4 *corev1.Secret + var s5 *corev1.Secret + var s6 *corev1.Secret BeforeEach(func() { mgr, err := manager.New(cfg, manager.Options{ @@ -75,19 +79,27 @@ var _ = Describe("Wave children Suite", func() { cm2 = utils.ExampleConfigMap2.DeepCopy() cm3 = utils.ExampleConfigMap3.DeepCopy() cm4 = utils.ExampleConfigMap4.DeepCopy() + cm5 = utils.ExampleConfigMap5.DeepCopy() + cm6 = utils.ExampleConfigMap6.DeepCopy() s1 = utils.ExampleSecret1.DeepCopy() s2 = utils.ExampleSecret2.DeepCopy() s3 = utils.ExampleSecret3.DeepCopy() s4 = utils.ExampleSecret4.DeepCopy() + s5 = utils.ExampleSecret5.DeepCopy() + s6 = utils.ExampleSecret6.DeepCopy() m.Create(cm1).Should(Succeed()) m.Create(cm2).Should(Succeed()) m.Create(cm3).Should(Succeed()) m.Create(cm4).Should(Succeed()) + m.Create(cm5).Should(Succeed()) + m.Create(cm6).Should(Succeed()) m.Create(s1).Should(Succeed()) m.Create(s2).Should(Succeed()) m.Create(s3).Should(Succeed()) m.Create(s4).Should(Succeed()) + m.Create(s5).Should(Succeed()) + m.Create(s6).Should(Succeed()) deploymentObject = utils.ExampleDeployment.DeepCopy() podControllerDeployment = &deployment{deploymentObject} @@ -101,10 +113,14 @@ var _ = Describe("Wave children Suite", func() { m.Get(cm2, timeout).Should(Succeed()) m.Get(cm3, timeout).Should(Succeed()) m.Get(cm4, timeout).Should(Succeed()) + m.Get(cm5, timeout).Should(Succeed()) + m.Get(cm6, timeout).Should(Succeed()) m.Get(s1, timeout).Should(Succeed()) m.Get(s2, timeout).Should(Succeed()) m.Get(s3, timeout).Should(Succeed()) m.Get(s4, timeout).Should(Succeed()) + m.Get(s5, timeout).Should(Succeed()) + m.Get(s6, timeout).Should(Succeed()) m.Get(deploymentObject, timeout).Should(Succeed()) }) @@ -134,6 +150,23 @@ var _ = Describe("Wave children Suite", func() { })) }) + It("returns ConfigMaps referenced in Volume Projections", func() { + Expect(currentChildren).To(ContainElement(configObject{ + object: cm6, + required: true, + allKeys: false, + keys: map[string]struct{}{ + "example6_key1": {}, + "example6_key3": {}, + }, + })) + Expect(currentChildren).To(ContainElement(configObject{ + object: cm5, + required: false, + allKeys: true, + })) + }) + It("returns ConfigMaps referenced in EnvFrom", func() { Expect(currentChildren).To(ContainElement(configObject{ object: cm2, @@ -171,6 +204,23 @@ var _ = Describe("Wave children Suite", func() { })) }) + It("returns Secrets referenced in Volume Projections", func() { + Expect(currentChildren).To(ContainElement(configObject{ + object: s6, + required: true, + allKeys: false, + keys: map[string]struct{}{ + "example6_key1": {}, + "example6_key3": {}, + }, + })) + Expect(currentChildren).To(ContainElement(configObject{ + object: s5, + required: false, + allKeys: true, + })) + }) + It("returns Secrets referenced in EnvFrom", func() { Expect(currentChildren).To(ContainElement(configObject{ object: s2, @@ -201,7 +251,7 @@ var _ = Describe("Wave children Suite", func() { }) It("does not return duplicate children", func() { - Expect(currentChildren).To(HaveLen(8)) + Expect(currentChildren).To(HaveLen(12)) }) It("returns an error if one of the referenced children is missing", func() { @@ -300,8 +350,8 @@ var _ = Describe("Wave children Suite", func() { }) It("does not return extra children", func() { - Expect(configMaps).To(HaveLen(7)) - Expect(secrets).To(HaveLen(7)) + Expect(configMaps).To(HaveLen(9)) + Expect(secrets).To(HaveLen(9)) }) }) @@ -319,32 +369,36 @@ var _ = Describe("Wave children Suite", func() { } var err error - existingChildren, err = h.getExistingChildren(podControllerDeployment) + _, err = h.getExistingChildren(podControllerDeployment) Expect(err).NotTo(HaveOccurred()) }) + existingChildrenFn := func() ([]Object, error) { + return h.getExistingChildren(podControllerDeployment) + } + It("returns ConfigMaps with the correct OwnerReference", func() { - Expect(existingChildren).To(ContainElement(cm1)) + Eventually(existingChildrenFn).Should(ContainElement(cm1)) }) It("doesn't return ConfigMaps without OwnerReferences", func() { - Expect(existingChildren).NotTo(ContainElement(cm2)) - Expect(existingChildren).NotTo(ContainElement(cm3)) - Expect(existingChildren).NotTo(ContainElement(cm4)) + Eventually(existingChildrenFn).ShouldNot(ContainElement(cm2)) + Eventually(existingChildrenFn).ShouldNot(ContainElement(cm3)) + Eventually(existingChildrenFn).ShouldNot(ContainElement(cm4)) }) It("returns Secrets with the correct OwnerReference", func() { - Expect(existingChildren).To(ContainElement(s1)) + Eventually(existingChildrenFn).Should(ContainElement(s1)) }) It("doesn't return Secrets without OwnerReferences", func() { - Expect(existingChildren).NotTo(ContainElement(s2)) - Expect(existingChildren).NotTo(ContainElement(s3)) - Expect(existingChildren).NotTo(ContainElement(s4)) + Eventually(existingChildrenFn).ShouldNot(ContainElement(s2)) + Eventually(existingChildrenFn).ShouldNot(ContainElement(s3)) + Eventually(existingChildrenFn).ShouldNot(ContainElement(s4)) }) It("does not return duplicate children", func() { - Expect(existingChildren).To(HaveLen(2)) + Eventually(existingChildrenFn).Should(HaveLen(2)) }) }) diff --git a/pkg/core/handler_test.go b/pkg/core/handler_test.go index b59ae8bf..b7c40718 100644 --- a/pkg/core/handler_test.go +++ b/pkg/core/handler_test.go @@ -53,9 +53,15 @@ var _ = Describe("Wave controller Suite", func() { var cm1 *corev1.ConfigMap var cm2 *corev1.ConfigMap var cm3 *corev1.ConfigMap + var cm4 *corev1.ConfigMap + var cm5 *corev1.ConfigMap + var cm6 *corev1.ConfigMap var s1 *corev1.Secret var s2 *corev1.Secret var s3 *corev1.Secret + var s4 *corev1.Secret + var s5 *corev1.Secret + var s6 *corev1.Secret var modified = "modified" @@ -79,22 +85,40 @@ var _ = Describe("Wave controller Suite", func() { cm1 = utils.ExampleConfigMap1.DeepCopy() cm2 = utils.ExampleConfigMap2.DeepCopy() cm3 = utils.ExampleConfigMap3.DeepCopy() + cm4 = utils.ExampleConfigMap4.DeepCopy() + cm5 = utils.ExampleConfigMap5.DeepCopy() + cm6 = utils.ExampleConfigMap6.DeepCopy() s1 = utils.ExampleSecret1.DeepCopy() s2 = utils.ExampleSecret2.DeepCopy() s3 = utils.ExampleSecret3.DeepCopy() + s4 = utils.ExampleSecret4.DeepCopy() + s5 = utils.ExampleSecret5.DeepCopy() + s6 = utils.ExampleSecret6.DeepCopy() m.Create(cm1).Should(Succeed()) m.Create(cm2).Should(Succeed()) m.Create(cm3).Should(Succeed()) + m.Create(cm4).Should(Succeed()) + m.Create(cm5).Should(Succeed()) + m.Create(cm6).Should(Succeed()) m.Create(s1).Should(Succeed()) m.Create(s2).Should(Succeed()) m.Create(s3).Should(Succeed()) + m.Create(s4).Should(Succeed()) + m.Create(s5).Should(Succeed()) + m.Create(s6).Should(Succeed()) m.Get(cm1, timeout).Should(Succeed()) m.Get(cm2, timeout).Should(Succeed()) m.Get(cm3, timeout).Should(Succeed()) + m.Get(cm4, timeout).Should(Succeed()) + m.Get(cm5, timeout).Should(Succeed()) + m.Get(cm6, timeout).Should(Succeed()) m.Get(s1, timeout).Should(Succeed()) m.Get(s2, timeout).Should(Succeed()) m.Get(s3, timeout).Should(Succeed()) + m.Get(s4, timeout).Should(Succeed()) + m.Get(s5, timeout).Should(Succeed()) + m.Get(s6, timeout).Should(Succeed()) deployment = utils.ExampleDeployment.DeepCopy() @@ -194,7 +218,7 @@ var _ = Describe("Wave controller Suite", func() { eventMessage := func(event *corev1.Event) string { return event.Message } - hashMessage := "Configuration hash updated to bd786f47ef9b79841ddba1059752f95c4fe21906df5e2964786b4658e02758d5" + hashMessage := "Configuration hash updated to 421778c325761f51dbf7a23a20eb9c1bc516ffd4aa7362ebec03175d427d7557" Eventually(func() *corev1.EventList { events := &corev1.EventList{} m.Client.List(context.TODO(), events) diff --git a/test/utils/test_objects.go b/test/utils/test_objects.go index bef03127..61e0b1df 100644 --- a/test/utils/test_objects.go +++ b/test/utils/test_objects.go @@ -83,6 +83,84 @@ var ExampleDeployment = &appsv1.Deployment{ }, }, }, + { + Name: "projection1", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{{ + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example5", + }, + Optional: &trueValue, + }, + }}, + }, + }, + }, + { + Name: "projection2", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{{ + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example5", + }, + Optional: &trueValue, + }, + }}, + }, + }, + }, + { + Name: "projection3", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{{ + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example6", + }, + Items: []corev1.KeyToPath{ + { + Key: "example6_key1", + Path: "example6_key1.txt", + }, + { + Key: "example6_key3", + Path: "example6_key3.txt", + }, + }, + }, + }}, + }, + }, + }, + { + Name: "projection4", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{{ + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example6", + }, + Items: []corev1.KeyToPath{ + { + Key: "example6_key1", + Path: "example6_key1.txt", + }, + { + Key: "example6_key3", + Path: "example6_key3.txt", + }, + }, + }, + }}, + }, + }, + }, }, Containers: []corev1.Container{ { @@ -785,6 +863,34 @@ var ExampleConfigMap4 = &corev1.ConfigMap{ }, } +// ExampleConfigMap5 is an example ConfigMap object for use within test suites +var ExampleConfigMap5 = &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example5", + Namespace: "default", + Labels: labels, + }, + Data: map[string]string{ + "key1": "example5:key1", + "key2": "example5:key2", + "key3": "example5:key3", + }, +} + +// ExampleConfigMap6 is an example ConfigMap object for use within test suites +var ExampleConfigMap6 = &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example6", + Namespace: "default", + Labels: labels, + }, + Data: map[string]string{ + "key1": "example6:key1", + "key2": "example6:key2", + "key3": "example6:key3", + }, +} + // ExampleSecret1 is an example Secret object for use within test suites var ExampleSecret1 = &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -840,3 +946,31 @@ var ExampleSecret4 = &corev1.Secret{ "key3": "example4:key3", }, } + +// ExampleSecret5 is an example Secret object for use within test suites +var ExampleSecret5 = &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example5", + Namespace: "default", + Labels: labels, + }, + StringData: map[string]string{ + "key1": "example5:key1", + "key2": "example5:key2", + "key3": "example5:key3", + }, +} + +// ExampleSecret6 is an example Secret object for use within test suites +var ExampleSecret6 = &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "example6", + Namespace: "default", + Labels: labels, + }, + StringData: map[string]string{ + "key1": "example6:key1", + "key2": "example6:key2", + "key3": "example6:key3", + }, +}