From 85e71bcdde80c2363665a38367fda74abb038a07 Mon Sep 17 00:00:00 2001 From: Kyle Wuolle Date: Fri, 28 Feb 2025 15:10:56 -0800 Subject: [PATCH 1/4] If there are no services present in the cluster deployment, delete the sveltos Profile which will trigger the addon controller to remove the installed services. --- internal/controller/clusterdeployment_controller.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/controller/clusterdeployment_controller.go b/internal/controller/clusterdeployment_controller.go index 8ca32bca5..f770a00d9 100644 --- a/internal/controller/clusterdeployment_controller.go +++ b/internal/controller/clusterdeployment_controller.go @@ -602,6 +602,12 @@ func (r *ClusterDeploymentReconciler) updateServices(ctx context.Context, mc *kc return ctrl.Result{}, nil } + if len(mc.Spec.ServiceSpec.Services) == 0 { + if err = r.Client.Delete(ctx, &profile); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to delete Profile %s: %w", profileRef.String(), err) + } + } + var servicesStatus []kcm.ServiceStatus servicesStatus, servicesErr = updateServicesStatus(ctx, r.Client, profileRef, profile.Status.MatchingClusterRefs, mc.Status.Services) if servicesErr != nil { From 0c57078a38f6a141143b32066baadb94966db820 Mon Sep 17 00:00:00 2001 From: Kyle Wuolle Date: Wed, 5 Mar 2025 12:09:18 -0800 Subject: [PATCH 2/4] Add check for service length prior to profile reconciliation. Added same logic for multiservice and also added check for service length so the status is updated properly when services are removed completely --- .../clusterdeployment_controller.go | 74 ++++++++++--------- .../multiclusterservice_controller.go | 62 +++++++++------- 2 files changed, 73 insertions(+), 63 deletions(-) diff --git a/internal/controller/clusterdeployment_controller.go b/internal/controller/clusterdeployment_controller.go index f770a00d9..95593b3e0 100644 --- a/internal/controller/clusterdeployment_controller.go +++ b/internal/controller/clusterdeployment_controller.go @@ -560,36 +560,37 @@ func (r *ClusterDeploymentReconciler) updateServices(ctx context.Context, mc *kc return ctrl.Result{}, err } - if _, err = sveltos.ReconcileProfile(ctx, r.Client, mc.Namespace, mc.Name, - sveltos.ReconcileProfileOpts{ - OwnerReference: &metav1.OwnerReference{ - APIVersion: kcm.GroupVersion.String(), - Kind: kcm.ClusterDeploymentKind, - Name: mc.Name, - UID: mc.UID, - }, - LabelSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - kcm.FluxHelmChartNamespaceKey: mc.Namespace, - kcm.FluxHelmChartNameKey: mc.Name, + if len(mc.Spec.ServiceSpec.Services) > 0 { + if _, err = sveltos.ReconcileProfile(ctx, r.Client, mc.Namespace, mc.Name, + sveltos.ReconcileProfileOpts{ + OwnerReference: &metav1.OwnerReference{ + APIVersion: kcm.GroupVersion.String(), + Kind: kcm.ClusterDeploymentKind, + Name: mc.Name, + UID: mc.UID, }, - }, - HelmChartOpts: opts, - Priority: mc.Spec.ServiceSpec.Priority, - StopOnConflict: mc.Spec.ServiceSpec.StopOnConflict, - Reload: mc.Spec.ServiceSpec.Reload, - TemplateResourceRefs: append( - getProjectTemplateResourceRefs(mc, cred), mc.Spec.ServiceSpec.TemplateResourceRefs..., - ), - PolicyRefs: getProjectPolicyRefs(mc, cred), - SyncMode: mc.Spec.ServiceSpec.SyncMode, - DriftIgnore: mc.Spec.ServiceSpec.DriftIgnore, - DriftExclusions: mc.Spec.ServiceSpec.DriftExclusions, - ContinueOnError: mc.Spec.ServiceSpec.ContinueOnError, - }); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to reconcile Profile: %w", err) + LabelSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + kcm.FluxHelmChartNamespaceKey: mc.Namespace, + kcm.FluxHelmChartNameKey: mc.Name, + }, + }, + HelmChartOpts: opts, + Priority: mc.Spec.ServiceSpec.Priority, + StopOnConflict: mc.Spec.ServiceSpec.StopOnConflict, + Reload: mc.Spec.ServiceSpec.Reload, + TemplateResourceRefs: append( + getProjectTemplateResourceRefs(mc, cred), mc.Spec.ServiceSpec.TemplateResourceRefs..., + ), + PolicyRefs: getProjectPolicyRefs(mc, cred), + SyncMode: mc.Spec.ServiceSpec.SyncMode, + DriftIgnore: mc.Spec.ServiceSpec.DriftIgnore, + DriftExclusions: mc.Spec.ServiceSpec.DriftExclusions, + ContinueOnError: mc.Spec.ServiceSpec.ContinueOnError, + }); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to reconcile Profile: %w", err) + } } - // NOTE: // We are returning nil in the return statements whenever servicesErr != nil // because we don't want the error content in servicesErr to be assigned to err. @@ -606,16 +607,17 @@ func (r *ClusterDeploymentReconciler) updateServices(ctx context.Context, mc *kc if err = r.Client.Delete(ctx, &profile); err != nil { return ctrl.Result{}, fmt.Errorf("failed to delete Profile %s: %w", profileRef.String(), err) } + mc.Status.Services = nil + } else { + var servicesStatus []kcm.ServiceStatus + servicesStatus, servicesErr = updateServicesStatus(ctx, r.Client, profileRef, profile.Status.MatchingClusterRefs, mc.Status.Services) + if servicesErr != nil { + return ctrl.Result{}, nil + } + mc.Status.Services = servicesStatus + l.Info("Successfully updated status of services") } - var servicesStatus []kcm.ServiceStatus - servicesStatus, servicesErr = updateServicesStatus(ctx, r.Client, profileRef, profile.Status.MatchingClusterRefs, mc.Status.Services) - if servicesErr != nil { - return ctrl.Result{}, nil - } - mc.Status.Services = servicesStatus - l.Info("Successfully updated status of services") - return ctrl.Result{}, nil } diff --git a/internal/controller/multiclusterservice_controller.go b/internal/controller/multiclusterservice_controller.go index 5caa4624d..d8a14e7d6 100644 --- a/internal/controller/multiclusterservice_controller.go +++ b/internal/controller/multiclusterservice_controller.go @@ -138,28 +138,29 @@ func (r *MultiClusterServiceReconciler) reconcileUpdate(ctx context.Context, mcs return ctrl.Result{}, err } - if _, err = sveltos.ReconcileClusterProfile(ctx, r.Client, mcs.Name, - sveltos.ReconcileProfileOpts{ - OwnerReference: &metav1.OwnerReference{ - APIVersion: kcm.GroupVersion.String(), - Kind: kcm.MultiClusterServiceKind, - Name: mcs.Name, - UID: mcs.UID, - }, - LabelSelector: mcs.Spec.ClusterSelector, - HelmChartOpts: opts, - Priority: mcs.Spec.ServiceSpec.Priority, - StopOnConflict: mcs.Spec.ServiceSpec.StopOnConflict, - Reload: mcs.Spec.ServiceSpec.Reload, - TemplateResourceRefs: mcs.Spec.ServiceSpec.TemplateResourceRefs, - SyncMode: mcs.Spec.ServiceSpec.SyncMode, - DriftIgnore: mcs.Spec.ServiceSpec.DriftIgnore, - DriftExclusions: mcs.Spec.ServiceSpec.DriftExclusions, - ContinueOnError: mcs.Spec.ServiceSpec.ContinueOnError, - }); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to reconcile ClusterProfile: %w", err) + if len(mcs.Spec.ServiceSpec.Services) > 0 { + if _, err = sveltos.ReconcileClusterProfile(ctx, r.Client, mcs.Name, + sveltos.ReconcileProfileOpts{ + OwnerReference: &metav1.OwnerReference{ + APIVersion: kcm.GroupVersion.String(), + Kind: kcm.MultiClusterServiceKind, + Name: mcs.Name, + UID: mcs.UID, + }, + LabelSelector: mcs.Spec.ClusterSelector, + HelmChartOpts: opts, + Priority: mcs.Spec.ServiceSpec.Priority, + StopOnConflict: mcs.Spec.ServiceSpec.StopOnConflict, + Reload: mcs.Spec.ServiceSpec.Reload, + TemplateResourceRefs: mcs.Spec.ServiceSpec.TemplateResourceRefs, + SyncMode: mcs.Spec.ServiceSpec.SyncMode, + DriftIgnore: mcs.Spec.ServiceSpec.DriftIgnore, + DriftExclusions: mcs.Spec.ServiceSpec.DriftExclusions, + ContinueOnError: mcs.Spec.ServiceSpec.ContinueOnError, + }); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to reconcile ClusterProfile: %w", err) + } } - // NOTE: // We are returning nil in the return statements whenever servicesErr != nil // because we don't want the error content in servicesErr to be assigned to err. @@ -172,13 +173,20 @@ func (r *MultiClusterServiceReconciler) reconcileUpdate(ctx context.Context, mcs return ctrl.Result{}, nil } - var servicesStatus []kcm.ServiceStatus - servicesStatus, servicesErr = updateServicesStatus(ctx, r.Client, profileRef, profile.Status.MatchingClusterRefs, mcs.Status.Services) - if servicesErr != nil { - return ctrl.Result{}, nil - } - mcs.Status.Services = servicesStatus + if len(mcs.Spec.ServiceSpec.Services) == 0 { + if err = r.Client.Delete(ctx, &profile); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to delete Profile %s: %w", profileRef.String(), err) + } + mcs.Status.Services = nil + } else { + var servicesStatus []kcm.ServiceStatus + servicesStatus, servicesErr = updateServicesStatus(ctx, r.Client, profileRef, profile.Status.MatchingClusterRefs, mcs.Status.Services) + if servicesErr != nil { + return ctrl.Result{}, nil + } + mcs.Status.Services = servicesStatus + } return ctrl.Result{}, nil } From 18595181e060030674710b0afb9fc0b9164d6b3e Mon Sep 17 00:00:00 2001 From: Kyle Wuolle Date: Wed, 5 Mar 2025 14:32:45 -0800 Subject: [PATCH 3/4] Remove the deletion of the sveltos profile --- .../clusterdeployment_controller.go | 60 +++++++++---------- .../multiclusterservice_controller.go | 46 +++++++------- 2 files changed, 49 insertions(+), 57 deletions(-) diff --git a/internal/controller/clusterdeployment_controller.go b/internal/controller/clusterdeployment_controller.go index 95593b3e0..4c5aea095 100644 --- a/internal/controller/clusterdeployment_controller.go +++ b/internal/controller/clusterdeployment_controller.go @@ -560,37 +560,36 @@ func (r *ClusterDeploymentReconciler) updateServices(ctx context.Context, mc *kc return ctrl.Result{}, err } - if len(mc.Spec.ServiceSpec.Services) > 0 { - if _, err = sveltos.ReconcileProfile(ctx, r.Client, mc.Namespace, mc.Name, - sveltos.ReconcileProfileOpts{ - OwnerReference: &metav1.OwnerReference{ - APIVersion: kcm.GroupVersion.String(), - Kind: kcm.ClusterDeploymentKind, - Name: mc.Name, - UID: mc.UID, - }, - LabelSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - kcm.FluxHelmChartNamespaceKey: mc.Namespace, - kcm.FluxHelmChartNameKey: mc.Name, - }, + if _, err = sveltos.ReconcileProfile(ctx, r.Client, mc.Namespace, mc.Name, + sveltos.ReconcileProfileOpts{ + OwnerReference: &metav1.OwnerReference{ + APIVersion: kcm.GroupVersion.String(), + Kind: kcm.ClusterDeploymentKind, + Name: mc.Name, + UID: mc.UID, + }, + LabelSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + kcm.FluxHelmChartNamespaceKey: mc.Namespace, + kcm.FluxHelmChartNameKey: mc.Name, }, - HelmChartOpts: opts, - Priority: mc.Spec.ServiceSpec.Priority, - StopOnConflict: mc.Spec.ServiceSpec.StopOnConflict, - Reload: mc.Spec.ServiceSpec.Reload, - TemplateResourceRefs: append( - getProjectTemplateResourceRefs(mc, cred), mc.Spec.ServiceSpec.TemplateResourceRefs..., - ), - PolicyRefs: getProjectPolicyRefs(mc, cred), - SyncMode: mc.Spec.ServiceSpec.SyncMode, - DriftIgnore: mc.Spec.ServiceSpec.DriftIgnore, - DriftExclusions: mc.Spec.ServiceSpec.DriftExclusions, - ContinueOnError: mc.Spec.ServiceSpec.ContinueOnError, - }); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to reconcile Profile: %w", err) - } + }, + HelmChartOpts: opts, + Priority: mc.Spec.ServiceSpec.Priority, + StopOnConflict: mc.Spec.ServiceSpec.StopOnConflict, + Reload: mc.Spec.ServiceSpec.Reload, + TemplateResourceRefs: append( + getProjectTemplateResourceRefs(mc, cred), mc.Spec.ServiceSpec.TemplateResourceRefs..., + ), + PolicyRefs: getProjectPolicyRefs(mc, cred), + SyncMode: mc.Spec.ServiceSpec.SyncMode, + DriftIgnore: mc.Spec.ServiceSpec.DriftIgnore, + DriftExclusions: mc.Spec.ServiceSpec.DriftExclusions, + ContinueOnError: mc.Spec.ServiceSpec.ContinueOnError, + }); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to reconcile Profile: %w", err) } + // NOTE: // We are returning nil in the return statements whenever servicesErr != nil // because we don't want the error content in servicesErr to be assigned to err. @@ -604,9 +603,6 @@ func (r *ClusterDeploymentReconciler) updateServices(ctx context.Context, mc *kc } if len(mc.Spec.ServiceSpec.Services) == 0 { - if err = r.Client.Delete(ctx, &profile); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to delete Profile %s: %w", profileRef.String(), err) - } mc.Status.Services = nil } else { var servicesStatus []kcm.ServiceStatus diff --git a/internal/controller/multiclusterservice_controller.go b/internal/controller/multiclusterservice_controller.go index d8a14e7d6..fa809041a 100644 --- a/internal/controller/multiclusterservice_controller.go +++ b/internal/controller/multiclusterservice_controller.go @@ -138,29 +138,28 @@ func (r *MultiClusterServiceReconciler) reconcileUpdate(ctx context.Context, mcs return ctrl.Result{}, err } - if len(mcs.Spec.ServiceSpec.Services) > 0 { - if _, err = sveltos.ReconcileClusterProfile(ctx, r.Client, mcs.Name, - sveltos.ReconcileProfileOpts{ - OwnerReference: &metav1.OwnerReference{ - APIVersion: kcm.GroupVersion.String(), - Kind: kcm.MultiClusterServiceKind, - Name: mcs.Name, - UID: mcs.UID, - }, - LabelSelector: mcs.Spec.ClusterSelector, - HelmChartOpts: opts, - Priority: mcs.Spec.ServiceSpec.Priority, - StopOnConflict: mcs.Spec.ServiceSpec.StopOnConflict, - Reload: mcs.Spec.ServiceSpec.Reload, - TemplateResourceRefs: mcs.Spec.ServiceSpec.TemplateResourceRefs, - SyncMode: mcs.Spec.ServiceSpec.SyncMode, - DriftIgnore: mcs.Spec.ServiceSpec.DriftIgnore, - DriftExclusions: mcs.Spec.ServiceSpec.DriftExclusions, - ContinueOnError: mcs.Spec.ServiceSpec.ContinueOnError, - }); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to reconcile ClusterProfile: %w", err) - } + if _, err = sveltos.ReconcileClusterProfile(ctx, r.Client, mcs.Name, + sveltos.ReconcileProfileOpts{ + OwnerReference: &metav1.OwnerReference{ + APIVersion: kcm.GroupVersion.String(), + Kind: kcm.MultiClusterServiceKind, + Name: mcs.Name, + UID: mcs.UID, + }, + LabelSelector: mcs.Spec.ClusterSelector, + HelmChartOpts: opts, + Priority: mcs.Spec.ServiceSpec.Priority, + StopOnConflict: mcs.Spec.ServiceSpec.StopOnConflict, + Reload: mcs.Spec.ServiceSpec.Reload, + TemplateResourceRefs: mcs.Spec.ServiceSpec.TemplateResourceRefs, + SyncMode: mcs.Spec.ServiceSpec.SyncMode, + DriftIgnore: mcs.Spec.ServiceSpec.DriftIgnore, + DriftExclusions: mcs.Spec.ServiceSpec.DriftExclusions, + ContinueOnError: mcs.Spec.ServiceSpec.ContinueOnError, + }); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to reconcile ClusterProfile: %w", err) } + // NOTE: // We are returning nil in the return statements whenever servicesErr != nil // because we don't want the error content in servicesErr to be assigned to err. @@ -174,9 +173,6 @@ func (r *MultiClusterServiceReconciler) reconcileUpdate(ctx context.Context, mcs } if len(mcs.Spec.ServiceSpec.Services) == 0 { - if err = r.Client.Delete(ctx, &profile); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to delete Profile %s: %w", profileRef.String(), err) - } mcs.Status.Services = nil } else { From 0ac589e607b5a2cc6ae66bf4afd37b61955ef8cf Mon Sep 17 00:00:00 2001 From: Kyle Wuolle Date: Thu, 6 Mar 2025 09:43:54 -0800 Subject: [PATCH 4/4] fix linting error --- internal/controller/multiclusterservice_controller.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/controller/multiclusterservice_controller.go b/internal/controller/multiclusterservice_controller.go index fa809041a..76ebeded8 100644 --- a/internal/controller/multiclusterservice_controller.go +++ b/internal/controller/multiclusterservice_controller.go @@ -175,7 +175,6 @@ func (r *MultiClusterServiceReconciler) reconcileUpdate(ctx context.Context, mcs if len(mcs.Spec.ServiceSpec.Services) == 0 { mcs.Status.Services = nil } else { - var servicesStatus []kcm.ServiceStatus servicesStatus, servicesErr = updateServicesStatus(ctx, r.Client, profileRef, profile.Status.MatchingClusterRefs, mcs.Status.Services) if servicesErr != nil {