diff --git a/docs/sources/gateway.md b/docs/sources/gateway.md index 059ccedfa..d62c42469 100644 --- a/docs/sources/gateway.md +++ b/docs/sources/gateway.md @@ -106,10 +106,17 @@ Iterates over all listeners for the parent's `parentRef.sectionName`: The targets of the DNS entries created from a \*Route are sourced from the following places: -1. If a matching parent Gateway has an `external-dns.alpha.kubernetes.io/target` annotation, uses +1. If the route has the `external-dns.alpha.kubernetes.io/target` annotation + with a non-empty value, uses the value from that. + +2. If the route has the `external-dns.alpha.kubernetes.io/target: ""` it + will disable the `external-dns.alpha.kubernetes.io/target` on the matching parent + Gateway(s) and continue the regular flow from step 4. + +3. If a matching parent Gateway has the `external-dns.alpha.kubernetes.io/target` annotation, uses the values from that. -2. Otherwise, iterates over that parent Gateway's `status.addresses`, +4. Otherwise, iterates over that parent Gateway's `status.addresses`, adding each address's `value`. The targets from each parent Gateway matching the \*Route are then combined and de-duplicated. diff --git a/source/gateway.go b/source/gateway.go index 445352838..1ba08a7d2 100644 --- a/source/gateway.go +++ b/source/gateway.go @@ -377,7 +377,15 @@ func (c *gatewayRouteResolver) resolve(rt gatewayRoute) (map[string]endpoint.Tar if !ok { continue } - override := annotations.TargetsFromTargetAnnotation(gw.gateway.Annotations) + var override endpoint.Targets + targetAnnotation, exists := meta.Annotations[targetAnnotationKey] + if exists && targetAnnotation != "" { + override = annotations.TargetsFromTargetAnnotation(meta.Annotations) + hostTargets[host] = append(hostTargets[host], override...) + } else if !exists { + override = annotations.TargetsFromTargetAnnotation(gw.gateway.Annotations) + hostTargets[host] = append(hostTargets[host], override...) + } hostTargets[host] = append(hostTargets[host], override...) if len(override) == 0 { for _, addr := range gw.gateway.Status.Addresses { diff --git a/source/gateway_httproute_test.go b/source/gateway_httproute_test.go index 2edbf8965..b569cd6b2 100644 --- a/source/gateway_httproute_test.go +++ b/source/gateway_httproute_test.go @@ -1362,6 +1362,144 @@ func TestGatewayHTTPRouteSourceEndpoints(t *testing.T) { newTestEndpoint("test.example.internal", "A", "4.3.2.1"), }, }, + { + title: "RouteAnnotationOverride", + config: Config{ + GatewayNamespace: "gateway-namespace", + }, + namespaces: namespaces("gateway-namespace", "route-namespace"), + gateways: []*v1beta1.Gateway{ + { + ObjectMeta: objectMeta("gateway-namespace", "test"), + Spec: v1.GatewaySpec{ + Listeners: []v1.Listener{{ + Protocol: v1.HTTPProtocolType, + AllowedRoutes: allowAllNamespaces, + }}, + }, + Status: gatewayStatus("1.2.3.4"), + }, + }, + routes: []*v1beta1.HTTPRoute{{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "route-namespace", + Annotations: map[string]string{ + targetAnnotationKey: "4.3.2.1", + }, + }, + Spec: v1.HTTPRouteSpec{ + Hostnames: hostnames("test.example.internal"), + CommonRouteSpec: v1.CommonRouteSpec{ + ParentRefs: []v1.ParentReference{ + gwParentRef("gateway-namespace", "test"), + }, + }, + }, + Status: httpRouteStatus( + gwParentRef("gateway-namespace", "test"), + ), + }}, + endpoints: []*endpoint.Endpoint{ + newTestEndpoint("test.example.internal", "A", "4.3.2.1"), + }, + }, + { + title: "RouteAnnotationGatewayOverride", + config: Config{ + GatewayNamespace: "gateway-namespace", + }, + namespaces: namespaces("gateway-namespace", "route-namespace"), + gateways: []*v1beta1.Gateway{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "overriden-gateway", + Namespace: "gateway-namespace", + Annotations: map[string]string{ + targetAnnotationKey: "4.3.2.1", + }, + }, + Spec: v1.GatewaySpec{ + Listeners: []v1.Listener{{ + Protocol: v1.HTTPProtocolType, + AllowedRoutes: allowAllNamespaces, + }}, + }, + Status: gatewayStatus("1.2.3.4"), + }, + }, + routes: []*v1beta1.HTTPRoute{{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "route-namespace", + Annotations: map[string]string{ + targetAnnotationKey: "2.3.4.5", + }, + }, + Spec: v1.HTTPRouteSpec{ + Hostnames: hostnames("test.example.internal"), + CommonRouteSpec: v1.CommonRouteSpec{ + ParentRefs: []v1.ParentReference{ + gwParentRef("gateway-namespace", "overriden-gateway"), + }, + }, + }, + Status: httpRouteStatus( + gwParentRef("gateway-namespace", "overriden-gateway"), + ), + }}, + endpoints: []*endpoint.Endpoint{ + newTestEndpoint("test.example.internal", "A", "2.3.4.5"), + }, + }, + { + title: "RouteAnnotationGatewayOverrideEmpty", + config: Config{ + GatewayNamespace: "gateway-namespace", + }, + namespaces: namespaces("gateway-namespace", "route-namespace"), + gateways: []*v1beta1.Gateway{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "overriden-gateway", + Namespace: "gateway-namespace", + Annotations: map[string]string{ + targetAnnotationKey: "4.3.2.1", + }, + }, + Spec: v1.GatewaySpec{ + Listeners: []v1.Listener{{ + Protocol: v1.HTTPProtocolType, + AllowedRoutes: allowAllNamespaces, + }}, + }, + Status: gatewayStatus("1.2.3.4"), + }, + }, + routes: []*v1beta1.HTTPRoute{{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "route-namespace", + Annotations: map[string]string{ + targetAnnotationKey: "", + }, + }, + Spec: v1.HTTPRouteSpec{ + Hostnames: hostnames("test.example.internal"), + CommonRouteSpec: v1.CommonRouteSpec{ + ParentRefs: []v1.ParentReference{ + gwParentRef("gateway-namespace", "overriden-gateway"), + }, + }, + }, + Status: httpRouteStatus( + gwParentRef("gateway-namespace", "overriden-gateway"), + ), + }}, + endpoints: []*endpoint.Endpoint{ + newTestEndpoint("test.example.internal", "A", "1.2.3.4"), + }, + }, { title: "MutlipleGatewaysOneAnnotationOverride", config: Config{