From 724b86b8b867db9420c51b6a8bc9d26118bf213d Mon Sep 17 00:00:00 2001 From: Steven Kreitzer Date: Wed, 12 Mar 2025 03:51:47 -0500 Subject: [PATCH] feat(source): fitler by gateway name (#5160) * feat: filter by gateway name Signed-off-by: Steven Kreitzer * address comments * address comments * address comments --------- Signed-off-by: Steven Kreitzer --- docs/flags.md | 1 + docs/sources/gateway-api.md | 2 ++ docs/sources/gateway.md | 33 +++++++++++++++++++++++ pkg/apis/externaldns/types.go | 3 +++ source/gateway.go | 7 +++++ source/gateway_httproute_test.go | 45 ++++++++++++++++++++++++++++++++ source/store.go | 1 + 7 files changed, 92 insertions(+) diff --git a/docs/flags.md b/docs/flags.md index e81766241..838da5066 100644 --- a/docs/flags.md +++ b/docs/flags.md @@ -28,6 +28,7 @@ | `--[no-]ignore-hostname-annotation` | Ignore hostname annotation when generating DNS names, valid only when --fqdn-template is set (default: false) | | `--[no-]ignore-non-host-network-pods` | Ignore pods not running on host network when using pod source (default: true) | | `--[no-]ignore-ingress-tls-spec` | Ignore the spec.tls section in Ingress resources (default: false) | +| `--gateway-name=GATEWAY-NAME` | Limit Gateways of Route endpoints to a specific name (default: all names) | | `--gateway-namespace=GATEWAY-NAMESPACE` | Limit Gateways of Route endpoints to a specific namespace (default: all namespaces) | | `--gateway-label-filter=GATEWAY-LABEL-FILTER` | Filter Gateways of Route endpoints via label selector (default: all gateways) | | `--compatibility=` | Process annotation semantics from legacy implementations (optional, options: mate, molecule, kops-dns-controller) | diff --git a/docs/sources/gateway-api.md b/docs/sources/gateway-api.md index fd16a9154..3906f28be 100644 --- a/docs/sources/gateway-api.md +++ b/docs/sources/gateway-api.md @@ -100,6 +100,8 @@ spec: - --namespace=my-route-namespace # Optionally, limit Routes to those matching the given label selector. - --label-filter=my-route-label==my-route-value + # Optionally, limit Route endpoints to those Gateways with the given name. + - --gateway-name=my-gateway-name # Optionally, limit Route endpoints to those Gateways in the given namespace. - --gateway-namespace=my-gateway-namespace # Optionally, limit Route endpoints to those Gateways matching the given label selector. diff --git a/docs/sources/gateway.md b/docs/sources/gateway.md index 6150b7a58..82fcba1de 100644 --- a/docs/sources/gateway.md +++ b/docs/sources/gateway.md @@ -43,6 +43,39 @@ Matching Gateways are discovered by iterating over the \*Route's `status.parents - Ignores parents with a `parentRef.group` other than `gateway.networking.k8s.io` or a `parentRef.kind` other than `Gateway`. +- If the `--gateway-name` flag was specified, ignores parents with a `parentRef.name` other than the + specified value. + + For example, given the following HTTPRoute: + + ```yaml + apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: echo + spec: + hostnames: + - echoserver.example.org + parentRefs: + - group: networking.k8s.io + kind: Gateway + name: internal + --- + apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: echo2 + spec: + hostnames: + - echoserver2.example.org + parentRefs: + - group: networking.k8s.io + kind: Gateway + name: external + ``` + + And using the `--gateway-name=external` flag, only the `echo2` HTTPRoute will be considered for DNS entries. + - If the `--gateway-namespace` flag was specified, ignores parents with a `parentRef.namespace` other than the specified value. diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index d4781909f..938fd1956 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -61,6 +61,7 @@ type Config struct { IgnoreIngressTLSSpec bool IgnoreIngressRulesSpec bool ListenEndpointEvents bool + GatewayName string GatewayNamespace string GatewayLabelFilter string Compatibility string @@ -230,6 +231,7 @@ var defaultConfig = &Config{ IgnoreHostnameAnnotation: false, IgnoreIngressTLSSpec: false, IgnoreIngressRulesSpec: false, + GatewayName: "", GatewayNamespace: "", GatewayLabelFilter: "", Compatibility: "", @@ -453,6 +455,7 @@ func App(cfg *Config) *kingpin.Application { app.Flag("ignore-hostname-annotation", "Ignore hostname annotation when generating DNS names, valid only when --fqdn-template is set (default: false)").BoolVar(&cfg.IgnoreHostnameAnnotation) app.Flag("ignore-non-host-network-pods", "Ignore pods not running on host network when using pod source (default: true)").BoolVar(&cfg.IgnoreNonHostNetworkPods) app.Flag("ignore-ingress-tls-spec", "Ignore the spec.tls section in Ingress resources (default: false)").BoolVar(&cfg.IgnoreIngressTLSSpec) + app.Flag("gateway-name", "Limit Gateways of Route endpoints to a specific name (default: all names)").StringVar(&cfg.GatewayName) app.Flag("gateway-namespace", "Limit Gateways of Route endpoints to a specific namespace (default: all namespaces)").StringVar(&cfg.GatewayNamespace) app.Flag("gateway-label-filter", "Filter Gateways of Route endpoints via label selector (default: all gateways)").StringVar(&cfg.GatewayLabelFilter) app.Flag("compatibility", "Process annotation semantics from legacy implementations (optional, options: mate, molecule, kops-dns-controller)").Default(defaultConfig.Compatibility).EnumVar(&cfg.Compatibility, "", "mate", "molecule", "kops-dns-controller") diff --git a/source/gateway.go b/source/gateway.go index a8741ee91..33ef3be3d 100644 --- a/source/gateway.go +++ b/source/gateway.go @@ -82,6 +82,7 @@ func newGatewayInformerFactory(client gateway.Interface, namespace string, label } type gatewayRouteSource struct { + gwName string gwNamespace string gwLabels labels.Selector gwInformer informers_v1beta1.GatewayInformer @@ -161,6 +162,7 @@ func newGatewayRouteSource(clients ClientGenerator, config *Config, kind string, } src := &gatewayRouteSource{ + gwName: config.GatewayName, gwNamespace: config.GatewayNamespace, gwLabels: gwLabels, gwInformer: gwInformer, @@ -309,6 +311,11 @@ func (c *gatewayRouteResolver) resolve(rt gatewayRoute) (map[string]endpoint.Tar log.Debugf("Gateway %s/%s not found for %s %s/%s", namespace, ref.Name, c.src.rtKind, meta.Namespace, meta.Name) continue } + // Confirm the Gateway has the correct name, if specified. + if c.src.gwName != "" && c.src.gwName != gw.gateway.Name { + log.Debugf("Gateway %s/%s does not match %s %s/%s", namespace, ref.Name, c.src.gwName, meta.Namespace, meta.Name) + continue + } // 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) diff --git a/source/gateway_httproute_test.go b/source/gateway_httproute_test.go index 19db8c773..629a9e581 100644 --- a/source/gateway_httproute_test.go +++ b/source/gateway_httproute_test.go @@ -142,6 +142,51 @@ func TestGatewayHTTPRouteSourceEndpoints(t *testing.T) { endpoints []*endpoint.Endpoint logExpectations []string }{ + { + title: "GatewayName", + config: Config{ + GatewayName: "gateway-name", + }, + namespaces: namespaces("gateway-namespace", "route-namespace"), + gateways: []*v1beta1.Gateway{ + { + ObjectMeta: objectMeta("gateway-namespace", "gateway-name"), + Spec: v1.GatewaySpec{ + Listeners: []v1.Listener{{ + Protocol: v1.HTTPProtocolType, + AllowedRoutes: allowAllNamespaces, + }}, + }, + Status: gatewayStatus("1.2.3.4"), + }, + { + ObjectMeta: objectMeta("gateway-namespace", "not-gateway-name"), + Spec: v1.GatewaySpec{ + Listeners: []v1.Listener{{ + Protocol: v1.HTTPProtocolType, + AllowedRoutes: allowAllNamespaces, + }}, + }, + Status: gatewayStatus("2.3.4.5"), + }, + }, + routes: []*v1beta1.HTTPRoute{{ + ObjectMeta: objectMeta("route-namespace", "test"), + Spec: v1.HTTPRouteSpec{ + Hostnames: hostnames("test.example.internal"), + }, + Status: httpRouteStatus( // The route is attached to both gateways. + gwParentRef("gateway-namespace", "gateway-name"), + gwParentRef("gateway-namespace", "not-gateway-name"), + ), + }}, + endpoints: []*endpoint.Endpoint{ + newTestEndpoint("test.example.internal", "A", "1.2.3.4"), + }, + logExpectations: []string{ + "level=debug msg=\"Gateway gateway-namespace/not-gateway-name does not match gateway-name route-namespace/test\"", + }, + }, { title: "GatewayNamespace", config: Config{ diff --git a/source/store.go b/source/store.go index 551df8ae1..e0a8c0a15 100644 --- a/source/store.go +++ b/source/store.go @@ -54,6 +54,7 @@ type Config struct { IgnoreIngressTLSSpec bool IgnoreIngressRulesSpec bool ListenEndpointEvents bool + GatewayName string GatewayNamespace string GatewayLabelFilter string Compatibility string