feat(source): fitler by gateway name (#5160)

* feat: filter by gateway name

Signed-off-by: Steven Kreitzer <skre@skre.me>

* address comments

* address comments

* address comments

---------

Signed-off-by: Steven Kreitzer <skre@skre.me>
This commit is contained in:
Steven Kreitzer 2025-03-12 03:51:47 -05:00 committed by GitHub
parent c72c499259
commit 724b86b8b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 92 additions and 0 deletions

View File

@ -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) |

View File

@ -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.

View File

@ -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.

View File

@ -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")

View File

@ -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)

View File

@ -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{

View File

@ -54,6 +54,7 @@ type Config struct {
IgnoreIngressTLSSpec bool
IgnoreIngressRulesSpec bool
ListenEndpointEvents bool
GatewayName string
GatewayNamespace string
GatewayLabelFilter string
Compatibility string