From 17557dc2066abf3ca293a11be87e6ff1406958b1 Mon Sep 17 00:00:00 2001 From: kazukousen Date: Mon, 24 May 2021 14:09:04 +0900 Subject: [PATCH 1/2] fixed ConfigTracker to be able to scan envFrom in init-containers Signed-off-by: kazukousen --- pkg/canary/config_tracker.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/canary/config_tracker.go b/pkg/canary/config_tracker.go index 77737d45..3bdf4aec 100644 --- a/pkg/canary/config_tracker.go +++ b/pkg/canary/config_tracker.go @@ -135,6 +135,7 @@ func (ct *ConfigTracker) GetTargetConfigs(cd *flaggerv1.Canary) (map[string]Conf } vs = targetDep.Spec.Template.Spec.Volumes cs = targetDep.Spec.Template.Spec.Containers + cs = append(cs, targetDep.Spec.Template.Spec.InitContainers...) case "DaemonSet": targetDae, err := ct.KubeClient.AppsV1().DaemonSets(cd.Namespace).Get(context.TODO(), targetName, metav1.GetOptions{}) if err != nil { @@ -142,6 +143,7 @@ func (ct *ConfigTracker) GetTargetConfigs(cd *flaggerv1.Canary) (map[string]Conf } vs = targetDae.Spec.Template.Spec.Volumes cs = targetDae.Spec.Template.Spec.Containers + cs = append(cs, targetDae.Spec.Template.Spec.InitContainers...) default: return nil, fmt.Errorf("TargetRef.Kind invalid: %s", cd.Spec.TargetRef.Kind) } From b26b49fac24e337f6e34d8af8a60d6053c56895e Mon Sep 17 00:00:00 2001 From: kazukousen Date: Tue, 25 May 2021 23:21:34 +0900 Subject: [PATCH 2/2] add unit tests Signed-off-by: kazukousen --- pkg/canary/config_tracker_test.go | 40 ++++++++++ pkg/canary/daemonset_fixture_test.go | 102 +++++++++++++++++++++++++ pkg/canary/deployment_fixture_test.go | 104 +++++++++++++++++++++++++- 3 files changed, 245 insertions(+), 1 deletion(-) diff --git a/pkg/canary/config_tracker_test.go b/pkg/canary/config_tracker_test.go index f229a5af..41c7ce03 100644 --- a/pkg/canary/config_tracker_test.go +++ b/pkg/canary/config_tracker_test.go @@ -57,6 +57,16 @@ func TestConfigTracker_ConfigMaps(t *testing.T) { configPrimaryVolName := depPrimary.Spec.Template.Spec.Volumes[0].VolumeSource.ConfigMap.LocalObjectReference.Name assert.Equal(t, "podinfo-config-vol-primary", configPrimaryVolName) + configPrimaryInit, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get(context.TODO(), "podinfo-config-init-env-primary", metav1.GetOptions{}) + if assert.NoError(t, err) { + assert.Equal(t, configMap.Data["color"], configPrimaryInit.Data["color"]) + } + + configPrimaryInitEnv, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get(context.TODO(), "podinfo-config-init-all-env-primary", metav1.GetOptions{}) + if assert.NoError(t, err) { + assert.Equal(t, configMap.Data["color"], configPrimaryInitEnv.Data["color"]) + } + configPrimary, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get(context.TODO(), "podinfo-config-env-primary", metav1.GetOptions{}) if assert.NoError(t, err) { assert.Equal(t, configMap.Data["color"], configPrimary.Data["color"]) @@ -123,6 +133,16 @@ func TestConfigTracker_ConfigMaps(t *testing.T) { configPrimaryVolName := daePrimary.Spec.Template.Spec.Volumes[0].VolumeSource.ConfigMap.LocalObjectReference.Name assert.Equal(t, "podinfo-config-vol-primary", configPrimaryVolName) + configPrimaryInit, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get(context.TODO(), "podinfo-config-init-env-primary", metav1.GetOptions{}) + if assert.NoError(t, err) { + assert.Equal(t, configMap.Data["color"], configPrimaryInit.Data["color"]) + } + + configPrimaryInitEnv, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get(context.TODO(), "podinfo-config-init-all-env-primary", metav1.GetOptions{}) + if assert.NoError(t, err) { + assert.Equal(t, configMap.Data["color"], configPrimaryInitEnv.Data["color"]) + } + configPrimary, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get(context.TODO(), "podinfo-config-env-primary", metav1.GetOptions{}) if assert.NoError(t, err) { assert.Equal(t, configMap.Data["color"], configPrimary.Data["color"]) @@ -190,6 +210,16 @@ func TestConfigTracker_Secrets(t *testing.T) { depPrimary.Spec.Template.Spec.Volumes[1].VolumeSource.Secret.SecretName) } + secretPrimaryInit, err := mocks.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "podinfo-secret-init-env-primary", metav1.GetOptions{}) + if assert.NoError(t, err) { + assert.Equal(t, string(secret.Data["apiKey"]), string(secretPrimaryInit.Data["apiKey"])) + } + + secretPrimaryInitEnv, err := mocks.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "podinfo-secret-init-all-env-primary", metav1.GetOptions{}) + if assert.NoError(t, err) { + assert.Equal(t, string(secret.Data["apiKey"]), string(secretPrimaryInitEnv.Data["apiKey"])) + } + secretPrimary, err := mocks.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "podinfo-secret-env-primary", metav1.GetOptions{}) if assert.NoError(t, err) { assert.Equal(t, string(secret.Data["apiKey"]), string(secretPrimary.Data["apiKey"])) @@ -255,6 +285,16 @@ func TestConfigTracker_Secrets(t *testing.T) { daePrimary.Spec.Template.Spec.Volumes[1].VolumeSource.Secret.SecretName) } + secretPrimaryInit, err := mocks.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "podinfo-secret-init-env-primary", metav1.GetOptions{}) + if assert.NoError(t, err) { + assert.Equal(t, string(secret.Data["apiKey"]), string(secretPrimaryInit.Data["apiKey"])) + } + + secretPrimaryInitEnv, err := mocks.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "podinfo-secret-init-all-env-primary", metav1.GetOptions{}) + if assert.NoError(t, err) { + assert.Equal(t, string(secret.Data["apiKey"]), string(secretPrimaryInitEnv.Data["apiKey"])) + } + secretPrimary, err := mocks.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "podinfo-secret-env-primary", metav1.GetOptions{}) if assert.NoError(t, err) { assert.Equal(t, string(secret.Data["apiKey"]), string(secretPrimary.Data["apiKey"])) diff --git a/pkg/canary/daemonset_fixture_test.go b/pkg/canary/daemonset_fixture_test.go index f309172a..7d3544b7 100644 --- a/pkg/canary/daemonset_fixture_test.go +++ b/pkg/canary/daemonset_fixture_test.go @@ -59,12 +59,16 @@ func newDaemonSetFixture(dc daemonsetConfigs) daemonSetControllerFixture { newDaemonSetControllerTestConfigProjected(), newDaemonSetControllerTestConfigMapTrackerEnabled(), newDaemonSetControllerTestConfigMapTrackerDisabled(), + newDaemonSetControllerTestConfigMapInit(), + newDaemonSetControllerTestConfigMapInitEnv(), newDaemonSetControllerTestSecret(), newDaemonSetControllerTestSecretEnv(), newDaemonSetControllerTestSecretVol(), newDaemonSetControllerTestSecretProjected(), newDaemonSetControllerTestSecretTrackerEnabled(), newDaemonSetControllerTestSecretTrackerDisabled(), + newDaemonSetControllerTestSecretInit(), + newDaemonSetControllerTestSecretInitEnv(), ) logger, _ := logger.NewLogger("debug") @@ -143,6 +147,32 @@ func newDaemonSetControllerTestConfigMapEnv() *corev1.ConfigMap { } } +func newDaemonSetControllerTestConfigMapInit() *corev1.ConfigMap { + return &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "podinfo-config-init-env", + }, + Data: map[string]string{ + "color": "red", + }, + } +} + +func newDaemonSetControllerTestConfigMapInitEnv() *corev1.ConfigMap { + return &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "podinfo-config-init-all-env", + }, + Data: map[string]string{ + "color": "red", + }, + } +} + func newDaemonSetControllerTestConfigMapVol() *corev1.ConfigMap { return &corev1.ConfigMap{ TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, @@ -286,6 +316,34 @@ func newDaemonSetControllerTestSecretTrackerDisabled() *corev1.Secret { } } +func newDaemonSetControllerTestSecretInit() *corev1.Secret { + return &corev1.Secret{ + TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "podinfo-secret-init-env", + }, + Type: corev1.SecretTypeOpaque, + Data: map[string][]byte{ + "apiKey": []byte("test"), + }, + } +} + +func newDaemonSetControllerTestSecretInitEnv() *corev1.Secret { + return &corev1.Secret{ + TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "podinfo-secret-init-all-env", + }, + Type: corev1.SecretTypeOpaque, + Data: map[string][]byte{ + "apiKey": []byte("test"), + }, + } +} + func newDaemonSetControllerTestCanary(dc daemonsetConfigs) *flaggerv1.Canary { cd := &flaggerv1.Canary{ TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()}, @@ -324,6 +382,50 @@ func newDaemonSetControllerTestPodInfo(dc daemonsetConfigs) *appsv1.DaemonSet { }, }, Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Env: []corev1.EnvVar{ + { + Name: "PODINFO_UI_COLOR", + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "podinfo-config-init-env", + }, + Key: "color", + }, + }, + }, + { + Name: "API_KEY", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "podinfo-secret-init-env", + }, + Key: "apiKey", + }, + }, + }, + }, + EnvFrom: []corev1.EnvFromSource{ + { + ConfigMapRef: &corev1.ConfigMapEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "podinfo-config-init-all-env", + }, + }, + }, + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "podinfo-secret-init-all-env", + }, + }, + }, + }, + }, + }, Containers: []corev1.Container{ { Name: "podinfo", diff --git a/pkg/canary/deployment_fixture_test.go b/pkg/canary/deployment_fixture_test.go index 561d15fe..45c317c5 100644 --- a/pkg/canary/deployment_fixture_test.go +++ b/pkg/canary/deployment_fixture_test.go @@ -98,12 +98,16 @@ func newCustomizableFixture(dc deploymentConfigs) (deploymentControllerFixture, newDeploymentControllerTestConfigProjected(), newDeploymentControllerTestConfigMapTrackerEnabled(), newDeploymentControllerTestConfigMapTrackerDisabled(), + newDeploymentControllerTestConfigMapInit(), + newDeploymentControllerTestConfigMapInitEnv(), newDeploymentControllerTestSecret(), newDeploymentControllerTestSecretEnv(), newDeploymentControllerTestSecretVol(), newDeploymentControllerTestSecretProjected(), newDeploymentControllerTestSecretTrackerEnabled(), newDeploymentControllerTestSecretTrackerDisabled(), + newDeploymentControllerTestSecretInit(), + newDeploymentControllerTestSecretInitEnv(), ) logger, _ := logger.NewLogger("debug") @@ -156,6 +160,32 @@ func newDeploymentControllerTestConfigMapV2() *corev1.ConfigMap { } } +func newDeploymentControllerTestConfigMapInit() *corev1.ConfigMap { + return &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "podinfo-config-init-env", + }, + Data: map[string]string{ + "color": "red", + }, + } +} + +func newDeploymentControllerTestConfigMapInitEnv() *corev1.ConfigMap { + return &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "podinfo-config-init-all-env", + }, + Data: map[string]string{ + "color": "red", + }, + } +} + func newDeploymentControllerTestConfigProjected() *corev1.ConfigMap { return &corev1.ConfigMap{ TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, @@ -325,6 +355,34 @@ func newDeploymentControllerTestSecretTrackerDisabled() *corev1.Secret { } } +func newDeploymentControllerTestSecretInit() *corev1.Secret { + return &corev1.Secret{ + TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "podinfo-secret-init-env", + }, + Type: corev1.SecretTypeOpaque, + Data: map[string][]byte{ + "apiKey": []byte("test"), + }, + } +} + +func newDeploymentControllerTestSecretInitEnv() *corev1.Secret { + return &corev1.Secret{ + TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()}, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "podinfo-secret-init-all-env", + }, + Type: corev1.SecretTypeOpaque, + Data: map[string][]byte{ + "apiKey": []byte("test"), + }, + } +} + func newDeploymentControllerTestCanary(cc canaryConfigs) *flaggerv1.Canary { cd := &flaggerv1.Canary{ TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()}, @@ -355,7 +413,7 @@ func newDeploymentControllerTestCanary(cc canaryConfigs) *flaggerv1.Canary { } func newDeploymentControllerTest(dc deploymentConfigs) *appsv1.Deployment { - var optional bool = false + optional := false d := &appsv1.Deployment{ TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()}, ObjectMeta: metav1.ObjectMeta{ @@ -375,6 +433,50 @@ func newDeploymentControllerTest(dc deploymentConfigs) *appsv1.Deployment { }, }, Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Env: []corev1.EnvVar{ + { + Name: "PODINFO_UI_COLOR", + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "podinfo-config-init-env", + }, + Key: "color", + }, + }, + }, + { + Name: "API_KEY", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "podinfo-secret-init-env", + }, + Key: "apiKey", + }, + }, + }, + }, + EnvFrom: []corev1.EnvFromSource{ + { + ConfigMapRef: &corev1.ConfigMapEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "podinfo-config-init-all-env", + }, + }, + }, + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "podinfo-secret-init-all-env", + }, + }, + }, + }, + }, + }, Containers: []corev1.Container{ { Name: "podinfo",