From 1508a2c221b7df4cd310b0da71b7a4244b8f0290 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Wed, 9 Oct 2024 15:14:05 +0200 Subject: [PATCH] Do not update gateway status when not selected by a gateway class Co-authored-by: Romain --- .../fixtures/gatewayclass_labelselector.yaml | 51 +++++++++++++++++++ pkg/provider/kubernetes/gateway/kubernetes.go | 12 +++-- .../kubernetes/gateway/kubernetes_test.go | 41 +++++++++++++++ 3 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 pkg/provider/kubernetes/gateway/fixtures/gatewayclass_labelselector.yaml diff --git a/pkg/provider/kubernetes/gateway/fixtures/gatewayclass_labelselector.yaml b/pkg/provider/kubernetes/gateway/fixtures/gatewayclass_labelselector.yaml new file mode 100644 index 000000000..a012ce69b --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/gatewayclass_labelselector.yaml @@ -0,0 +1,51 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: traefik-internal + labels: + name: traefik-internal +spec: + controllerName: traefik.io/gateway-controller + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: traefik-internal + namespace: default +spec: + gatewayClassName: traefik-internal + listeners: + - name: http + protocol: HTTP + port: 9080 + allowedRoutes: + namespaces: + from: Same + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: traefik-external + labels: + name: traefik-external +spec: + controllerName: traefik.io/gateway-controller + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: traefik-external + namespace: default +spec: + gatewayClassName: traefik-external + listeners: + - name: http + protocol: HTTP + port: 9080 + allowedRoutes: + namespaces: + from: Same diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index 2588182b5..faea170e3 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -357,7 +357,13 @@ func (p *Provider) loadConfigurationFromGateways(ctx context.Context) *dynamic.C } } - gateways := p.client.ListGateways() + var gateways []*gatev1.Gateway + for _, gateway := range p.client.ListGateways() { + if _, ok := gatewayClassNames[string(gateway.Spec.GatewayClassName)]; !ok { + continue + } + gateways = append(gateways, gateway) + } var gatewayListeners []gatewayListener for _, gateway := range gateways { @@ -366,10 +372,6 @@ func (p *Provider) loadConfigurationFromGateways(ctx context.Context) *dynamic.C Str("namespace", gateway.Namespace). Logger() - if _, ok := gatewayClassNames[string(gateway.Spec.GatewayClassName)]; !ok { - continue - } - gatewayListeners = append(gatewayListeners, p.loadGatewayListeners(logger.WithContext(ctx), gateway, conf)...) } diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index e8929b639..f885515c3 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -49,6 +49,47 @@ func init() { } } +func TestGatewayClassLabelSelector(t *testing.T) { + k8sObjects, gwObjects := readResources(t, []string{"gatewayclass_labelselector.yaml"}) + + kubeClient := kubefake.NewSimpleClientset(k8sObjects...) + gwClient := newGatewaySimpleClientSet(t, gwObjects...) + + client := newClientImpl(kubeClient, gwClient) + + // This is initialized by the Provider init method but this cannot be called in a unit test. + client.labelSelector = "name=traefik-internal" + + eventCh, err := client.WatchAll(nil, make(chan struct{})) + require.NoError(t, err) + + if len(k8sObjects) > 0 || len(gwObjects) > 0 { + // just wait for the first event + <-eventCh + } + + p := Provider{ + EntryPoints: map[string]Entrypoint{"http": {Address: ":9080"}}, + StatusAddress: &StatusAddress{IP: "1.2.3.4"}, + client: client, + } + + _ = p.loadConfigurationFromGateways(context.Background()) + + gw, err := gwClient.GatewayV1().Gateways("default").Get(context.Background(), "traefik-external", metav1.GetOptions{}) + require.NoError(t, err) + + assert.Empty(t, gw.Status.Addresses) + + gw, err = gwClient.GatewayV1().Gateways("default").Get(context.Background(), "traefik-internal", metav1.GetOptions{}) + require.NoError(t, err) + require.Len(t, gw.Status.Addresses, 1) + require.NotNil(t, gw.Status.Addresses[0].Type) + + assert.Equal(t, gatev1.IPAddressType, *gw.Status.Addresses[0].Type) + assert.Equal(t, "1.2.3.4", gw.Status.Addresses[0].Value) +} + func TestLoadHTTPRoutes(t *testing.T) { testCases := []struct { desc string