From f7bf5088a4617ca4f02c2dcf787dff15f65459f0 Mon Sep 17 00:00:00 2001 From: Dan Jones <108552543+danj-replicated@users.noreply.github.com> Date: Tue, 30 Jan 2024 08:27:01 +0000 Subject: [PATCH] bug: merge chart values before comparing (#82) * combine charts earlier so we can compare the final values * add k0s cluster object to unit tests * add unit tests for drift/no drift with overridden values --------- Co-authored-by: Andrew Lavery --- controllers/installation_controller.go | 25 +-- controllers/installation_controller_test.go | 212 +++++++++++++++++++- 2 files changed, 224 insertions(+), 13 deletions(-) diff --git a/controllers/installation_controller.go b/controllers/installation_controller.go index 00ef19879..f578006cd 100644 --- a/controllers/installation_controller.go +++ b/controllers/installation_controller.go @@ -286,11 +286,24 @@ func (r *InstallationReconciler) ReconcileHelmCharts(ctx context.Context, in *v1 combinedConfigs := mergeHelmConfigs(meta, in) + // fetch the current clusterconfig + var clusterconfig k0sv1beta1.ClusterConfig + if err := r.Get(ctx, client.ObjectKey{Name: "k0s", Namespace: "kube-system"}, &clusterconfig); err != nil { + return fmt.Errorf("failed to get cluster config: %w", err) + } + + finalChartList, err := generateDesiredCharts(meta, clusterconfig, combinedConfigs) + if err != nil { + return err + } + combinedConfigs.Charts = finalChartList + // detect drift between the cluster config and the installer metadata var installedCharts k0shelm.ChartList if err := r.List(ctx, &installedCharts); err != nil { return fmt.Errorf("failed to list installed charts: %w", err) } + chartErrors, chartDrift, err := detectChartDrift(combinedConfigs, installedCharts) if err != nil { return fmt.Errorf("failed to check chart drift: %w", err) @@ -320,19 +333,7 @@ func (r *InstallationReconciler) ReconcileHelmCharts(ctx context.Context, in *v1 return nil } - // fetch the current clusterconfig - var clusterconfig k0sv1beta1.ClusterConfig - if err := r.Get(ctx, client.ObjectKey{Name: "k0s", Namespace: "kube-system"}, &clusterconfig); err != nil { - return fmt.Errorf("failed to get cluster config: %w", err) - } - - finalChartList, err := generateDesiredCharts(meta, clusterconfig, combinedConfigs) - if err != nil { - return err - } - // Replace the current chart configs with the new chart configs - combinedConfigs.Charts = finalChartList clusterconfig.Spec.Extensions.Helm = combinedConfigs in.Status.SetState(v1beta1.InstallationStateAddonsInstalling, "Installing addons") //Update the clusterconfig diff --git a/controllers/installation_controller_test.go b/controllers/installation_controller_test.go index 0d4539752..1b96be6a6 100644 --- a/controllers/installation_controller_test.go +++ b/controllers/installation_controller_test.go @@ -115,6 +115,17 @@ func TestInstallationReconciler_ReconcileHelmCharts(t *testing.T) { Spec: k0shelmv1beta1.ChartSpec{ReleaseName: "extchart"}, Status: k0shelmv1beta1.ChartStatus{Version: "2"}, }, + &k0sv1beta1.ClusterConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "k0s", + Namespace: "kube-system", + }, + Spec: &k0sv1beta1.ClusterSpec{ + Extensions: &k0sv1beta1.ClusterExtensions{ + Helm: &k0sv1beta1.HelmExtensions{}, + }, + }, + }, }, }, }, @@ -168,6 +179,17 @@ func TestInstallationReconciler_ReconcileHelmCharts(t *testing.T) { Spec: k0shelmv1beta1.ChartSpec{ReleaseName: "extchart"}, Status: k0shelmv1beta1.ChartStatus{Version: "2", Error: "exterror"}, }, + &k0sv1beta1.ClusterConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "k0s", + Namespace: "kube-system", + }, + Spec: &k0sv1beta1.ClusterSpec{ + Extensions: &k0sv1beta1.ClusterExtensions{ + Helm: &k0sv1beta1.HelmExtensions{}, + }, + }, + }, }, }, }, @@ -205,7 +227,19 @@ func TestInstallationReconciler_ReconcileHelmCharts(t *testing.T) { }, }, fields: fields{ - State: []runtime.Object{}, + State: []runtime.Object{ + &k0sv1beta1.ClusterConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "k0s", + Namespace: "kube-system", + }, + Spec: &k0sv1beta1.ClusterSpec{ + Extensions: &k0sv1beta1.ClusterExtensions{ + Helm: &k0sv1beta1.HelmExtensions{}, + }, + }, + }, + }, }, }, { @@ -270,6 +304,182 @@ func TestInstallationReconciler_ReconcileHelmCharts(t *testing.T) { }, }, }, + { + name: "k8s install completed, good version, overridden values, both types of charts, no drift", + in: v1beta1.Installation{ + Status: v1beta1.InstallationStatus{State: v1beta1.InstallationStateKubernetesInstalled}, + Spec: v1beta1.InstallationSpec{ + Config: &v1beta1.ConfigSpec{ + Version: "goodver", + Extensions: v1beta1.Extensions{ + Helm: &k0sv1beta1.HelmExtensions{ + Charts: []k0sv1beta1.Chart{ + { + Name: "extchart", + Version: "2", + }, + }, + }, + }, + }, + }, + }, + out: v1beta1.InstallationStatus{ + State: v1beta1.InstallationStateInstalled, + Reason: "Addons upgraded", + }, + releaseMeta: release.Meta{ + Configs: &k0sv1beta1.HelmExtensions{ + Charts: []k0sv1beta1.Chart{ + { + Name: "metachart", + Version: "1", + Values: ` +abc: xyz +password: overridden`, + }, + }, + }, + Protected: map[string][]string{ + "metachart": {"password"}, + }, + }, + fields: fields{ + State: []runtime.Object{ + &k0shelmv1beta1.Chart{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metachart", + }, + Spec: k0shelmv1beta1.ChartSpec{ + ReleaseName: "metachart", + Values: `abc: xyz +password: original`, + }, + Status: k0shelmv1beta1.ChartStatus{Version: "1"}, + }, + &k0shelmv1beta1.Chart{ + ObjectMeta: metav1.ObjectMeta{ + Name: "extchart", + }, + Spec: k0shelmv1beta1.ChartSpec{ReleaseName: "extchart"}, + Status: k0shelmv1beta1.ChartStatus{Version: "2"}, + }, + &k0sv1beta1.ClusterConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "k0s", + Namespace: "kube-system", + }, + Spec: &k0sv1beta1.ClusterSpec{ + Extensions: &k0sv1beta1.ClusterExtensions{ + Helm: &k0sv1beta1.HelmExtensions{ + Charts: []k0sv1beta1.Chart{ + { + Name: "metachart", + Version: "1", + Values: ` +abc: xyz +password: original`, + }, + { + Name: "extchart", + Version: "2", + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "k8s install completed, good version, overridden values, both types of charts, values drift", + in: v1beta1.Installation{ + Status: v1beta1.InstallationStatus{State: v1beta1.InstallationStateKubernetesInstalled}, + Spec: v1beta1.InstallationSpec{ + Config: &v1beta1.ConfigSpec{ + Version: "goodver", + Extensions: v1beta1.Extensions{ + Helm: &k0sv1beta1.HelmExtensions{ + Charts: []k0sv1beta1.Chart{ + { + Name: "extchart", + Version: "2", + }, + }, + }, + }, + }, + }, + }, + out: v1beta1.InstallationStatus{ + State: v1beta1.InstallationStateAddonsInstalling, + Reason: "Installing addons", + }, + releaseMeta: release.Meta{ + Configs: &k0sv1beta1.HelmExtensions{ + Charts: []k0sv1beta1.Chart{ + { + Name: "metachart", + Version: "1", + Values: ` +abc: xyz +password: overridden`, + }, + }, + }, + Protected: map[string][]string{ + "metachart": {"password"}, + }, + }, + fields: fields{ + State: []runtime.Object{ + &k0shelmv1beta1.Chart{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metachart", + }, + Spec: k0shelmv1beta1.ChartSpec{ + ReleaseName: "metachart", + Values: `abc: original +password: original`, + }, + Status: k0shelmv1beta1.ChartStatus{Version: "1"}, + }, + &k0shelmv1beta1.Chart{ + ObjectMeta: metav1.ObjectMeta{ + Name: "extchart", + }, + Spec: k0shelmv1beta1.ChartSpec{ReleaseName: "extchart"}, + Status: k0shelmv1beta1.ChartStatus{Version: "2"}, + }, + &k0sv1beta1.ClusterConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "k0s", + Namespace: "kube-system", + }, + Spec: &k0sv1beta1.ClusterSpec{ + Extensions: &k0sv1beta1.ClusterExtensions{ + Helm: &k0sv1beta1.HelmExtensions{ + Charts: []k0sv1beta1.Chart{ + { + Name: "metachart", + Version: "1", + Values: ` +abc: original +password: original`, + }, + { + Name: "extchart", + Version: "2", + }, + }, + }, + }, + }, + }, + }, + }, + }, } for _, tt := range tests {