From a45a09a612b7d096eed68c9760e9e92396f4f267 Mon Sep 17 00:00:00 2001 From: jukie Date: Sat, 28 Feb 2026 12:22:48 -0700 Subject: [PATCH 1/7] route overlap Signed-off-by: jukie --- internal/gatewayapi/overlap_test.go | 286 ++++++++++++++++++ internal/gatewayapi/route.go | 137 ++++++++- internal/gatewayapi/status/error.go | 3 + .../httproute-overlapping-matches.in.yaml | 50 +++ .../httproute-overlapping-matches.out.yaml | 237 +++++++++++++++ 5 files changed, 709 insertions(+), 4 deletions(-) create mode 100644 internal/gatewayapi/overlap_test.go create mode 100644 internal/gatewayapi/testdata/httproute-overlapping-matches.in.yaml create mode 100644 internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml diff --git a/internal/gatewayapi/overlap_test.go b/internal/gatewayapi/overlap_test.go new file mode 100644 index 0000000000..ae19e2b001 --- /dev/null +++ b/internal/gatewayapi/overlap_test.go @@ -0,0 +1,286 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package gatewayapi + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/utils/ptr" + + "github.com/envoyproxy/gateway/internal/ir" +) + +func TestRouteMatchesOverlap(t *testing.T) { + tests := []struct { + name string + a *ir.HTTPRoute + b *ir.HTTPRoute + overlap bool + }{ + { + name: "identical exact path and hostname", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + }, + overlap: true, + }, + { + name: "different exact paths", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/bar")}, + }, + overlap: false, + }, + { + name: "different hostnames", + a: &ir.HTTPRoute{ + Hostname: "a.example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + }, + b: &ir.HTTPRoute{ + Hostname: "b.example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + }, + overlap: false, + }, + { + name: "prefix paths are not detected as overlap", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Prefix: ptr.To("/api")}, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Prefix: ptr.To("/api")}, + }, + overlap: false, + }, + { + name: "nil path matches are not detected as overlap", + a: &ir.HTTPRoute{ + Hostname: "example.com", + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + }, + overlap: false, + }, + { + name: "exact vs prefix same value not overlap", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Prefix: ptr.To("/foo")}, + }, + overlap: false, + }, + { + name: "identical exact path with identical header matches", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + HeaderMatches: []*ir.StringMatch{ + {Name: "X-Custom", Exact: ptr.To("val1")}, + }, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + HeaderMatches: []*ir.StringMatch{ + {Name: "X-Custom", Exact: ptr.To("val1")}, + }, + }, + overlap: true, + }, + { + name: "identical exact path with different header matches", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + HeaderMatches: []*ir.StringMatch{ + {Name: "X-Custom", Exact: ptr.To("val1")}, + }, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + HeaderMatches: []*ir.StringMatch{ + {Name: "X-Custom", Exact: ptr.To("val2")}, + }, + }, + overlap: false, + }, + { + name: "identical exact path one has headers other does not", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + HeaderMatches: []*ir.StringMatch{ + {Name: "X-Custom", Exact: ptr.To("val1")}, + }, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + }, + overlap: false, + }, + { + name: "identical exact path with identical query param matches", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + QueryParamMatches: []*ir.StringMatch{ + {Name: "key", Exact: ptr.To("value")}, + }, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + QueryParamMatches: []*ir.StringMatch{ + {Name: "key", Exact: ptr.To("value")}, + }, + }, + overlap: true, + }, + { + name: "regex path matches are not detected as overlap", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, + }, + overlap: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.overlap, routeMatchesOverlap(tt.a, tt.b)) + }) + } +} + +func TestStringMatchEqual(t *testing.T) { + tests := []struct { + name string + a *ir.StringMatch + b *ir.StringMatch + equal bool + }{ + { + name: "both nil", + a: nil, + b: nil, + equal: true, + }, + { + name: "one nil", + a: &ir.StringMatch{Exact: ptr.To("foo")}, + b: nil, + equal: false, + }, + { + name: "identical exact", + a: &ir.StringMatch{Name: "h", Exact: ptr.To("v")}, + b: &ir.StringMatch{Name: "h", Exact: ptr.To("v")}, + equal: true, + }, + { + name: "different name", + a: &ir.StringMatch{Name: "a", Exact: ptr.To("v")}, + b: &ir.StringMatch{Name: "b", Exact: ptr.To("v")}, + equal: false, + }, + { + name: "different value", + a: &ir.StringMatch{Name: "h", Exact: ptr.To("v1")}, + b: &ir.StringMatch{Name: "h", Exact: ptr.To("v2")}, + equal: false, + }, + { + name: "different distinct", + a: &ir.StringMatch{Name: "h", Distinct: true}, + b: &ir.StringMatch{Name: "h", Distinct: false}, + equal: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.equal, stringMatchEqual(tt.a, tt.b)) + }) + } +} + +func TestStringMatchSliceEqual(t *testing.T) { + tests := []struct { + name string + a []*ir.StringMatch + b []*ir.StringMatch + equal bool + }{ + { + name: "both empty", + a: nil, + b: nil, + equal: true, + }, + { + name: "different lengths", + a: []*ir.StringMatch{{Name: "a", Exact: ptr.To("1")}}, + b: nil, + equal: false, + }, + { + name: "identical", + a: []*ir.StringMatch{ + {Name: "a", Exact: ptr.To("1")}, + {Name: "b", Exact: ptr.To("2")}, + }, + b: []*ir.StringMatch{ + {Name: "a", Exact: ptr.To("1")}, + {Name: "b", Exact: ptr.To("2")}, + }, + equal: true, + }, + { + name: "same elements different order", + a: []*ir.StringMatch{ + {Name: "a", Exact: ptr.To("1")}, + {Name: "b", Exact: ptr.To("2")}, + }, + b: []*ir.StringMatch{ + {Name: "b", Exact: ptr.To("2")}, + {Name: "a", Exact: ptr.To("1")}, + }, + equal: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.equal, stringMatchSliceEqual(tt.a, tt.b)) + }) + } +} diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index aa3e205054..1376f0ee1b 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -179,7 +179,7 @@ func (t *Translator) processHTTPRouteParentRefs(httpRoute *HTTPRouteContext, res "Resolved all the Object references for the Route", ) } - hasHostnameIntersection := t.processHTTPRouteParentRefListener(httpRoute, routeRoutes, parentRef, xdsIR) + hasHostnameIntersection, hasOverlap := t.processHTTPRouteParentRefListener(httpRoute, routeRoutes, parentRef, xdsIR) if !hasHostnameIntersection { routeStatus := GetRouteStatus(httpRoute) status.SetRouteStatusCondition(routeStatus, @@ -192,6 +192,18 @@ func (t *Translator) processHTTPRouteParentRefs(httpRoute *HTTPRouteContext, res ) } + if hasOverlap { + routeStatus := GetRouteStatus(httpRoute) + status.SetRouteStatusCondition(routeStatus, + parentRef.routeParentStatusIdx, + httpRoute.GetGeneration(), + gwapiv1.RouteConditionResolvedRefs, + metav1.ConditionFalse, + status.RouteReasonOverlap, + "Overlapping match conditions with another HTTPRoute on the same listener and hostname", + ) + } + // Skip parent refs that did not accept the route if parentRef.HasCondition(httpRoute, gwapiv1.RouteConditionAccepted, metav1.ConditionFalse) { continue @@ -908,7 +920,7 @@ func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, res if parentRef.HasCondition(grpcRoute, gwapiv1.RouteConditionAccepted, metav1.ConditionFalse) { continue } - hasHostnameIntersection := t.processHTTPRouteParentRefListener(grpcRoute, routeRoutes, parentRef, xdsIR) + hasHostnameIntersection, hasOverlap := t.processHTTPRouteParentRefListener(grpcRoute, routeRoutes, parentRef, xdsIR) if !hasHostnameIntersection { routeStatus := GetRouteStatus(grpcRoute) status.SetRouteStatusCondition(routeStatus, @@ -921,6 +933,18 @@ func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, res ) } + if hasOverlap { + routeStatus := GetRouteStatus(grpcRoute) + status.SetRouteStatusCondition(routeStatus, + parentRef.routeParentStatusIdx, + grpcRoute.GetGeneration(), + gwapiv1.RouteConditionResolvedRefs, + metav1.ConditionFalse, + status.RouteReasonOverlap, + "Overlapping match conditions with another GRPCRoute on the same listener and hostname", + ) + } + // If no negative conditions have been set, the route is considered "Accepted=True". if parentRef.GRPCRoute != nil && len(parentRef.GRPCRoute.Status.Parents[parentRef.routeParentStatusIdx].Conditions) == 0 { @@ -1245,9 +1269,11 @@ func (t *Translator) processGRPCRouteMethodRegularExpression(method *gwapiv1.GRP } } -func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, routeRoutes []*ir.HTTPRoute, parentRef *RouteParentContext, xdsIR resource.XdsIRMap) bool { +func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, routeRoutes []*ir.HTTPRoute, parentRef *RouteParentContext, xdsIR resource.XdsIRMap) (bool, bool) { // need to check hostname intersection if there are listeners hasHostnameIntersection := len(parentRef.listeners) == 0 + var hasOverlap bool + for _, listener := range parentRef.listeners { hosts := computeHosts(GetHostnames(route), listener) if len(hosts) == 0 { @@ -1301,11 +1327,114 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route irListener.GRPC.EnableGRPCWeb = ptr.To(true) irListener.GRPC.EnableGRPCStats = ptr.To(true) } + + // Check for overlapping route matches before adding new routes. + // Two routes overlap when they are from different route resources + // but have identical match conditions on the same hostname. + routePrefix := irRoutePrefix(route) + for _, newRoute := range perHostRoutes { + for _, existingRoute := range irListener.Routes { + if strings.HasPrefix(existingRoute.Name, routePrefix) { + // Same route resource, skip. + continue + } + if routeMatchesOverlap(existingRoute, newRoute) { + hasOverlap = true + break + } + } + if hasOverlap { + break + } + } + irListener.Routes = append(irListener.Routes, perHostRoutes...) } } - return hasHostnameIntersection + return hasHostnameIntersection, hasOverlap +} + +// routeMatchesOverlap checks if two IR HTTP routes have identical match conditions, +// indicating that they match the same set of requests. +// This detects routes with the same hostname and identical exact path, header, query param, +// and cookie match conditions. Only routes with explicit exact path matches are checked; +// prefix path matches can intentionally overlap across HTTPRoute resources +// and are resolved through precedence ordering. +func routeMatchesOverlap(a, b *ir.HTTPRoute) bool { + if a.Hostname != b.Hostname { + return false + } + // Only detect overlap for routes with explicit exact path matches. + if a.PathMatch == nil || b.PathMatch == nil { + return false + } + if a.PathMatch.Exact == nil || b.PathMatch.Exact == nil { + return false + } + if !stringMatchEqual(a.PathMatch, b.PathMatch) { + return false + } + if !stringMatchSliceEqual(a.HeaderMatches, b.HeaderMatches) { + return false + } + if !stringMatchSliceEqual(a.QueryParamMatches, b.QueryParamMatches) { + return false + } + if !stringMatchSliceEqual(a.CookieMatches, b.CookieMatches) { + return false + } + return true +} + +func stringMatchEqual(a, b *ir.StringMatch) bool { + if a == nil && b == nil { + return true + } + if a == nil || b == nil { + return false + } + if !ptrStringEqual(a.Exact, b.Exact) { + return false + } + if !ptrStringEqual(a.Prefix, b.Prefix) { + return false + } + if !ptrStringEqual(a.Suffix, b.Suffix) { + return false + } + if !ptrStringEqual(a.SafeRegex, b.SafeRegex) { + return false + } + if a.Name != b.Name { + return false + } + if a.Distinct != b.Distinct { + return false + } + return true +} + +func stringMatchSliceEqual(a, b []*ir.StringMatch) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if !stringMatchEqual(a[i], b[i]) { + return false + } + } + return true +} + +func ptrStringEqual(a, b *string) bool { + if a == nil && b == nil { + return true + } + if a == nil || b == nil { + return false + } + return *a == *b } func buildResourceMetadata(resource client.Object, sectionName *gwapiv1.SectionName) *ir.ResourceMetadata { diff --git a/internal/gatewayapi/status/error.go b/internal/gatewayapi/status/error.go index 7e310da62b..bd9be60e64 100644 --- a/internal/gatewayapi/status/error.go +++ b/internal/gatewayapi/status/error.go @@ -31,6 +31,9 @@ const ( RouteReasonInvalidAddress gwapiv1.RouteConditionReason = "InvalidAddress" RouteReasonEndpointsNotFound gwapiv1.RouteConditionReason = "EndpointsNotFound" + // Route overlap reason + RouteReasonOverlap gwapiv1.RouteConditionReason = "Overlap" + // Network configuration related condition types RouteConditionBackendsAvailable gwapiv1.RouteConditionType = "BackendsAvailable" ) diff --git a/internal/gatewayapi/testdata/httproute-overlapping-matches.in.yaml b/internal/gatewayapi/testdata/httproute-overlapping-matches.in.yaml new file mode 100644 index 0000000000..9510e62777 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-overlapping-matches.in.yaml @@ -0,0 +1,50 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + type: Exact + value: "/testPath" + backendRefs: + - name: service-1 + port: 8080 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + type: Exact + value: "/testPath" + backendRefs: + - name: service-2 + port: 8080 diff --git a/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml b/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml new file mode 100644 index 0000000000..3c5e6dd309 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml @@ -0,0 +1,237 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 2 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + type: Exact + value: /testPath + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-2 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - name: service-2 + port: 8080 + matches: + - path: + type: Exact + value: /testPath + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Overlapping match conditions with another HTTPRoute on the same listener + and hostname + reason: Overlap + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + kind: Service + name: service-1 + namespace: default + sectionName: "8080" + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: '*' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + exact: /testPath + name: "" + - destination: + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + kind: Service + name: service-2 + namespace: default + sectionName: "8080" + name: httproute/default/httproute-2/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: '*' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/* + pathMatch: + distinct: false + exact: /testPath + name: "" + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 From 92aa64af22cf568ea7709d82e97ec41b631c6cf1 Mon Sep 17 00:00:00 2001 From: jukie Date: Mon, 9 Mar 2026 08:56:08 -0600 Subject: [PATCH 2/7] Check all route types vs only HTTPRoute Signed-off-by: jukie --- internal/gatewayapi/route.go | 163 +++++++++++++----- internal/gatewayapi/status/error.go | 5 +- .../httproute-overlapping-matches.out.yaml | 18 +- internal/gatewayapi/translator.go | 5 + 4 files changed, 140 insertions(+), 51 deletions(-) diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 1376f0ee1b..416fe32ee9 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "net" + "sort" "strconv" "strings" "time" @@ -179,7 +180,7 @@ func (t *Translator) processHTTPRouteParentRefs(httpRoute *HTTPRouteContext, res "Resolved all the Object references for the Route", ) } - hasHostnameIntersection, hasOverlap := t.processHTTPRouteParentRefListener(httpRoute, routeRoutes, parentRef, xdsIR) + hasHostnameIntersection := t.processHTTPRouteParentRefListener(httpRoute, routeRoutes, parentRef, xdsIR) if !hasHostnameIntersection { routeStatus := GetRouteStatus(httpRoute) status.SetRouteStatusCondition(routeStatus, @@ -192,18 +193,6 @@ func (t *Translator) processHTTPRouteParentRefs(httpRoute *HTTPRouteContext, res ) } - if hasOverlap { - routeStatus := GetRouteStatus(httpRoute) - status.SetRouteStatusCondition(routeStatus, - parentRef.routeParentStatusIdx, - httpRoute.GetGeneration(), - gwapiv1.RouteConditionResolvedRefs, - metav1.ConditionFalse, - status.RouteReasonOverlap, - "Overlapping match conditions with another HTTPRoute on the same listener and hostname", - ) - } - // Skip parent refs that did not accept the route if parentRef.HasCondition(httpRoute, gwapiv1.RouteConditionAccepted, metav1.ConditionFalse) { continue @@ -920,7 +909,7 @@ func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, res if parentRef.HasCondition(grpcRoute, gwapiv1.RouteConditionAccepted, metav1.ConditionFalse) { continue } - hasHostnameIntersection, hasOverlap := t.processHTTPRouteParentRefListener(grpcRoute, routeRoutes, parentRef, xdsIR) + hasHostnameIntersection := t.processHTTPRouteParentRefListener(grpcRoute, routeRoutes, parentRef, xdsIR) if !hasHostnameIntersection { routeStatus := GetRouteStatus(grpcRoute) status.SetRouteStatusCondition(routeStatus, @@ -933,18 +922,6 @@ func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, res ) } - if hasOverlap { - routeStatus := GetRouteStatus(grpcRoute) - status.SetRouteStatusCondition(routeStatus, - parentRef.routeParentStatusIdx, - grpcRoute.GetGeneration(), - gwapiv1.RouteConditionResolvedRefs, - metav1.ConditionFalse, - status.RouteReasonOverlap, - "Overlapping match conditions with another GRPCRoute on the same listener and hostname", - ) - } - // If no negative conditions have been set, the route is considered "Accepted=True". if parentRef.GRPCRoute != nil && len(parentRef.GRPCRoute.Status.Parents[parentRef.routeParentStatusIdx].Conditions) == 0 { @@ -1269,10 +1246,9 @@ func (t *Translator) processGRPCRouteMethodRegularExpression(method *gwapiv1.GRP } } -func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, routeRoutes []*ir.HTTPRoute, parentRef *RouteParentContext, xdsIR resource.XdsIRMap) (bool, bool) { +func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, routeRoutes []*ir.HTTPRoute, parentRef *RouteParentContext, xdsIR resource.XdsIRMap) bool { // need to check hostname intersection if there are listeners hasHostnameIntersection := len(parentRef.listeners) == 0 - var hasOverlap bool for _, listener := range parentRef.listeners { hosts := computeHosts(GetHostnames(route), listener) @@ -1328,31 +1304,130 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route irListener.GRPC.EnableGRPCStats = ptr.To(true) } - // Check for overlapping route matches before adding new routes. - // Two routes overlap when they are from different route resources - // but have identical match conditions on the same hostname. - routePrefix := irRoutePrefix(route) - for _, newRoute := range perHostRoutes { - for _, existingRoute := range irListener.Routes { - if strings.HasPrefix(existingRoute.Name, routePrefix) { - // Same route resource, skip. + irListener.Routes = append(irListener.Routes, perHostRoutes...) + } + } + + return hasHostnameIntersection +} + +// checkRouteOverlaps detects overlapping route matches across all IR listeners +// and sets a warning Overlap condition on the affected HTTPRoutes. +// This runs once after all routes are processed, checking each listener's routes +// for duplicates from different HTTPRoute resources. +// routeKey returns a "namespace/name" key for a route resource metadata. +func routeKey(namespace, name string) string { + return namespace + "/" + name +} + +// checkRouteOverlaps detects overlapping route matches across all IR listeners +// and sets a warning Overlap condition on the affected HTTPRoutes and GRPCRoutes. +// This runs once after all routes are processed, rather than inside the per-route +// processing loop where it would execute N times. +func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRoutes []*GRPCRouteContext, xdsIR resource.XdsIRMap) { + // Build a combined lookup from "namespace/name" to RouteContext and its ParentRefs. + type routeInfo struct { + route RouteContext + parentRefs map[gwapiv1.ParentReference]*RouteParentContext + } + routeByKey := make(map[string]*routeInfo, len(httpRoutes)+len(grpcRoutes)) + for _, hr := range httpRoutes { + routeByKey[routeKey(hr.GetNamespace(), hr.GetName())] = &routeInfo{route: hr, parentRefs: hr.ParentRefs} + } + for _, gr := range grpcRoutes { + routeByKey[routeKey(gr.GetNamespace(), gr.GetName())] = &routeInfo{route: gr, parentRefs: gr.ParentRefs} + } + + // overlaps tracks per IR listener which routes overlap with which others. + // Key: IR listener name -> route key -> set of conflicting route keys. + type listenerOverlaps map[string]map[string]struct{} + overlaps := make(map[string]listenerOverlaps) + + for _, xds := range xdsIR { + for _, httpListener := range xds.HTTP { + routes := httpListener.Routes + for i := 0; i < len(routes); i++ { + if routes[i].Metadata == nil { + continue + } + aKey := routeKey(routes[i].Metadata.Namespace, routes[i].Metadata.Name) + for j := i + 1; j < len(routes); j++ { + if routes[j].Metadata == nil { continue } - if routeMatchesOverlap(existingRoute, newRoute) { - hasOverlap = true - break + bKey := routeKey(routes[j].Metadata.Namespace, routes[j].Metadata.Name) + if aKey == bKey { + continue + } + if routeMatchesOverlap(routes[i], routes[j]) { + if overlaps[httpListener.Name] == nil { + overlaps[httpListener.Name] = make(listenerOverlaps) + } + lo := overlaps[httpListener.Name] + if lo[aKey] == nil { + lo[aKey] = make(map[string]struct{}) + } + if lo[bKey] == nil { + lo[bKey] = make(map[string]struct{}) + } + lo[aKey][bKey] = struct{}{} + lo[bKey][aKey] = struct{}{} } } - if hasOverlap { - break + } + } + } + + // Set the Overlap warning condition only on parentRefs whose listeners + // match an IR listener where the overlap was detected. + for rKey, info := range routeByKey { + // Collect all conflicts for this route across the parentRefs that have overlaps. + for _, parentRef := range info.parentRefs { + var conflicts map[string]struct{} + for _, listener := range parentRef.listeners { + irKey := t.getIRKey(listener.gateway.Gateway) + irListener := xdsIR[irKey].GetHTTPListener(irListenerName(listener)) + if irListener == nil { + continue + } + lo, ok := overlaps[irListener.Name] + if !ok { + continue + } + routeConflicts, ok := lo[rKey] + if !ok { + continue } + if conflicts == nil { + conflicts = make(map[string]struct{}) + } + for c := range routeConflicts { + conflicts[c] = struct{}{} + } + } + if len(conflicts) == 0 { + continue } - irListener.Routes = append(irListener.Routes, perHostRoutes...) + conflictNames := make([]string, 0, len(conflicts)) + for name := range conflicts { + conflictNames = append(conflictNames, name) + } + sort.Strings(conflictNames) + + msg := fmt.Sprintf("Overlapping match conditions with route(s): %s", strings.Join(conflictNames, ", ")) + + routeStatus := GetRouteStatus(info.route) + status.SetRouteStatusCondition(routeStatus, + parentRef.routeParentStatusIdx, + info.route.GetGeneration(), + status.RouteConditionOverlap, + metav1.ConditionTrue, + status.RouteReasonOverlap, + msg, + ) } } - - return hasHostnameIntersection, hasOverlap } // routeMatchesOverlap checks if two IR HTTP routes have identical match conditions, diff --git a/internal/gatewayapi/status/error.go b/internal/gatewayapi/status/error.go index bd9be60e64..3b256fe81e 100644 --- a/internal/gatewayapi/status/error.go +++ b/internal/gatewayapi/status/error.go @@ -31,8 +31,9 @@ const ( RouteReasonInvalidAddress gwapiv1.RouteConditionReason = "InvalidAddress" RouteReasonEndpointsNotFound gwapiv1.RouteConditionReason = "EndpointsNotFound" - // Route overlap reason - RouteReasonOverlap gwapiv1.RouteConditionReason = "Overlap" + // Route overlap reason and condition type + RouteReasonOverlap gwapiv1.RouteConditionReason = "Overlap" + RouteConditionOverlap gwapiv1.RouteConditionType = "Overlap" // Network configuration related condition types RouteConditionBackendsAvailable gwapiv1.RouteConditionType = "BackendsAvailable" diff --git a/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml b/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml index 3c5e6dd309..63e9ea18a0 100644 --- a/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml +++ b/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml @@ -69,6 +69,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -99,11 +104,15 @@ httpRoutes: status: "True" type: Accepted - lastTransitionTime: null - message: Overlapping match conditions with another HTTPRoute on the same listener - and hostname - reason: Overlap - status: "False" + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -158,7 +167,6 @@ xdsIR: externalPort: 80 hostnames: - '*' - isHTTP2: false metadata: kind: Gateway name: gateway-1 diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go index 19dc472683..a709bd25ac 100644 --- a/internal/gatewayapi/translator.go +++ b/internal/gatewayapi/translator.go @@ -286,6 +286,11 @@ func (t *Translator) Translate(resources *resource.Resources) (*TranslateResult, // Process all relevant GRPCRoutes. grpcRoutes := t.ProcessGRPCRoutes(resources.GRPCRoutes, acceptedGateways, resources, xdsIR) + // Check for overlapping route matches across all listeners after all HTTP and + // GRPC routes have been processed. This runs once rather than inside the + // per-route processing loop where it would execute N times. + t.checkRouteOverlaps(httpRoutes, grpcRoutes, xdsIR) + // Process all relevant TLSRoutes. tlsRoutes := t.ProcessTLSRoutes(resources.TLSRoutes, acceptedGateways, resources, xdsIR) From ed22848fb41b0f2777da22ccecf9ffb709ad4a80 Mon Sep 17 00:00:00 2001 From: jukie Date: Mon, 9 Mar 2026 09:53:47 -0600 Subject: [PATCH 3/7] lint Signed-off-by: jukie --- internal/gatewayapi/route.go | 4 ---- internal/gatewayapi/status/error.go | 4 ++-- internal/gatewayapi/translator.go | 3 +-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 416fe32ee9..e4776eb4e6 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -1313,8 +1313,6 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route // checkRouteOverlaps detects overlapping route matches across all IR listeners // and sets a warning Overlap condition on the affected HTTPRoutes. -// This runs once after all routes are processed, checking each listener's routes -// for duplicates from different HTTPRoute resources. // routeKey returns a "namespace/name" key for a route resource metadata. func routeKey(namespace, name string) string { return namespace + "/" + name @@ -1322,8 +1320,6 @@ func routeKey(namespace, name string) string { // checkRouteOverlaps detects overlapping route matches across all IR listeners // and sets a warning Overlap condition on the affected HTTPRoutes and GRPCRoutes. -// This runs once after all routes are processed, rather than inside the per-route -// processing loop where it would execute N times. func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRoutes []*GRPCRouteContext, xdsIR resource.XdsIRMap) { // Build a combined lookup from "namespace/name" to RouteContext and its ParentRefs. type routeInfo struct { diff --git a/internal/gatewayapi/status/error.go b/internal/gatewayapi/status/error.go index 3b256fe81e..8f7274a7c0 100644 --- a/internal/gatewayapi/status/error.go +++ b/internal/gatewayapi/status/error.go @@ -32,8 +32,8 @@ const ( RouteReasonEndpointsNotFound gwapiv1.RouteConditionReason = "EndpointsNotFound" // Route overlap reason and condition type - RouteReasonOverlap gwapiv1.RouteConditionReason = "Overlap" - RouteConditionOverlap gwapiv1.RouteConditionType = "Overlap" + RouteReasonOverlap gwapiv1.RouteConditionReason = "Overlap" + RouteConditionOverlap gwapiv1.RouteConditionType = "Overlap" // Network configuration related condition types RouteConditionBackendsAvailable gwapiv1.RouteConditionType = "BackendsAvailable" diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go index a709bd25ac..ef4c58b976 100644 --- a/internal/gatewayapi/translator.go +++ b/internal/gatewayapi/translator.go @@ -287,8 +287,7 @@ func (t *Translator) Translate(resources *resource.Resources) (*TranslateResult, grpcRoutes := t.ProcessGRPCRoutes(resources.GRPCRoutes, acceptedGateways, resources, xdsIR) // Check for overlapping route matches across all listeners after all HTTP and - // GRPC routes have been processed. This runs once rather than inside the - // per-route processing loop where it would execute N times. + // GRPC routes have been processed. t.checkRouteOverlaps(httpRoutes, grpcRoutes, xdsIR) // Process all relevant TLSRoutes. From 1b002aa51358f3ae2cef6d753c0085a4fd5aae9c Mon Sep 17 00:00:00 2001 From: jukie <10012479+jukie@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:24:23 -0600 Subject: [PATCH 4/7] feedback Signed-off-by: jukie <10012479+jukie@users.noreply.github.com> Signed-off-by: jukie <10012479+Jukie@users.noreply.github.com> --- internal/gatewayapi/overlap_test.go | 24 ++- internal/gatewayapi/route.go | 90 +++------ .../backend-tls-settings-invalid.out.yaml | 10 + .../testdata/backend-tls-settings.out.yaml | 49 +++++ ...olicy-status-conditions-truncated.out.yaml | 180 ++++++++++++++++++ ...y-multiple-targets-targetselector.out.yaml | 10 + ...ficpolicy-strategic-merge-section.out.yaml | 10 + ...policy-with-healthcheck-overrides.out.yaml | 10 + ...endtrafficpolicy-with-healthcheck.out.yaml | 28 +++ ...fficpolicy-with-httproute-timeout.out.yaml | 10 + ...fficpolicy-with-response-override.out.yaml | 10 + ...olicy-with-same-prefix-httproutes.out.yaml | 10 + .../backendtrafficpolicy-with-stats.out.yaml | 10 + ...enttrafficpolicy-invalid-settings.out.yaml | 10 + ...nsionpolicy-section-name-override.out.yaml | 10 + ...ith-invalid-lua-validation-syntax.out.yaml | 10 + .../gateway-with-attached-routes.out.yaml | 10 + .../httproute-dynamic-resolver.out.yaml | 10 + ...ervice-backends-and-app-protocols.out.yaml | 10 + ...-non-service-backends-and-weights.out.yaml | 10 + ...ttproute-with-conflicting-filters.out.yaml | 10 + ...tproute-with-credential-injection.out.yaml | 10 + .../testdata/listenerset-httproute.out.yaml | 16 ++ 23 files changed, 487 insertions(+), 70 deletions(-) diff --git a/internal/gatewayapi/overlap_test.go b/internal/gatewayapi/overlap_test.go index ae19e2b001..09710d2327 100644 --- a/internal/gatewayapi/overlap_test.go +++ b/internal/gatewayapi/overlap_test.go @@ -58,7 +58,7 @@ func TestRouteMatchesOverlap(t *testing.T) { overlap: false, }, { - name: "prefix paths are not detected as overlap", + name: "identical prefix paths are detected as overlap", a: &ir.HTTPRoute{ Hostname: "example.com", PathMatch: &ir.StringMatch{Prefix: ptr.To("/api")}, @@ -67,17 +67,17 @@ func TestRouteMatchesOverlap(t *testing.T) { Hostname: "example.com", PathMatch: &ir.StringMatch{Prefix: ptr.To("/api")}, }, - overlap: false, + overlap: true, }, { - name: "nil path matches are not detected as overlap", + name: "nil path matches are detected as overlap", a: &ir.HTTPRoute{ Hostname: "example.com", }, b: &ir.HTTPRoute{ Hostname: "example.com", }, - overlap: false, + overlap: true, }, { name: "exact vs prefix same value not overlap", @@ -161,7 +161,7 @@ func TestRouteMatchesOverlap(t *testing.T) { overlap: true, }, { - name: "regex path matches are not detected as overlap", + name: "identical regex path matches are detected as overlap", a: &ir.HTTPRoute{ Hostname: "example.com", PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, @@ -170,7 +170,7 @@ func TestRouteMatchesOverlap(t *testing.T) { Hostname: "example.com", PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, }, - overlap: false, + overlap: true, }, } @@ -224,6 +224,18 @@ func TestStringMatchEqual(t *testing.T) { b: &ir.StringMatch{Name: "h", Distinct: false}, equal: false, }, + { + name: "different invert", + a: &ir.StringMatch{Name: "h", Exact: ptr.To("v"), Invert: ptr.To(true)}, + b: &ir.StringMatch{Name: "h", Exact: ptr.To("v")}, + equal: false, + }, + { + name: "same invert", + a: &ir.StringMatch{Name: "h", Exact: ptr.To("v"), Invert: ptr.To(true)}, + b: &ir.StringMatch{Name: "h", Exact: ptr.To("v"), Invert: ptr.To(true)}, + equal: true, + }, } for _, tt := range tests { diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 4fccdda896..2b50472d4f 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "net" + "slices" "sort" "strconv" "strings" @@ -1327,8 +1328,6 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route return hasHostnameIntersection } -// checkRouteOverlaps detects overlapping route matches across all IR listeners -// and sets a warning Overlap condition on the affected HTTPRoutes. // routeKey returns a "namespace/name" key for a route resource metadata. func routeKey(namespace, name string) string { return namespace + "/" + name @@ -1358,17 +1357,19 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout for _, xds := range xdsIR { for _, httpListener := range xds.HTTP { routes := httpListener.Routes + // Pre-compute route keys + keys := make([]string, len(routes)) + for i, r := range routes { + if r.Metadata != nil { + keys[i] = routeKey(r.Metadata.Namespace, r.Metadata.Name) + } + } for i := 0; i < len(routes); i++ { - if routes[i].Metadata == nil { + if keys[i] == "" { continue } - aKey := routeKey(routes[i].Metadata.Namespace, routes[i].Metadata.Name) for j := i + 1; j < len(routes); j++ { - if routes[j].Metadata == nil { - continue - } - bKey := routeKey(routes[j].Metadata.Namespace, routes[j].Metadata.Name) - if aKey == bKey { + if keys[j] == "" || keys[i] == keys[j] { continue } if routeMatchesOverlap(routes[i], routes[j]) { @@ -1376,14 +1377,14 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout overlaps[httpListener.Name] = make(listenerOverlaps) } lo := overlaps[httpListener.Name] - if lo[aKey] == nil { - lo[aKey] = make(map[string]struct{}) + if lo[keys[i]] == nil { + lo[keys[i]] = make(map[string]struct{}) } - if lo[bKey] == nil { - lo[bKey] = make(map[string]struct{}) + if lo[keys[j]] == nil { + lo[keys[j]] = make(map[string]struct{}) } - lo[aKey][bKey] = struct{}{} - lo[bKey][aKey] = struct{}{} + lo[keys[i]][keys[j]] = struct{}{} + lo[keys[j]][keys[i]] = struct{}{} } } } @@ -1444,21 +1445,12 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout // routeMatchesOverlap checks if two IR HTTP routes have identical match conditions, // indicating that they match the same set of requests. -// This detects routes with the same hostname and identical exact path, header, query param, -// and cookie match conditions. Only routes with explicit exact path matches are checked; -// prefix path matches can intentionally overlap across HTTPRoute resources -// and are resolved through precedence ordering. +// This detects routes with the same hostname and identical path, header, query param, +// and cookie match conditions across all path match types (exact, prefix, regex). func routeMatchesOverlap(a, b *ir.HTTPRoute) bool { if a.Hostname != b.Hostname { return false } - // Only detect overlap for routes with explicit exact path matches. - if a.PathMatch == nil || b.PathMatch == nil { - return false - } - if a.PathMatch.Exact == nil || b.PathMatch.Exact == nil { - return false - } if !stringMatchEqual(a.PathMatch, b.PathMatch) { return false } @@ -1481,47 +1473,17 @@ func stringMatchEqual(a, b *ir.StringMatch) bool { if a == nil || b == nil { return false } - if !ptrStringEqual(a.Exact, b.Exact) { - return false - } - if !ptrStringEqual(a.Prefix, b.Prefix) { - return false - } - if !ptrStringEqual(a.Suffix, b.Suffix) { - return false - } - if !ptrStringEqual(a.SafeRegex, b.SafeRegex) { - return false - } - if a.Name != b.Name { - return false - } - if a.Distinct != b.Distinct { - return false - } - return true + return a.Name == b.Name && + a.Distinct == b.Distinct && + ptr.Equal(a.Exact, b.Exact) && + ptr.Equal(a.Prefix, b.Prefix) && + ptr.Equal(a.Suffix, b.Suffix) && + ptr.Equal(a.SafeRegex, b.SafeRegex) && + ptr.Equal(a.Invert, b.Invert) } func stringMatchSliceEqual(a, b []*ir.StringMatch) bool { - if len(a) != len(b) { - return false - } - for i := range a { - if !stringMatchEqual(a[i], b[i]) { - return false - } - } - return true -} - -func ptrStringEqual(a, b *string) bool { - if a == nil && b == nil { - return true - } - if a == nil || b == nil { - return false - } - return *a == *b + return slices.EqualFunc(a, b, stringMatchEqual) } func buildResourceMetadata(resource client.Object, sectionName *gwapiv1.SectionName) *ir.ResourceMetadata { diff --git a/internal/gatewayapi/testdata/backend-tls-settings-invalid.out.yaml b/internal/gatewayapi/testdata/backend-tls-settings-invalid.out.yaml index ca0322916a..3ffd604ac4 100644 --- a/internal/gatewayapi/testdata/backend-tls-settings-invalid.out.yaml +++ b/internal/gatewayapi/testdata/backend-tls-settings-invalid.out.yaml @@ -150,6 +150,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -184,6 +189,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backend-tls-settings.out.yaml b/internal/gatewayapi/testdata/backend-tls-settings.out.yaml index dee70c0bd8..77f457de40 100644 --- a/internal/gatewayapi/testdata/backend-tls-settings.out.yaml +++ b/internal/gatewayapi/testdata/backend-tls-settings.out.yaml @@ -431,6 +431,13 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2, + default/httproute-3, default/httproute-4, default/httproute-5, default/httproute-6, + envoy-gateway/httproute-7-override-client-tls-settings' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -465,6 +472,13 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1, + default/httproute-3, default/httproute-4, default/httproute-5, default/httproute-6, + envoy-gateway/httproute-7-override-client-tls-settings' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -499,6 +513,13 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1, + default/httproute-2, default/httproute-4, default/httproute-5, default/httproute-6, + envoy-gateway/httproute-7-override-client-tls-settings' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -534,6 +555,13 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1, + default/httproute-2, default/httproute-3, default/httproute-5, default/httproute-6, + envoy-gateway/httproute-7-override-client-tls-settings' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -570,6 +598,13 @@ httpRoutes: reason: InvalidBackendRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1, + default/httproute-2, default/httproute-3, default/httproute-4, default/httproute-6, + envoy-gateway/httproute-7-override-client-tls-settings' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -607,6 +642,13 @@ httpRoutes: reason: InvalidBackendRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1, + default/httproute-2, default/httproute-3, default/httproute-4, default/httproute-5, + envoy-gateway/httproute-7-override-client-tls-settings' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -642,6 +684,13 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1, + default/httproute-2, default/httproute-3, default/httproute-4, default/httproute-5, + default/httproute-6' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtlspolicy-status-conditions-truncated.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-status-conditions-truncated.out.yaml index cc46cac2e1..8e050bb811 100644 --- a/internal/gatewayapi/testdata/backendtlspolicy-status-conditions-truncated.out.yaml +++ b/internal/gatewayapi/testdata/backendtlspolicy-status-conditions-truncated.out.yaml @@ -1296,6 +1296,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -1311,6 +1316,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 @@ -1326,6 +1336,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-3 @@ -1341,6 +1356,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-4 @@ -1356,6 +1376,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-5 @@ -1371,6 +1396,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-6 @@ -1386,6 +1416,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-7 @@ -1401,6 +1436,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-8 @@ -1416,6 +1456,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-9 @@ -1431,6 +1476,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-10 @@ -1446,6 +1496,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-11 @@ -1461,6 +1516,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-12 @@ -1476,6 +1536,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-13 @@ -1491,6 +1556,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-14 @@ -1506,6 +1576,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-15 @@ -1521,6 +1596,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-16 @@ -1536,6 +1616,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-17 @@ -1551,6 +1636,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-18 @@ -1619,6 +1709,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -1635,6 +1730,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 @@ -1651,6 +1751,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-3 @@ -1667,6 +1772,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-4 @@ -1683,6 +1793,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-5 @@ -1699,6 +1814,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-6 @@ -1715,6 +1835,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-7 @@ -1731,6 +1856,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-8 @@ -1747,6 +1877,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-9 @@ -1763,6 +1898,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-10 @@ -1779,6 +1919,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-11 @@ -1795,6 +1940,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-12 @@ -1811,6 +1961,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-13 @@ -1827,6 +1982,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-14 @@ -1843,6 +2003,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-15 @@ -1859,6 +2024,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-16 @@ -1875,6 +2045,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-17 @@ -1891,6 +2066,11 @@ httpRoutes: reason: InvalidBackendTLS status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-18 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml index a1c8a4e287..86715e66c6 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml @@ -101,6 +101,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/httproute' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -141,6 +146,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-section.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-section.out.yaml index 57af373649..692f4734c4 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-section.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-section.out.yaml @@ -408,6 +408,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -442,6 +447,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml index f6b26324dc..05178d3117 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml @@ -229,6 +229,11 @@ grpcRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/grpcroute-with-no-overrides' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway @@ -261,6 +266,11 @@ grpcRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/grpcroute-with-overrides' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml index a1480de5e0..27c7effed2 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml @@ -505,6 +505,12 @@ grpcRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/grpcroute-2, + default/grpcroute-3' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -537,6 +543,12 @@ grpcRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/grpcroute-1, + default/grpcroute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -569,6 +581,12 @@ grpcRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/grpcroute-1, + default/grpcroute-3' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -644,6 +662,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-4' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 @@ -718,6 +741,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-httproute-timeout.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-httproute-timeout.out.yaml index 0545d716c1..f6151f71c4 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-httproute-timeout.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-httproute-timeout.out.yaml @@ -147,6 +147,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -186,6 +191,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-response-override.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-response-override.out.yaml index 429804c25b..775743047a 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-response-override.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-response-override.out.yaml @@ -379,6 +379,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-3' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 @@ -416,6 +421,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml index 7e1b42ffd4..2653347e76 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml @@ -106,6 +106,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -143,6 +148,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml index 72bfc454a5..8575c5dac0 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml @@ -210,6 +210,11 @@ grpcRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/grpcroute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -242,6 +247,11 @@ grpcRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/grpcroute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml index dcee0c7609..1f2ee89505 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml @@ -717,6 +717,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -749,6 +754,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-section-name-override.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-section-name-override.out.yaml index 2312844481..b8eeae6eae 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-section-name-override.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-section-name-override.out.yaml @@ -264,6 +264,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -301,6 +306,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-syntax.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-syntax.out.yaml index a8c02a1853..da1d6bebd3 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-syntax.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-syntax.out.yaml @@ -164,6 +164,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -201,6 +206,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml b/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml index c2ac20067f..5b1d4509eb 100644 --- a/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml @@ -178,6 +178,11 @@ httpRoutes: reason: BackendNotFound status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/http-route-3' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: kind: Gateway @@ -211,6 +216,11 @@ httpRoutes: reason: BackendNotFound status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): envoy-gateway/http-route-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: kind: Gateway diff --git a/internal/gatewayapi/testdata/httproute-dynamic-resolver.out.yaml b/internal/gatewayapi/testdata/httproute-dynamic-resolver.out.yaml index 117afe3269..40c61f76fa 100644 --- a/internal/gatewayapi/testdata/httproute-dynamic-resolver.out.yaml +++ b/internal/gatewayapi/testdata/httproute-dynamic-resolver.out.yaml @@ -107,6 +107,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -142,6 +147,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml index e6d915ea41..9ae6ad8bf6 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml @@ -110,6 +110,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -144,6 +149,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml index f942a44d0e..9e0a475127 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml @@ -108,6 +108,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -142,6 +147,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/httproute-with-conflicting-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-conflicting-filters.out.yaml index ab7a2e2f57..76a0373c9e 100644 --- a/internal/gatewayapi/testdata/httproute-with-conflicting-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-conflicting-filters.out.yaml @@ -98,6 +98,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/mirror-request-redirect' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -157,6 +162,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/mirror-direct-response' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/httproute-with-credential-injection.out.yaml b/internal/gatewayapi/testdata/httproute-with-credential-injection.out.yaml index 17ac89bf03..cbbf10b3f9 100644 --- a/internal/gatewayapi/testdata/httproute-with-credential-injection.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-credential-injection.out.yaml @@ -90,6 +90,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-2' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -134,6 +139,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/httproute-1' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/listenerset-httproute.out.yaml b/internal/gatewayapi/testdata/listenerset-httproute.out.yaml index 69aa62ae91..80d28370c2 100644 --- a/internal/gatewayapi/testdata/listenerset-httproute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-httproute.out.yaml @@ -107,6 +107,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/route-entire-xls' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: group: gateway.networking.k8s.io @@ -143,6 +148,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/route-entire-xls' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: group: gateway.networking.k8s.io @@ -178,6 +188,12 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): default/route-extra-http-one, + default/route-extra-http-two' + reason: Overlap + status: "True" + type: Overlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: group: gateway.networking.k8s.io From 8e75daa6b7b94c9e4464482f4e162a2f8a19c0ff Mon Sep 17 00:00:00 2001 From: jukie <10012479+Jukie@users.noreply.github.com> Date: Wed, 8 Apr 2026 23:20:10 -0600 Subject: [PATCH 5/7] use listener name map to avoid repeated linear scans in checkRouteOverlaps Signed-off-by: jukie <10012479+Jukie@users.noreply.github.com> --- internal/gatewayapi/route.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 2b50472d4f..ea89c18494 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -1391,6 +1391,14 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout } } + // Pre-build listener name lookup to avoid repeated linear scans via GetHTTPListener. + listenerByName := make(map[string]*ir.HTTPListener) + for _, xds := range xdsIR { + for _, hl := range xds.HTTP { + listenerByName[hl.Name] = hl + } + } + // Set the Overlap warning condition only on parentRefs whose listeners // match an IR listener where the overlap was detected. for rKey, info := range routeByKey { @@ -1398,8 +1406,7 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout for _, parentRef := range info.parentRefs { var conflicts map[string]struct{} for _, listener := range parentRef.listeners { - irKey := t.getIRKey(listener.gateway.Gateway) - irListener := xdsIR[irKey].GetHTTPListener(irListenerName(listener)) + irListener := listenerByName[irListenerName(listener)] if irListener == nil { continue } From 4071e970d2e80de9c27d2da0f4eea08d57b181d9 Mon Sep 17 00:00:00 2001 From: jukie <10012479+jukie@users.noreply.github.com> Date: Mon, 13 Apr 2026 19:39:51 -0600 Subject: [PATCH 6/7] Feedback Signed-off-by: jukie <10012479+jukie@users.noreply.github.com> --- internal/gatewayapi/listener_test.go | 4 +- internal/gatewayapi/overlap_test.go | 192 ++++++--------- internal/gatewayapi/route.go | 233 ++++++++++++------ internal/gatewayapi/status/error.go | 4 +- .../backend-tls-settings-invalid.out.yaml | 12 +- .../testdata/backend-tls-settings.out.yaml | 70 +++--- ...olicy-status-conditions-truncated.out.yaml | 216 ++++++++-------- ...y-multiple-targets-targetselector.out.yaml | 12 +- ...ficpolicy-strategic-merge-section.out.yaml | 12 +- ...policy-with-healthcheck-overrides.out.yaml | 12 +- ...endtrafficpolicy-with-healthcheck.out.yaml | 36 +-- ...fficpolicy-with-httproute-timeout.out.yaml | 12 +- ...fficpolicy-with-response-override.out.yaml | 12 +- ...olicy-with-same-prefix-httproutes.out.yaml | 12 +- .../backendtrafficpolicy-with-stats.out.yaml | 12 +- ...enttrafficpolicy-invalid-settings.out.yaml | 12 +- ...nsionpolicy-section-name-override.out.yaml | 12 +- ...ith-invalid-lua-validation-syntax.out.yaml | 12 +- .../gateway-with-attached-routes.out.yaml | 12 +- .../httproute-dynamic-resolver.out.yaml | 12 +- .../httproute-overlapping-matches.out.yaml | 12 +- ...ervice-backends-and-app-protocols.out.yaml | 12 +- ...-non-service-backends-and-weights.out.yaml | 12 +- ...ttproute-with-conflicting-filters.out.yaml | 12 +- ...tproute-with-credential-injection.out.yaml | 12 +- .../testdata/listenerset-httproute.out.yaml | 20 +- release-notes/current.yaml | 1 + 27 files changed, 521 insertions(+), 471 deletions(-) diff --git a/internal/gatewayapi/listener_test.go b/internal/gatewayapi/listener_test.go index 2a108fd261..4b28dc96fd 100644 --- a/internal/gatewayapi/listener_test.go +++ b/internal/gatewayapi/listener_test.go @@ -1379,7 +1379,7 @@ func TestProcessBackendRefsBackendTLSPolicy(t *testing.T) { }, } backendEndpoints := []*ir.DestinationEndpoint{{Host: "otel.example.com", Port: 443}} - backendMetadata := &ir.ResourceMetadata{Name: backendName, Namespace: ns} + backendMetadata := &ir.ResourceMetadata{Kind: resource.KindBackend, Name: backendName, Namespace: ns} backendPolicyTLS := &ir.TLSUpstreamConfig{ SNI: ptr.To("otel.example.com"), UseSystemTrustStore: true, CACertificate: &ir.TLSCACertificate{Name: "otel-tls/test-ns-ca"}, SubjectAltNames: []ir.SubjectAltName{}, @@ -1417,7 +1417,7 @@ func TestProcessBackendRefsBackendTLSPolicy(t *testing.T) { }, } serviceEndpoints := []*ir.DestinationEndpoint{{Host: "7.7.7.7", Port: 4317}} - serviceMetadata := &ir.ResourceMetadata{Name: serviceName, Namespace: ns, SectionName: "4317"} + serviceMetadata := &ir.ResourceMetadata{Kind: resource.KindService, Name: serviceName, Namespace: ns, SectionName: "4317"} servicePolicyTLS := &ir.TLSUpstreamConfig{ SNI: ptr.To("otel-svc.example.com"), UseSystemTrustStore: true, CACertificate: &ir.TLSCACertificate{Name: "otel-svc-tls/test-ns-ca"}, SubjectAltNames: []ir.SubjectAltName{}, diff --git a/internal/gatewayapi/overlap_test.go b/internal/gatewayapi/overlap_test.go index 09710d2327..e3b3aa5e3c 100644 --- a/internal/gatewayapi/overlap_test.go +++ b/internal/gatewayapi/overlap_test.go @@ -14,7 +14,13 @@ import ( "github.com/envoyproxy/gateway/internal/ir" ) -func TestRouteMatchesOverlap(t *testing.T) { +// routesOverlap is a test helper that returns true if two routes produce the +// same canonical overlap key (i.e., they match the same set of requests). +func routesOverlap(a, b *ir.HTTPRoute) bool { + return buildOverlapKey(a) == buildOverlapKey(b) +} + +func TestBuildOverlapKey(t *testing.T) { tests := []struct { name string a *ir.HTTPRoute @@ -143,156 +149,114 @@ func TestRouteMatchesOverlap(t *testing.T) { overlap: false, }, { - name: "identical exact path with identical query param matches", + name: "header names are compared case-insensitively", a: &ir.HTTPRoute{ Hostname: "example.com", PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, - QueryParamMatches: []*ir.StringMatch{ - {Name: "key", Exact: ptr.To("value")}, + HeaderMatches: []*ir.StringMatch{ + {Name: "X-Custom", Exact: ptr.To("val1")}, }, }, b: &ir.HTTPRoute{ Hostname: "example.com", PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, - QueryParamMatches: []*ir.StringMatch{ - {Name: "key", Exact: ptr.To("value")}, + HeaderMatches: []*ir.StringMatch{ + {Name: "x-custom", Exact: ptr.To("val1")}, }, }, overlap: true, }, { - name: "identical regex path matches are detected as overlap", + name: "header matches in different order still overlap", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + HeaderMatches: []*ir.StringMatch{ + {Name: "X-A", Exact: ptr.To("1")}, + {Name: "X-B", Exact: ptr.To("2")}, + }, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + HeaderMatches: []*ir.StringMatch{ + {Name: "X-B", Exact: ptr.To("2")}, + {Name: "X-A", Exact: ptr.To("1")}, + }, }, overlap: true, }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.overlap, routeMatchesOverlap(tt.a, tt.b)) - }) - } -} - -func TestStringMatchEqual(t *testing.T) { - tests := []struct { - name string - a *ir.StringMatch - b *ir.StringMatch - equal bool - }{ - { - name: "both nil", - a: nil, - b: nil, - equal: true, - }, - { - name: "one nil", - a: &ir.StringMatch{Exact: ptr.To("foo")}, - b: nil, - equal: false, - }, - { - name: "identical exact", - a: &ir.StringMatch{Name: "h", Exact: ptr.To("v")}, - b: &ir.StringMatch{Name: "h", Exact: ptr.To("v")}, - equal: true, - }, - { - name: "different name", - a: &ir.StringMatch{Name: "a", Exact: ptr.To("v")}, - b: &ir.StringMatch{Name: "b", Exact: ptr.To("v")}, - equal: false, - }, { - name: "different value", - a: &ir.StringMatch{Name: "h", Exact: ptr.To("v1")}, - b: &ir.StringMatch{Name: "h", Exact: ptr.To("v2")}, - equal: false, - }, - { - name: "different distinct", - a: &ir.StringMatch{Name: "h", Distinct: true}, - b: &ir.StringMatch{Name: "h", Distinct: false}, - equal: false, - }, - { - name: "different invert", - a: &ir.StringMatch{Name: "h", Exact: ptr.To("v"), Invert: ptr.To(true)}, - b: &ir.StringMatch{Name: "h", Exact: ptr.To("v")}, - equal: false, - }, - { - name: "same invert", - a: &ir.StringMatch{Name: "h", Exact: ptr.To("v"), Invert: ptr.To(true)}, - b: &ir.StringMatch{Name: "h", Exact: ptr.To("v"), Invert: ptr.To(true)}, - equal: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.equal, stringMatchEqual(tt.a, tt.b)) - }) - } -} - -func TestStringMatchSliceEqual(t *testing.T) { - tests := []struct { - name string - a []*ir.StringMatch - b []*ir.StringMatch - equal bool - }{ - { - name: "both empty", - a: nil, - b: nil, - equal: true, + name: "identical exact path with identical query param matches", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + QueryParamMatches: []*ir.StringMatch{ + {Name: "key", Exact: ptr.To("value")}, + }, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + QueryParamMatches: []*ir.StringMatch{ + {Name: "key", Exact: ptr.To("value")}, + }, + }, + overlap: true, }, { - name: "different lengths", - a: []*ir.StringMatch{{Name: "a", Exact: ptr.To("1")}}, - b: nil, - equal: false, + name: "query param matches in different order still overlap", + a: &ir.HTTPRoute{ + Hostname: "example.com", + QueryParamMatches: []*ir.StringMatch{ + {Name: "a", Exact: ptr.To("1")}, + {Name: "b", Exact: ptr.To("2")}, + }, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + QueryParamMatches: []*ir.StringMatch{ + {Name: "b", Exact: ptr.To("2")}, + {Name: "a", Exact: ptr.To("1")}, + }, + }, + overlap: true, }, { - name: "identical", - a: []*ir.StringMatch{ - {Name: "a", Exact: ptr.To("1")}, - {Name: "b", Exact: ptr.To("2")}, + name: "cookie matches in different order still overlap", + a: &ir.HTTPRoute{ + Hostname: "example.com", + CookieMatches: []*ir.StringMatch{ + {Name: "a", Exact: ptr.To("1")}, + {Name: "b", Exact: ptr.To("2")}, + }, }, - b: []*ir.StringMatch{ - {Name: "a", Exact: ptr.To("1")}, - {Name: "b", Exact: ptr.To("2")}, + b: &ir.HTTPRoute{ + Hostname: "example.com", + CookieMatches: []*ir.StringMatch{ + {Name: "b", Exact: ptr.To("2")}, + {Name: "a", Exact: ptr.To("1")}, + }, }, - equal: true, + overlap: true, }, { - name: "same elements different order", - a: []*ir.StringMatch{ - {Name: "a", Exact: ptr.To("1")}, - {Name: "b", Exact: ptr.To("2")}, + name: "identical regex path matches are detected as overlap", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, }, - b: []*ir.StringMatch{ - {Name: "b", Exact: ptr.To("2")}, - {Name: "a", Exact: ptr.To("1")}, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, }, - equal: false, + overlap: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.equal, stringMatchSliceEqual(tt.a, tt.b)) + assert.Equal(t, tt.overlap, routesOverlap(tt.a, tt.b)) }) } } diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index ea89c18494..5d2d780c4d 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "net" - "slices" "sort" "strconv" "strings" @@ -1328,25 +1327,48 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route return hasHostnameIntersection } -// routeKey returns a "namespace/name" key for a route resource metadata. -func routeKey(namespace, name string) string { - return namespace + "/" + name +// routeKey returns a "kind/namespace/name" key for a route resource. +// Kind is included so HTTPRoute and GRPCRoute with the same namespace/name +// do not collide in the route lookup. +func routeKey(kind, namespace, name string) string { + return kind + "/" + namespace + "/" + name +} + +// routeDisplayNameFromKey converts a routeKey ("Kind/namespace/name") into a +// human-readable form ("Kind namespace/name") for user-facing status messages. +func routeDisplayNameFromKey(key string) string { + kind, nsName, ok := strings.Cut(key, "/") + if !ok { + return key + } + return kind + " " + nsName +} + +// overlapKey is a canonical representation of a route's match conditions. +// Routes sharing the same overlapKey within a listener match the exact same +// set of requests and are therefore considered overlapping. +type overlapKey struct { + hostname string + path string + headers string + query string + cookies string } // checkRouteOverlaps detects overlapping route matches across all IR listeners // and sets a warning Overlap condition on the affected HTTPRoutes and GRPCRoutes. func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRoutes []*GRPCRouteContext, xdsIR resource.XdsIRMap) { - // Build a combined lookup from "namespace/name" to RouteContext and its ParentRefs. + // Build a combined lookup from "kind/namespace/name" to RouteContext and its ParentRefs. type routeInfo struct { route RouteContext parentRefs map[gwapiv1.ParentReference]*RouteParentContext } routeByKey := make(map[string]*routeInfo, len(httpRoutes)+len(grpcRoutes)) for _, hr := range httpRoutes { - routeByKey[routeKey(hr.GetNamespace(), hr.GetName())] = &routeInfo{route: hr, parentRefs: hr.ParentRefs} + routeByKey[routeKey(string(hr.GetRouteType()), hr.GetNamespace(), hr.GetName())] = &routeInfo{route: hr, parentRefs: hr.ParentRefs} } for _, gr := range grpcRoutes { - routeByKey[routeKey(gr.GetNamespace(), gr.GetName())] = &routeInfo{route: gr, parentRefs: gr.ParentRefs} + routeByKey[routeKey(string(gr.GetRouteType()), gr.GetNamespace(), gr.GetName())] = &routeInfo{route: gr, parentRefs: gr.ParentRefs} } // overlaps tracks per IR listener which routes overlap with which others. @@ -1356,35 +1378,37 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout for _, xds := range xdsIR { for _, httpListener := range xds.HTTP { - routes := httpListener.Routes - // Pre-compute route keys - keys := make([]string, len(routes)) - for i, r := range routes { - if r.Metadata != nil { - keys[i] = routeKey(r.Metadata.Namespace, r.Metadata.Name) + // Bucket routes by their canonical overlap key. Any bucket with + // more than one distinct route contains overlapping routes. + buckets := make(map[overlapKey]map[string]struct{}) + for _, r := range httpListener.Routes { + if r.Metadata == nil { + continue + } + rKey := routeKey(r.Metadata.Kind, r.Metadata.Namespace, r.Metadata.Name) + k := buildOverlapKey(r) + if buckets[k] == nil { + buckets[k] = make(map[string]struct{}) } + buckets[k][rKey] = struct{}{} } - for i := 0; i < len(routes); i++ { - if keys[i] == "" { + for _, routeKeys := range buckets { + if len(routeKeys) < 2 { continue } - for j := i + 1; j < len(routes); j++ { - if keys[j] == "" || keys[i] == keys[j] { - continue - } - if routeMatchesOverlap(routes[i], routes[j]) { - if overlaps[httpListener.Name] == nil { - overlaps[httpListener.Name] = make(listenerOverlaps) - } - lo := overlaps[httpListener.Name] - if lo[keys[i]] == nil { - lo[keys[i]] = make(map[string]struct{}) + if overlaps[httpListener.Name] == nil { + overlaps[httpListener.Name] = make(listenerOverlaps) + } + lo := overlaps[httpListener.Name] + for ki := range routeKeys { + for kj := range routeKeys { + if ki == kj { + continue } - if lo[keys[j]] == nil { - lo[keys[j]] = make(map[string]struct{}) + if lo[ki] == nil { + lo[ki] = make(map[string]struct{}) } - lo[keys[i]][keys[j]] = struct{}{} - lo[keys[j]][keys[i]] = struct{}{} + lo[ki][kj] = struct{}{} } } } @@ -1431,7 +1455,7 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout conflictNames := make([]string, 0, len(conflicts)) for name := range conflicts { - conflictNames = append(conflictNames, name) + conflictNames = append(conflictNames, routeDisplayNameFromKey(name)) } sort.Strings(conflictNames) @@ -1441,64 +1465,99 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout status.SetRouteStatusCondition(routeStatus, parentRef.routeParentStatusIdx, info.route.GetGeneration(), - status.RouteConditionOverlap, + status.RouteConditionRouteRulesOverlap, metav1.ConditionTrue, - status.RouteReasonOverlap, + status.RouteReasonRouteRulesOverlap, msg, ) } } } -// routeMatchesOverlap checks if two IR HTTP routes have identical match conditions, -// indicating that they match the same set of requests. -// This detects routes with the same hostname and identical path, header, query param, -// and cookie match conditions across all path match types (exact, prefix, regex). -func routeMatchesOverlap(a, b *ir.HTTPRoute) bool { - if a.Hostname != b.Hostname { - return false - } - if !stringMatchEqual(a.PathMatch, b.PathMatch) { - return false - } - if !stringMatchSliceEqual(a.HeaderMatches, b.HeaderMatches) { - return false - } - if !stringMatchSliceEqual(a.QueryParamMatches, b.QueryParamMatches) { - return false +// buildOverlapKey returns a canonical key capturing a route's match conditions. +// Two routes with the same overlapKey match the exact same set of requests. +// Header names are normalized to lowercase since HTTP header names are +// case-insensitive, and slice-valued matches (headers, query params, cookies) +// are sorted so that ordering does not affect equality. +func buildOverlapKey(r *ir.HTTPRoute) overlapKey { + return overlapKey{ + hostname: r.Hostname, + path: stringMatchKey(r.PathMatch, false), + headers: stringMatchSliceKey(r.HeaderMatches, true), + query: stringMatchSliceKey(r.QueryParamMatches, false), + cookies: stringMatchSliceKey(r.CookieMatches, false), } - if !stringMatchSliceEqual(a.CookieMatches, b.CookieMatches) { - return false - } - return true } -func stringMatchEqual(a, b *ir.StringMatch) bool { - if a == nil && b == nil { - return true - } - if a == nil || b == nil { - return false - } - return a.Name == b.Name && - a.Distinct == b.Distinct && - ptr.Equal(a.Exact, b.Exact) && - ptr.Equal(a.Prefix, b.Prefix) && - ptr.Equal(a.Suffix, b.Suffix) && - ptr.Equal(a.SafeRegex, b.SafeRegex) && - ptr.Equal(a.Invert, b.Invert) +// stringMatchKey serializes a StringMatch into a canonical string. +// When lowercaseName is true, the Name field is normalized to lowercase. +func stringMatchKey(s *ir.StringMatch, lowercaseName bool) string { + if s == nil { + return "" + } + name := s.Name + if lowercaseName { + name = strings.ToLower(name) + } + var b strings.Builder + b.WriteString(name) + b.WriteByte('\x00') + if s.Exact != nil { + b.WriteByte('e') + b.WriteString(*s.Exact) + } + b.WriteByte('\x00') + if s.Prefix != nil { + b.WriteByte('p') + b.WriteString(*s.Prefix) + } + b.WriteByte('\x00') + if s.Suffix != nil { + b.WriteByte('s') + b.WriteString(*s.Suffix) + } + b.WriteByte('\x00') + if s.SafeRegex != nil { + b.WriteByte('r') + b.WriteString(*s.SafeRegex) + } + b.WriteByte('\x00') + if s.Distinct { + b.WriteByte('d') + } + b.WriteByte('\x00') + if s.Invert != nil && *s.Invert { + b.WriteByte('i') + } + return b.String() } -func stringMatchSliceEqual(a, b []*ir.StringMatch) bool { - return slices.EqualFunc(a, b, stringMatchEqual) +// stringMatchSliceKey serializes a slice of StringMatch into a canonical string +// that is independent of element order. +func stringMatchSliceKey(s []*ir.StringMatch, lowercaseName bool) string { + if len(s) == 0 { + return "" + } + keys := make([]string, len(s)) + for i, m := range s { + keys[i] = stringMatchKey(m, lowercaseName) + } + sort.Strings(keys) + return strings.Join(keys, "\x01") } -func buildResourceMetadata(resource client.Object, sectionName *gwapiv1.SectionName) *ir.ResourceMetadata { +func buildResourceMetadata(obj client.Object, sectionName *gwapiv1.SectionName) *ir.ResourceMetadata { + kind := obj.GetObjectKind().GroupVersionKind().Kind + if kind == "" { + // Typed objects fetched via controller-runtime clients typically have an + // empty TypeMeta, so fall back to a type-based lookup to keep Kind reliable. + kind = kindForObject(obj) + } metadata := &ir.ResourceMetadata{ - Kind: resource.GetObjectKind().GroupVersionKind().Kind, - Name: resource.GetName(), - Namespace: resource.GetNamespace(), - Annotations: ir.MapToSlice(filterEGPrefix(resource.GetAnnotations())), + Kind: kind, + Name: obj.GetName(), + Namespace: obj.GetNamespace(), + Annotations: ir.MapToSlice(filterEGPrefix(obj.GetAnnotations())), } if sectionName != nil { metadata.SectionName = string(*sectionName) @@ -1506,6 +1565,32 @@ func buildResourceMetadata(resource client.Object, sectionName *gwapiv1.SectionN return metadata } +// kindForObject returns the Kind string for a known Gateway API or Kubernetes +// object type. Returns an empty string for unknown types. +func kindForObject(obj client.Object) string { + switch obj.(type) { + case *gwapiv1.HTTPRoute: + return resource.KindHTTPRoute + case *gwapiv1.GRPCRoute: + return resource.KindGRPCRoute + case *gwapiv1a2.TLSRoute: + return resource.KindTLSRoute + case *gwapiv1a2.TCPRoute: + return resource.KindTCPRoute + case *gwapiv1a2.UDPRoute: + return resource.KindUDPRoute + case *gwapiv1.Gateway: + return resource.KindGateway + case *corev1.Service: + return resource.KindService + case *mcsapiv1a1.ServiceImport: + return resource.KindServiceImport + case *egv1a1.Backend: + return resource.KindBackend + } + return "" +} + func filterEGPrefix(in map[string]string) map[string]string { if len(in) == 0 { return nil diff --git a/internal/gatewayapi/status/error.go b/internal/gatewayapi/status/error.go index 8f7274a7c0..2615c1f886 100644 --- a/internal/gatewayapi/status/error.go +++ b/internal/gatewayapi/status/error.go @@ -32,8 +32,8 @@ const ( RouteReasonEndpointsNotFound gwapiv1.RouteConditionReason = "EndpointsNotFound" // Route overlap reason and condition type - RouteReasonOverlap gwapiv1.RouteConditionReason = "Overlap" - RouteConditionOverlap gwapiv1.RouteConditionType = "Overlap" + RouteReasonRouteRulesOverlap gwapiv1.RouteConditionReason = "RouteRulesOverlap" + RouteConditionRouteRulesOverlap gwapiv1.RouteConditionType = "RouteRulesOverlap" // Network configuration related condition types RouteConditionBackendsAvailable gwapiv1.RouteConditionType = "BackendsAvailable" diff --git a/internal/gatewayapi/testdata/backend-tls-settings-invalid.out.yaml b/internal/gatewayapi/testdata/backend-tls-settings-invalid.out.yaml index 3ffd604ac4..32fff4a7b7 100644 --- a/internal/gatewayapi/testdata/backend-tls-settings-invalid.out.yaml +++ b/internal/gatewayapi/testdata/backend-tls-settings-invalid.out.yaml @@ -151,10 +151,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -190,10 +190,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backend-tls-settings.out.yaml b/internal/gatewayapi/testdata/backend-tls-settings.out.yaml index 77f457de40..45587f893d 100644 --- a/internal/gatewayapi/testdata/backend-tls-settings.out.yaml +++ b/internal/gatewayapi/testdata/backend-tls-settings.out.yaml @@ -432,12 +432,12 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2, - default/httproute-3, default/httproute-4, default/httproute-5, default/httproute-6, - envoy-gateway/httproute-7-override-client-tls-settings' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2, + HTTPRoute default/httproute-3, HTTPRoute default/httproute-4, HTTPRoute + default/httproute-5, HTTPRoute default/httproute-6, HTTPRoute envoy-gateway/httproute-7-override-client-tls-settings' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -473,12 +473,12 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1, - default/httproute-3, default/httproute-4, default/httproute-5, default/httproute-6, - envoy-gateway/httproute-7-override-client-tls-settings' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1, + HTTPRoute default/httproute-3, HTTPRoute default/httproute-4, HTTPRoute + default/httproute-5, HTTPRoute default/httproute-6, HTTPRoute envoy-gateway/httproute-7-override-client-tls-settings' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -514,12 +514,12 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1, - default/httproute-2, default/httproute-4, default/httproute-5, default/httproute-6, - envoy-gateway/httproute-7-override-client-tls-settings' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1, + HTTPRoute default/httproute-2, HTTPRoute default/httproute-4, HTTPRoute + default/httproute-5, HTTPRoute default/httproute-6, HTTPRoute envoy-gateway/httproute-7-override-client-tls-settings' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -556,12 +556,12 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1, - default/httproute-2, default/httproute-3, default/httproute-5, default/httproute-6, - envoy-gateway/httproute-7-override-client-tls-settings' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1, + HTTPRoute default/httproute-2, HTTPRoute default/httproute-3, HTTPRoute + default/httproute-5, HTTPRoute default/httproute-6, HTTPRoute envoy-gateway/httproute-7-override-client-tls-settings' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -599,12 +599,12 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1, - default/httproute-2, default/httproute-3, default/httproute-4, default/httproute-6, - envoy-gateway/httproute-7-override-client-tls-settings' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1, + HTTPRoute default/httproute-2, HTTPRoute default/httproute-3, HTTPRoute + default/httproute-4, HTTPRoute default/httproute-6, HTTPRoute envoy-gateway/httproute-7-override-client-tls-settings' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -643,12 +643,12 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1, - default/httproute-2, default/httproute-3, default/httproute-4, default/httproute-5, - envoy-gateway/httproute-7-override-client-tls-settings' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1, + HTTPRoute default/httproute-2, HTTPRoute default/httproute-3, HTTPRoute + default/httproute-4, HTTPRoute default/httproute-5, HTTPRoute envoy-gateway/httproute-7-override-client-tls-settings' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -685,12 +685,12 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1, - default/httproute-2, default/httproute-3, default/httproute-4, default/httproute-5, - default/httproute-6' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1, + HTTPRoute default/httproute-2, HTTPRoute default/httproute-3, HTTPRoute + default/httproute-4, HTTPRoute default/httproute-5, HTTPRoute default/httproute-6' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtlspolicy-status-conditions-truncated.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-status-conditions-truncated.out.yaml index 8e050bb811..ffd1516a46 100644 --- a/internal/gatewayapi/testdata/backendtlspolicy-status-conditions-truncated.out.yaml +++ b/internal/gatewayapi/testdata/backendtlspolicy-status-conditions-truncated.out.yaml @@ -1297,10 +1297,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -1317,10 +1317,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 @@ -1337,10 +1337,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-3 @@ -1357,10 +1357,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-4 @@ -1377,10 +1377,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-5 @@ -1397,10 +1397,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-6 @@ -1417,10 +1417,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-7 @@ -1437,10 +1437,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-8 @@ -1457,10 +1457,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-9 @@ -1477,10 +1477,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-10 @@ -1497,10 +1497,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-11 @@ -1517,10 +1517,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-12 @@ -1537,10 +1537,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-13 @@ -1557,10 +1557,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-14 @@ -1577,10 +1577,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-15 @@ -1597,10 +1597,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-16 @@ -1617,10 +1617,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-17 @@ -1637,10 +1637,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-18 @@ -1710,10 +1710,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -1731,10 +1731,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 @@ -1752,10 +1752,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-3 @@ -1773,10 +1773,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-4 @@ -1794,10 +1794,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-5 @@ -1815,10 +1815,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-6 @@ -1836,10 +1836,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-7 @@ -1857,10 +1857,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-8 @@ -1878,10 +1878,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-9 @@ -1899,10 +1899,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-10 @@ -1920,10 +1920,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-11 @@ -1941,10 +1941,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-12 @@ -1962,10 +1962,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-13 @@ -1983,10 +1983,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-14 @@ -2004,10 +2004,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-15 @@ -2025,10 +2025,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-16 @@ -2046,10 +2046,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-17 @@ -2067,10 +2067,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-18 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml index 86715e66c6..295b453b74 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-multiple-targets-targetselector.out.yaml @@ -102,10 +102,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/httproute' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/httproute' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -147,10 +147,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-section.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-section.out.yaml index 692f4734c4..6632dbf155 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-section.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-section.out.yaml @@ -409,10 +409,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -448,10 +448,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml index 05178d3117..356465b0bb 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml @@ -230,10 +230,10 @@ grpcRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/grpcroute-with-no-overrides' - reason: Overlap + message: 'Overlapping match conditions with route(s): GRPCRoute default/grpcroute-with-no-overrides' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway @@ -267,10 +267,10 @@ grpcRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/grpcroute-with-overrides' - reason: Overlap + message: 'Overlapping match conditions with route(s): GRPCRoute default/grpcroute-with-overrides' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml index 27c7effed2..335bb16280 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml @@ -506,11 +506,11 @@ grpcRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/grpcroute-2, - default/grpcroute-3' - reason: Overlap + message: 'Overlapping match conditions with route(s): GRPCRoute default/grpcroute-2, + GRPCRoute default/grpcroute-3' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -544,11 +544,11 @@ grpcRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/grpcroute-1, - default/grpcroute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): GRPCRoute default/grpcroute-1, + GRPCRoute default/grpcroute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -582,11 +582,11 @@ grpcRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/grpcroute-1, - default/grpcroute-3' - reason: Overlap + message: 'Overlapping match conditions with route(s): GRPCRoute default/grpcroute-1, + GRPCRoute default/grpcroute-3' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -663,10 +663,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-4' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-4' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 @@ -742,10 +742,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-httproute-timeout.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-httproute-timeout.out.yaml index f6151f71c4..952b440541 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-httproute-timeout.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-httproute-timeout.out.yaml @@ -148,10 +148,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -192,10 +192,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-response-override.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-response-override.out.yaml index 775743047a..caadc5c01c 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-response-override.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-response-override.out.yaml @@ -380,10 +380,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-3' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-3' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 @@ -422,10 +422,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-2 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml index 2653347e76..99d036108e 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml @@ -107,10 +107,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -149,10 +149,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml index 8575c5dac0..daa825e67c 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-stats.out.yaml @@ -211,10 +211,10 @@ grpcRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/grpcroute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): GRPCRoute default/grpcroute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -248,10 +248,10 @@ grpcRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/grpcroute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): GRPCRoute default/grpcroute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml index 1f2ee89505..a0a1abbddd 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-invalid-settings.out.yaml @@ -718,10 +718,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -755,10 +755,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-section-name-override.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-section-name-override.out.yaml index b8eeae6eae..7bef534a60 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-section-name-override.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-section-name-override.out.yaml @@ -265,10 +265,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -307,10 +307,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-syntax.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-syntax.out.yaml index da1d6bebd3..6fe81ab6a2 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-syntax.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-invalid-lua-validation-syntax.out.yaml @@ -165,10 +165,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -207,10 +207,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml b/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml index 5b1d4509eb..1ee7dbbece 100644 --- a/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml @@ -179,10 +179,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/http-route-3' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/http-route-3' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: kind: Gateway @@ -217,10 +217,10 @@ httpRoutes: status: "False" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): envoy-gateway/http-route-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute envoy-gateway/http-route-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: kind: Gateway diff --git a/internal/gatewayapi/testdata/httproute-dynamic-resolver.out.yaml b/internal/gatewayapi/testdata/httproute-dynamic-resolver.out.yaml index 40c61f76fa..e71694ca67 100644 --- a/internal/gatewayapi/testdata/httproute-dynamic-resolver.out.yaml +++ b/internal/gatewayapi/testdata/httproute-dynamic-resolver.out.yaml @@ -108,10 +108,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -148,10 +148,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml b/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml index 63e9ea18a0..cef8461152 100644 --- a/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml +++ b/internal/gatewayapi/testdata/httproute-overlapping-matches.out.yaml @@ -70,10 +70,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -109,10 +109,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml index 9ae6ad8bf6..21463c39aa 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-app-protocols.out.yaml @@ -111,10 +111,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -150,10 +150,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml index 9e0a475127..540a898752 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-non-service-backends-and-weights.out.yaml @@ -109,10 +109,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -148,10 +148,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/httproute-with-conflicting-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-conflicting-filters.out.yaml index 76a0373c9e..1c853a0cad 100644 --- a/internal/gatewayapi/testdata/httproute-with-conflicting-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-conflicting-filters.out.yaml @@ -99,10 +99,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/mirror-request-redirect' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/mirror-request-redirect' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -163,10 +163,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/mirror-direct-response' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/mirror-direct-response' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/httproute-with-credential-injection.out.yaml b/internal/gatewayapi/testdata/httproute-with-credential-injection.out.yaml index cbbf10b3f9..ca577509dc 100644 --- a/internal/gatewayapi/testdata/httproute-with-credential-injection.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-credential-injection.out.yaml @@ -91,10 +91,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-2' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -140,10 +140,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/httproute-1' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/internal/gatewayapi/testdata/listenerset-httproute.out.yaml b/internal/gatewayapi/testdata/listenerset-httproute.out.yaml index 80d28370c2..ba5c8f1662 100644 --- a/internal/gatewayapi/testdata/listenerset-httproute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-httproute.out.yaml @@ -108,10 +108,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/route-entire-xls' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/route-entire-xls' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: group: gateway.networking.k8s.io @@ -149,10 +149,10 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/route-entire-xls' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/route-entire-xls' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: group: gateway.networking.k8s.io @@ -189,11 +189,11 @@ httpRoutes: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: 'Overlapping match conditions with route(s): default/route-extra-http-one, - default/route-extra-http-two' - reason: Overlap + message: 'Overlapping match conditions with route(s): HTTPRoute default/route-extra-http-one, + HTTPRoute default/route-extra-http-two' + reason: RouteRulesOverlap status: "True" - type: Overlap + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: group: gateway.networking.k8s.io diff --git a/release-notes/current.yaml b/release-notes/current.yaml index a100f6bea1..5d3b858fde 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -70,6 +70,7 @@ bug fixes: | BackendTLSPolicy was ignored when configuring TLS for telemetry backends (access logs, tracing, metrics). Fixed client certificate secret never delivered when it is exclusively referenced by a SecurityPolicy `extAuth`/`jwt`/`oidc` Backend Fixed xRoute status condition when route has mirror filter and the mirror backend has no endpoints. + Added a `RouteRulesOverlap` warning status condition for routes whose match conditions are identical to another route on the same listener, so users can identify silently-shadowed routes. # Enhancements that improve performance. performance improvements: | From e5adbc8155479df746e7984be0ec2870155d07ef Mon Sep 17 00:00:00 2001 From: jukie <10012479+jukie@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:45:36 -0600 Subject: [PATCH 7/7] feedback and tweaks Signed-off-by: jukie <10012479+jukie@users.noreply.github.com> --- internal/gatewayapi/overlap_test.go | 257 ++++++++++++++---- internal/gatewayapi/route.go | 41 ++- internal/gatewayapi/status/route.go | 11 + .../httproute-with-header-match.out.yaml | 10 + release-notes/current.yaml | 2 +- 5 files changed, 260 insertions(+), 61 deletions(-) diff --git a/internal/gatewayapi/overlap_test.go b/internal/gatewayapi/overlap_test.go index e3b3aa5e3c..0a7a588507 100644 --- a/internal/gatewayapi/overlap_test.go +++ b/internal/gatewayapi/overlap_test.go @@ -9,8 +9,15 @@ import ( "testing" "github.com/stretchr/testify/assert" - "k8s.io/utils/ptr" + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + "github.com/envoyproxy/gateway/internal/gatewayapi/resource" + "github.com/envoyproxy/gateway/internal/gatewayapi/status" "github.com/envoyproxy/gateway/internal/ir" ) @@ -31,11 +38,11 @@ func TestBuildOverlapKey(t *testing.T) { name: "identical exact path and hostname", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, }, overlap: true, }, @@ -43,11 +50,11 @@ func TestBuildOverlapKey(t *testing.T) { name: "different exact paths", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/bar")}, + PathMatch: &ir.StringMatch{Exact: new("/bar")}, }, overlap: false, }, @@ -55,11 +62,11 @@ func TestBuildOverlapKey(t *testing.T) { name: "different hostnames", a: &ir.HTTPRoute{ Hostname: "a.example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, }, b: &ir.HTTPRoute{ Hostname: "b.example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, }, overlap: false, }, @@ -67,11 +74,11 @@ func TestBuildOverlapKey(t *testing.T) { name: "identical prefix paths are detected as overlap", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Prefix: ptr.To("/api")}, + PathMatch: &ir.StringMatch{Prefix: new("/api")}, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Prefix: ptr.To("/api")}, + PathMatch: &ir.StringMatch{Prefix: new("/api")}, }, overlap: true, }, @@ -85,15 +92,38 @@ func TestBuildOverlapKey(t *testing.T) { }, overlap: true, }, + { + name: "nil path and root prefix path are detected as overlap", + a: &ir.HTTPRoute{ + Hostname: "example.com", + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Prefix: new("/")}, + }, + overlap: true, + }, + { + name: "path prefixes with equivalent trailing slash are detected as overlap", + a: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Prefix: new("/api")}, + }, + b: &ir.HTTPRoute{ + Hostname: "example.com", + PathMatch: &ir.StringMatch{Prefix: new("/api/")}, + }, + overlap: true, + }, { name: "exact vs prefix same value not overlap", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Prefix: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Prefix: new("/foo")}, }, overlap: false, }, @@ -101,16 +131,16 @@ func TestBuildOverlapKey(t *testing.T) { name: "identical exact path with identical header matches", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, HeaderMatches: []*ir.StringMatch{ - {Name: "X-Custom", Exact: ptr.To("val1")}, + {Name: "X-Custom", Exact: new("val1")}, }, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, HeaderMatches: []*ir.StringMatch{ - {Name: "X-Custom", Exact: ptr.To("val1")}, + {Name: "X-Custom", Exact: new("val1")}, }, }, overlap: true, @@ -119,16 +149,16 @@ func TestBuildOverlapKey(t *testing.T) { name: "identical exact path with different header matches", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, HeaderMatches: []*ir.StringMatch{ - {Name: "X-Custom", Exact: ptr.To("val1")}, + {Name: "X-Custom", Exact: new("val1")}, }, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, HeaderMatches: []*ir.StringMatch{ - {Name: "X-Custom", Exact: ptr.To("val2")}, + {Name: "X-Custom", Exact: new("val2")}, }, }, overlap: false, @@ -137,14 +167,14 @@ func TestBuildOverlapKey(t *testing.T) { name: "identical exact path one has headers other does not", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, HeaderMatches: []*ir.StringMatch{ - {Name: "X-Custom", Exact: ptr.To("val1")}, + {Name: "X-Custom", Exact: new("val1")}, }, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, }, overlap: false, }, @@ -152,16 +182,16 @@ func TestBuildOverlapKey(t *testing.T) { name: "header names are compared case-insensitively", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, HeaderMatches: []*ir.StringMatch{ - {Name: "X-Custom", Exact: ptr.To("val1")}, + {Name: "X-Custom", Exact: new("val1")}, }, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, HeaderMatches: []*ir.StringMatch{ - {Name: "x-custom", Exact: ptr.To("val1")}, + {Name: "x-custom", Exact: new("val1")}, }, }, overlap: true, @@ -170,18 +200,18 @@ func TestBuildOverlapKey(t *testing.T) { name: "header matches in different order still overlap", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, HeaderMatches: []*ir.StringMatch{ - {Name: "X-A", Exact: ptr.To("1")}, - {Name: "X-B", Exact: ptr.To("2")}, + {Name: "X-A", Exact: new("1")}, + {Name: "X-B", Exact: new("2")}, }, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, HeaderMatches: []*ir.StringMatch{ - {Name: "X-B", Exact: ptr.To("2")}, - {Name: "X-A", Exact: ptr.To("1")}, + {Name: "X-B", Exact: new("2")}, + {Name: "X-A", Exact: new("1")}, }, }, overlap: true, @@ -190,16 +220,16 @@ func TestBuildOverlapKey(t *testing.T) { name: "identical exact path with identical query param matches", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, QueryParamMatches: []*ir.StringMatch{ - {Name: "key", Exact: ptr.To("value")}, + {Name: "key", Exact: new("value")}, }, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{Exact: ptr.To("/foo")}, + PathMatch: &ir.StringMatch{Exact: new("/foo")}, QueryParamMatches: []*ir.StringMatch{ - {Name: "key", Exact: ptr.To("value")}, + {Name: "key", Exact: new("value")}, }, }, overlap: true, @@ -209,15 +239,15 @@ func TestBuildOverlapKey(t *testing.T) { a: &ir.HTTPRoute{ Hostname: "example.com", QueryParamMatches: []*ir.StringMatch{ - {Name: "a", Exact: ptr.To("1")}, - {Name: "b", Exact: ptr.To("2")}, + {Name: "a", Exact: new("1")}, + {Name: "b", Exact: new("2")}, }, }, b: &ir.HTTPRoute{ Hostname: "example.com", QueryParamMatches: []*ir.StringMatch{ - {Name: "b", Exact: ptr.To("2")}, - {Name: "a", Exact: ptr.To("1")}, + {Name: "b", Exact: new("2")}, + {Name: "a", Exact: new("1")}, }, }, overlap: true, @@ -227,15 +257,15 @@ func TestBuildOverlapKey(t *testing.T) { a: &ir.HTTPRoute{ Hostname: "example.com", CookieMatches: []*ir.StringMatch{ - {Name: "a", Exact: ptr.To("1")}, - {Name: "b", Exact: ptr.To("2")}, + {Name: "a", Exact: new("1")}, + {Name: "b", Exact: new("2")}, }, }, b: &ir.HTTPRoute{ Hostname: "example.com", CookieMatches: []*ir.StringMatch{ - {Name: "b", Exact: ptr.To("2")}, - {Name: "a", Exact: ptr.To("1")}, + {Name: "b", Exact: new("2")}, + {Name: "a", Exact: new("1")}, }, }, overlap: true, @@ -244,11 +274,11 @@ func TestBuildOverlapKey(t *testing.T) { name: "identical regex path matches are detected as overlap", a: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, + PathMatch: &ir.StringMatch{SafeRegex: new("/foo.*")}, }, b: &ir.HTTPRoute{ Hostname: "example.com", - PathMatch: &ir.StringMatch{SafeRegex: ptr.To("/foo.*")}, + PathMatch: &ir.StringMatch{SafeRegex: new("/foo.*")}, }, overlap: true, }, @@ -260,3 +290,138 @@ func TestBuildOverlapKey(t *testing.T) { }) } } + +func TestBuildResourceMetadataWrappedRouteKinds(t *testing.T) { + tests := []struct { + name string + obj client.Object + want string + }{ + { + name: "http route context", + obj: &HTTPRouteContext{ + HTTPRoute: &gwapiv1.HTTPRoute{}, + }, + want: resource.KindHTTPRoute, + }, + { + name: "grpc route context", + obj: &GRPCRouteContext{ + GRPCRoute: &gwapiv1.GRPCRoute{}, + }, + want: resource.KindGRPCRoute, + }, + { + name: "tls route context", + obj: &TLSRouteContext{ + TLSRoute: &gwapiv1.TLSRoute{}, + }, + want: resource.KindTLSRoute, + }, + { + name: "tcp route context", + obj: &TCPRouteContext{ + TCPRoute: &gwapiv1a2.TCPRoute{}, + }, + want: resource.KindTCPRoute, + }, + { + name: "udp route context", + obj: &UDPRouteContext{ + UDPRoute: &gwapiv1a2.UDPRoute{}, + }, + want: resource.KindUDPRoute, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + metadata := buildResourceMetadata(tt.obj, nil) + require.Equal(t, tt.want, metadata.Kind) + }) + } +} + +func TestCheckRouteOverlapsRemovesStaleCondition(t *testing.T) { + parentRef := gwapiv1.ParentReference{Name: "gateway-1"} + httpRoute := &gwapiv1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: "route-1", + Namespace: "default", + }, + Status: gwapiv1.HTTPRouteStatus{ + RouteStatus: gwapiv1.RouteStatus{ + Parents: []gwapiv1.RouteParentStatus{ + { + ParentRef: parentRef, + Conditions: []metav1.Condition{ + { + Type: string(gwapiv1.RouteConditionAccepted), + Status: metav1.ConditionTrue, + Reason: string(gwapiv1.RouteReasonAccepted), + }, + { + Type: string(status.RouteConditionRouteRulesOverlap), + Status: metav1.ConditionTrue, + Reason: string(status.RouteReasonRouteRulesOverlap), + }, + }, + }, + }, + }, + }, + } + route := &HTTPRouteContext{ + HTTPRoute: httpRoute, + } + + gateway := &GatewayContext{ + Gateway: &gwapiv1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "gateway-1", + Namespace: "default", + }, + }, + } + listener := &ListenerContext{ + Listener: &gwapiv1.Listener{Name: "http"}, + gateway: gateway, + } + route.ParentRefs = map[gwapiv1.ParentReference]*RouteParentContext{ + parentRef: { + ParentReference: &parentRef, + HTTPRoute: httpRoute, + routeParentStatusIdx: 0, + listeners: []*ListenerContext{listener}, + }, + } + + xdsIR := resource.XdsIRMap{ + "default/gateway-1": { + HTTP: []*ir.HTTPListener{ + { + CoreListenerDetails: ir.CoreListenerDetails{ + Name: irListenerName(listener), + }, + Routes: []*ir.HTTPRoute{ + { + Hostname: "example.com", + Metadata: &ir.ResourceMetadata{ + Kind: resource.KindHTTPRoute, + Namespace: "default", + Name: "route-1", + }, + }, + }, + }, + }, + }, + } + + translator := &Translator{} + translator.checkRouteOverlaps([]*HTTPRouteContext{route}, nil, xdsIR) + + conditions := route.Status.RouteStatus.Parents[0].Conditions + require.NotNil(t, meta.FindStatusCondition(conditions, string(gwapiv1.RouteConditionAccepted))) + assert.Nil(t, meta.FindStatusCondition(conditions, string(status.RouteConditionRouteRulesOverlap))) +} diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 8227e0995f..4eea3c544b 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -1428,6 +1428,7 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout // Set the Overlap warning condition only on parentRefs whose listeners // match an IR listener where the overlap was detected. for rKey, info := range routeByKey { + routeStatus := GetRouteStatus(info.route) // Collect all conflicts for this route across the parentRefs that have overlaps. for _, parentRef := range info.parentRefs { var conflicts map[string]struct{} @@ -1452,6 +1453,7 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout } } if len(conflicts) == 0 { + status.RemoveRouteStatusCondition(routeStatus, parentRef.routeParentStatusIdx, status.RouteConditionRouteRulesOverlap) continue } @@ -1463,7 +1465,6 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout msg := fmt.Sprintf("Overlapping match conditions with route(s): %s", strings.Join(conflictNames, ", ")) - routeStatus := GetRouteStatus(info.route) status.SetRouteStatusCondition(routeStatus, parentRef.routeParentStatusIdx, info.route.GetGeneration(), @@ -1484,13 +1485,29 @@ func (t *Translator) checkRouteOverlaps(httpRoutes []*HTTPRouteContext, grpcRout func buildOverlapKey(r *ir.HTTPRoute) overlapKey { return overlapKey{ hostname: r.Hostname, - path: stringMatchKey(r.PathMatch, false), + path: pathMatchKey(r.PathMatch), headers: stringMatchSliceKey(r.HeaderMatches, true), query: stringMatchSliceKey(r.QueryParamMatches, false), cookies: stringMatchSliceKey(r.CookieMatches, false), } } +// pathMatchKey serializes route path matches the same way they are interpreted +// by the xDS translator: no path match is equivalent to prefix "/", and +// non-root prefixes have one trailing slash trimmed before translation. +func pathMatchKey(s *ir.StringMatch) string { + if s == nil { + return stringMatchKey(&ir.StringMatch{Prefix: new("/")}, false) + } + if s.Prefix == nil || *s.Prefix == "/" { + return stringMatchKey(s, false) + } + + normalized := s.DeepCopy() + normalized.Prefix = new(strings.TrimSuffix(*s.Prefix, "/")) + return stringMatchKey(normalized, false) +} + // stringMatchKey serializes a StringMatch into a canonical string. // When lowercaseName is true, the Name field is normalized to lowercase. func stringMatchKey(s *ir.StringMatch, lowercaseName bool) string { @@ -1551,8 +1568,8 @@ func stringMatchSliceKey(s []*ir.StringMatch, lowercaseName bool) string { func buildResourceMetadata(obj client.Object, sectionName *gwapiv1.SectionName) *ir.ResourceMetadata { kind := obj.GetObjectKind().GroupVersionKind().Kind if kind == "" { - // Typed objects fetched via controller-runtime clients typically have an - // empty TypeMeta, so fall back to a type-based lookup to keep Kind reliable. + // Typed objects fetched via controller-runtime clients have an empty + // TypeMeta; fall back to a type-based lookup so Kind stays reliable. kind = kindForObject(obj) } metadata := &ir.ResourceMetadata{ @@ -1570,17 +1587,13 @@ func buildResourceMetadata(obj client.Object, sectionName *gwapiv1.SectionName) // kindForObject returns the Kind string for a known Gateway API or Kubernetes // object type. Returns an empty string for unknown types. func kindForObject(obj client.Object) string { + // Route wrapper types (HTTPRouteContext, GRPCRouteContext, etc.) report + // their Kind via the RouteContext interface; the switch below matches the + // raw types only. + if r, ok := obj.(RouteContext); ok { + return string(r.GetRouteType()) + } switch obj.(type) { - case *gwapiv1.HTTPRoute: - return resource.KindHTTPRoute - case *gwapiv1.GRPCRoute: - return resource.KindGRPCRoute - case *gwapiv1a2.TLSRoute: - return resource.KindTLSRoute - case *gwapiv1a2.TCPRoute: - return resource.KindTCPRoute - case *gwapiv1a2.UDPRoute: - return resource.KindUDPRoute case *gwapiv1.Gateway: return resource.KindGateway case *corev1.Service: diff --git a/internal/gatewayapi/status/route.go b/internal/gatewayapi/status/route.go index 4b8f6bc743..96eedf6ff4 100644 --- a/internal/gatewayapi/status/route.go +++ b/internal/gatewayapi/status/route.go @@ -32,6 +32,17 @@ func SetRouteStatusCondition(route *gwapiv1.RouteStatus, routeParentStatusIdx in route.Parents[routeParentStatusIdx].Conditions = MergeConditions(route.Parents[routeParentStatusIdx].Conditions, cond) } +// RemoveRouteStatusCondition removes conditionType from the given parent's +// Conditions if present. The pre-check avoids meta.RemoveStatusCondition's +// unconditional slice reallocation when the condition is absent. +func RemoveRouteStatusCondition(route *gwapiv1.RouteStatus, routeParentStatusIdx int, conditionType gwapiv1.RouteConditionType) { + conds := &route.Parents[routeParentStatusIdx].Conditions + if meta.FindStatusCondition(*conds, string(conditionType)) == nil { + return + } + meta.RemoveStatusCondition(conds, string(conditionType)) +} + // TruncateRouteParents trims RouteStatus.Parents down to at most 32 entries. // The first 31 parents are shown as-is. // The last 32nd parent is shown as-is and gets the Aggregated condition. diff --git a/internal/gatewayapi/testdata/httproute-with-header-match.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-match.out.yaml index 85db3194db..8b90481574 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-match.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-match.out.yaml @@ -74,6 +74,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-2' + reason: RouteRulesOverlap + status: "True" + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 @@ -123,6 +128,11 @@ httpRoutes: reason: ResolvedRefs status: "True" type: ResolvedRefs + - lastTransitionTime: null + message: 'Overlapping match conditions with route(s): HTTPRoute default/httproute-1' + reason: RouteRulesOverlap + status: "True" + type: RouteRulesOverlap controllerName: gateway.envoyproxy.io/gatewayclass-controller parentRef: name: gateway-1 diff --git a/release-notes/current.yaml b/release-notes/current.yaml index f55062edf0..b59fc8b25c 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -46,6 +46,7 @@ new features: | Added support for OpenTelemetry sampler configuration for tracing. Added support for default EnvoyProxy settings on EnvoyGatewaySpec that can be overridden by GatewayClass or Gateway-level EnvoyProxy configurations. A new MergeType field allows choosing between Replace (default), StrategicMerge, or JSONMerge strategies for combining configurations. Added support for sending Envoy Gateway route metadata to external authorization backends via `SecurityPolicy.spec.extAuth.includeRouteMetadata`. + Added a `RouteRulesOverlap` warning status condition for routes whose match conditions are identical to another route on the same listener, so users can identify silently-shadowed routes. bug fixes: | Fixed local rate limit rules with identical sourceCIDR client selectors producing conflicting descriptors. @@ -71,7 +72,6 @@ bug fixes: | BackendTLSPolicy was ignored when configuring TLS for telemetry backends (access logs, tracing, metrics). Fixed client certificate secret never delivered when it is exclusively referenced by a SecurityPolicy `extAuth`/`jwt`/`oidc` Backend Fixed xRoute status condition when route has mirror filter and the mirror backend has no endpoints. - Added a `RouteRulesOverlap` warning status condition for routes whose match conditions are identical to another route on the same listener, so users can identify silently-shadowed routes. Fixed gateway-helm RBAC in GatewayNamespace mode with explicit `watch.namespaces` list by adding controller-namespace secret read permissions to infra-manager. Fixed a control plane panic caused by concurrent Status mutation racing with the watchable Map coalesce goroutine.