-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[gw api] Implement ALB target of NLB #4430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
50b997a
0819b45
8fb9a04
9bd4c27
2f442de
76da6d4
819879e
66fa78c
2f550be
5599bda
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import ( | |
| "github.com/go-logr/logr" | ||
| corev1 "k8s.io/api/core/v1" | ||
| "k8s.io/apimachinery/pkg/types" | ||
| "k8s.io/apimachinery/pkg/util/sets" | ||
| "k8s.io/client-go/tools/record" | ||
| "k8s.io/client-go/util/workqueue" | ||
| elbv2gw "sigs.k8s.io/aws-load-balancer-controller/apis/gateway/v1beta1" | ||
|
|
@@ -13,66 +14,122 @@ import ( | |
| "sigs.k8s.io/controller-runtime/pkg/event" | ||
| "sigs.k8s.io/controller-runtime/pkg/handler" | ||
| "sigs.k8s.io/controller-runtime/pkg/reconcile" | ||
| gwalpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" | ||
| ) | ||
|
|
||
| // NewEnqueueRequestsForTargetGroupConfigurationEvent creates handler for TargetGroupConfiguration resources | ||
| func NewEnqueueRequestsForTargetGroupConfigurationEvent(svcEventChan chan<- event.TypedGenericEvent[*corev1.Service], | ||
| func NewEnqueueRequestsForTargetGroupConfigurationEvent(svcEventChan chan<- event.TypedGenericEvent[*corev1.Service], tcpRouteEventChan chan<- event.TypedGenericEvent[*gwalpha2.TCPRoute], | ||
| k8sClient client.Client, eventRecorder record.EventRecorder, logger logr.Logger) handler.TypedEventHandler[*elbv2gw.TargetGroupConfiguration, reconcile.Request] { | ||
| return &enqueueRequestsForTargetGroupConfigurationEvent{ | ||
| svcEventChan: svcEventChan, | ||
| k8sClient: k8sClient, | ||
| eventRecorder: eventRecorder, | ||
| logger: logger, | ||
| svcEventChan: svcEventChan, | ||
| tcpRouteEventChan: tcpRouteEventChan, | ||
| k8sClient: k8sClient, | ||
| eventRecorder: eventRecorder, | ||
| logger: logger, | ||
| } | ||
| } | ||
|
|
||
| var _ handler.TypedEventHandler[*elbv2gw.TargetGroupConfiguration, reconcile.Request] = (*enqueueRequestsForTargetGroupConfigurationEvent)(nil) | ||
|
|
||
| // enqueueRequestsForTargetGroupConfigurationEvent handles TargetGroupConfiguration events | ||
| type enqueueRequestsForTargetGroupConfigurationEvent struct { | ||
| svcEventChan chan<- event.TypedGenericEvent[*corev1.Service] | ||
| k8sClient client.Client | ||
| eventRecorder record.EventRecorder | ||
| logger logr.Logger | ||
| svcEventChan chan<- event.TypedGenericEvent[*corev1.Service] | ||
| tcpRouteEventChan chan<- event.TypedGenericEvent[*gwalpha2.TCPRoute] | ||
| k8sClient client.Client | ||
| eventRecorder record.EventRecorder | ||
| logger logr.Logger | ||
| } | ||
|
|
||
| func (h *enqueueRequestsForTargetGroupConfigurationEvent) Create(ctx context.Context, e event.TypedCreateEvent[*elbv2gw.TargetGroupConfiguration], queue workqueue.TypedRateLimitingInterface[reconcile.Request]) { | ||
| tgconfigNew := e.Object | ||
| h.logger.V(1).Info("enqueue targetgroupconfiguration create event", "targetgroupconfiguration", tgconfigNew.Name) | ||
| h.enqueueImpactedService(ctx, tgconfigNew, queue) | ||
| h.enqueueImpactedObject(ctx, tgconfigNew, queue) | ||
| } | ||
|
|
||
| func (h *enqueueRequestsForTargetGroupConfigurationEvent) Update(ctx context.Context, e event.TypedUpdateEvent[*elbv2gw.TargetGroupConfiguration], queue workqueue.TypedRateLimitingInterface[reconcile.Request]) { | ||
| tgconfigNew := e.ObjectNew | ||
| h.logger.V(1).Info("enqueue targetgroupconfiguration update event", "targetgroupconfiguration", tgconfigNew.Name) | ||
| h.enqueueImpactedService(ctx, tgconfigNew, queue) | ||
| h.enqueueImpactedObject(ctx, tgconfigNew, queue) | ||
| } | ||
|
|
||
| func (h *enqueueRequestsForTargetGroupConfigurationEvent) Delete(ctx context.Context, e event.TypedDeleteEvent[*elbv2gw.TargetGroupConfiguration], queue workqueue.TypedRateLimitingInterface[reconcile.Request]) { | ||
| tgconfig := e.Object | ||
| h.logger.V(1).Info("enqueue targetgroupconfiguration delete event", "targetgroupconfiguration", tgconfig.Name) | ||
| h.enqueueImpactedService(ctx, tgconfig, queue) | ||
| h.enqueueImpactedObject(ctx, tgconfig, queue) | ||
| } | ||
|
|
||
| func (h *enqueueRequestsForTargetGroupConfigurationEvent) Generic(ctx context.Context, e event.TypedGenericEvent[*elbv2gw.TargetGroupConfiguration], queue workqueue.TypedRateLimitingInterface[reconcile.Request]) { | ||
| tgconfig := e.Object | ||
| h.logger.V(1).Info("enqueue targetgroupconfiguration generic event", "targetgroupconfiguration", tgconfig.Name) | ||
| h.enqueueImpactedService(ctx, tgconfig, queue) | ||
| h.enqueueImpactedObject(ctx, tgconfig, queue) | ||
| } | ||
|
|
||
| func (h *enqueueRequestsForTargetGroupConfigurationEvent) enqueueImpactedService(ctx context.Context, tgconfig *elbv2gw.TargetGroupConfiguration, queue workqueue.TypedRateLimitingInterface[reconcile.Request]) { | ||
| svcName := types.NamespacedName{Namespace: tgconfig.Namespace, Name: tgconfig.Spec.TargetReference.Name} | ||
| svc := &corev1.Service{} | ||
| if err := h.k8sClient.Get(ctx, svcName, svc); err != nil { | ||
| h.logger.V(1).Info("ignoring targetgroupconfiguration event for unknown service", | ||
| func (h *enqueueRequestsForTargetGroupConfigurationEvent) enqueueImpactedObject(ctx context.Context, tgconfig *elbv2gw.TargetGroupConfiguration, queue workqueue.TypedRateLimitingInterface[reconcile.Request]) { | ||
| objName := types.NamespacedName{Namespace: tgconfig.Namespace, Name: tgconfig.Spec.TargetReference.Name} | ||
|
|
||
| if tgconfig.Spec.TargetReference.Kind == nil || *tgconfig.Spec.TargetReference.Kind == "Service" { | ||
| svc := &corev1.Service{} | ||
| if err := h.k8sClient.Get(ctx, objName, svc); err != nil { | ||
| h.logger.V(1).Info("ignoring targetgroupconfiguration event for unknown service", | ||
| "targetgroupconfiguration", k8s.NamespacedName(tgconfig), | ||
| "service", k8s.NamespacedName(svc)) | ||
| return | ||
| } | ||
| h.logger.V(1).Info("enqueue service for targetgroupconfiguration event", | ||
| "targetgroupconfiguration", k8s.NamespacedName(tgconfig), | ||
| "service", k8s.NamespacedName(svc)) | ||
| return | ||
| h.svcEventChan <- event.TypedGenericEvent[*corev1.Service]{ | ||
| Object: svc, | ||
| } | ||
| } | ||
|
|
||
| // TODO - We should probably use an indexer here, we have a task to do this. | ||
| if tgconfig.Spec.TargetReference.Kind != nil && *tgconfig.Spec.TargetReference.Kind == "Gateway" && h.tcpRouteEventChan != nil { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is required to support TG config updates that impact ALB typed target groups. We need to find out all TCP Routes that reference the Gateway which the config references it. See the added tests. |
||
| tcpRouteList := &gwalpha2.TCPRouteList{} | ||
|
|
||
| if err := h.k8sClient.List(ctx, tcpRouteList); err != nil { | ||
| h.logger.V(1).Info("failed to list tcp routes for target group configuration event", "targetgroupconfiguration", k8s.NamespacedName(tgconfig)) | ||
| return | ||
| } | ||
|
|
||
| impactedRoutes := getImpactedTCPRoutes(tcpRouteList, tgconfig) | ||
| for i := range impactedRoutes { | ||
| h.tcpRouteEventChan <- event.TypedGenericEvent[*gwalpha2.TCPRoute]{ | ||
| Object: impactedRoutes[i], | ||
| } | ||
| } | ||
|
|
||
| } | ||
| h.logger.V(1).Info("enqueue service for targetgroupconfiguration event", | ||
| "targetgroupconfiguration", k8s.NamespacedName(tgconfig), | ||
| "service", k8s.NamespacedName(svc)) | ||
| h.svcEventChan <- event.TypedGenericEvent[*corev1.Service]{ | ||
| Object: svc, | ||
| } | ||
|
|
||
| func getImpactedTCPRoutes(list *gwalpha2.TCPRouteList, tgconfig *elbv2gw.TargetGroupConfiguration) []*gwalpha2.TCPRoute { | ||
| seen := sets.Set[types.NamespacedName]{} | ||
| res := make([]*gwalpha2.TCPRoute, 0) | ||
|
|
||
| for i, route := range list.Items { | ||
| nsn := k8s.NamespacedName(&route) | ||
| for _, rule := range route.Spec.Rules { | ||
| for _, beRef := range rule.BackendRefs { | ||
| if beRef.Kind != nil && *beRef.Kind == "Gateway" { | ||
| if string(beRef.Name) == tgconfig.Spec.TargetReference.Name { | ||
|
|
||
| // The route backend ns | ||
| var routeNs string | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is to support optional namespace, which mandates that when the backend ns is omitted we should use the route namespace. |
||
| if beRef.Namespace == nil { | ||
| routeNs = route.Namespace | ||
| } else { | ||
| routeNs = string(*beRef.Namespace) | ||
| } | ||
|
|
||
| if routeNs == tgconfig.Namespace && !seen.Has(nsn) { | ||
| res = append(res, &list.Items[i]) | ||
| seen.Insert(nsn) | ||
| } | ||
|
|
||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return res | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This enum validation was incorrect, which made the field unusable as the casing should be all upper case.