Avoid updating Accepted status for routes matching no Gateways

Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
This commit is contained in:
Romain 2024-10-09 15:50:04 +02:00 committed by GitHub
parent 1508a2c221
commit c441d04788
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 164 additions and 96 deletions

View file

@ -32,6 +32,11 @@ func (p *Provider) loadGRPCRoutes(ctx context.Context, gatewayListeners []gatewa
Str("namespace", route.Namespace). Str("namespace", route.Namespace).
Logger() Logger()
routeListeners := matchingGatewayListeners(gatewayListeners, route.Namespace, route.Spec.ParentRefs)
if len(routeListeners) == 0 {
continue
}
var parentStatuses []gatev1.RouteParentStatus var parentStatuses []gatev1.RouteParentStatus
for _, parentRef := range route.Spec.ParentRefs { for _, parentRef := range route.Spec.ParentRefs {
parentStatus := &gatev1.RouteParentStatus{ parentStatus := &gatev1.RouteParentStatus{
@ -48,11 +53,9 @@ func (p *Provider) loadGRPCRoutes(ctx context.Context, gatewayListeners []gatewa
}, },
} }
for _, listener := range gatewayListeners { for _, listener := range routeListeners {
accepted := true accepted := matchListener(listener, parentRef)
if !matchListener(listener, route.Namespace, parentRef) {
accepted = false
}
if accepted && !allowRoute(listener, route.Namespace, kindGRPCRoute) { if accepted && !allowRoute(listener, route.Namespace, kindGRPCRoute) {
parentStatus.Conditions = updateRouteConditionAccepted(parentStatus.Conditions, string(gatev1.RouteReasonNotAllowedByListeners)) parentStatus.Conditions = updateRouteConditionAccepted(parentStatus.Conditions, string(gatev1.RouteReasonNotAllowedByListeners))
accepted = false accepted = false

View file

@ -36,6 +36,11 @@ func (p *Provider) loadHTTPRoutes(ctx context.Context, gatewayListeners []gatewa
Str("namespace", route.Namespace). Str("namespace", route.Namespace).
Logger() Logger()
routeListeners := matchingGatewayListeners(gatewayListeners, route.Namespace, route.Spec.ParentRefs)
if len(routeListeners) == 0 {
continue
}
var parentStatuses []gatev1.RouteParentStatus var parentStatuses []gatev1.RouteParentStatus
for _, parentRef := range route.Spec.ParentRefs { for _, parentRef := range route.Spec.ParentRefs {
parentStatus := &gatev1.RouteParentStatus{ parentStatus := &gatev1.RouteParentStatus{
@ -52,11 +57,9 @@ func (p *Provider) loadHTTPRoutes(ctx context.Context, gatewayListeners []gatewa
}, },
} }
for _, listener := range gatewayListeners { for _, listener := range routeListeners {
accepted := true accepted := matchListener(listener, parentRef)
if !matchListener(listener, route.Namespace, parentRef) {
accepted = false
}
if accepted && !allowRoute(listener, route.Namespace, kindHTTPRoute) { if accepted && !allowRoute(listener, route.Namespace, kindHTTPRoute) {
parentStatus.Conditions = updateRouteConditionAccepted(parentStatus.Conditions, string(gatev1.RouteReasonNotAllowedByListeners)) parentStatus.Conditions = updateRouteConditionAccepted(parentStatus.Conditions, string(gatev1.RouteReasonNotAllowedByListeners))
accepted = false accepted = false

View file

@ -1119,24 +1119,36 @@ func allowRoute(listener gatewayListener, routeNamespace, routeKind string) bool
}) })
} }
func matchListener(listener gatewayListener, routeNamespace string, parentRef gatev1.ParentReference) bool { func matchingGatewayListeners(gatewayListeners []gatewayListener, routeNamespace string, parentRefs []gatev1.ParentReference) []gatewayListener {
if ptr.Deref(parentRef.Group, gatev1.GroupName) != gatev1.GroupName { var listeners []gatewayListener
return false
for _, listener := range gatewayListeners {
for _, parentRef := range parentRefs {
if ptr.Deref(parentRef.Group, gatev1.GroupName) != gatev1.GroupName {
continue
}
if ptr.Deref(parentRef.Kind, kindGateway) != kindGateway {
continue
}
parentRefNamespace := string(ptr.Deref(parentRef.Namespace, gatev1.Namespace(routeNamespace)))
if listener.GWNamespace != parentRefNamespace {
continue
}
if string(parentRef.Name) != listener.GWName {
continue
}
listeners = append(listeners, listener)
}
} }
if ptr.Deref(parentRef.Kind, kindGateway) != kindGateway { return listeners
return false }
}
parentRefNamespace := string(ptr.Deref(parentRef.Namespace, gatev1.Namespace(routeNamespace)))
if listener.GWNamespace != parentRefNamespace {
return false
}
if string(parentRef.Name) != listener.GWName {
return false
}
func matchListener(listener gatewayListener, parentRef gatev1.ParentReference) bool {
sectionName := string(ptr.Deref(parentRef.SectionName, "")) sectionName := string(ptr.Deref(parentRef.SectionName, ""))
if sectionName != "" && sectionName != listener.Name { if sectionName != "" && sectionName != listener.Name {
return false return false

View file

@ -6779,127 +6779,171 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) {
} }
} }
func Test_matchListener(t *testing.T) { func Test_matchingGatewayListener(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
gwListener gatewayListener gwListeners []gatewayListener
parentRef gatev1.ParentReference parentRefs []gatev1.ParentReference
routeNamespace string routeNamespace string
wantMatch bool wantLen int
}{ }{
{ {
desc: "Unsupported group", desc: "Unsupported group",
gwListener: gatewayListener{ gwListeners: []gatewayListener{{
Name: "foo", Name: "foo",
GWName: "gateway", GWName: "gateway",
GWNamespace: "default", GWNamespace: "default",
}, }},
parentRef: gatev1.ParentReference{ parentRefs: []gatev1.ParentReference{{
Group: ptr.To(gatev1.Group("foo")), Group: ptr.To(gatev1.Group("foo")),
}, }},
wantMatch: false, wantLen: 0,
}, },
{ {
desc: "Unsupported kind", desc: "Unsupported kind",
gwListener: gatewayListener{ gwListeners: []gatewayListener{{
Name: "foo", Name: "foo",
GWName: "gateway", GWName: "gateway",
GWNamespace: "default", GWNamespace: "default",
}, }},
parentRef: gatev1.ParentReference{ parentRefs: []gatev1.ParentReference{{
Group: ptr.To(gatev1.Group(gatev1.GroupName)), Group: ptr.To(gatev1.Group(gatev1.GroupName)),
Kind: ptr.To(gatev1.Kind("foo")), Kind: ptr.To(gatev1.Kind("foo")),
}, }},
wantMatch: false, wantLen: 0,
}, },
{ {
desc: "Namespace does not match the listener", desc: "Namespace does not match the listener",
gwListener: gatewayListener{ gwListeners: []gatewayListener{{
Name: "foo", Name: "foo",
GWName: "gateway", GWName: "gateway",
GWNamespace: "default", GWNamespace: "default",
}, }},
parentRef: gatev1.ParentReference{ parentRefs: []gatev1.ParentReference{{
Namespace: ptr.To(gatev1.Namespace("foo")), Namespace: ptr.To(gatev1.Namespace("foo")),
Group: ptr.To(gatev1.Group(gatev1.GroupName)), Group: ptr.To(gatev1.Group(gatev1.GroupName)),
Kind: ptr.To(gatev1.Kind("Gateway")), Kind: ptr.To(gatev1.Kind("Gateway")),
}, }},
wantMatch: false, wantLen: 0,
}, },
{ {
desc: "Route namespace defaulting does not match the listener", desc: "Route namespace defaulting does not match the listener",
gwListener: gatewayListener{ gwListeners: []gatewayListener{{
Name: "foo", Name: "foo",
GWName: "gateway", GWName: "gateway",
GWNamespace: "default", GWNamespace: "default",
}, }},
routeNamespace: "foo", routeNamespace: "foo",
parentRef: gatev1.ParentReference{ parentRefs: []gatev1.ParentReference{{
Group: ptr.To(gatev1.Group(gatev1.GroupName)), Group: ptr.To(gatev1.Group(gatev1.GroupName)),
Kind: ptr.To(gatev1.Kind("Gateway")), Kind: ptr.To(gatev1.Kind("Gateway")),
}, }},
wantMatch: false, wantLen: 0,
}, },
{ {
desc: "Name does not match the listener", desc: "Name does not match the listener",
gwListener: gatewayListener{ gwListeners: []gatewayListener{{
Name: "foo",
GWName: "gateway", GWName: "gateway",
GWNamespace: "default", GWNamespace: "default",
}, }},
parentRef: gatev1.ParentReference{ parentRefs: []gatev1.ParentReference{{
Namespace: ptr.To(gatev1.Namespace("default")), Namespace: ptr.To(gatev1.Namespace("default")),
Name: "foo", Name: "foo",
Group: ptr.To(gatev1.Group(gatev1.GroupName)), Group: ptr.To(gatev1.Group(gatev1.GroupName)),
Kind: ptr.To(gatev1.Kind("Gateway")), Kind: ptr.To(gatev1.Kind("Gateway")),
}, }},
wantMatch: false, wantLen: 0,
},
{
desc: "SectionName does not match a listener",
gwListener: gatewayListener{
Name: "foo",
GWName: "gateway",
GWNamespace: "default",
},
parentRef: gatev1.ParentReference{
SectionName: ptr.To(gatev1.SectionName("bar")),
Name: "gateway",
Namespace: ptr.To(gatev1.Namespace("default")),
Group: ptr.To(gatev1.Group(gatev1.GroupName)),
Kind: ptr.To(gatev1.Kind("Gateway")),
},
wantMatch: false,
}, },
{ {
desc: "Match", desc: "Match",
gwListener: gatewayListener{ gwListeners: []gatewayListener{{
Name: "foo",
GWName: "gateway", GWName: "gateway",
GWNamespace: "default", GWNamespace: "default",
}},
parentRefs: []gatev1.ParentReference{{
Name: "gateway",
Namespace: ptr.To(gatev1.Namespace("default")),
Group: ptr.To(gatev1.Group(gatev1.GroupName)),
Kind: ptr.To(gatev1.Kind("Gateway")),
}},
wantLen: 1,
},
{
desc: "Match with route namespace defaulting",
gwListeners: []gatewayListener{{
GWName: "gateway",
GWNamespace: "default",
}},
routeNamespace: "default",
parentRefs: []gatev1.ParentReference{{
Name: "gateway",
Group: ptr.To(gatev1.Group(gatev1.GroupName)),
Kind: ptr.To(gatev1.Kind("Gateway")),
}},
wantLen: 1,
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
listeners := matchingGatewayListeners(test.gwListeners, test.routeNamespace, test.parentRefs)
assert.Len(t, listeners, test.wantLen)
})
}
}
func Test_matchListener(t *testing.T) {
testCases := []struct {
desc string
gwListener gatewayListener
parentRef gatev1.ParentReference
wantMatch bool
}{
{
desc: "Section do not match",
gwListener: gatewayListener{
Name: "foo",
Port: gatev1.PortNumber(80),
},
parentRef: gatev1.ParentReference{
SectionName: ptr.To(gatev1.SectionName("bar")),
Port: ptr.To(gatev1.PortNumber(80)),
},
},
{
desc: "Section matches",
gwListener: gatewayListener{
Name: "foo",
Port: gatev1.PortNumber(80),
}, },
parentRef: gatev1.ParentReference{ parentRef: gatev1.ParentReference{
SectionName: ptr.To(gatev1.SectionName("foo")), SectionName: ptr.To(gatev1.SectionName("foo")),
Name: "gateway", Port: ptr.To(gatev1.PortNumber(80)),
Namespace: ptr.To(gatev1.Namespace("default")),
Group: ptr.To(gatev1.Group(gatev1.GroupName)),
Kind: ptr.To(gatev1.Kind("Gateway")),
}, },
wantMatch: true, wantMatch: true,
}, },
{ {
desc: "Match with route namespace defaulting", desc: "Port do not match",
gwListener: gatewayListener{ gwListener: gatewayListener{
Name: "foo", Name: "foo",
GWName: "gateway", Port: gatev1.PortNumber(90),
GWNamespace: "default",
}, },
routeNamespace: "default",
parentRef: gatev1.ParentReference{ parentRef: gatev1.ParentReference{
SectionName: ptr.To(gatev1.SectionName("foo")), SectionName: ptr.To(gatev1.SectionName("foo")),
Name: "gateway", Port: ptr.To(gatev1.PortNumber(80)),
Group: ptr.To(gatev1.Group(gatev1.GroupName)), },
Kind: ptr.To(gatev1.Kind("Gateway")), },
{
desc: "Port matches",
gwListener: gatewayListener{
Name: "foo",
Port: gatev1.PortNumber(80),
},
parentRef: gatev1.ParentReference{
SectionName: ptr.To(gatev1.SectionName("foo")),
Port: ptr.To(gatev1.PortNumber(80)),
}, },
wantMatch: true, wantMatch: true,
}, },
@ -6909,7 +6953,7 @@ func Test_matchListener(t *testing.T) {
t.Run(test.desc, func(t *testing.T) { t.Run(test.desc, func(t *testing.T) {
t.Parallel() t.Parallel()
gotMatch := matchListener(test.gwListener, test.routeNamespace, test.parentRef) gotMatch := matchListener(test.gwListener, test.parentRef)
assert.Equal(t, test.wantMatch, gotMatch) assert.Equal(t, test.wantMatch, gotMatch)
}) })
} }

View file

@ -32,6 +32,11 @@ func (p *Provider) loadTCPRoutes(ctx context.Context, gatewayListeners []gateway
Str("namespace", route.Namespace). Str("namespace", route.Namespace).
Logger() Logger()
routeListeners := matchingGatewayListeners(gatewayListeners, route.Namespace, route.Spec.ParentRefs)
if len(routeListeners) == 0 {
continue
}
var parentStatuses []gatev1alpha2.RouteParentStatus var parentStatuses []gatev1alpha2.RouteParentStatus
for _, parentRef := range route.Spec.ParentRefs { for _, parentRef := range route.Spec.ParentRefs {
parentStatus := &gatev1alpha2.RouteParentStatus{ parentStatus := &gatev1alpha2.RouteParentStatus{
@ -48,11 +53,9 @@ func (p *Provider) loadTCPRoutes(ctx context.Context, gatewayListeners []gateway
}, },
} }
for _, listener := range gatewayListeners { for _, listener := range routeListeners {
accepted := true accepted := matchListener(listener, parentRef)
if !matchListener(listener, route.Namespace, parentRef) {
accepted = false
}
if accepted && !allowRoute(listener, route.Namespace, kindTCPRoute) { if accepted && !allowRoute(listener, route.Namespace, kindTCPRoute) {
parentStatus.Conditions = updateRouteConditionAccepted(parentStatus.Conditions, string(gatev1.RouteReasonNotAllowedByListeners)) parentStatus.Conditions = updateRouteConditionAccepted(parentStatus.Conditions, string(gatev1.RouteReasonNotAllowedByListeners))
accepted = false accepted = false

View file

@ -32,6 +32,11 @@ func (p *Provider) loadTLSRoutes(ctx context.Context, gatewayListeners []gateway
Str("tls_route", route.Name). Str("tls_route", route.Name).
Str("namespace", route.Namespace).Logger() Str("namespace", route.Namespace).Logger()
routeListeners := matchingGatewayListeners(gatewayListeners, route.Namespace, route.Spec.ParentRefs)
if len(routeListeners) == 0 {
continue
}
var parentStatuses []gatev1alpha2.RouteParentStatus var parentStatuses []gatev1alpha2.RouteParentStatus
for _, parentRef := range route.Spec.ParentRefs { for _, parentRef := range route.Spec.ParentRefs {
parentStatus := &gatev1alpha2.RouteParentStatus{ parentStatus := &gatev1alpha2.RouteParentStatus{
@ -48,11 +53,9 @@ func (p *Provider) loadTLSRoutes(ctx context.Context, gatewayListeners []gateway
}, },
} }
for _, listener := range gatewayListeners { for _, listener := range routeListeners {
accepted := true accepted := matchListener(listener, parentRef)
if !matchListener(listener, route.Namespace, parentRef) {
accepted = false
}
if accepted && !allowRoute(listener, route.Namespace, kindTLSRoute) { if accepted && !allowRoute(listener, route.Namespace, kindTLSRoute) {
parentStatus.Conditions = updateRouteConditionAccepted(parentStatus.Conditions, string(gatev1.RouteReasonNotAllowedByListeners)) parentStatus.Conditions = updateRouteConditionAccepted(parentStatus.Conditions, string(gatev1.RouteReasonNotAllowedByListeners))
accepted = false accepted = false