diff --git a/controllers/handlers_helm.go b/controllers/handlers_helm.go index b15a4cf2..0be345fa 100644 --- a/controllers/handlers_helm.go +++ b/controllers/handlers_helm.go @@ -5429,6 +5429,16 @@ func getInstantiatedChart(ctx context.Context, dCtx *deploymentContext, // Create a deep copy of the chart to avoid modifying the original. instantiatedChart := currentChart.DeepCopy() + // Values are deliberately left out of the instantiation below: they are templated by + // getHelmChartInstantiatedValues at the point of use (install/upgrade/hash). This method + // is also called on paths that only need the chart identity (chartManager registration, + // uninstall): failing those paths on values that are not valid Sveltos templates (e.g. + // helm-style {{ .Values.x }} placeholders meant for the chart's own tpl rendering) would + // permanently wedge undeploy of every chart in the profile and, through + // allMatchingProfilesProcessed, block helm uninstalls of other profiles on the cluster. + values := instantiatedChart.Values + instantiatedChart.Values = "" + // Call the new recursive helper function to instantiate all fields. if err := instantiateStructFields(ctx, getManagementClusterConfig(), getManagementClusterClient(), instantiatedChart, dCtx.clusterSummary, dCtx.clusterObjects, dCtx.mgmtResources, logger); err != nil { @@ -5437,6 +5447,8 @@ func getInstantiatedChart(ctx context.Context, dCtx *deploymentContext, return nil, &configv1beta1.TemplateInstantiationError{Message: msg} } + instantiatedChart.Values = values + return instantiatedChart, nil } diff --git a/controllers/handlers_helm_test.go b/controllers/handlers_helm_test.go index a56a54e6..d2691d56 100644 --- a/controllers/handlers_helm_test.go +++ b/controllers/handlers_helm_test.go @@ -1329,6 +1329,52 @@ var _ = Describe("HandlersHelm", func() { Expect(instaniatedChart.ChartVersion).To(Equal("25.0.2")) }) + It("getInstantiatedChart leaves Values alone even when they are not a valid Sveltos template", func() { + helmChart := &configv1beta1.HelmChart{ + ReleaseName: randomString(), ReleaseNamespace: randomString(), + ChartName: randomString(), ChartVersion: randomString(), + RepositoryURL: randomString(), RepositoryName: randomString(), + HelmChartAction: configv1beta1.HelmChartActionInstall, + // Helm-style placeholders meant for the chart's own tpl rendering. They are not + // valid Sveltos templates (.Values does not exist in the Sveltos template context): + // instantiating them here used to fail and wedge chart registration and uninstall. + Values: `config: + service: | + [SERVICE] + Flush {{ .Values.flush }} + Log_Level {{ .Values.logLevel }}`, + } + + clusterSummary.Namespace = defaultNamespace + clusterSummary.Spec.ClusterNamespace = defaultNamespace + + cluster := &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterSummary.Spec.ClusterName, + Namespace: clusterSummary.Spec.ClusterNamespace, + }, + } + + Expect(testEnv.Create(context.TODO(), cluster)).To(Succeed()) + Expect(waitForObject(context.TODO(), testEnv.Client, cluster)).To(Succeed()) + + Expect(testEnv.Create(context.TODO(), clusterSummary)).To(Succeed()) + Expect(waitForObject(context.TODO(), testEnv.Client, clusterSummary)).To(Succeed()) + + clusterObjects, err := controllers.FetchClusterObjects(context.TODO(), testEnv.Config, testEnv.Client, + clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, libsveltosv1beta1.ClusterTypeCapi, + textlogger.NewLogger(textlogger.NewConfig())) + Expect(err).To(BeNil()) + + instaniatedChart, err := controllers.GetInstantiatedChart(context.TODO(), + controllers.NewDeploymentContext(clusterSummary, clusterObjects, nil), helmChart, + textlogger.NewLogger(textlogger.NewConfig())) + Expect(err).To(BeNil()) + Expect(instaniatedChart.Values).To(Equal(helmChart.Values)) + Expect(instaniatedChart.ReleaseName).To(Equal(helmChart.ReleaseName)) + Expect(instaniatedChart.ReleaseNamespace).To(Equal(helmChart.ReleaseNamespace)) + }) + It("updateClusterReportWithHelmReports updates ClusterReports with HelmReports", func() { helmChart := &configv1beta1.HelmChart{ ReleaseName: randomString(), ReleaseNamespace: randomString(),