sigs.k8s.io/cluster-api-provider-aws@v1.5.5/exp/controllers/awsfargatepool_controller.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package controllers 18 19 import ( 20 "context" 21 "fmt" 22 23 "github.com/go-logr/logr" 24 "github.com/pkg/errors" 25 apierrors "k8s.io/apimachinery/pkg/api/errors" 26 "k8s.io/client-go/tools/record" 27 ctrl "sigs.k8s.io/controller-runtime" 28 "sigs.k8s.io/controller-runtime/pkg/client" 29 "sigs.k8s.io/controller-runtime/pkg/controller" 30 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 31 "sigs.k8s.io/controller-runtime/pkg/handler" 32 "sigs.k8s.io/controller-runtime/pkg/reconcile" 33 "sigs.k8s.io/controller-runtime/pkg/source" 34 35 ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/controlplane/eks/api/v1beta1" 36 expinfrav1 "sigs.k8s.io/cluster-api-provider-aws/exp/api/v1beta1" 37 "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" 38 "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/eks" 39 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 40 "sigs.k8s.io/cluster-api/util" 41 "sigs.k8s.io/cluster-api/util/conditions" 42 "sigs.k8s.io/cluster-api/util/predicates" 43 ) 44 45 // AWSFargateProfileReconciler reconciles a AWSFargateProfile object. 46 type AWSFargateProfileReconciler struct { 47 client.Client 48 Recorder record.EventRecorder 49 Endpoints []scope.ServiceEndpoint 50 EnableIAM bool 51 WatchFilterValue string 52 } 53 54 // SetupWithManager is used to setup the controller. 55 func (r *AWSFargateProfileReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error { 56 managedControlPlaneToFargateProfileMap := managedControlPlaneToFargateProfileMapFunc(r.Client, ctrl.LoggerFrom(ctx)) 57 return ctrl.NewControllerManagedBy(mgr). 58 For(&expinfrav1.AWSFargateProfile{}). 59 WithOptions(options). 60 WithEventFilter(predicates.ResourceNotPausedAndHasFilterLabel(ctrl.LoggerFrom(ctx), r.WatchFilterValue)). 61 Watches( 62 &source.Kind{Type: &ekscontrolplanev1.AWSManagedControlPlane{}}, 63 handler.EnqueueRequestsFromMapFunc(managedControlPlaneToFargateProfileMap), 64 ). 65 Complete(r) 66 } 67 68 // +kubebuilder:rbac:groups=core,resources=events,verbs=get;list;watch;create;patch 69 // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters;clusters/status,verbs=get;list;watch 70 // +kubebuilder:rbac:groups=controlplane.cluster.x-k8s.io,resources=awsmanagedcontrolplanes;awsmanagedcontrolplanes/status,verbs=get;list;watch 71 // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsfargateprofiles,verbs=get;list;watch;create;update;patch;delete 72 // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=awsfargateprofiles/status,verbs=get;update;patch 73 74 // Reconcile reconciles AWSFargateProfiles. 75 func (r *AWSFargateProfileReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) { 76 log := ctrl.LoggerFrom(ctx) 77 78 fargateProfile := &expinfrav1.AWSFargateProfile{} 79 if err := r.Get(ctx, req.NamespacedName, fargateProfile); err != nil { 80 if apierrors.IsNotFound(err) { 81 return ctrl.Result{}, nil 82 } 83 return ctrl.Result{Requeue: true}, nil 84 } 85 86 cluster, err := util.GetClusterByName(ctx, r.Client, fargateProfile.Namespace, fargateProfile.Spec.ClusterName) 87 if err != nil { 88 log.Info("Failed to retrieve Cluster from AWSFargateProfile") 89 return reconcile.Result{}, nil 90 } 91 92 log = log.WithValues("Cluster", cluster.Name) 93 94 controlPlaneKey := client.ObjectKey{ 95 Namespace: fargateProfile.Namespace, 96 Name: cluster.Spec.ControlPlaneRef.Name, 97 } 98 controlPlane := &ekscontrolplanev1.AWSManagedControlPlane{} 99 if err := r.Client.Get(ctx, controlPlaneKey, controlPlane); err != nil { 100 log.Info("Failed to retrieve ControlPlane from AWSFargateProfile") 101 return reconcile.Result{}, nil 102 } 103 104 fargateProfileScope, err := scope.NewFargateProfileScope(scope.FargateProfileScopeParams{ 105 Client: r.Client, 106 ControllerName: "awsfargateprofile", 107 Cluster: cluster, 108 ControlPlane: controlPlane, 109 FargateProfile: fargateProfile, 110 EnableIAM: r.EnableIAM, 111 Endpoints: r.Endpoints, 112 }) 113 if err != nil { 114 return ctrl.Result{}, errors.Wrap(err, "failed to create scope") 115 } 116 117 defer func() { 118 applicableConditions := []clusterv1.ConditionType{ 119 expinfrav1.IAMFargateRolesReadyCondition, 120 expinfrav1.EKSFargateProfileReadyCondition, 121 } 122 123 conditions.SetSummary(fargateProfileScope.FargateProfile, conditions.WithConditions(applicableConditions...), conditions.WithStepCounter()) 124 125 if err := fargateProfileScope.Close(); err != nil && reterr == nil { 126 reterr = err 127 } 128 }() 129 130 if !controlPlane.Status.Ready { 131 log.Info("Control plane is not ready yet") 132 conditions.MarkFalse(fargateProfile, clusterv1.ReadyCondition, expinfrav1.WaitingForEKSControlPlaneReason, clusterv1.ConditionSeverityInfo, "") 133 return ctrl.Result{}, nil 134 } 135 136 if !fargateProfile.ObjectMeta.DeletionTimestamp.IsZero() { 137 return r.reconcileDelete(ctx, fargateProfileScope) 138 } 139 140 return r.reconcileNormal(ctx, fargateProfileScope) 141 } 142 143 func (r *AWSFargateProfileReconciler) reconcileNormal( 144 _ context.Context, 145 fargateProfileScope *scope.FargateProfileScope, 146 ) (ctrl.Result, error) { 147 fargateProfileScope.Info("Reconciling AWSFargateProfile") 148 149 controllerutil.AddFinalizer(fargateProfileScope.FargateProfile, expinfrav1.FargateProfileFinalizer) 150 if err := fargateProfileScope.PatchObject(); err != nil { 151 return ctrl.Result{}, err 152 } 153 154 ekssvc := eks.NewFargateService(fargateProfileScope) 155 156 res, err := ekssvc.Reconcile() 157 if err != nil { 158 return res, errors.Wrapf(err, "failed to reconcile fargate profile for AWSFargateProfile %s/%s", fargateProfileScope.FargateProfile.Namespace, fargateProfileScope.FargateProfile.Name) 159 } 160 161 return res, nil 162 } 163 164 func (r *AWSFargateProfileReconciler) reconcileDelete( 165 _ context.Context, 166 fargateProfileScope *scope.FargateProfileScope, 167 ) (ctrl.Result, error) { 168 fargateProfileScope.Info("Reconciling deletion of AWSFargateProfile") 169 170 ekssvc := eks.NewFargateService(fargateProfileScope) 171 172 res, err := ekssvc.ReconcileDelete() 173 if err != nil { 174 return res, errors.Wrapf(err, "failed to reconcile fargate profile deletion for AWSFargateProfile %s/%s", fargateProfileScope.FargateProfile.Namespace, fargateProfileScope.FargateProfile.Name) 175 } 176 177 if res.IsZero() { 178 controllerutil.RemoveFinalizer(fargateProfileScope.FargateProfile, expinfrav1.FargateProfileFinalizer) 179 } 180 181 return res, nil 182 } 183 184 func managedControlPlaneToFargateProfileMapFunc(c client.Client, log logr.Logger) handler.MapFunc { 185 return func(o client.Object) []ctrl.Request { 186 ctx := context.Background() 187 188 awsControlPlane, ok := o.(*ekscontrolplanev1.AWSManagedControlPlane) 189 if !ok { 190 panic(fmt.Sprintf("Expected a AWSManagedControlPlane but got a %T", o)) 191 } 192 193 if !awsControlPlane.ObjectMeta.DeletionTimestamp.IsZero() { 194 return nil 195 } 196 197 clusterKey, err := GetOwnerClusterKey(awsControlPlane.ObjectMeta) 198 if err != nil { 199 log.Error(err, "couldn't get AWS control plane owner ObjectKey") 200 return nil 201 } 202 if clusterKey == nil { 203 return nil 204 } 205 206 fargateProfileForClusterList := expinfrav1.AWSFargateProfileList{} 207 if err := c.List( 208 ctx, &fargateProfileForClusterList, client.InNamespace(clusterKey.Namespace), client.MatchingLabels{clusterv1.ClusterLabelName: clusterKey.Name}, 209 ); err != nil { 210 log.Error(err, "couldn't list fargate profiles for cluster") 211 return nil 212 } 213 214 var results []ctrl.Request 215 for i := range fargateProfileForClusterList.Items { 216 fp := fargateProfileForClusterList.Items[i] 217 results = append(results, reconcile.Request{ 218 NamespacedName: client.ObjectKey{ 219 Namespace: fp.Namespace, 220 Name: fp.Name, 221 }, 222 }) 223 } 224 225 return results 226 } 227 }