diff --git a/internal/controller/reconcile_kubernetes.go b/internal/controller/reconcile_kubernetes.go index 0629d80..ff2e89f 100644 --- a/internal/controller/reconcile_kubernetes.go +++ b/internal/controller/reconcile_kubernetes.go @@ -3,9 +3,11 @@ package controller import ( "context" "fmt" + "strings" lifecyclev1alpha1 "github.com/suse-edge/upgrade-controller/api/v1alpha1" "github.com/suse-edge/upgrade-controller/internal/upgrade" + "github.com/suse-edge/upgrade-controller/pkg/release" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -14,9 +16,19 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func (r *UpgradePlanReconciler) reconcileKubernetes(ctx context.Context, upgradePlan *lifecyclev1alpha1.UpgradePlan, kubernetesVersion string) (ctrl.Result, error) { +func (r *UpgradePlanReconciler) reconcileKubernetes(ctx context.Context, upgradePlan *lifecyclev1alpha1.UpgradePlan, release *release.Release) (ctrl.Result, error) { + nodeList := &corev1.NodeList{} + if err := r.List(ctx, nodeList); err != nil { + return ctrl.Result{}, fmt.Errorf("listing nodes: %w", err) + } + + kubernetesVersion, err := targetKubernetesVersion(nodeList, release) + if err != nil { + return ctrl.Result{}, fmt.Errorf("identifying target kubernetes version: %w", err) + } + controlPlanePlan := upgrade.KubernetesControlPlanePlan(kubernetesVersion) - if err := r.Get(ctx, client.ObjectKeyFromObject(controlPlanePlan), controlPlanePlan); err != nil { + if err = r.Get(ctx, client.ObjectKeyFromObject(controlPlanePlan), controlPlanePlan); err != nil { if !errors.IsNotFound(err) { return ctrl.Result{}, err } @@ -24,11 +36,6 @@ func (r *UpgradePlanReconciler) reconcileKubernetes(ctx context.Context, upgrade return ctrl.Result{}, r.createPlan(ctx, upgradePlan, controlPlanePlan) } - nodeList := &corev1.NodeList{} - if err := r.List(ctx, nodeList); err != nil { - return ctrl.Result{}, fmt.Errorf("listing nodes: %w", err) - } - selector, err := metav1.LabelSelectorAsSelector(controlPlanePlan.Spec.NodeSelector) if err != nil { return ctrl.Result{}, fmt.Errorf("parsing node selector: %w", err) @@ -65,6 +72,23 @@ func (r *UpgradePlanReconciler) reconcileKubernetes(ctx context.Context, upgrade return ctrl.Result{Requeue: true}, nil } +func targetKubernetesVersion(nodeList *corev1.NodeList, release *release.Release) (string, error) { + if len(nodeList.Items) == 0 { + return "", fmt.Errorf("unable to determine current kubernetes version due to empty node list") + } + + kubeletVersion := nodeList.Items[0].Status.NodeInfo.KubeletVersion + + switch { + case strings.Contains(kubeletVersion, "k3s"): + return release.Components.Kubernetes.K3S.Version, nil + case strings.Contains(kubeletVersion, "rke2"): + return release.Components.Kubernetes.RKE2.Version, nil + default: + return "", fmt.Errorf("upgrading from kubernetes version %s is not supported", kubeletVersion) + } +} + func isKubernetesUpgraded(nodeList *corev1.NodeList, selector labels.Selector, kubernetesVersion string) bool { for _, node := range nodeList.Items { if !selector.Matches(labels.Set(node.Labels)) { diff --git a/internal/controller/upgradeplan_controller.go b/internal/controller/upgradeplan_controller.go index c0e20f3..87200f1 100644 --- a/internal/controller/upgradeplan_controller.go +++ b/internal/controller/upgradeplan_controller.go @@ -88,7 +88,7 @@ func (r *UpgradePlanReconciler) executePlan(ctx context.Context, upgradePlan *li // Upgrade OS here... if !meta.IsStatusConditionTrue(upgradePlan.Status.Conditions, lifecyclev1alpha1.KubernetesUpgradedCondition) { - return r.reconcileKubernetes(ctx, upgradePlan, release.Components.Kubernetes.RKE2.Version) + return r.reconcileKubernetes(ctx, upgradePlan, release) } // Upgrade rest of the components here... diff --git a/internal/upgrade/kubernetes.go b/internal/upgrade/kubernetes.go index fc9315f..4bcde12 100644 --- a/internal/upgrade/kubernetes.go +++ b/internal/upgrade/kubernetes.go @@ -11,6 +11,7 @@ import ( const ( rke2UpgradeImage = "rancher/rke2-upgrade" + k3sUpgradeImage = "rancher/k3s-upgrade" controlPlaneKey = "control-plane" workersKey = "workers" @@ -20,12 +21,21 @@ func kubernetesPlanName(typeKey, version string) string { return fmt.Sprintf("%s-%s", typeKey, strings.ReplaceAll(version, "+", "-")) } +func kubernetesUpgradeImage(version string) string { + if strings.Contains(version, "k3s") { + return k3sUpgradeImage + } + + return rke2UpgradeImage +} + func KubernetesControlPlanePlan(version string) *upgradecattlev1.Plan { controlPlanePlanName := kubernetesPlanName(controlPlaneKey, version) + upgradeImage := kubernetesUpgradeImage(version) controlPlanePlan := baseUpgradePlan(controlPlanePlanName) controlPlanePlan.Labels = map[string]string{ - "rke2-upgrade": "control-plane", + "k8s-upgrade": "control-plane", } controlPlanePlan.Spec.NodeSelector = &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ @@ -40,7 +50,7 @@ func KubernetesControlPlanePlan(version string) *upgradecattlev1.Plan { } controlPlanePlan.Spec.Concurrency = 1 controlPlanePlan.Spec.Upgrade = &upgradecattlev1.ContainerSpec{ - Image: rke2UpgradeImage, + Image: upgradeImage, } controlPlanePlan.Spec.Version = version controlPlanePlan.Spec.Cordon = true @@ -71,10 +81,11 @@ func KubernetesControlPlanePlan(version string) *upgradecattlev1.Plan { func KubernetesWorkerPlan(version string) *upgradecattlev1.Plan { controlPlanePlanName := kubernetesPlanName(controlPlaneKey, version) workerPlanName := kubernetesPlanName(workersKey, version) + upgradeImage := kubernetesUpgradeImage(version) workerPlan := baseUpgradePlan(workerPlanName) workerPlan.Labels = map[string]string{ - "rke2-upgrade": "worker", + "k8s-upgrade": "worker", } workerPlan.Spec.Concurrency = 2 workerPlan.Spec.NodeSelector = &metav1.LabelSelector{ @@ -93,10 +104,10 @@ func KubernetesWorkerPlan(version string) *upgradecattlev1.Plan { "prepare", controlPlanePlanName, }, - Image: rke2UpgradeImage, + Image: upgradeImage, } workerPlan.Spec.Upgrade = &upgradecattlev1.ContainerSpec{ - Image: rke2UpgradeImage, + Image: upgradeImage, } workerPlan.Spec.Version = version workerPlan.Spec.Cordon = true