From 3981b9d3dd8453d7b71072fcab436db4716130b1 Mon Sep 17 00:00:00 2001 From: Guillermo Gaston Date: Thu, 7 Dec 2023 22:57:23 +0000 Subject: [PATCH] Move iam logic to a separate controller --- controllers/cluster_controller.go | 35 +-------- controllers/iamconfig_reconciler.go | 112 ++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 33 deletions(-) create mode 100644 controllers/iamconfig_reconciler.go diff --git a/controllers/cluster_controller.go b/controllers/cluster_controller.go index b0d91aab2f74..9c9eeb189937 100644 --- a/controllers/cluster_controller.go +++ b/controllers/cluster_controller.go @@ -18,7 +18,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1" @@ -46,7 +45,6 @@ const ( type ClusterReconciler struct { client client.Client providerReconcilerRegistry ProviderClusterReconcilerRegistry - awsIamAuth AWSIamConfigReconciler clusterValidator ClusterValidator packagesClient PackagesClient machineHealthCheck MachineHealthCheckReconciler @@ -64,13 +62,6 @@ type ProviderClusterReconcilerRegistry interface { Get(datacenterKind string) clusters.ProviderClusterReconciler } -// AWSIamConfigReconciler manages aws-iam-authenticator installation and configuration for an eks-a cluster. -type AWSIamConfigReconciler interface { - EnsureCASecret(ctx context.Context, logger logr.Logger, cluster *anywherev1.Cluster) (controller.Result, error) - Reconcile(ctx context.Context, logger logr.Logger, cluster *anywherev1.Cluster) (controller.Result, error) - ReconcileDelete(ctx context.Context, logger logr.Logger, cluster *anywherev1.Cluster) error -} - // MachineHealthCheckReconciler manages machine health checks for an eks-a cluster. type MachineHealthCheckReconciler interface { Reconcile(ctx context.Context, logger logr.Logger, cluster *anywherev1.Cluster) error @@ -85,11 +76,10 @@ type ClusterValidator interface { type ClusterReconcilerOption func(*ClusterReconciler) // NewClusterReconciler constructs a new ClusterReconciler. -func NewClusterReconciler(client client.Client, registry ProviderClusterReconcilerRegistry, awsIamAuth AWSIamConfigReconciler, clusterValidator ClusterValidator, pkgs PackagesClient, machineHealthCheck MachineHealthCheckReconciler, opts ...ClusterReconcilerOption) *ClusterReconciler { +func NewClusterReconciler(client client.Client, registry ProviderClusterReconcilerRegistry, clusterValidator ClusterValidator, pkgs PackagesClient, machineHealthCheck MachineHealthCheckReconciler, opts ...ClusterReconcilerOption) *ClusterReconciler { c := &ClusterReconciler{ client: client, providerReconcilerRegistry: registry, - awsIamAuth: awsIamAuth, clusterValidator: clusterValidator, packagesClient: pkgs, machineHealthCheck: machineHealthCheck, @@ -210,7 +200,7 @@ func (r *ClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (re log.Info("Reconciling cluster") if err := r.client.Get(ctx, req.NamespacedName, cluster); err != nil { if apierrors.IsNotFound(err) { - return reconcile.Result{}, nil + return ctrl.Result{}, nil } return ctrl.Result{}, err } @@ -351,13 +341,6 @@ func (r *ClusterReconciler) reconcile(ctx context.Context, log logr.Logger, clus func (r *ClusterReconciler) preClusterProviderReconcile(ctx context.Context, log logr.Logger, cluster *anywherev1.Cluster) (controller.Result, error) { // Run some preflight validations that can't be checked in webhook - if cluster.HasAWSIamConfig() { - if result, err := r.awsIamAuth.EnsureCASecret(ctx, log, cluster); err != nil { - return controller.Result{}, err - } else if result.Return() { - return result, nil - } - } if cluster.IsManaged() { if err := r.clusterValidator.ValidateManagementClusterName(ctx, log, cluster); err != nil { log.Error(err, "Invalid cluster configuration") @@ -390,14 +373,6 @@ func (r *ClusterReconciler) preClusterProviderReconcile(ctx context.Context, log } func (r *ClusterReconciler) postClusterProviderReconcile(ctx context.Context, log logr.Logger, cluster *anywherev1.Cluster) (controller.Result, error) { - if cluster.HasAWSIamConfig() { - if result, err := r.awsIamAuth.Reconcile(ctx, log, cluster); err != nil { - return controller.Result{}, err - } else if result.Return() { - return result, nil - } - } - if err := r.machineHealthCheck.Reconcile(ctx, log, cluster); err != nil { return controller.Result{}, err } @@ -498,12 +473,6 @@ func (r *ClusterReconciler) reconcileDelete(ctx context.Context, log logr.Logger } - if cluster.HasAWSIamConfig() { - if err := r.awsIamAuth.ReconcileDelete(ctx, log, cluster); err != nil { - return ctrl.Result{}, err - } - } - if cluster.IsManaged() { if err := r.packagesClient.ReconcileDelete(ctx, log, r.client, cluster); err != nil { return ctrl.Result{}, fmt.Errorf("deleting packages for cluster %q: %w", cluster.Name, err) diff --git a/controllers/iamconfig_reconciler.go b/controllers/iamconfig_reconciler.go new file mode 100644 index 000000000000..f577002c171a --- /dev/null +++ b/controllers/iamconfig_reconciler.go @@ -0,0 +1,112 @@ +package controllers + +import ( + "context" + + "github.com/go-logr/logr" + apierrors "k8s.io/apimachinery/pkg/api/errors" + kerrors "k8s.io/apimachinery/pkg/util/errors" + "sigs.k8s.io/cluster-api/util/conditions" + "sigs.k8s.io/cluster-api/util/patch" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/source" + + anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1" + "github.com/aws/eks-anywhere/pkg/controller" + "github.com/aws/eks-anywhere/pkg/controller/handlers" +) + +const IAMConfigClusterFinalizerName = "clusters.anywhere.eks.amazonaws.com/iam-finalizer" + +// IAMConfigClusterReconciler reconciles the IAM installation for Clusters. +type IAMConfigClusterReconciler struct { + client client.Client + awsIamAuth AWSIamConfigReconciler +} + +// AWSIamConfigReconciler manages aws-iam-authenticator installation and configuration for an eks-a cluster. +type AWSIamConfigReconciler interface { + EnsureCASecret(ctx context.Context, logger logr.Logger, cluster *anywherev1.Cluster) (controller.Result, error) + Reconcile(ctx context.Context, logger logr.Logger, cluster *anywherev1.Cluster) (controller.Result, error) + ReconcileDelete(ctx context.Context, logger logr.Logger, cluster *anywherev1.Cluster) error +} + +// SetupWithManager sets up the controller with the Manager. +func (r *IAMConfigClusterReconciler) SetupWithManager(mgr ctrl.Manager, log logr.Logger) error { + childObjectHandler := handlers.ChildObjectToClusters(log) + + return ctrl.NewControllerManagedBy(mgr). + For(&anywherev1.Cluster{}). + Watches( + &source.Kind{Type: &anywherev1.AWSIamConfig{}}, + handler.EnqueueRequestsFromMapFunc(childObjectHandler), + ). + Complete(r) +} + +// Reconcile installs AWS IAM components in a cluster. It implements controller-runtime Reconciler. +func (r *IAMConfigClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, reterr error) { + log := ctrl.LoggerFrom(ctx) + cluster := &anywherev1.Cluster{} + if err := r.client.Get(ctx, req.NamespacedName, cluster); err != nil { + if apierrors.IsNotFound(err) { + return ctrl.Result{}, nil + } + return ctrl.Result{}, err + } + + if cluster.HasAWSIamConfig() { + return ctrl.Result{}, nil + } + + patchHelper, err := patch.NewHelper(cluster, r.client) + if err != nil { + return ctrl.Result{}, err + } + + defer func() { + if err := patchCluster(ctx, patchHelper, cluster); err != nil { + reterr = kerrors.NewAggregate([]error{reterr, err}) + } + }() + + // AddFinalizer is idempotent + controllerutil.AddFinalizer(cluster, ClusterFinalizerName) + + if !cluster.DeletionTimestamp.IsZero() { + result, reterr = r.reconcileDelete(ctx, log, cluster) + return result, reterr + } + + result, reterr = r.reconcile(ctx, log, cluster) + return result, reterr +} + +func (r *IAMConfigClusterReconciler) reconcile(ctx context.Context, log logr.Logger, cluster *anywherev1.Cluster) (ctrl.Result, error) { + if result, err := r.awsIamAuth.EnsureCASecret(ctx, log, cluster); err != nil { + return ctrl.Result{}, err + } else if result.Return() { + return result.ToCtrlResult(), nil + } + + if conditions.IsFalse(cluster, anywherev1.ControlPlaneReadyCondition) { + return ctrl.Result{}, nil + } + + result, err := r.awsIamAuth.Reconcile(ctx, log, cluster) + + return result.ToCtrlResult(), err +} + +func (r *IAMConfigClusterReconciler) reconcileDelete(ctx context.Context, log logr.Logger, cluster *anywherev1.Cluster) (ctrl.Result, error) { + if err := r.awsIamAuth.ReconcileDelete(ctx, log, cluster); err != nil { + return ctrl.Result{}, err + } + + controllerutil.RemoveFinalizer(cluster, ClusterFinalizerName) + + return ctrl.Result{}, nil +}