From 5bfa4b799163c769954408c7a82f8ce5d773b744 Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Thu, 22 Feb 2024 15:34:04 +0530 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20manual=20upgrade=20if=20no=20?= =?UTF-8?q?k8s=20version=20is=20changed=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add manual upgrade if no k8s version is changed Signed-off-by: Aniruddha Basak --- api/v1alpha1/clusteraddon_types.go | 4 ++ .../clusterstack.x-k8s.io_clusteraddons.yaml | 4 ++ .../controller/clusteraddon_controller.go | 54 +++++++++++++++++-- .../metrics-server/overwrite.yaml | 4 ++ 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 test/cluster-stacks/docker/ferrol/1-27/cluster-addon/metrics-server/overwrite.yaml diff --git a/api/v1alpha1/clusteraddon_types.go b/api/v1alpha1/clusteraddon_types.go index 9d6e8d0f..f9bf7b25 100644 --- a/api/v1alpha1/clusteraddon_types.go +++ b/api/v1alpha1/clusteraddon_types.go @@ -68,6 +68,10 @@ type ClusterAddonStatus struct { // +optional CurrentHook string `json:"currentHook,omitempty"` + // KubernetesVersion is the kubernetes version of the current cluster stack release. + // +optional + KubernetesVersion string `json:"kubernetesVersion,omitempty"` + // HelmChartStatus defines the status of helm chart in the cluster addon. // +optional HelmChartStatus map[string]HelmChartStatusConditions `json:"helmChartStatus,omitempty"` diff --git a/config/crd/bases/clusterstack.x-k8s.io_clusteraddons.yaml b/config/crd/bases/clusterstack.x-k8s.io_clusteraddons.yaml index 85b8b348..90ba1620 100644 --- a/config/crd/bases/clusterstack.x-k8s.io_clusteraddons.yaml +++ b/config/crd/bases/clusterstack.x-k8s.io_clusteraddons.yaml @@ -177,6 +177,10 @@ spec: description: HelmChartStatus defines the status of helm chart in the cluster addon. type: object + kubernetesVersion: + description: KubernetesVersion is the kubernetes version of the current + cluster stack release. + type: string ready: default: false type: boolean diff --git a/internal/controller/clusteraddon_controller.go b/internal/controller/clusteraddon_controller.go index addfd1cb..c34beb2e 100644 --- a/internal/controller/clusteraddon_controller.go +++ b/internal/controller/clusteraddon_controller.go @@ -276,6 +276,24 @@ func (r *ClusterAddonReconciler) Reconcile(ctx context.Context, req reconcile.Re clusterAddon.Status.Ready = false } + // In case the Kubernetes version stays the same, the hook server does not trigger. + // Therefore, we have to check whether the ClusterStack is upgraded and if that is the case, the ClusterAddons have to be upgraded as well. + if clusterAddon.Spec.ClusterStack != cluster.Spec.Topology.Class && clusterAddon.Status.KubernetesVersion == releaseAsset.Meta.Versions.Kubernetes { + if clusterAddon.Spec.Version != releaseAsset.Meta.Versions.Components.ClusterAddon { + clusterAddon.Status.HelmChartStatus = make(map[string]csov1alpha1.HelmChartStatusConditions) + clusterAddon.Status.CurrentHook = clusterAddon.Spec.Hook + clusterAddon.Status.Ready = false + conditions.Delete(clusterAddon, csov1alpha1.HelmChartAppliedCondition) + } else { + // If the cluster addon version don't change we don't want to apply helm charts again. + clusterAddon.Spec.ClusterStack = cluster.Spec.Topology.Class + clusterAddon.Status.Ready = true + } + } + + clusterAddon.Spec.ClusterStack = cluster.Spec.Topology.Class + clusterAddon.Spec.Version = releaseAsset.Meta.Versions.Components.ClusterAddon + if clusterAddon.Status.Ready { return reconcile.Result{}, nil } @@ -291,8 +309,38 @@ func (r *ClusterAddonReconciler) Reconcile(ctx context.Context, req reconcile.Re return reconcile.Result{}, fmt.Errorf("failed to parse clusteraddon.yaml config: %w", err) } - for _, stage := range clusterAddonConfig.AddonStages[in.clusterAddon.Spec.Hook] { - shouldRequeue, err := executeStage(ctx, stage, in) + // In case the Kubernetes version stayed the same during an upgrade, the hook server does not trigger and + // we just take the Helm charts that are supposed to be installed in the BeforeClusterUpgrade hook and apply them. + if clusterAddon.Status.KubernetesVersion == releaseAsset.Meta.Versions.Kubernetes { + clusterAddon.Spec.Hook = "BeforeClusterUpgrade" + for _, stage := range clusterAddonConfig.AddonStages["BeforeClusterUpgrade"] { + shouldRequeue, err := r.executeStage(ctx, stage, in) + if err != nil { + return reconcile.Result{}, fmt.Errorf("failed to execute stage: %w", err) + } + if shouldRequeue { + return reconcile.Result{RequeueAfter: 20 * time.Second}, nil + } + } + + // Helm chart has been applied successfully + // clusterAddon.Spec.Version = metadata.Versions.Components.ClusterAddon + conditions.MarkTrue(clusterAddon, csov1alpha1.HelmChartAppliedCondition) + + // store the release kubernetes version and current hook + clusterAddon.Status.Ready = true + + return ctrl.Result{}, nil + } + + // If hook is empty we can don't want to proceed executing staged according to current hook + // hence we can return. + if clusterAddon.Spec.Hook == "" { + return reconcile.Result{}, nil + } + + for _, stage := range clusterAddonConfig.AddonStages[clusterAddon.Spec.Hook] { + shouldRequeue, err := r.executeStage(ctx, stage, in) if err != nil { return reconcile.Result{}, fmt.Errorf("failed to execute stage: %w", err) } @@ -412,7 +460,7 @@ func (r *ClusterAddonReconciler) templateAndApplyClusterAddonHelmChart(ctx conte return shouldRequeue, nil } -func executeStage(ctx context.Context, stage clusteraddon.Stage, in templateAndApplyClusterAddonInput) (bool, error) { +func (r *ClusterAddonReconciler) executeStage(ctx context.Context, stage clusteraddon.Stage, in templateAndApplyClusterAddonInput) (bool, error) { var ( newResources []*csov1alpha1.Resource shouldRequeue bool diff --git a/test/cluster-stacks/docker/ferrol/1-27/cluster-addon/metrics-server/overwrite.yaml b/test/cluster-stacks/docker/ferrol/1-27/cluster-addon/metrics-server/overwrite.yaml new file mode 100644 index 00000000..30a4ded9 --- /dev/null +++ b/test/cluster-stacks/docker/ferrol/1-27/cluster-addon/metrics-server/overwrite.yaml @@ -0,0 +1,4 @@ +metrics-server: + commonLabels: + domain: "{{ .Cluster.spec.controlPlaneEndpoint.host }}" + clusterAddonVersion: "v2"