Skip to content

Commit 36b6eb8

Browse files
committed
process routes for gateway
Change-Id: If9522e9446f7363a1a4d18dfcc9576ff0241ed93
1 parent 5834a0f commit 36b6eb8

File tree

5 files changed

+917
-8
lines changed

5 files changed

+917
-8
lines changed

pkg/controller/controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,6 @@ func startCloudControllerManager(ctx context.Context, clusterName string, config
251251
}
252252
go nodeController.Run(ctx.Done(), ccmMetrics)
253253

254-
sharedInformers.Start(ctx.Done())
255-
256254
// Gateway setup
257255
crdManager, err := gateway.NewCRDManager(config)
258256
if err != nil {
@@ -281,6 +279,7 @@ func startCloudControllerManager(ctx context.Context, clusterName string, config
281279
gatewayController, err := gateway.New(
282280
clusterName,
283281
gwClient,
282+
sharedInformers.Core().V1().Namespaces(),
284283
sharedGwInformers.Gateway().V1().Gateways(),
285284
sharedGwInformers.Gateway().V1().HTTPRoutes(),
286285
sharedGwInformers.Gateway().V1().GRPCRoutes(),
@@ -302,6 +301,7 @@ func startCloudControllerManager(ctx context.Context, clusterName string, config
302301
_ = gatewayController.Run(ctx)
303302
}()
304303

304+
sharedInformers.Start(ctx.Done())
305305
sharedGwInformers.Start(ctx.Done())
306306

307307
// This has to cleanup all the resources allocated by the cloud provider in this cluster

pkg/gateway/controller.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1313
"k8s.io/apimachinery/pkg/util/runtime"
1414
"k8s.io/apimachinery/pkg/util/wait"
15+
corev1informers "k8s.io/client-go/informers/core/v1"
16+
corev1listers "k8s.io/client-go/listers/core/v1"
1517
"k8s.io/client-go/tools/cache"
1618
"k8s.io/client-go/util/workqueue"
1719
"k8s.io/klog/v2"
@@ -59,6 +61,9 @@ type Controller struct {
5961
clusterName string
6062
gwClient gatewayclient.Interface
6163

64+
namespaceLister corev1listers.NamespaceLister
65+
namespaceListerSynced cache.InformerSynced
66+
6267
gatewayLister gatewaylisters.GatewayLister
6368
gatewayListerSynced cache.InformerSynced
6469
gatewayqueue workqueue.TypedRateLimitingInterface[string]
@@ -84,15 +89,18 @@ type Controller struct {
8489
func New(
8590
clusterName string,
8691
gwClient *gatewayclient.Clientset,
92+
namespaceInformer corev1informers.NamespaceInformer,
8793
gatewayInformer gatewayinformers.GatewayInformer,
8894
httprouteInformer gatewayinformers.HTTPRouteInformer,
8995
grpcrouteInformer gatewayinformers.GRPCRouteInformer,
9096
) (*Controller, error) {
9197
c := &Controller{
92-
clusterName: clusterName,
93-
gwClient: gwClient,
94-
gatewayLister: gatewayInformer.Lister(),
95-
gatewayListerSynced: gatewayInformer.Informer().HasSynced,
98+
clusterName: clusterName,
99+
namespaceLister: namespaceInformer.Lister(),
100+
namespaceListerSynced: namespaceInformer.Informer().HasSynced,
101+
gwClient: gwClient,
102+
gatewayLister: gatewayInformer.Lister(),
103+
gatewayListerSynced: gatewayInformer.Informer().HasSynced,
96104
gatewayqueue: workqueue.NewTypedRateLimitingQueueWithConfig(
97105
workqueue.DefaultTypedControllerRateLimiter[string](),
98106
workqueue.TypedRateLimitingQueueConfig[string]{Name: "gateway"},
@@ -328,7 +336,7 @@ func (c *Controller) Run(ctx context.Context) error {
328336
klog.Info("Starting Gateway API controller")
329337

330338
// Wait for all involved caches to be synced, before processing items from the queue is started
331-
if !cache.WaitForNamedCacheSync(controllerName, ctx.Done(), c.gatewayListerSynced, c.httprouteListerSynced, c.grpcrouteListerSynced) {
339+
if !cache.WaitForNamedCacheSync(controllerName, ctx.Done(), c.gatewayListerSynced, c.httprouteListerSynced, c.grpcrouteListerSynced, c.namespaceListerSynced) {
332340
return fmt.Errorf("timed out waiting for caches to sync")
333341
}
334342

pkg/gateway/gateway.go

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
resourcev3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3"
1515

1616
apierrors "k8s.io/apimachinery/pkg/api/errors"
17+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18+
"k8s.io/apimachinery/pkg/labels"
1719
"k8s.io/apimachinery/pkg/util/runtime"
1820
"k8s.io/client-go/tools/cache"
1921
"k8s.io/klog/v2"
@@ -195,7 +197,7 @@ func (c *Controller) syncGateway(key string) error {
195197

196198
// Update configuration
197199
resources := map[resourcev3.Type][]envoyproxytypes.Resource{}
198-
200+
conditions := []metav1.Condition{}
199201
for _, listener := range gw.Spec.Listeners {
200202
// Determine the Envoy protocol based on the Gateway API protocol
201203
var envoyProto corev3.SocketAddress_Protocol
@@ -217,9 +219,106 @@ func (c *Controller) syncGateway(key string) error {
217219
}}},
218220
})
219221

222+
// Process HTTP Routes
223+
for _, route := range c.getHTTPRoutesForListener(gw, listener) {
224+
klog.V(2).Infof("Processing route %s/%s for gw %s/%s", route.Namespace, route.Name, gw.Namespace, gw.Name)
225+
conditions = append(conditions, metav1.Condition{})
226+
}
227+
228+
for _, route := range c.getHTTPRoutesForListener(gw, listener) {
229+
klog.V(2).Infof("Processing route %s/%s for gw %s/%s", route.Namespace, route.Name, gw.Namespace, gw.Name)
230+
conditions = append(conditions, metav1.Condition{})
231+
}
232+
233+
// Process GRPC Routes
220234
}
221235
return c.UpdateXDSServer(context.Background(), containerName, resources)
236+
}
237+
238+
// getHTTPRoutesForListener returns a slice of HTTPRoutes that reference the given Gateway and listener.
239+
func (c *Controller) getHTTPRoutesForListener(gw *gatewayv1.Gateway, listener gatewayv1.Listener) []*gatewayv1.HTTPRoute {
240+
var matchingRoutes []*gatewayv1.HTTPRoute
241+
242+
// TODO: optimize this
243+
// List all HTTPRoutes in all namespaces
244+
httpRoutes, err := c.httprouteLister.List(labels.Everything())
245+
if err != nil {
246+
klog.Infof("failed to list HTTPRoutes: %v", err)
247+
return matchingRoutes
248+
}
249+
250+
for _, route := range httpRoutes {
251+
// Check 1: Does the route *want* to attach to this specific listener?
252+
// This verifies the route's parentRefs target this gateway and listener section/port.
253+
if !isRouteReferenced(gw, listener, route) {
254+
klog.V(5).Infof("Route %s/%s skipped for Gateway %s/%s Listener %s: not referenced in ParentRefs", route.Namespace, route.Name, gw.Namespace, gw.Name, listener.Name)
255+
continue
256+
}
257+
258+
// Check 2: Does the listener *allow* this route to attach?
259+
// This verifies listener.spec.allowedRoutes (namespace and kind).
260+
// Assumes c.namespaceLister is populated.
261+
if !isRouteAllowed(gw, listener, route, c.namespaceLister) {
262+
klog.V(5).Infof("Route %s/%s skipped for Gateway %s/%s Listener %s: denied by AllowedRoutes", route.Namespace, route.Name, gw.Namespace, gw.Name, listener.Name)
263+
continue
264+
}
265+
266+
// Check 3: Is the route kind compatible with the listener protocol?
267+
// For this function specifically getting HTTPRoutes, the listener must accept HTTP or HTTPS.
268+
if listener.Protocol != gatewayv1.HTTPProtocolType && listener.Protocol != gatewayv1.HTTPSProtocolType {
269+
klog.V(5).Infof("Route %s/%s skipped for Gateway %s/%s Listener %s: incompatible listener protocol %s", route.Namespace, route.Name, gw.Namespace, gw.Name, listener.Name, listener.Protocol)
270+
continue // Skip route if listener protocol isn't HTTP/HTTPS
271+
}
272+
273+
// If all checks pass, add the route
274+
matchingRoutes = append(matchingRoutes, route)
275+
klog.V(4).Infof("Route %s/%s matched for Gateway %s/%s Listener %s", route.Namespace, route.Name, gw.Namespace, gw.Name, listener.Name)
276+
}
277+
278+
return matchingRoutes
279+
}
280+
281+
// getGRPCRoutesForListener returns a slice of GRPCRoutes that reference the given Gateway and listener.
282+
func (c *Controller) getGRPCRoutesForListener(gw *gatewayv1.Gateway, listener gatewayv1.Listener) []*gatewayv1.GRPCRoute {
283+
var matchingRoutes []*gatewayv1.GRPCRoute
284+
285+
// TODO: optimize this
286+
// List all GRPCRoutes in all namespaces
287+
grpcRoutes, err := c.grpcrouteLister.List(labels.Everything())
288+
if err != nil {
289+
klog.Infof("failed to list GRPCRoutes: %v", err)
290+
return matchingRoutes
291+
}
292+
293+
for _, route := range grpcRoutes {
294+
// Check 1: Does the route *want* to attach to this specific listener?
295+
// This verifies the route's parentRefs target this gateway and listener section/port.
296+
if !isRouteReferenced(gw, listener, route) {
297+
klog.V(5).Infof("Route %s/%s skipped for Gateway %s/%s Listener %s: not referenced in ParentRefs", route.Namespace, route.Name, gw.Namespace, gw.Name, listener.Name)
298+
continue
299+
}
300+
301+
// Check 2: Does the listener *allow* this route to attach?
302+
// This verifies listener.spec.allowedRoutes (namespace and kind).
303+
// Assumes c.namespaceLister is populated.
304+
if !isRouteAllowed(gw, listener, route, c.namespaceLister) {
305+
klog.V(5).Infof("Route %s/%s skipped for Gateway %s/%s Listener %s: denied by AllowedRoutes", route.Namespace, route.Name, gw.Namespace, gw.Name, listener.Name)
306+
continue
307+
}
308+
309+
// Check 3: Is the route kind compatible with the listener protocol?
310+
// For this function specifically getting HTTPRoutes, the listener must accept HTTP or HTTPS.
311+
if listener.Protocol != gatewayv1.HTTPProtocolType && listener.Protocol != gatewayv1.HTTPSProtocolType {
312+
klog.V(5).Infof("Route %s/%s skipped for Gateway %s/%s Listener %s: incompatible listener protocol %s", route.Namespace, route.Name, gw.Namespace, gw.Name, listener.Name, listener.Protocol)
313+
continue // Skip route if listener protocol isn't HTTP/HTTPS
314+
}
315+
316+
// If all checks pass, add the route
317+
matchingRoutes = append(matchingRoutes, route)
318+
klog.V(4).Infof("Route %s/%s matched for Gateway %s/%s Listener %s", route.Namespace, route.Name, gw.Namespace, gw.Name, listener.Name)
319+
}
222320

321+
return matchingRoutes
223322
}
224323

225324
// handleErr checks if an error happened and makes sure we will retry later.

0 commit comments

Comments
 (0)