diff --git a/source/gateway.go b/source/gateway.go index 2a71352126..77203819b9 100644 --- a/source/gateway.go +++ b/source/gateway.go @@ -333,10 +333,11 @@ func (c *gatewayRouteResolver) resolve(rt gatewayRoute) (map[string]endpoint.Tar } // Confirm the Gateway has accepted the Route. - if !gwRouteIsAccepted(rps.Conditions) { - log.Debugf("Gateway %s/%s has not accepted %s %s/%s", namespace, ref.Name, c.src.rtKind, meta.Namespace, meta.Name) + if !gwRouteIsAccepted(rps.Conditions, meta) { + log.Debugf("Gateway %s/%s has not accepted the current generation %s %s/%s", namespace, ref.Name, c.src.rtKind, meta.Namespace, meta.Name) continue } + // Match the Route to all possible Listeners. match := false section := sectionVal(ref.SectionName, "") @@ -494,10 +495,10 @@ func gwRouteHasParentRef(routeParentRefs []v1.ParentReference, ref v1.ParentRefe return false } -func gwRouteIsAccepted(conds []metav1.Condition) bool { +func gwRouteIsAccepted(conds []metav1.Condition, meta *metav1.ObjectMeta) bool { for _, c := range conds { if v1.RouteConditionType(c.Type) == v1.RouteConditionAccepted { - return c.Status == metav1.ConditionTrue + return c.Status == metav1.ConditionTrue && c.ObservedGeneration == meta.Generation } } return false diff --git a/source/gateway_httproute_test.go b/source/gateway_httproute_test.go index 19f009fb75..a7f9bbe90e 100644 --- a/source/gateway_httproute_test.go +++ b/source/gateway_httproute_test.go @@ -70,6 +70,36 @@ func gwRouteStatus(refs ...v1.ParentReference) v1.RouteStatus { return v } +func omWithGeneration(meta metav1.ObjectMeta, generation int64) metav1.ObjectMeta { + meta.Generation = generation + return meta +} + +func rsWithGeneration(routeStatus v1.HTTPRouteStatus, generation ...int64) v1.HTTPRouteStatus { + for i, parent := range routeStatus.Parents { + if len(generation) <= i { + break + } + + parent.Conditions[0].ObservedGeneration = generation[i] + } + + return routeStatus +} + +func rsWithoutAccepted(routeStatus v1.HTTPRouteStatus) v1.HTTPRouteStatus { + for _, parent := range routeStatus.Parents { + for j := range parent.Conditions { + cond := &parent.Conditions[j] + if cond.Type == string(v1.RouteConditionAccepted) { + cond.Type = "NotAccepted" // fake type to test for having no accepted condition + } + } + } + + return routeStatus +} + func gwParentRef(namespace, name string, options ...gwParentRefOption) v1.ParentReference { group := v1.Group("gateway.networking.k8s.io") kind := v1.Kind("Gateway") @@ -192,6 +222,81 @@ func TestGatewayHTTPRouteSourceEndpoints(t *testing.T) { "level=debug msg=\"Gateway gateway-namespace/not-gateway-name does not match gateway-name route-namespace/test\"", }, }, + { + title: "GatewayNameOldGeneration", + config: Config{ + GatewayName: "gateway-name", + }, + namespaces: namespaces("gateway-namespace", "route-namespace"), + gateways: []*v1beta1.Gateway{ + { + ObjectMeta: omWithGeneration(objectMeta("gateway-namespace", "gateway-name"), 2), + Spec: v1.GatewaySpec{ + Listeners: []v1.Listener{{ + Protocol: v1.HTTPProtocolType, + AllowedRoutes: allowAllNamespaces, + }}, + }, + Status: gatewayStatus("1.2.3.4"), + }, + }, + routes: []*v1beta1.HTTPRoute{{ + ObjectMeta: omWithGeneration(objectMeta("route-namespace", "old-test"), 5), + Spec: v1.HTTPRouteSpec{ + Hostnames: hostnames("test.example.internal"), + CommonRouteSpec: v1.CommonRouteSpec{ + ParentRefs: []v1.ParentReference{ + gwParentRef("gateway-namespace", "gateway-name"), + }, + }, + }, + Status: rsWithGeneration(httpRouteStatus( // The route was previously attached in a different generation + gwParentRef("gateway-namespace", "gateway-name"), + gwParentRef("gateway-namespace", "gateway-name"), + ), 5, 4), + }}, + endpoints: []*endpoint.Endpoint{ + newTestEndpoint("test.example.internal", "A", "1.2.3.4"), + }, + logExpectations: []string{ + "level=debug msg=\"Gateway gateway-namespace/gateway-name has not accepted the current generation HTTPRoute route-namespace/old-test\"", + }, + }, + { + title: "GatewayNameNoneAccepted", + config: Config{ + GatewayName: "gateway-name", + }, + namespaces: namespaces("gateway-namespace", "route-namespace"), + gateways: []*v1beta1.Gateway{ + { + ObjectMeta: omWithGeneration(objectMeta("gateway-namespace", "gateway-name"), 2), + Spec: v1.GatewaySpec{ + Listeners: []v1.Listener{{ + Protocol: v1.HTTPProtocolType, + AllowedRoutes: allowAllNamespaces, + }}, + }, + Status: gatewayStatus("1.2.3.4"), + }, + }, + routes: []*v1beta1.HTTPRoute{{ + ObjectMeta: omWithGeneration(objectMeta("route-namespace", "old-test"), 5), + Spec: v1.HTTPRouteSpec{ + Hostnames: hostnames("test.example.internal"), + CommonRouteSpec: v1.CommonRouteSpec{ + ParentRefs: []v1.ParentReference{ + gwParentRef("gateway-namespace", "gateway-name"), + }, + }, + }, + Status: rsWithoutAccepted(httpRouteStatus(gwParentRef("gateway-namespace", "gateway-name"))), + }}, + endpoints: []*endpoint.Endpoint{}, + logExpectations: []string{ + "level=debug msg=\"Gateway gateway-namespace/gateway-name has not accepted the current generation HTTPRoute route-namespace/old-test\"", + }, + }, { title: "GatewayNamespace", config: Config{