@@ -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 (
@@ -83,7 +87,7 @@ const (
8387func NewGlobalAcceleratorReconciler (k8sClient client.Client , eventRecorder record.EventRecorder , finalizerManager k8s.FinalizerManager , config config.ControllerConfig , cloud services.Cloud , logger logr.Logger , metricsCollector lbcmetrics.MetricCollector , reconcileCounters * metricsutil.ReconcileCounters ) * globalAcceleratorReconciler {
8488
8589 // Create tracking provider
86- trackingProvider := tracking .NewDefaultProvider (agaTagPrefix , config .ClusterName , tracking .WithRegion (config . AWSConfig . Region ))
90+ trackingProvider := tracking .NewDefaultProvider (agaTagPrefix , config .ClusterName , tracking .WithRegion (cloud . Region () ))
8791
8892 // Create model builder
8993 agaModelBuilder := aga .NewDefaultModelBuilder (
@@ -92,7 +96,7 @@ func NewGlobalAcceleratorReconciler(k8sClient client.Client, eventRecorder recor
9296 trackingProvider ,
9397 config .FeatureGates ,
9498 config .ClusterName ,
95- config . AWSConfig . Region ,
99+ cloud . Region () ,
96100 config .DefaultTags ,
97101 config .ExternalManagedTags ,
98102 logger .WithName ("aga-model-builder" ),
@@ -108,6 +112,18 @@ func NewGlobalAcceleratorReconciler(k8sClient client.Client, eventRecorder recor
108112 // Create status updater
109113 statusUpdater := agastatus .NewStatusUpdater (k8sClient , logger )
110114
115+ // Create reference tracker for endpoint tracking
116+ referenceTracker := aga .NewReferenceTracker (logger .WithName ("reference-tracker" ))
117+
118+ // Create DNS resolver
119+ dnsResolver , err := aga .NewDNSResolver (cloud .ELBV2 ())
120+ if err != nil {
121+ logger .Error (err , "Failed to create DNS resolver" )
122+ }
123+
124+ // Create unified endpoint loader
125+ endpointLoader := aga .NewEndpointLoader (k8sClient , dnsResolver , logger .WithName ("endpoint-loader" ))
126+
111127 return & globalAcceleratorReconciler {
112128 k8sClient : k8sClient ,
113129 eventRecorder : eventRecorder ,
@@ -120,6 +136,13 @@ func NewGlobalAcceleratorReconciler(k8sClient client.Client, eventRecorder recor
120136 metricsCollector : metricsCollector ,
121137 reconcileTracker : reconcileCounters .IncrementAGA ,
122138
139+ // Components for endpoint reference tracking
140+ referenceTracker : referenceTracker ,
141+ dnsResolver : dnsResolver ,
142+
143+ // Unified endpoint loader
144+ endpointLoader : endpointLoader ,
145+
123146 maxConcurrentReconciles : config .GlobalAcceleratorMaxConcurrentReconciles ,
124147 maxExponentialBackoffDelay : config .GlobalAcceleratorMaxExponentialBackoffDelay ,
125148 }
@@ -138,6 +161,21 @@ type globalAcceleratorReconciler struct {
138161 metricsCollector lbcmetrics.MetricCollector
139162 reconcileTracker func (namespaceName ktypes.NamespacedName )
140163
164+ // Components for endpoint reference tracking
165+ referenceTracker * aga.ReferenceTracker
166+ dnsResolver * aga.DNSResolver
167+
168+ // Unified endpoint loader
169+ endpointLoader aga.EndpointLoader
170+
171+ // Resources manager for dedicated endpoint resource watchers
172+ endpointResourcesManager aga.EndpointResourcesManager
173+
174+ // Event channels for dedicated watchers
175+ serviceEventChan chan event.GenericEvent
176+ ingressEventChan chan event.GenericEvent
177+ gatewayEventChan chan event.GenericEvent
178+
141179 maxConcurrentReconciles int
142180 maxExponentialBackoffDelay time.Duration
143181}
@@ -194,6 +232,13 @@ func (r *globalAcceleratorReconciler) reconcileGlobalAccelerator(ctx context.Con
194232
195233func (r * globalAcceleratorReconciler ) cleanupGlobalAccelerator (ctx context.Context , ga * agaapi.GlobalAccelerator ) error {
196234 if k8s .HasFinalizer (ga , shared_constants .GlobalAcceleratorFinalizer ) {
235+ // Clean up references in the reference tracker
236+ gaKey := k8s .NamespacedName (ga )
237+ r .referenceTracker .RemoveGA (gaKey )
238+
239+ // Clean up resource watches
240+ r .endpointResourcesManager .RemoveGA (gaKey )
241+
197242 // TODO: Implement cleanup logic for AWS Global Accelerator resources (Only cleaning up accelerator for now)
198243 if err := r .cleanupGlobalAcceleratorResources (ctx , ga ); err != nil {
199244 r .eventRecorder .Event (ga , corev1 .EventTypeWarning , k8s .GlobalAcceleratorEventReasonFailedCleanup , fmt .Sprintf ("Failed cleanup due to %v" , err ))
@@ -224,6 +269,29 @@ func (r *globalAcceleratorReconciler) buildModel(ctx context.Context, ga *agaapi
224269
225270func (r * globalAcceleratorReconciler ) reconcileGlobalAcceleratorResources (ctx context.Context , ga * agaapi.GlobalAccelerator ) error {
226271 r .logger .Info ("Reconciling GlobalAccelerator resources" , "globalAccelerator" , k8s .NamespacedName (ga ))
272+
273+ // Get all endpoints from GA
274+ endpoints := aga .GetAllEndpointsFromGA (ga )
275+
276+ // Track referenced endpoints
277+ r .referenceTracker .UpdateReferencesForGA (ga , endpoints )
278+
279+ // Update resource watches with the endpointResourcesManager
280+ r .endpointResourcesManager .MonitorEndpointResources (ga , endpoints )
281+
282+ // Validate and load endpoint status using the endpoint loader
283+ _ , fatalErrors := r .endpointLoader .LoadEndpoints (ctx , ga , endpoints )
284+ if len (fatalErrors ) > 0 {
285+ err := fmt .Errorf ("failed to load endpoints: %v" , fatalErrors [0 ])
286+ r .eventRecorder .Event (ga , corev1 .EventTypeWarning , k8s .GlobalAcceleratorEventReasonFailedEndpointLoad , fmt .Sprintf ("Failed to reconcile due to %v" , err ))
287+ r .logger .Error (err , fmt .Sprintf ("fatal error loading endpoints for %v" , k8s .NamespacedName (ga )))
288+ // Handle other endpoint loading errors
289+ if statusErr := r .statusUpdater .UpdateStatusFailure (ctx , ga , agadeploy .EndpointLoadFailed , err .Error ()); statusErr != nil {
290+ r .logger .Error (statusErr , "Failed to update GlobalAccelerator status after endpoint load failure" )
291+ }
292+ return err
293+ }
294+
227295 var stack core.Stack
228296 var accelerator * agamodel.Accelerator
229297 var err error
@@ -232,6 +300,8 @@ func (r *globalAcceleratorReconciler) reconcileGlobalAcceleratorResources(ctx co
232300 }
233301 r .metricsCollector .ObserveControllerReconcileLatency (controllerName , MetricStageBuildModel , buildModelFn )
234302 if err != nil {
303+ r .eventRecorder .Event (ga , corev1 .EventTypeWarning , k8s .GatewayEventReasonFailedBuildModel , fmt .Sprintf ("Failed to build model: %v" , err ))
304+ r .logger .Error (err , fmt .Sprintf ("Failed to build model for: %v" , k8s .NamespacedName (ga )))
235305 // Update status to indicate model building failure
236306 if statusErr := r .statusUpdater .UpdateStatusFailure (ctx , ga , agadeploy .ModelBuildFailed , fmt .Sprintf ("Failed to build model: %v" , err )); statusErr != nil {
237307 r .logger .Error (statusErr , "Failed to update GlobalAccelerator status after model build failure" )
@@ -246,7 +316,7 @@ func (r *globalAcceleratorReconciler) reconcileGlobalAcceleratorResources(ctx co
246316 r .metricsCollector .ObserveControllerReconcileLatency (controllerName , MetricStageDeployStack , deployStackFn )
247317 if err != nil {
248318 r .eventRecorder .Event (ga , corev1 .EventTypeWarning , k8s .GlobalAcceleratorEventReasonFailedDeploy , fmt .Sprintf ("Failed to deploy stack due to %v" , err ))
249-
319+ r . logger . Error ( err , fmt . Sprintf ( "Failed to deploy stack for: %v" , k8s . NamespacedName ( ga )))
250320 // Update status to indicate deployment failure
251321 if statusErr := r .statusUpdater .UpdateStatusFailure (ctx , ga , agadeploy .DeploymentFailed , fmt .Sprintf ("Failed to deploy stack: %v" , err )); statusErr != nil {
252322 r .logger .Error (statusErr , "Failed to update GlobalAccelerator status after deployment failure" )
@@ -335,21 +405,91 @@ func (r *globalAcceleratorReconciler) SetupWithManager(ctx context.Context, mgr
335405 return nil
336406 }
337407
338- if err := r .setupIndexes (ctx , mgr .GetFieldIndexer ()); err != nil {
408+ // Create event channels for dedicated watchers
409+ r .serviceEventChan = make (chan event.GenericEvent )
410+ r .ingressEventChan = make (chan event.GenericEvent )
411+ r .gatewayEventChan = make (chan event.GenericEvent )
412+
413+ // Initialize Gateway API client using the same config
414+ gwClient , err := gwclientset .NewForConfig (mgr .GetConfig ())
415+ if err != nil {
416+ r .logger .Error (err , "Failed to create Gateway API client" )
339417 return err
340418 }
341419
342- // TODO: Add event handlers for Services, Ingresses, and Gateways
343- // that are referenced by GlobalAccelerator endpoints
420+ // Initialize the endpoint resources manager with clients
421+ r .endpointResourcesManager = aga .NewEndpointResourcesManager (
422+ clientSet ,
423+ gwClient ,
424+ r .serviceEventChan ,
425+ r .ingressEventChan ,
426+ r .gatewayEventChan ,
427+ r .logger .WithName ("endpoint-resources-manager" ),
428+ )
429+
430+ if err := r .setupIndexes (ctx , mgr .GetFieldIndexer ()); err != nil {
431+ return err
432+ }
344433
345- return ctrl .NewControllerManagedBy (mgr ).
434+ // Set up the controller builder
435+ ctrl , err := ctrl .NewControllerManagedBy (mgr ).
346436 For (& agaapi.GlobalAccelerator {}).
347437 Named (controllerName ).
348438 WithOptions (controller.Options {
349439 MaxConcurrentReconciles : r .maxConcurrentReconciles ,
350440 RateLimiter : workqueue .NewTypedItemExponentialFailureRateLimiter [reconcile.Request ](5 * time .Second , r .maxExponentialBackoffDelay ),
351441 }).
352- Complete (r )
442+ Build (r )
443+
444+ if err != nil {
445+ return err
446+ }
447+
448+ // Setup watches for resource events
449+ if err := r .setupGlobalAcceleratorWatches (ctrl ); err != nil {
450+ return err
451+ }
452+
453+ return nil
454+ }
455+
456+ // setupGlobalAcceleratorWatches sets up watches for resources that can trigger reconciliation of GlobalAccelerator objects
457+ func (r * globalAcceleratorReconciler ) setupGlobalAcceleratorWatches (c controller.Controller ) error {
458+ loggerPrefix := r .logger .WithName ("eventHandlers" )
459+
460+ // Create handlers for our dedicated watchers
461+ serviceHandler := eventhandlers .NewEnqueueRequestsForResourceEvent (
462+ aga .ServiceResourceType ,
463+ r .referenceTracker ,
464+ loggerPrefix .WithName ("service-handler" ),
465+ )
466+
467+ ingressHandler := eventhandlers .NewEnqueueRequestsForResourceEvent (
468+ aga .IngressResourceType ,
469+ r .referenceTracker ,
470+ loggerPrefix .WithName ("ingress-handler" ),
471+ )
472+
473+ gatewayHandler := eventhandlers .NewEnqueueRequestsForResourceEvent (
474+ aga .GatewayResourceType ,
475+ r .referenceTracker ,
476+ loggerPrefix .WithName ("gateway-handler" ),
477+ )
478+
479+ // Add watches using the channel sources with event handlers
480+ if err := c .Watch (source .Channel (r .serviceEventChan , serviceHandler )); err != nil {
481+ return err
482+ }
483+
484+ if err := c .Watch (source .Channel (r .ingressEventChan , ingressHandler )); err != nil {
485+ return err
486+ }
487+
488+ if err := c .Watch (source .Channel (r .gatewayEventChan , gatewayHandler )); err != nil {
489+ return err
490+ }
491+
492+ return nil
353493}
354494
355495func (r * globalAcceleratorReconciler ) setupIndexes (ctx context.Context , fieldIndexer client.FieldIndexer ) error {
0 commit comments