diff --git a/cmd/main.go b/cmd/main.go index 6fcdaae02..99f9b27f0 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -219,10 +219,11 @@ func main() { os.Exit(1) } if err = (&controller.ManagementReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Config: mgr.GetConfig(), - SystemNamespace: currentNamespace, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Config: mgr.GetConfig(), + SystemNamespace: currentNamespace, + CreateTemplateManagement: createTemplateManagement, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Management") os.Exit(1) @@ -254,13 +255,12 @@ func main() { } if err = (&controller.ReleaseReconciler{ - Client: mgr.GetClient(), - Config: mgr.GetConfig(), - CreateManagement: createManagement, - CreateTemplateManagement: createTemplateManagement, - CreateTemplates: createTemplates, - HMCTemplatesChartName: hmcTemplatesChartName, - SystemNamespace: currentNamespace, + Client: mgr.GetClient(), + Config: mgr.GetConfig(), + CreateManagement: createManagement, + CreateTemplates: createTemplates, + HMCTemplatesChartName: hmcTemplatesChartName, + SystemNamespace: currentNamespace, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Release") os.Exit(1) diff --git a/internal/controller/management_controller.go b/internal/controller/management_controller.go index 3e6f5bffd..dc4eb81f7 100644 --- a/internal/controller/management_controller.go +++ b/internal/controller/management_controller.go @@ -25,6 +25,7 @@ import ( sourcev1 "github.com/fluxcd/source-controller/api/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/rest" @@ -41,9 +42,10 @@ import ( // ManagementReconciler reconciles a Management object type ManagementReconciler struct { client.Client - Scheme *runtime.Scheme - Config *rest.Config - SystemNamespace string + Scheme *runtime.Scheme + Config *rest.Config + SystemNamespace string + CreateTemplateManagement bool } func (r *ManagementReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { @@ -75,11 +77,17 @@ func (r *ManagementReconciler) Update(ctx context.Context, management *hmc.Manag finalizersUpdated := controllerutil.AddFinalizer(management, hmc.ManagementFinalizer) if finalizersUpdated { if err := r.Client.Update(ctx, management); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to update Management %s: %w", management.Name, err) + l.Error(err, "Failed to update Management finalizers") + return ctrl.Result{}, err } return ctrl.Result{}, nil } + if err := r.ensureTemplateManagement(ctx, management); err != nil { + l.Error(err, "Failed to ensure TemplateManagement is created") + return ctrl.Result{}, err + } + release := &hmc.Release{} if err := r.Client.Get(ctx, client.ObjectKey{Name: management.Spec.Release}, release); err != nil { l.Error(err, "failed to get Release object") @@ -145,6 +153,42 @@ func (r *ManagementReconciler) Update(ctx context.Context, management *hmc.Manag return ctrl.Result{}, nil } +func (r *ManagementReconciler) ensureTemplateManagement(ctx context.Context, mgmt *hmc.Management) error { + l := ctrl.LoggerFrom(ctx) + if !r.CreateTemplateManagement { + return nil + } + l.Info("Ensuring TemplateManagement is created") + tmObj := &hmc.TemplateManagement{ + ObjectMeta: metav1.ObjectMeta{ + Name: hmc.TemplateManagementName, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: hmc.GroupVersion.String(), + Kind: mgmt.Kind, + Name: mgmt.Name, + UID: mgmt.UID, + }, + }, + }, + } + err := r.Get(ctx, client.ObjectKey{ + Name: hmc.TemplateManagementName, + }, tmObj) + if err == nil { + return nil + } + if !apierrors.IsNotFound(err) { + return fmt.Errorf("failed to get %s TemplateManagement object: %w", hmc.TemplateManagementName, err) + } + err = r.Create(ctx, tmObj) + if err != nil { + return fmt.Errorf("failed to create %s TemplateManagement object: %w", hmc.TemplateManagementName, err) + } + l.Info("Successfully created TemplateManagement object") + return nil +} + func (r *ManagementReconciler) Delete(ctx context.Context, management *hmc.Management) (ctrl.Result, error) { l := ctrl.LoggerFrom(ctx) listOpts := &client.ListOptions{ diff --git a/internal/controller/release_controller.go b/internal/controller/release_controller.go index 66f1362f3..61675b8fd 100644 --- a/internal/controller/release_controller.go +++ b/internal/controller/release_controller.go @@ -51,9 +51,8 @@ type ReleaseReconciler struct { Config *rest.Config - CreateManagement bool - CreateTemplateManagement bool - CreateTemplates bool + CreateManagement bool + CreateTemplates bool HMCTemplatesChartName string SystemNamespace string @@ -71,16 +70,10 @@ func (r *ReleaseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct } if initialReconcile(req) { - mgmt, err := r.getOrCreateManagement(ctx) - if err != nil { + if err := r.ensureManagement(ctx); err != nil { l.Error(err, "failed to get or create Management object") return ctrl.Result{}, err } - err = r.ensureTemplateManagement(ctx, mgmt) - if err != nil { - l.Error(err, "failed to ensure default TemplateManagement object") - return ctrl.Result{}, err - } } return ctrl.Result{}, nil } @@ -89,8 +82,12 @@ func initialReconcile(req ctrl.Request) bool { return req.Name == "" } -func (r *ReleaseReconciler) getOrCreateManagement(ctx context.Context) (*hmc.Management, error) { +func (r *ReleaseReconciler) ensureManagement(ctx context.Context) error { l := ctrl.LoggerFrom(ctx) + if !r.CreateManagement { + return nil + } + l.Info("Ensuring Management is created") mgmtObj := &hmc.Management{ ObjectMeta: metav1.ObjectMeta{ Name: hmc.ManagementName, @@ -100,102 +97,61 @@ func (r *ReleaseReconciler) getOrCreateManagement(ctx context.Context) (*hmc.Man err := r.Get(ctx, client.ObjectKey{ Name: hmc.ManagementName, }, mgmtObj) + if err == nil { + return nil + } + if !apierrors.IsNotFound(err) { + return fmt.Errorf("failed to get %s Management object: %w", hmc.TemplateManagementName, err) + } + mgmtObj.Spec.Release, err = r.getCurrentReleaseName(ctx) if err != nil { - if !apierrors.IsNotFound(err) { - return nil, fmt.Errorf("failed to get %s Management object: %w", hmc.ManagementName, err) - } - if !r.CreateManagement { - return nil, nil - } - mgmtObj.Spec.Release, err = r.getCurrentReleaseName(ctx) - if err != nil { - return nil, err - } - - if err := mgmtObj.Spec.SetProvidersDefaults(); err != nil { - return nil, err - } - - getter := helm.NewMemoryRESTClientGetter(r.Config, r.RESTMapper()) - actionConfig := new(action.Configuration) - err = actionConfig.Init(getter, r.SystemNamespace, "secret", l.Info) - if err != nil { - return nil, err - } - - hmcConfig := make(chartutil.Values) - release, err := actionConfig.Releases.Last("hmc") - if err != nil { - if !errors.Is(err, driver.ErrReleaseNotFound) { - return nil, err - } - } else { - if len(release.Config) > 0 { - chartutil.CoalesceTables(hmcConfig, release.Config) - } - } + return err + } + if err := mgmtObj.Spec.SetProvidersDefaults(); err != nil { + return err + } + getter := helm.NewMemoryRESTClientGetter(r.Config, r.RESTMapper()) + actionConfig := new(action.Configuration) + err = actionConfig.Init(getter, r.SystemNamespace, "secret", l.Info) + if err != nil { + return err + } - // Initially set createManagement:false to automatically create Management object only once - chartutil.CoalesceTables(hmcConfig, map[string]any{ - "controller": map[string]any{ - "createManagement": false, - }, - }) - rawConfig, err := json.Marshal(hmcConfig) - if err != nil { - return nil, err - } - mgmtObj.Spec.Core = &hmc.Core{ - HMC: hmc.Component{ - Config: &apiextensionsv1.JSON{ - Raw: rawConfig, - }, - }, + hmcConfig := make(chartutil.Values) + release, err := actionConfig.Releases.Last("hmc") + if err != nil { + if !errors.Is(err, driver.ErrReleaseNotFound) { + return err } - - err = r.Create(ctx, mgmtObj) - if err != nil { - return nil, fmt.Errorf("failed to create %s Management object: %s", hmc.ManagementName, err) + } else { + if len(release.Config) > 0 { + chartutil.CoalesceTables(hmcConfig, release.Config) } - l.Info("Successfully created Management object with default configuration") } - return mgmtObj, nil -} -func (r *ReleaseReconciler) ensureTemplateManagement(ctx context.Context, mgmt *hmc.Management) error { - l := ctrl.LoggerFrom(ctx) - if !r.CreateTemplateManagement { - return nil - } - if mgmt == nil { - return fmt.Errorf("management object is not found") + // Initially set createManagement:false to automatically create Management object only once + chartutil.CoalesceTables(hmcConfig, map[string]any{ + "controller": map[string]any{ + "createManagement": false, + }, + }) + rawConfig, err := json.Marshal(hmcConfig) + if err != nil { + return err } - tmObj := &hmc.TemplateManagement{ - ObjectMeta: metav1.ObjectMeta{ - Name: hmc.TemplateManagementName, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: hmc.GroupVersion.String(), - Kind: mgmt.Kind, - Name: mgmt.Name, - UID: mgmt.UID, - }, + mgmtObj.Spec.Core = &hmc.Core{ + HMC: hmc.Component{ + Config: &apiextensionsv1.JSON{ + Raw: rawConfig, }, }, } - err := r.Get(ctx, client.ObjectKey{ - Name: hmc.TemplateManagementName, - }, tmObj) + err = r.Create(ctx, mgmtObj) if err != nil { - if !apierrors.IsNotFound(err) { - return fmt.Errorf("failed to get %s TemplateManagement object: %w", hmc.TemplateManagementName, err) - } - err = r.Create(ctx, tmObj) - if err != nil { - return fmt.Errorf("failed to create %s TemplateManagement object: %w", hmc.TemplateManagementName, err) - } - l.Info("Successfully created TemplateManagement object") + return fmt.Errorf("failed to create %s Management object: %w", hmc.TemplateManagementName, err) } + + l.Info("Successfully created Management object with default configuration") return nil }