@@ -19,12 +19,13 @@ package controllers
1919import (
2020 "context"
2121 "fmt"
22+ discv1 "k8s.io/api/discovery/v1"
23+ "sigs.k8s.io/controller-runtime/pkg/handler"
2224 "time"
2325
2426 "github.com/aws/aws-sdk-go-v2/aws"
2527 "github.com/pkg/errors"
2628 corev1 "k8s.io/api/core/v1"
27- discv1 "k8s.io/api/discovery/v1"
2829 "k8s.io/client-go/tools/record"
2930 "k8s.io/client-go/util/workqueue"
3031 "sigs.k8s.io/aws-load-balancer-controller/controllers/elbv2/eventhandlers"
@@ -48,15 +49,16 @@ const (
4849
4950// NewTargetGroupBindingReconciler constructs new targetGroupBindingReconciler
5051func NewTargetGroupBindingReconciler (k8sClient client.Client , eventRecorder record.EventRecorder , finalizerManager k8s.FinalizerManager ,
51- tgbResourceManager targetgroupbinding.ResourceManager , config config.ControllerConfig ,
52+ tgbResourceManager targetgroupbinding.ResourceManager , config config.ControllerConfig , deferredTargetGroupBindingReconciler DeferredTargetGroupBindingReconciler ,
5253 logger logr.Logger ) * targetGroupBindingReconciler {
5354
5455 return & targetGroupBindingReconciler {
55- k8sClient : k8sClient ,
56- eventRecorder : eventRecorder ,
57- finalizerManager : finalizerManager ,
58- tgbResourceManager : tgbResourceManager ,
59- logger : logger ,
56+ k8sClient : k8sClient ,
57+ eventRecorder : eventRecorder ,
58+ finalizerManager : finalizerManager ,
59+ tgbResourceManager : tgbResourceManager ,
60+ deferredTargetGroupBindingReconciler : deferredTargetGroupBindingReconciler ,
61+ logger : logger ,
6062
6163 maxConcurrentReconciles : config .TargetGroupBindingMaxConcurrentReconciles ,
6264 maxExponentialBackoffDelay : config .TargetGroupBindingMaxExponentialBackoffDelay ,
@@ -66,11 +68,12 @@ func NewTargetGroupBindingReconciler(k8sClient client.Client, eventRecorder reco
6668
6769// targetGroupBindingReconciler reconciles a TargetGroupBinding object
6870type targetGroupBindingReconciler struct {
69- k8sClient client.Client
70- eventRecorder record.EventRecorder
71- finalizerManager k8s.FinalizerManager
72- tgbResourceManager targetgroupbinding.ResourceManager
73- logger logr.Logger
71+ k8sClient client.Client
72+ eventRecorder record.EventRecorder
73+ finalizerManager k8s.FinalizerManager
74+ tgbResourceManager targetgroupbinding.ResourceManager
75+ deferredTargetGroupBindingReconciler DeferredTargetGroupBindingReconciler
76+ logger logr.Logger
7477
7578 maxConcurrentReconciles int
7679 maxExponentialBackoffDelay time.Duration
@@ -110,11 +113,18 @@ func (r *targetGroupBindingReconciler) reconcileTargetGroupBinding(ctx context.C
110113 return err
111114 }
112115
113- if err := r .tgbResourceManager .Reconcile (ctx , tgb ); err != nil {
116+ checkPoint , deferred , err := r .tgbResourceManager .Reconcile (ctx , tgb )
117+
118+ if err != nil {
114119 return err
115120 }
116121
117- if err := r .updateTargetGroupBindingStatus (ctx , tgb ); err != nil {
122+ if deferred {
123+ r .deferredTargetGroupBindingReconciler .Enqueue (tgb )
124+ return nil
125+ }
126+
127+ if err := r .updateTargetGroupBindingStatus (ctx , tgb , checkPoint ); err != nil {
118128 r .eventRecorder .Event (tgb , corev1 .EventTypeWarning , k8s .TargetGroupBindingEventReasonFailedUpdateStatus , fmt .Sprintf ("Failed update status due to %v" , err ))
119129 return err
120130 }
@@ -137,15 +147,24 @@ func (r *targetGroupBindingReconciler) cleanupTargetGroupBinding(ctx context.Con
137147 return nil
138148}
139149
140- func (r * targetGroupBindingReconciler ) updateTargetGroupBindingStatus (ctx context.Context , tgb * elbv2api.TargetGroupBinding ) error {
141- if aws .ToInt64 (tgb .Status .ObservedGeneration ) == tgb .Generation {
150+ func (r * targetGroupBindingReconciler ) updateTargetGroupBindingStatus (ctx context.Context , tgb * elbv2api.TargetGroupBinding , newCheckPoint string ) error {
151+ savedCheckPoint := targetgroupbinding .GetTGBReconcileCheckpoint (tgb )
152+ if aws .ToInt64 (tgb .Status .ObservedGeneration ) == tgb .Generation && savedCheckPoint == newCheckPoint {
142153 return nil
143154 }
155+
144156 tgbOld := tgb .DeepCopy ()
157+ targetgroupbinding .SaveTGBReconcileCheckpoint (tgb , newCheckPoint )
158+
159+ if err := r .k8sClient .Patch (ctx , tgb , client .MergeFrom (tgbOld )); err != nil {
160+ return errors .Wrapf (err , "failed to update targetGroupBinding checkpoint: %v" , k8s .NamespacedName (tgb ))
161+ }
162+
145163 tgb .Status .ObservedGeneration = aws .Int64 (tgb .Generation )
146164 if err := r .k8sClient .Status ().Patch (ctx , tgb , client .MergeFrom (tgbOld )); err != nil {
147165 return errors .Wrapf (err , "failed to update targetGroupBinding status: %v" , k8s .NamespacedName (tgb ))
148166 }
167+
149168 return nil
150169}
151170
@@ -159,34 +178,29 @@ func (r *targetGroupBindingReconciler) SetupWithManager(ctx context.Context, mgr
159178 nodeEventsHandler := eventhandlers .NewEnqueueRequestsForNodeEvent (r .k8sClient ,
160179 r .logger .WithName ("eventHandlers" ).WithName ("node" ))
161180
162- // Use the config flag to decide whether to use and watch an Endpoints event handler or an EndpointSlices event handler
181+ var eventHandler handler.EventHandler
182+ var clientObj client.Object
183+
163184 if r .enableEndpointSlices {
164- epSliceEventsHandler := eventhandlers .NewEnqueueRequestsForEndpointSlicesEvent (r .k8sClient ,
185+ clientObj = & discv1.EndpointSlice {}
186+ eventHandler = eventhandlers .NewEnqueueRequestsForEndpointSlicesEvent (r .k8sClient ,
165187 r .logger .WithName ("eventHandlers" ).WithName ("endpointslices" ))
166- return ctrl .NewControllerManagedBy (mgr ).
167- For (& elbv2api.TargetGroupBinding {}).
168- Named (controllerName ).
169- Watches (& corev1.Service {}, svcEventHandler ).
170- Watches (& discv1.EndpointSlice {}, epSliceEventsHandler ).
171- Watches (& corev1.Node {}, nodeEventsHandler ).
172- WithOptions (controller.Options {
173- MaxConcurrentReconciles : r .maxConcurrentReconciles ,
174- RateLimiter : workqueue .NewItemExponentialFailureRateLimiter (5 * time .Millisecond , r .maxExponentialBackoffDelay )}).
175- Complete (r )
176188 } else {
177- epsEventsHandler := eventhandlers .NewEnqueueRequestsForEndpointsEvent (r .k8sClient ,
189+ clientObj = & corev1.Endpoints {}
190+ eventHandler = eventhandlers .NewEnqueueRequestsForEndpointsEvent (r .k8sClient ,
178191 r .logger .WithName ("eventHandlers" ).WithName ("endpoints" ))
179- return ctrl .NewControllerManagedBy (mgr ).
180- For (& elbv2api.TargetGroupBinding {}).
181- Named (controllerName ).
182- Watches (& corev1.Service {}, svcEventHandler ).
183- Watches (& corev1.Endpoints {}, epsEventsHandler ).
184- Watches (& corev1.Node {}, nodeEventsHandler ).
185- WithOptions (controller.Options {
186- MaxConcurrentReconciles : r .maxConcurrentReconciles ,
187- RateLimiter : workqueue .NewItemExponentialFailureRateLimiter (5 * time .Millisecond , r .maxExponentialBackoffDelay )}).
188- Complete (r )
189192 }
193+
194+ return ctrl .NewControllerManagedBy (mgr ).
195+ For (& elbv2api.TargetGroupBinding {}).
196+ Named (controllerName ).
197+ Watches (& corev1.Service {}, svcEventHandler ).
198+ Watches (clientObj , eventHandler ).
199+ Watches (& corev1.Node {}, nodeEventsHandler ).
200+ WithOptions (controller.Options {
201+ MaxConcurrentReconciles : r .maxConcurrentReconciles ,
202+ RateLimiter : workqueue .NewItemExponentialFailureRateLimiter (5 * time .Millisecond , r .maxExponentialBackoffDelay )}).
203+ Complete (r )
190204}
191205
192206func (r * targetGroupBindingReconciler ) setupIndexes (ctx context.Context , fieldIndexer client.FieldIndexer ) error {
0 commit comments