From 3c6dab8f73ebae6544c359bc1f21378269f65611 Mon Sep 17 00:00:00 2001 From: Michael Beaumont Date: Wed, 16 Sep 2020 15:54:15 +0200 Subject: [PATCH] Reconcile AWSManagedMachinePool on AWSManagedControlPlane changes --- .../awsmanagedmachinepool_controller.go | 76 ++++++++++++++++++- pkg/cloud/services/eks/nodegroup.go | 6 +- pkg/cloud/services/eks/roles.go | 6 +- 3 files changed, 79 insertions(+), 9 deletions(-) diff --git a/exp/controllers/awsmanagedmachinepool_controller.go b/exp/controllers/awsmanagedmachinepool_controller.go index c436d44016..a670cdf29b 100644 --- a/exp/controllers/awsmanagedmachinepool_controller.go +++ b/exp/controllers/awsmanagedmachinepool_controller.go @@ -33,6 +33,7 @@ import ( "sigs.k8s.io/cluster-api/util/predicates" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" @@ -57,6 +58,11 @@ type AWSManagedMachinePoolReconciler struct { // SetupWithManager is used to setup the controller func (r *AWSManagedMachinePoolReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error { + gvk, err := apiutil.GVKForObject(new(infrav1exp.AWSManagedMachinePool), mgr.GetScheme()) + if err != nil { + return errors.Wrapf(err, "failed to find GVK for AWSManagedMachinePool") + } + managedControlPlaneToManagedMachinePoolMap := managedControlPlaneToManagedMachinePoolMapFunc(r.Client, gvk, r.Log) return ctrl.NewControllerManagedBy(mgr). For(&infrav1exp.AWSManagedMachinePool{}). WithOptions(options). @@ -64,7 +70,13 @@ func (r *AWSManagedMachinePoolReconciler) SetupWithManager(mgr ctrl.Manager, opt Watches( &source.Kind{Type: &capiv1exp.MachinePool{}}, &handler.EnqueueRequestsFromMapFunc{ - ToRequests: machinePoolToInfrastructureMapFunc(infrav1exp.GroupVersion.WithKind("AWSManagedMachinePool")), + ToRequests: machinePoolToInfrastructureMapFunc(gvk), + }, + ). + Watches( + &source.Kind{Type: &controlplanev1.AWSManagedControlPlane{}}, + &handler.EnqueueRequestsFromMapFunc{ + ToRequests: managedControlPlaneToManagedMachinePoolMap, }, ). Complete(r) @@ -197,3 +209,65 @@ func (r *AWSManagedMachinePoolReconciler) reconcileDelete( return reconcile.Result{}, nil } + +// GetOwnerClusterKey returns only the Cluster name and namespace +func GetOwnerClusterKey(obj metav1.ObjectMeta) (*client.ObjectKey, error) { + for _, ref := range obj.OwnerReferences { + if ref.Kind != "Cluster" { + continue + } + gv, err := schema.ParseGroupVersion(ref.APIVersion) + if err != nil { + return nil, errors.WithStack(err) + } + if gv.Group == clusterv1.GroupVersion.Group { + return &client.ObjectKey{ + Namespace: obj.Namespace, + Name: ref.Name, + }, nil + } + } + return nil, nil +} + +func managedControlPlaneToManagedMachinePoolMapFunc(c client.Client, gvk schema.GroupVersionKind, log logr.Logger) handler.ToRequestsFunc { + return func(o handler.MapObject) []reconcile.Request { + ctx := context.Background() + awsControlPlane, ok := o.Object.(*controlplanev1.AWSManagedControlPlane) + if !ok { + return nil + } + if !awsControlPlane.ObjectMeta.DeletionTimestamp.IsZero() { + return nil + } + + clusterKey, err := GetOwnerClusterKey(awsControlPlane.ObjectMeta) + if err != nil { + log.Error(err, "couldn't get AWS control plane owner ObjectKey") + return nil + } + if clusterKey == nil { + return nil + } + + managedPoolForClusterList := capiv1exp.MachinePoolList{} + if err := c.List( + ctx, &managedPoolForClusterList, client.InNamespace(clusterKey.Namespace), client.MatchingLabels{clusterv1.ClusterLabelName: clusterKey.Name}, + ); err != nil { + log.Error(err, "couldn't list pools for cluster") + return nil + } + + mapFunc := machinePoolToInfrastructureMapFunc(gvk) + + var results []ctrl.Request + for i := range managedPoolForClusterList.Items { + managedPool := mapFunc.Map(handler.MapObject{ + Object: &managedPoolForClusterList.Items[i], + }) + results = append(results, managedPool...) + } + + return results + } +} diff --git a/pkg/cloud/services/eks/nodegroup.go b/pkg/cloud/services/eks/nodegroup.go index cbfbcdb641..6e8d52d72a 100644 --- a/pkg/cloud/services/eks/nodegroup.go +++ b/pkg/cloud/services/eks/nodegroup.go @@ -178,10 +178,8 @@ func (s *NodegroupService) deleteNodegroupAndWait() (reterr error) { if err := s.scope.NodegroupReadyFalse("DeletingFailed", reterr.Error()); err != nil { reterr = err } - } else { - if err := s.scope.NodegroupReadyFalse(clusterv1.DeletedReason, ""); err != nil { - reterr = err - } + } else if err := s.scope.NodegroupReadyFalse(clusterv1.DeletedReason, ""); err != nil { + reterr = err } }() input := &eks.DeleteNodegroupInput{ diff --git a/pkg/cloud/services/eks/roles.go b/pkg/cloud/services/eks/roles.go index a534ee626e..1f1fe918ab 100644 --- a/pkg/cloud/services/eks/roles.go +++ b/pkg/cloud/services/eks/roles.go @@ -204,10 +204,8 @@ func (s *NodegroupService) deleteNodegroupIAMRole() (reterr error) { if err := s.scope.IAMReadyFalse("DeletingFailed", reterr.Error()); err != nil { reterr = err } - } else { - if err := s.scope.IAMReadyFalse(clusterv1.DeletedReason, ""); err != nil { - reterr = err - } + } else if err := s.scope.IAMReadyFalse(clusterv1.DeletedReason, ""); err != nil { + reterr = err } }() roleName := s.scope.RoleName()