From 50800857b6aa2ccfec7d38135f162343bae2947c Mon Sep 17 00:00:00 2001 From: Zacharias Taubert Date: Sun, 14 Nov 2021 23:27:15 +0100 Subject: [PATCH] Append to list of ownerReferences for cm and secrets If a "primary" ConfigMap or Secret already exists, keep the list of ownerReferences and append the updating Canary as ownerReference if it's not already in the list. This will prevent the GC from deleting primary ConfigMaps and Secrets used by multiple primary deployments when one is deleted. Signed-off-by: Zacharias Taubert --- pkg/canary/config_tracker.go | 75 ++++++++++++++++++++++--------- pkg/canary/config_tracker_test.go | 24 ++++++++++ 2 files changed, 77 insertions(+), 22 deletions(-) diff --git a/pkg/canary/config_tracker.go b/pkg/canary/config_tracker.go index ecd16a76c..c821312e6 100644 --- a/pkg/canary/config_tracker.go +++ b/pkg/canary/config_tracker.go @@ -299,22 +299,38 @@ func (ct *ConfigTracker) CreatePrimaryConfigs(cd *flaggerv1.Canary, refs map[str case ConfigRefMap: config, err := ct.KubeClient.CoreV1().ConfigMaps(cd.Namespace).Get(context.TODO(), ref.Name, metav1.GetOptions{}) if err != nil { - return fmt.Errorf("configmap %s.%s get query failed : %w", ref.Name, cd.Name, err) + return fmt.Errorf("configmap %s.%s get query failed : %w", ref.Name, cd.Namespace, err) } primaryName := fmt.Sprintf("%s-primary", config.GetName()) + ownerReferences := []metav1.OwnerReference{ + *metav1.NewControllerRef(cd, schema.GroupVersionKind{ + Group: flaggerv1.SchemeGroupVersion.Group, + Version: flaggerv1.SchemeGroupVersion.Version, + Kind: flaggerv1.CanaryKind, + }), + } + + oldPrimary, err := ct.KubeClient.CoreV1().ConfigMaps(cd.Namespace).Get(context.TODO(), primaryName, metav1.GetOptions{}) + if err != nil { + if !errors.IsNotFound(err) { + return fmt.Errorf("configmap %s.%s get query failed : %w", primaryName, cd.Namespace, err) + } + } else { + for _, ownerRef := range oldPrimary.OwnerReferences { + if ownerRef.Kind != flaggerv1.CanaryKind || ownerRef.Name != cd.Name { + ownerRef.Controller = new(bool) + ownerReferences = append(ownerReferences, ownerRef) + } + } + } + labels := includeLabelsByPrefix(config.Labels, includeLabelPrefix) primaryConfigMap := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: primaryName, - Namespace: cd.Namespace, - Labels: labels, - OwnerReferences: []metav1.OwnerReference{ - *metav1.NewControllerRef(cd, schema.GroupVersionKind{ - Group: flaggerv1.SchemeGroupVersion.Group, - Version: flaggerv1.SchemeGroupVersion.Version, - Kind: flaggerv1.CanaryKind, - }), - }, + Name: primaryName, + Namespace: cd.Namespace, + Labels: labels, + OwnerReferences: ownerReferences, }, Data: config.Data, } @@ -337,22 +353,37 @@ func (ct *ConfigTracker) CreatePrimaryConfigs(cd *flaggerv1.Canary, refs map[str case ConfigRefSecret: secret, err := ct.KubeClient.CoreV1().Secrets(cd.Namespace).Get(context.TODO(), ref.Name, metav1.GetOptions{}) if err != nil { - return fmt.Errorf("secret %s.%s get query failed : %w", ref.Name, cd.Name, err) + return fmt.Errorf("secret %s.%s get query failed : %w", ref.Name, cd.Namespace, err) } primaryName := fmt.Sprintf("%s-primary", secret.GetName()) + ownerReferences := []metav1.OwnerReference{ + *metav1.NewControllerRef(cd, schema.GroupVersionKind{ + Group: flaggerv1.SchemeGroupVersion.Group, + Version: flaggerv1.SchemeGroupVersion.Version, + Kind: flaggerv1.CanaryKind, + }), + } + + oldPrimary, err := ct.KubeClient.CoreV1().Secrets(cd.Namespace).Get(context.TODO(), primaryName, metav1.GetOptions{}) + if err != nil { + if !errors.IsNotFound(err) { + return fmt.Errorf("secret %s.%s get query failed : %w", primaryName, cd.Namespace, err) + } + } else { + for _, ownerRef := range oldPrimary.OwnerReferences { + if ownerRef.Kind != flaggerv1.CanaryKind || ownerRef.Name != cd.Name { + ownerRef.Controller = new(bool) + ownerReferences = append(ownerReferences, ownerRef) + } + } + } labels := includeLabelsByPrefix(secret.Labels, includeLabelPrefix) primarySecret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: primaryName, - Namespace: cd.Namespace, - Labels: labels, - OwnerReferences: []metav1.OwnerReference{ - *metav1.NewControllerRef(cd, schema.GroupVersionKind{ - Group: flaggerv1.SchemeGroupVersion.Group, - Version: flaggerv1.SchemeGroupVersion.Version, - Kind: flaggerv1.CanaryKind, - }), - }, + Name: primaryName, + Namespace: cd.Namespace, + Labels: labels, + OwnerReferences: ownerReferences, }, Type: secret.Type, Data: secret.Data, diff --git a/pkg/canary/config_tracker_test.go b/pkg/canary/config_tracker_test.go index 2134a5f69..cc2ebab42 100644 --- a/pkg/canary/config_tracker_test.go +++ b/pkg/canary/config_tracker_test.go @@ -399,3 +399,27 @@ func Test_fieldIsMandatory(t *testing.T) { assert.Equal(t, tt.expected, actual) } } + +func TestConfigTracker_ConfigOwnerMultiDeployment(t *testing.T) { + t.Run("deployment", func(t *testing.T) { + dc := deploymentConfigs{name: "podinfo", label: "name", labelValue: "podinfo"} + mocks := newDeploymentFixture(dc) + mocks.initializeCanary(t) + + dep := newDeploymentControllerTest(dc) + dep.Name = "podinfo2" + canary := newDeploymentControllerTestCanary(canaryConfigs{targetName: "podinfo2"}) + canary.Name = "podinfo2" + canary.Spec.TargetRef.Name = dep.Name + mocks.kubeClient.AppsV1().Deployments("default").Create(context.TODO(), dep, metav1.CreateOptions{}) + mocks.controller.Initialize(canary) + + configMapPrimary, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get(context.TODO(), "podinfo-config-env-primary", metav1.GetOptions{}) + require.NoError(t, err) + assert.Len(t, configMapPrimary.OwnerReferences, 2) + + secretPrimary, err := mocks.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "podinfo-secret-env-primary", metav1.GetOptions{}) + require.NoError(t, err) + assert.Len(t, secretPrimary.OwnerReferences, 2) + }) +}