From 105bdf129a141e543f2279ffc25d386c5e514274 Mon Sep 17 00:00:00 2001 From: Atanas Dinov Date: Fri, 19 Jul 2024 15:37:59 +0300 Subject: [PATCH 1/2] Support control plane only clusters Signed-off-by: Atanas Dinov --- internal/controller/reconcile_kubernetes.go | 43 +++++++++++-------- internal/controller/upgradeplan_controller.go | 10 +++++ internal/upgrade/base.go | 2 +- internal/upgrade/kubernetes.go | 6 +-- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/internal/controller/reconcile_kubernetes.go b/internal/controller/reconcile_kubernetes.go index 613f274..da0596e 100644 --- a/internal/controller/reconcile_kubernetes.go +++ b/internal/controller/reconcile_kubernetes.go @@ -8,7 +8,6 @@ import ( "github.com/suse-edge/upgrade-controller/internal/upgrade" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" ctrl "sigs.k8s.io/controller-runtime" @@ -25,15 +24,6 @@ func (r *UpgradePlanReconciler) reconcileKubernetes(ctx context.Context, upgrade return r.createPlan(ctx, upgradePlan, controlPlanePlan) } - workerPlan := upgrade.KubernetesWorkerPlan(kubernetesVersion) - if err := r.Get(ctx, client.ObjectKeyFromObject(workerPlan), workerPlan); err != nil { - if !errors.IsNotFound(err) { - return ctrl.Result{}, err - } - - return r.createPlan(ctx, upgradePlan, workerPlan) - } - nodeList := &corev1.NodeList{} if err := r.List(ctx, nodeList); err != nil { return ctrl.Result{}, fmt.Errorf("listing nodes: %w", err) @@ -45,10 +35,20 @@ func (r *UpgradePlanReconciler) reconcileKubernetes(ctx context.Context, upgrade } if !isKubernetesUpgraded(nodeList, selector, kubernetesVersion) { - condition := metav1.Condition{Type: lifecyclev1alpha1.KubernetesUpgradedCondition, Status: metav1.ConditionFalse, Reason: lifecyclev1alpha1.UpgradeInProgress, Message: "Control plane nodes are being upgraded"} - meta.SetStatusCondition(&upgradePlan.Status.Conditions, condition) - + setInProgressCondition(upgradePlan, lifecyclev1alpha1.KubernetesUpgradedCondition, "Control plane nodes are being upgraded") return ctrl.Result{}, nil + } else if controlPlaneOnlyCluster(nodeList) { + setSuccessfulCondition(upgradePlan, lifecyclev1alpha1.KubernetesUpgradedCondition, "All cluster nodes are upgraded") + return ctrl.Result{Requeue: true}, nil + } + + workerPlan := upgrade.KubernetesWorkerPlan(kubernetesVersion) + if err = r.Get(ctx, client.ObjectKeyFromObject(workerPlan), workerPlan); err != nil { + if !errors.IsNotFound(err) { + return ctrl.Result{}, err + } + + return r.createPlan(ctx, upgradePlan, workerPlan) } selector, err = metav1.LabelSelectorAsSelector(workerPlan.Spec.NodeSelector) @@ -57,14 +57,11 @@ func (r *UpgradePlanReconciler) reconcileKubernetes(ctx context.Context, upgrade } if !isKubernetesUpgraded(nodeList, selector, kubernetesVersion) { - condition := metav1.Condition{Type: lifecyclev1alpha1.KubernetesUpgradedCondition, Status: metav1.ConditionFalse, Reason: lifecyclev1alpha1.UpgradeInProgress, Message: "Worker nodes are being upgraded"} - meta.SetStatusCondition(&upgradePlan.Status.Conditions, condition) + setInProgressCondition(upgradePlan, lifecyclev1alpha1.KubernetesUpgradedCondition, "Worker nodes are being upgraded") return ctrl.Result{}, nil } - condition := metav1.Condition{Type: lifecyclev1alpha1.KubernetesUpgradedCondition, Status: metav1.ConditionTrue, Reason: lifecyclev1alpha1.UpgradeSucceeded, Message: "All cluster nodes are upgraded"} - meta.SetStatusCondition(&upgradePlan.Status.Conditions, condition) - + setSuccessfulCondition(upgradePlan, lifecyclev1alpha1.KubernetesUpgradedCondition, "All cluster nodes are upgraded") return ctrl.Result{Requeue: true}, nil } @@ -93,3 +90,13 @@ func isKubernetesUpgraded(nodeList *corev1.NodeList, selector labels.Selector, k return true } + +func controlPlaneOnlyCluster(nodeList *corev1.NodeList) bool { + for _, node := range nodeList.Items { + if node.Labels[upgrade.ControlPlaneLabel] != "true" { + return false + } + } + + return true +} diff --git a/internal/controller/upgradeplan_controller.go b/internal/controller/upgradeplan_controller.go index 7c4b5c6..123cff4 100644 --- a/internal/controller/upgradeplan_controller.go +++ b/internal/controller/upgradeplan_controller.go @@ -117,6 +117,16 @@ func (r *UpgradePlanReconciler) createPlan(ctx context.Context, upgradePlan *lif return ctrl.Result{Requeue: true}, nil } +func setInProgressCondition(plan *lifecyclev1alpha1.UpgradePlan, conditionType, message string) { + condition := metav1.Condition{Type: conditionType, Status: metav1.ConditionFalse, Reason: lifecyclev1alpha1.UpgradeInProgress, Message: message} + meta.SetStatusCondition(&plan.Status.Conditions, condition) +} + +func setSuccessfulCondition(plan *lifecyclev1alpha1.UpgradePlan, conditionType, message string) { + condition := metav1.Condition{Type: conditionType, Status: metav1.ConditionTrue, Reason: lifecyclev1alpha1.UpgradeSucceeded, Message: message} + meta.SetStatusCondition(&plan.Status.Conditions, condition) +} + // SetupWithManager sets up the controller with the Manager. func (r *UpgradePlanReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/internal/upgrade/base.go b/internal/upgrade/base.go index d709017..321cee0 100644 --- a/internal/upgrade/base.go +++ b/internal/upgrade/base.go @@ -8,7 +8,7 @@ import ( const ( upgradeNamespace = "cattle-system" - controlPlaneLabel = "node-role.kubernetes.io/control-plane" + ControlPlaneLabel = "node-role.kubernetes.io/control-plane" ) func baseUpgradePlan(name string) *upgradecattlev1.Plan { diff --git a/internal/upgrade/kubernetes.go b/internal/upgrade/kubernetes.go index 0759875..fc9315f 100644 --- a/internal/upgrade/kubernetes.go +++ b/internal/upgrade/kubernetes.go @@ -30,7 +30,7 @@ func KubernetesControlPlanePlan(version string) *upgradecattlev1.Plan { controlPlanePlan.Spec.NodeSelector = &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ { - Key: controlPlaneLabel, + Key: ControlPlaneLabel, Operator: "In", Values: []string{ "true", @@ -52,7 +52,7 @@ func KubernetesControlPlanePlan(version string) *upgradecattlev1.Plan { Effect: "NoExecute", }, { - Key: controlPlaneLabel, + Key: ControlPlaneLabel, Operator: "Equal", Value: "", Effect: "NoSchedule", @@ -80,7 +80,7 @@ func KubernetesWorkerPlan(version string) *upgradecattlev1.Plan { workerPlan.Spec.NodeSelector = &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ { - Key: controlPlaneLabel, + Key: ControlPlaneLabel, Operator: "NotIn", Values: []string{ "true", From f4ec8734f5011cb92dff9f0fc82183192273fa79 Mon Sep 17 00:00:00 2001 From: Atanas Dinov Date: Mon, 22 Jul 2024 10:44:26 +0300 Subject: [PATCH 2/2] Drop unnecessary reconciliations Signed-off-by: Atanas Dinov --- internal/controller/reconcile_kubernetes.go | 4 ++-- internal/controller/upgradeplan_controller.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/controller/reconcile_kubernetes.go b/internal/controller/reconcile_kubernetes.go index da0596e..0629d80 100644 --- a/internal/controller/reconcile_kubernetes.go +++ b/internal/controller/reconcile_kubernetes.go @@ -21,7 +21,7 @@ func (r *UpgradePlanReconciler) reconcileKubernetes(ctx context.Context, upgrade return ctrl.Result{}, err } - return r.createPlan(ctx, upgradePlan, controlPlanePlan) + return ctrl.Result{}, r.createPlan(ctx, upgradePlan, controlPlanePlan) } nodeList := &corev1.NodeList{} @@ -48,7 +48,7 @@ func (r *UpgradePlanReconciler) reconcileKubernetes(ctx context.Context, upgrade return ctrl.Result{}, err } - return r.createPlan(ctx, upgradePlan, workerPlan) + return ctrl.Result{}, r.createPlan(ctx, upgradePlan, workerPlan) } selector, err = metav1.LabelSelectorAsSelector(workerPlan.Spec.NodeSelector) diff --git a/internal/controller/upgradeplan_controller.go b/internal/controller/upgradeplan_controller.go index 123cff4..c0e20f3 100644 --- a/internal/controller/upgradeplan_controller.go +++ b/internal/controller/upgradeplan_controller.go @@ -103,18 +103,18 @@ func (r *UpgradePlanReconciler) recordCreatedPlan(upgradePlan *lifecyclev1alpha1 r.Recorder.Eventf(upgradePlan, corev1.EventTypeNormal, "PlanCreated", "Upgrade plan created: %s/%s", namespace, name) } -func (r *UpgradePlanReconciler) createPlan(ctx context.Context, upgradePlan *lifecyclev1alpha1.UpgradePlan, plan *upgradecattlev1.Plan) (ctrl.Result, error) { +func (r *UpgradePlanReconciler) createPlan(ctx context.Context, upgradePlan *lifecyclev1alpha1.UpgradePlan, plan *upgradecattlev1.Plan) error { if err := ctrl.SetControllerReference(upgradePlan, plan, r.Scheme); err != nil { - return ctrl.Result{}, fmt.Errorf("setting controller reference: %w", err) + return fmt.Errorf("setting controller reference: %w", err) } if err := r.Create(ctx, plan); err != nil { - return ctrl.Result{}, fmt.Errorf("creating upgrade plan: %w", err) + return fmt.Errorf("creating upgrade plan: %w", err) } r.recordCreatedPlan(upgradePlan, plan.Name, plan.Namespace) - return ctrl.Result{Requeue: true}, nil + return nil } func setInProgressCondition(plan *lifecyclev1alpha1.UpgradePlan, conditionType, message string) {