Skip to content

Commit 52f747b

Browse files
fix(attachedRoutes): fixed count in case of HTTPRoute with multiple parentRefs (#7517) (#7522)
* fixing the attachedRoutes count in case of HTTPRoute with multiple parentRefs * changelog update for #7517 (cherry picked from commit 1ff5b45)
1 parent becfd73 commit 52f747b

File tree

3 files changed

+162
-0
lines changed

3 files changed

+162
-0
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ Adding a new version? You'll need three changes:
106106
- [0.0.5](#005)
107107
- [0.0.4 and prior](#004-and-prior)
108108

109+
## Unreleased
110+
111+
### Fixed
112+
113+
- Count the `attachedRoutes` of a `Gateway` in the correct way in case of `HTTPRoute`s
114+
with multiple parent references.
115+
[#7517](https://github.com/Kong/kubernetes-ingress-controller/pull/7517)
116+
109117
## [3.4.6]
110118

111119
> Release date: 2025-06-06

internal/controllers/gateway/gateway_utils.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,7 @@ func getAttachedRoutesForListener(ctx context.Context, mgrc client.Client, gatew
734734
}
735735
if accepted {
736736
attachedRoutes++
737+
break
737738
}
738739
}
739740
}

internal/controllers/gateway/gateway_utils_test.go

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,159 @@ func TestGetListenerStatus(t *testing.T) {
279279
}
280280
}
281281

282+
func TestGetAttachedRoutesForListener(t *testing.T) {
283+
group := gatewayapi.V1Group
284+
kind := gatewayapi.Kind("Gateway")
285+
sectionName := gatewayapi.SectionName("http")
286+
gatewayName := "my-gateway"
287+
myGateway := gatewayapi.Gateway{
288+
ObjectMeta: metav1.ObjectMeta{
289+
Name: gatewayName,
290+
Namespace: "default",
291+
},
292+
Spec: gatewayapi.GatewaySpec{
293+
Listeners: []gatewayapi.Listener{{
294+
Name: sectionName,
295+
Port: 80,
296+
Protocol: gatewayapi.HTTPProtocolType,
297+
}},
298+
},
299+
Status: gatewayapi.GatewayStatus{
300+
Listeners: []gatewayapi.ListenerStatus{
301+
{
302+
Name: sectionName,
303+
SupportedKinds: []gatewayapi.RouteGroupKind{
304+
{
305+
Group: lo.ToPtr(gatewayapi.V1Group),
306+
Kind: gatewayapi.Kind("HTTPRoute"),
307+
},
308+
},
309+
},
310+
},
311+
},
312+
}
313+
314+
ctx := t.Context()
315+
scheme := runtime.NewScheme()
316+
require.NoError(t, gatewayapi.InstallV1(scheme))
317+
318+
client := fake.NewClientBuilder().WithScheme(scheme).Build()
319+
320+
generateHTTPRoute := func(gateways []gatewayapi.ObjectName) gatewayapi.HTTPRoute {
321+
var parentRefs []gatewayapi.ParentReference
322+
for _, gateway := range gateways {
323+
parentRefs = append(parentRefs, gatewayapi.ParentReference{
324+
Group: &group,
325+
Kind: &kind,
326+
Name: gateway,
327+
})
328+
}
329+
var parentRefsStatus []gatewayapi.RouteParentStatus
330+
for _, gateway := range gateways {
331+
parentRefsStatus = append(parentRefsStatus, gatewayapi.RouteParentStatus{
332+
ParentRef: gatewayapi.ParentReference{
333+
Group: &group,
334+
Kind: &kind,
335+
Name: gateway,
336+
},
337+
})
338+
}
339+
// Create a single HTTPRoute with the specified parentRefs
340+
return gatewayapi.HTTPRoute{
341+
ObjectMeta: metav1.ObjectMeta{
342+
GenerateName: "http-1-",
343+
Namespace: "default",
344+
},
345+
Spec: gatewayapi.HTTPRouteSpec{
346+
CommonRouteSpec: gatewayapi.CommonRouteSpec{
347+
ParentRefs: parentRefs,
348+
},
349+
},
350+
Status: gatewayapi.HTTPRouteStatus{
351+
RouteStatus: gatewayapi.RouteStatus{
352+
Parents: parentRefsStatus,
353+
},
354+
},
355+
}
356+
}
357+
358+
tests := []struct {
359+
name string
360+
routes []gatewayapi.HTTPRoute
361+
listenerIndex int
362+
want int32
363+
}{
364+
{
365+
name: "single route with single parentRef",
366+
routes: []gatewayapi.HTTPRoute{
367+
generateHTTPRoute(
368+
[]gatewayapi.ObjectName{gatewayapi.ObjectName(gatewayName)},
369+
),
370+
},
371+
listenerIndex: 0,
372+
want: 1,
373+
},
374+
{
375+
name: "single route with multiple parentRefs",
376+
routes: []gatewayapi.HTTPRoute{
377+
generateHTTPRoute(
378+
[]gatewayapi.ObjectName{
379+
gatewayapi.ObjectName(gatewayName), "other-gateway",
380+
},
381+
),
382+
},
383+
listenerIndex: 0,
384+
want: 1,
385+
},
386+
{
387+
name: "multiple routes with multiple parentRefs",
388+
routes: []gatewayapi.HTTPRoute{
389+
generateHTTPRoute(
390+
[]gatewayapi.ObjectName{
391+
gatewayapi.ObjectName(gatewayName), "other-gateway",
392+
},
393+
),
394+
generateHTTPRoute(
395+
[]gatewayapi.ObjectName{
396+
gatewayapi.ObjectName(gatewayName), "other-gateway",
397+
},
398+
),
399+
},
400+
listenerIndex: 0,
401+
want: 2,
402+
},
403+
{
404+
name: "route not accepted by gateway",
405+
routes: []gatewayapi.HTTPRoute{
406+
generateHTTPRoute(
407+
[]gatewayapi.ObjectName{
408+
"other-gateway",
409+
},
410+
),
411+
},
412+
listenerIndex: 0,
413+
want: 0,
414+
},
415+
}
416+
417+
for _, tt := range tests {
418+
t.Run(tt.name, func(t *testing.T) {
419+
for _, route := range tt.routes {
420+
require.NoError(t, client.Create(ctx, &route))
421+
}
422+
423+
got, err := getAttachedRoutesForListener(ctx, client, myGateway, tt.listenerIndex)
424+
425+
// Tear down the created routes
426+
require.NoError(t, client.DeleteAllOf(ctx, &gatewayapi.HTTPRoute{}))
427+
428+
// Check that the number of routes returned matches the expected count
429+
assert.NoError(t, err)
430+
assert.Equal(t, tt.want, got)
431+
})
432+
}
433+
}
434+
282435
func assertOnlyOneConditionForType(t *testing.T, conditions []metav1.Condition) {
283436
conditionsNum := lo.CountValuesBy(conditions, func(c metav1.Condition) string {
284437
return c.Type

0 commit comments

Comments
 (0)