@@ -35,9 +35,12 @@ import (
3535 ctrl "sigs.k8s.io/controller-runtime"
3636 "sigs.k8s.io/controller-runtime/pkg/client"
3737 "sigs.k8s.io/controller-runtime/pkg/controller"
38+ "sigs.k8s.io/controller-runtime/pkg/event"
3839 "sigs.k8s.io/controller-runtime/pkg/reconcile"
40+ "sigs.k8s.io/controller-runtime/pkg/source"
3941
4042 agaapi "sigs.k8s.io/aws-load-balancer-controller/apis/aga/v1beta1"
43+ "sigs.k8s.io/aws-load-balancer-controller/controllers/aga/eventhandlers"
4144 "sigs.k8s.io/aws-load-balancer-controller/pkg/aga"
4245 "sigs.k8s.io/aws-load-balancer-controller/pkg/config"
4346 "sigs.k8s.io/aws-load-balancer-controller/pkg/deploy"
@@ -50,6 +53,7 @@ import (
5053 "sigs.k8s.io/aws-load-balancer-controller/pkg/model/core"
5154 "sigs.k8s.io/aws-load-balancer-controller/pkg/runtime"
5255 agastatus "sigs.k8s.io/aws-load-balancer-controller/pkg/status/aga"
56+ gwclientset "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned"
5357)
5458
5559const (
@@ -64,6 +68,9 @@ const (
6468 requeueMessage = "Monitoring provisioning state"
6569 statusUpdateRequeueTime = 1 * time .Minute
6670
71+ // Status reason constants
72+ EndpointLoadFailed = "EndpointLoadFailed"
73+
6774 // Metric stage constants
6875 MetricStageFetchGlobalAccelerator = "fetch_globalAccelerator"
6976 MetricStageAddFinalizers = "add_finalizers"
@@ -108,6 +115,18 @@ func NewGlobalAcceleratorReconciler(k8sClient client.Client, eventRecorder recor
108115 // Create status updater
109116 statusUpdater := agastatus .NewStatusUpdater (k8sClient , logger )
110117
118+ // Create reference tracker for endpoint tracking
119+ referenceTracker := aga .NewReferenceTracker (logger .WithName ("reference-tracker" ))
120+
121+ // Create DNS resolver
122+ dnsResolver , err := aga .NewDNSResolver (cloud .ELBV2 ())
123+ if err != nil {
124+ logger .Error (err , "Failed to create DNS resolver" )
125+ }
126+
127+ // Create unified endpoint loader
128+ endpointLoader := aga .NewEndpointLoader (k8sClient , dnsResolver , logger .WithName ("endpoint-loader" ))
129+
111130 return & globalAcceleratorReconciler {
112131 k8sClient : k8sClient ,
113132 eventRecorder : eventRecorder ,
@@ -120,6 +139,13 @@ func NewGlobalAcceleratorReconciler(k8sClient client.Client, eventRecorder recor
120139 metricsCollector : metricsCollector ,
121140 reconcileTracker : reconcileCounters .IncrementAGA ,
122141
142+ // Components for endpoint reference tracking
143+ referenceTracker : referenceTracker ,
144+ dnsResolver : dnsResolver ,
145+
146+ // Unified endpoint loader
147+ endpointLoader : endpointLoader ,
148+
123149 maxConcurrentReconciles : config .GlobalAcceleratorMaxConcurrentReconciles ,
124150 maxExponentialBackoffDelay : config .GlobalAcceleratorMaxExponentialBackoffDelay ,
125151 }
@@ -138,6 +164,21 @@ type globalAcceleratorReconciler struct {
138164 metricsCollector lbcmetrics.MetricCollector
139165 reconcileTracker func (namespaceName ktypes.NamespacedName )
140166
167+ // Components for endpoint reference tracking
168+ referenceTracker * aga.ReferenceTracker
169+ dnsResolver * aga.DNSResolver
170+
171+ // Unified endpoint loader
172+ endpointLoader aga.EndpointLoader
173+
174+ // Resources manager for dedicated endpoint resource watchers
175+ endpointResourcesManager aga.EndpointResourcesManager
176+
177+ // Event channels for dedicated watchers
178+ serviceEventChan chan event.GenericEvent
179+ ingressEventChan chan event.GenericEvent
180+ gatewayEventChan chan event.GenericEvent
181+
141182 maxConcurrentReconciles int
142183 maxExponentialBackoffDelay time.Duration
143184}
@@ -194,6 +235,13 @@ func (r *globalAcceleratorReconciler) reconcileGlobalAccelerator(ctx context.Con
194235
195236func (r * globalAcceleratorReconciler ) cleanupGlobalAccelerator (ctx context.Context , ga * agaapi.GlobalAccelerator ) error {
196237 if k8s .HasFinalizer (ga , shared_constants .GlobalAcceleratorFinalizer ) {
238+ // Clean up references in the reference tracker
239+ gaKey := k8s .NamespacedName (ga )
240+ r .referenceTracker .RemoveGA (gaKey )
241+
242+ // Clean up resource watches
243+ r .endpointResourcesManager .RemoveGA (gaKey )
244+
197245 // TODO: Implement cleanup logic for AWS Global Accelerator resources (Only cleaning up accelerator for now)
198246 if err := r .cleanupGlobalAcceleratorResources (ctx , ga ); err != nil {
199247 r .eventRecorder .Event (ga , corev1 .EventTypeWarning , k8s .GlobalAcceleratorEventReasonFailedCleanup , fmt .Sprintf ("Failed cleanup due to %v" , err ))
@@ -224,6 +272,29 @@ func (r *globalAcceleratorReconciler) buildModel(ctx context.Context, ga *agaapi
224272
225273func (r * globalAcceleratorReconciler ) reconcileGlobalAcceleratorResources (ctx context.Context , ga * agaapi.GlobalAccelerator ) error {
226274 r .logger .Info ("Reconciling GlobalAccelerator resources" , "globalAccelerator" , k8s .NamespacedName (ga ))
275+
276+ // Get all endpoints from GA
277+ endpoints := aga .GetAllEndpointsFromGA (ga )
278+
279+ // Track referenced endpoints
280+ r .referenceTracker .UpdateReferencesForGA (ga , endpoints )
281+
282+ // Update resource watches with the endpointResourcesManager
283+ r .endpointResourcesManager .MonitorEndpointResources (ga , endpoints )
284+
285+ // Validate and load endpoint status using the endpoint loader
286+ _ , fatalErrors := r .endpointLoader .LoadEndpoints (ctx , ga , endpoints )
287+ if len (fatalErrors ) > 0 {
288+ err := fmt .Errorf ("failed to load endpoints: %v" , fatalErrors [0 ])
289+ r .logger .Error (err , "Fatal error loading endpoints" )
290+
291+ // Handle other endpoint loading errors
292+ if statusErr := r .statusUpdater .UpdateStatusFailure (ctx , ga , EndpointLoadFailed , err .Error ()); statusErr != nil {
293+ r .logger .Error (statusErr , "Failed to update GlobalAccelerator status after endpoint load failure" )
294+ }
295+ return err
296+ }
297+
227298 var stack core.Stack
228299 var accelerator * agamodel.Accelerator
229300 var err error
@@ -335,21 +406,91 @@ func (r *globalAcceleratorReconciler) SetupWithManager(ctx context.Context, mgr
335406 return nil
336407 }
337408
338- if err := r .setupIndexes (ctx , mgr .GetFieldIndexer ()); err != nil {
409+ // Create event channels for dedicated watchers
410+ r .serviceEventChan = make (chan event.GenericEvent )
411+ r .ingressEventChan = make (chan event.GenericEvent )
412+ r .gatewayEventChan = make (chan event.GenericEvent )
413+
414+ // Initialize Gateway API client using the same config
415+ gwClient , err := gwclientset .NewForConfig (mgr .GetConfig ())
416+ if err != nil {
417+ r .logger .Error (err , "Failed to create Gateway API client" )
339418 return err
340419 }
341420
342- // TODO: Add event handlers for Services, Ingresses, and Gateways
343- // that are referenced by GlobalAccelerator endpoints
421+ // Initialize the endpoint resources manager with clients
422+ r .endpointResourcesManager = aga .NewEndpointResourcesManager (
423+ clientSet ,
424+ gwClient ,
425+ r .serviceEventChan ,
426+ r .ingressEventChan ,
427+ r .gatewayEventChan ,
428+ r .logger .WithName ("endpoint-resources-manager" ),
429+ )
344430
345- return ctrl .NewControllerManagedBy (mgr ).
431+ if err := r .setupIndexes (ctx , mgr .GetFieldIndexer ()); err != nil {
432+ return err
433+ }
434+
435+ // Set up the controller builder
436+ ctrl , err := ctrl .NewControllerManagedBy (mgr ).
346437 For (& agaapi.GlobalAccelerator {}).
347438 Named (controllerName ).
348439 WithOptions (controller.Options {
349440 MaxConcurrentReconciles : r .maxConcurrentReconciles ,
350441 RateLimiter : workqueue .NewTypedItemExponentialFailureRateLimiter [reconcile.Request ](5 * time .Second , r .maxExponentialBackoffDelay ),
351442 }).
352- Complete (r )
443+ Build (r )
444+
445+ if err != nil {
446+ return err
447+ }
448+
449+ // Setup watches for resource events
450+ if err := r .setupGlobalAcceleratorWatches (ctrl ); err != nil {
451+ return err
452+ }
453+
454+ return nil
455+ }
456+
457+ // setupGlobalAcceleratorWatches sets up watches for resources that can trigger reconciliation of GlobalAccelerator objects
458+ func (r * globalAcceleratorReconciler ) setupGlobalAcceleratorWatches (c controller.Controller ) error {
459+ loggerPrefix := r .logger .WithName ("eventHandlers" )
460+
461+ // Create handlers for our dedicated watchers
462+ serviceHandler := eventhandlers .NewEnqueueRequestsForResourceEvent (
463+ aga .ServiceResourceType ,
464+ r .referenceTracker ,
465+ loggerPrefix .WithName ("service-handler" ),
466+ )
467+
468+ ingressHandler := eventhandlers .NewEnqueueRequestsForResourceEvent (
469+ aga .IngressResourceType ,
470+ r .referenceTracker ,
471+ loggerPrefix .WithName ("ingress-handler" ),
472+ )
473+
474+ gatewayHandler := eventhandlers .NewEnqueueRequestsForResourceEvent (
475+ aga .GatewayResourceType ,
476+ r .referenceTracker ,
477+ loggerPrefix .WithName ("gateway-handler" ),
478+ )
479+
480+ // Add watches using the channel sources with event handlers
481+ if err := c .Watch (source .Channel (r .serviceEventChan , serviceHandler )); err != nil {
482+ return err
483+ }
484+
485+ if err := c .Watch (source .Channel (r .ingressEventChan , ingressHandler )); err != nil {
486+ return err
487+ }
488+
489+ if err := c .Watch (source .Channel (r .gatewayEventChan , gatewayHandler )); err != nil {
490+ return err
491+ }
492+
493+ return nil
353494}
354495
355496func (r * globalAcceleratorReconciler ) setupIndexes (ctx context.Context , fieldIndexer client.FieldIndexer ) error {
0 commit comments