Skip to content

Commit c1dd270

Browse files
committed
Fix invalid backend attachment
1 parent 095f23d commit c1dd270

File tree

4 files changed

+156
-13
lines changed

4 files changed

+156
-13
lines changed

internal/mode/static/state/graph/route_common.go

+11-10
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ type ParentRefAttachmentStatus struct {
4242
// AcceptedHostnames is an intersection between the hostnames supported by an attached Listener
4343
// and the hostnames from this Route. Key is <gatewayNamespacedName/listenerName>, value is list of hostnames.
4444
AcceptedHostnames map[string][]string
45-
// FailedConditions are the conditions that describes why the ParentRef is not attached to the Gateway. They are
46-
// set when Attached is false.
45+
// FailedConditions are the conditions that describe why the ParentRef is not attached to the Gateway, or other
46+
// failures that may lead to partial attachments. For example, a backendRef could be invalid, but the route can
47+
// still attach. The backendRef condition would be displayed here.
4748
FailedConditions []conditions.Condition
4849
// ListenerPort is the port on the Listener that the Route is attached to.
4950
ListenerPort v1.PortNumber
@@ -549,14 +550,14 @@ func bindL4RouteToListeners(
549550

550551
attachment, attachableListeners := validateParentRef(ref, gw)
551552

552-
if cond, ok := route.Spec.BackendRef.InvalidForGateways[gwNsName]; ok {
553-
attachment.FailedConditions = append(attachment.FailedConditions, cond)
554-
}
555-
556553
if len(attachment.FailedConditions) > 0 {
557554
continue
558555
}
559556

557+
if cond, ok := route.Spec.BackendRef.InvalidForGateways[gwNsName]; ok {
558+
attachment.FailedConditions = append(attachment.FailedConditions, cond)
559+
}
560+
560561
// Try to attach Route to all matching listeners
561562

562563
cond, attached := tryToAttachL4RouteToListeners(
@@ -721,6 +722,10 @@ func bindL7RouteToListeners(
721722
)
722723
}
723724

725+
if len(attachment.FailedConditions) > 0 {
726+
continue
727+
}
728+
724729
for _, rule := range route.Spec.Rules {
725730
for _, backendRef := range rule.BackendRefs {
726731
if cond, ok := backendRef.InvalidForGateways[gwNsName]; ok {
@@ -729,10 +734,6 @@ func bindL7RouteToListeners(
729734
}
730735
}
731736

732-
if len(attachment.FailedConditions) > 0 {
733-
continue
734-
}
735-
736737
// Try to attach Route to all matching listeners
737738

738739
cond, attached := tryToAttachL7RouteToListeners(

internal/mode/static/state/graph/route_common_test.go

+98
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,19 @@ func TestBindRouteToListeners(t *testing.T) {
465465
l.Source.Hostname = helpers.GetPointer[gatewayv1.Hostname]("bar.example.com")
466466
})
467467

468+
routeWithInvalidBackendRefs := createNormalHTTPRoute(gw)
469+
routeWithInvalidBackendRefs.Spec.Rules = []RouteRule{
470+
{
471+
BackendRefs: []BackendRef{
472+
{
473+
InvalidForGateways: map[types.NamespacedName]conditions.Condition{
474+
client.ObjectKeyFromObject(gw): {Message: "invalid backend"},
475+
},
476+
},
477+
},
478+
},
479+
}
480+
468481
createGRPCRouteWithSectionNameAndPort := func(
469482
sectionName *gatewayv1.SectionName,
470483
port *gatewayv1.PortNumber,
@@ -1290,6 +1303,43 @@ func TestBindRouteToListeners(t *testing.T) {
12901303
},
12911304
name: "http route allowed when listener kind is HTTPRoute",
12921305
},
1306+
{
1307+
route: routeWithInvalidBackendRefs,
1308+
gateway: &Gateway{
1309+
Source: gw,
1310+
Valid: true,
1311+
Listeners: []*Listener{
1312+
createListener("listener-80-1"),
1313+
},
1314+
},
1315+
expectedSectionNameRefs: []ParentRef{
1316+
{
1317+
Idx: 0,
1318+
Gateway: &ParentRefGateway{NamespacedName: client.ObjectKeyFromObject(gw)},
1319+
SectionName: hr.Spec.ParentRefs[0].SectionName,
1320+
Attachment: &ParentRefAttachmentStatus{
1321+
Attached: true,
1322+
FailedConditions: []conditions.Condition{
1323+
{Message: "invalid backend"},
1324+
},
1325+
AcceptedHostnames: map[string][]string{
1326+
CreateGatewayListenerKey(
1327+
client.ObjectKeyFromObject(gw),
1328+
"listener-80-1",
1329+
): {"foo.example.com"},
1330+
},
1331+
},
1332+
},
1333+
},
1334+
expectedGatewayListeners: []*Listener{
1335+
createModifiedListener("listener-80-1", func(l *Listener) {
1336+
l.Routes = map[RouteKey]*L7Route{
1337+
CreateRouteKey(hr): routeWithInvalidBackendRefs,
1338+
}
1339+
}),
1340+
},
1341+
name: "route still allowed if backendRef failure conditions exist",
1342+
},
12931343
}
12941344

12951345
namespaces := map[types.NamespacedName]*v1.Namespace{
@@ -1706,6 +1756,13 @@ func TestBindL4RouteToListeners(t *testing.T) {
17061756
Attachable: true,
17071757
}
17081758

1759+
routeWithInvalidBackendRefs := createNormalRoute(gw)
1760+
routeWithInvalidBackendRefs.Spec.BackendRef = BackendRef{
1761+
InvalidForGateways: map[types.NamespacedName]conditions.Condition{
1762+
client.ObjectKeyFromObject(gw): {Message: "invalid backend"},
1763+
},
1764+
}
1765+
17091766
tests := []struct {
17101767
route *L4Route
17111768
gateway *Gateway
@@ -2178,6 +2235,47 @@ func TestBindL4RouteToListeners(t *testing.T) {
21782235
},
21792236
name: "route kind not allowed",
21802237
},
2238+
{
2239+
route: routeWithInvalidBackendRefs,
2240+
gateway: &Gateway{
2241+
Source: gw,
2242+
Valid: true,
2243+
DeploymentName: types.NamespacedName{
2244+
Namespace: "test",
2245+
Name: "gateway",
2246+
},
2247+
Listeners: []*Listener{
2248+
createListener("listener-443"),
2249+
},
2250+
},
2251+
expectedSectionNameRefs: []ParentRef{
2252+
{
2253+
Idx: 0,
2254+
Gateway: &ParentRefGateway{NamespacedName: client.ObjectKeyFromObject(gw)},
2255+
SectionName: tr.Spec.ParentRefs[0].SectionName,
2256+
Attachment: &ParentRefAttachmentStatus{
2257+
Attached: true,
2258+
FailedConditions: []conditions.Condition{
2259+
{Message: "invalid backend"},
2260+
},
2261+
AcceptedHostnames: map[string][]string{
2262+
CreateGatewayListenerKey(
2263+
client.ObjectKeyFromObject(gw),
2264+
"listener-443",
2265+
): {"foo.example.com"},
2266+
},
2267+
},
2268+
},
2269+
},
2270+
expectedGatewayListeners: []*Listener{
2271+
createModifiedListener("listener-443", func(l *Listener) {
2272+
l.L4Routes = map[L4RouteKey]*L4Route{
2273+
CreateRouteKeyL4(tr): routeWithInvalidBackendRefs,
2274+
}
2275+
}),
2276+
},
2277+
name: "route still allowed if backendRef failure conditions exist",
2278+
},
21812279
}
21822280

21832281
namespaces := map[types.NamespacedName]*v1.Namespace{

internal/mode/static/status/prepare_requests.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,16 @@ func prepareRouteStatus(
111111

112112
for _, ref := range parentRefs {
113113
failedAttachmentCondCount := 0
114-
if ref.Attachment != nil && !ref.Attachment.Attached {
115-
failedAttachmentCondCount = 1
114+
if ref.Attachment != nil {
115+
failedAttachmentCondCount = len(ref.Attachment.FailedConditions)
116116
}
117117
allConds := make([]conditions.Condition, 0, len(conds)+len(defaultConds)+failedAttachmentCondCount)
118118

119119
// We add defaultConds first, so that any additional conditions will override them, which is
120120
// ensured by DeduplicateConditions.
121121
allConds = append(allConds, defaultConds...)
122122
allConds = append(allConds, conds...)
123-
if failedAttachmentCondCount == 1 {
123+
if failedAttachmentCondCount > 0 {
124124
allConds = append(allConds, ref.Attachment.FailedConditions...)
125125
}
126126

internal/mode/static/status/prepare_requests_test.go

+44
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ var (
7171
{
7272
SectionName: helpers.GetPointer[v1.SectionName]("listener-80-2"),
7373
},
74+
{
75+
SectionName: helpers.GetPointer[v1.SectionName]("listener-80-3"),
76+
},
7477
},
7578
}
7679

@@ -100,6 +103,15 @@ var (
100103
FailedConditions: []conditions.Condition{invalidAttachmentCondition},
101104
},
102105
},
106+
{
107+
Idx: 2,
108+
Gateway: &graph.ParentRefGateway{NamespacedName: gwNsName},
109+
SectionName: commonRouteSpecValid.ParentRefs[2].SectionName,
110+
Attachment: &graph.ParentRefAttachmentStatus{
111+
Attached: true,
112+
FailedConditions: []conditions.Condition{invalidAttachmentCondition},
113+
},
114+
},
103115
}
104116

105117
parentRefsInvalid = []graph.ParentRef{
@@ -171,6 +183,38 @@ var (
171183
},
172184
},
173185
},
186+
{
187+
ParentRef: v1.ParentReference{
188+
Namespace: helpers.GetPointer(v1.Namespace(gwNsName.Namespace)),
189+
Name: v1.ObjectName(gwNsName.Name),
190+
SectionName: helpers.GetPointer[v1.SectionName]("listener-80-3"),
191+
},
192+
ControllerName: gatewayCtlrName,
193+
Conditions: []metav1.Condition{
194+
{
195+
Type: string(v1.RouteConditionAccepted),
196+
Status: metav1.ConditionTrue,
197+
ObservedGeneration: 3,
198+
LastTransitionTime: transitionTime,
199+
Reason: string(v1.RouteReasonAccepted),
200+
Message: "The route is accepted",
201+
},
202+
{
203+
Type: string(v1.RouteConditionResolvedRefs),
204+
Status: metav1.ConditionTrue,
205+
ObservedGeneration: 3,
206+
LastTransitionTime: transitionTime,
207+
Reason: string(v1.RouteReasonResolvedRefs),
208+
Message: "All references are resolved",
209+
},
210+
{
211+
Type: invalidAttachmentCondition.Type,
212+
Status: metav1.ConditionTrue,
213+
ObservedGeneration: 3,
214+
LastTransitionTime: transitionTime,
215+
},
216+
},
217+
},
174218
},
175219
}
176220

0 commit comments

Comments
 (0)