diff --git a/internal/controller/release_controller.go b/internal/controller/release_controller.go index 91595df4c..6e2091ccb 100644 --- a/internal/controller/release_controller.go +++ b/internal/controller/release_controller.go @@ -25,6 +25,7 @@ import ( sourcev1 "github.com/fluxcd/source-controller/api/v1" "github.com/pkg/errors" "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/storage/driver" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -131,6 +132,8 @@ func (p *Poller) ensureManagement(ctx context.Context) error { if err != nil { return err } + + hmcConfig := make(chartutil.Values) release, err := actionConfig.Releases.Last("hmc") if err != nil { if !errors.Is(err, driver.ErrReleaseNotFound) { @@ -138,21 +141,28 @@ func (p *Poller) ensureManagement(ctx context.Context) error { } } else { if len(release.Config) > 0 { - values, err := json.Marshal(release.Config) - if err != nil { - return err - } - _ = applyDefaultCoreConfiguration(mgmtObj) - mgmtObj.Spec.Core = &hmc.DefaultCoreConfiguration - mgmtObj.Spec.Core.HMC.Config = &apiextensionsv1.JSON{ - Raw: values, - } + helm.OverrideValuesWithValues(hmcConfig, release.Config) } } + // Initially set createManagement:false to automatically create Management object only once + helm.OverrideValuesWithValues(hmcConfig, map[string]interface{}{ + "controller": map[string]interface{}{ + "createManagement": false, + }, + }) + rawConfig, err := json.Marshal(hmcConfig) + if err != nil { + return err + } + mgmtObj.Spec.Core = &hmc.DefaultCoreConfiguration + mgmtObj.Spec.Core.HMC.Config = &apiextensionsv1.JSON{ + Raw: rawConfig, + } + err = p.Create(ctx, mgmtObj) if err != nil { - return fmt.Errorf("failed to create %s/%s Management object", hmc.ManagementNamespace, hmc.ManagementName) + return fmt.Errorf("failed to create %s/%s Management object: %s", hmc.ManagementNamespace, hmc.ManagementName, err) } l.Info("Successfully created Management object with default configuration") } diff --git a/internal/helm/values.go b/internal/helm/values.go new file mode 100644 index 000000000..a533b44cc --- /dev/null +++ b/internal/helm/values.go @@ -0,0 +1,45 @@ +// Copyright 2024 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package helm + +import ( + "helm.sh/helm/v3/pkg/chartutil" +) + +func ToValues(v interface{}) (chartutil.Values, bool) { + switch c := v.(type) { + case chartutil.Values: + return c, true + case map[string]interface{}: + return c, true + default: + return nil, false + } +} + +func OverrideValuesWithValues(dst chartutil.Values, src chartutil.Values) { + for k, sv := range src { + dv, ok := dst[k] + if ok { + dvc, dvisv := ToValues(dv) + svc, svisv := ToValues(sv) + if dvisv && svisv { + OverrideValuesWithValues(dvc, svc) + continue + } + } + dst[k] = sv + } +}