diff --git a/cmd/main.go b/cmd/main.go index c72bed4fd..161b9a53b 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -39,6 +39,7 @@ import ( hmcmirantiscomv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" "github.com/Mirantis/hmc/internal/controller" + "github.com/Mirantis/hmc/internal/helm" "github.com/Mirantis/hmc/internal/telemetry" "github.com/Mirantis/hmc/internal/utils" hmcwebhook "github.com/Mirantis/hmc/internal/webhook" @@ -183,13 +184,15 @@ func main() { currentNamespace := utils.CurrentNamespace() templateReconciler := controller.TemplateReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - SystemNamespace: currentNamespace, - DefaultRegistryURL: defaultRegistryURL, - DefaultRepoType: determinedRepositoryType, - RegistryCredentialsSecret: registryCredentialsSecret, - InsecureRegistry: insecureRegistry, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + SystemNamespace: currentNamespace, + DefaultRegistryConfig: helm.DefaultRegistryConfig{ + URL: defaultRegistryURL, + RepoType: determinedRepositoryType, + CredentialsSecret: registryCredentialsSecret, + Insecure: insecureRegistry, + }, } if err = (&controller.ClusterTemplateReconciler{ diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index 6ea6f98db..da312028f 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -21,7 +21,6 @@ import ( "strings" helmcontrollerv2 "github.com/fluxcd/helm-controller/api/v2" - "github.com/fluxcd/pkg/apis/meta" sourcev1 "github.com/fluxcd/source-controller/api/v1" "helm.sh/helm/v3/pkg/chart" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -30,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" hmc "github.com/Mirantis/hmc/api/v1alpha1" "github.com/Mirantis/hmc/internal/helm" @@ -46,14 +44,7 @@ type TemplateReconciler struct { Scheme *runtime.Scheme SystemNamespace string - // DefaultRepoType is the type specified by default in HelmRepository - // objects. Valid types are 'default' for http/https repositories, and - // 'oci' for OCI repositories. The RepositoryType is set in main based on - // the URI scheme of the DefaultRegistryURL. - DefaultRepoType string - DefaultRegistryURL string - RegistryCredentialsSecret string - InsecureRegistry bool + DefaultRegistryConfig helm.DefaultRegistryConfig downloadHelmChartFunc func(context.Context, *sourcev1.Artifact) (*chart.Chart, error) } @@ -148,7 +139,11 @@ func (r *TemplateReconciler) ReconcileTemplate(ctx context.Context, template Tem return ctrl.Result{}, err } if template.GetNamespace() == r.SystemNamespace || !templateManagedByHMC(template) { - err := r.reconcileDefaultHelmRepository(ctx, template.GetNamespace()) + namespace := template.GetNamespace() + if namespace == "" { + namespace = r.SystemNamespace + } + err := helm.ReconcileHelmRepository(ctx, r.Client, defaultRepoName, namespace, r.DefaultRegistryConfig.HelmRepositorySpec()) if err != nil { l.Error(err, "Failed to reconcile default HelmRepository", "namespace", template.GetNamespace()) return ctrl.Result{}, err @@ -271,45 +266,6 @@ func (r *TemplateReconciler) updateStatus(ctx context.Context, template Template return nil } -func (r *TemplateReconciler) reconcileDefaultHelmRepository(ctx context.Context, namespace string) error { - l := ctrl.LoggerFrom(ctx) - if namespace == "" { - namespace = r.SystemNamespace - } - helmRepo := &sourcev1.HelmRepository{ - ObjectMeta: metav1.ObjectMeta{ - Name: defaultRepoName, - Namespace: namespace, - }, - } - operation, err := ctrl.CreateOrUpdate(ctx, r.Client, helmRepo, func() error { - if helmRepo.Labels == nil { - helmRepo.Labels = make(map[string]string) - } - - helmRepo.Labels[hmc.HMCManagedLabelKey] = hmc.HMCManagedLabelValue - helmRepo.Spec = sourcev1.HelmRepositorySpec{ - Type: r.DefaultRepoType, - URL: r.DefaultRegistryURL, - Interval: metav1.Duration{Duration: helm.DefaultReconcileInterval}, - Insecure: r.InsecureRegistry, - } - if r.RegistryCredentialsSecret != "" { - helmRepo.Spec.SecretRef = &meta.LocalObjectReference{ - Name: r.RegistryCredentialsSecret, - } - } - return nil - }) - if err != nil { - return err - } - if operation == controllerutil.OperationResultCreated || operation == controllerutil.OperationResultUpdated { - l.Info(fmt.Sprintf("Successfully %s %s/%s HelmRepository", operation, namespace, defaultRepoName)) - } - return nil -} - func (r *TemplateReconciler) reconcileHelmChart(ctx context.Context, template Template) (*sourcev1.HelmChart, error) { spec := template.GetSpec() namespace := template.GetNamespace() diff --git a/internal/helm/repo.go b/internal/helm/repo.go new file mode 100644 index 000000000..e6756a9da --- /dev/null +++ b/internal/helm/repo.go @@ -0,0 +1,83 @@ +// 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 ( + "context" + "fmt" + + "github.com/fluxcd/pkg/apis/meta" + sourcev1 "github.com/fluxcd/source-controller/api/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + hmc "github.com/Mirantis/hmc/api/v1alpha1" +) + +type DefaultRegistryConfig struct { + // RepoType is the type specified by default in HelmRepository + // objects. Valid types are 'default' for http/https repositories, and + // 'oci' for OCI repositories. The RepositoryType is set in main based on + // the URI scheme of the DefaultRegistryURL. + RepoType string + URL string + CredentialsSecret string + Insecure bool +} + +func (r *DefaultRegistryConfig) HelmRepositorySpec() sourcev1.HelmRepositorySpec { + return sourcev1.HelmRepositorySpec{ + Type: r.RepoType, + URL: r.URL, + Interval: metav1.Duration{Duration: DefaultReconcileInterval}, + Insecure: r.Insecure, + SecretRef: func() *meta.LocalObjectReference { + if r.CredentialsSecret != "" { + return &meta.LocalObjectReference{ + Name: r.CredentialsSecret, + } + } + return nil + }(), + } +} + +func ReconcileHelmRepository(ctx context.Context, cl client.Client, name, namespace string, spec sourcev1.HelmRepositorySpec) error { + l := ctrl.LoggerFrom(ctx) + helmRepo := &sourcev1.HelmRepository{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } + operation, err := ctrl.CreateOrUpdate(ctx, cl, helmRepo, func() error { + if helmRepo.Labels == nil { + helmRepo.Labels = make(map[string]string) + } + + helmRepo.Labels[hmc.HMCManagedLabelKey] = hmc.HMCManagedLabelValue + helmRepo.Spec = spec + return nil + }) + if err != nil { + return err + } + if operation == controllerutil.OperationResultCreated || operation == controllerutil.OperationResultUpdated { + l.Info(fmt.Sprintf("Successfully %s %s/%s HelmRepository", operation, namespace, name)) + } + return nil +}