From 1280e0de03bfa6132631c7b3d172e8caa0e280d5 Mon Sep 17 00:00:00 2001 From: John Gardiner Myers Date: Thu, 28 Sep 2023 22:23:30 -0700 Subject: [PATCH] Make --ignore-hostname-annotation flag more consistent --- docs/annotations/annotations.md | 4 +- source/kong_tcpingress.go | 36 ++-- source/kong_tcpingress_test.go | 72 +++++++- source/store.go | 4 +- source/traefik_proxy.go | 28 +-- source/traefik_proxy_test.go | 298 ++++++++++++++++++++++++++++---- 6 files changed, 377 insertions(+), 65 deletions(-) diff --git a/docs/annotations/annotations.md b/docs/annotations/annotations.md index 6f54dd4db4..d9f4c335df 100644 --- a/docs/annotations/annotations.md +++ b/docs/annotations/annotations.md @@ -16,13 +16,13 @@ The following table documents which sources support which annotations: | Gloo | | | | Yes | Yes[^5] | Yes[^5] | | Ingress | Yes | Yes[^1] | | Yes | Yes | Yes | | Istio | Yes | Yes[^1] | | Yes | Yes | Yes | -| Kong | | Yes | | Yes | Yes | Yes | +| Kong | | Yes[^1] | | Yes | Yes | Yes | | Node | Yes | | | Yes | Yes | | | OpenShift | Yes | Yes[^1] | | Yes | Yes | Yes | | Pod | | Yes | Yes | Yes | | | | Service | Yes | Yes[^1] | Yes[^1][^2] | Yes[^3] | Yes | Yes | | Skipper | Yes | Yes[^1] | | Yes | Yes | Yes | -| Traefik | | Yes | | Yes | Yes | Yes | +| Traefik | | Yes[^1] | | Yes | Yes | Yes | [^1]: Unless the `--ignore-hostname-annotation` flag is specified. [^2]: Only behaves differently than `hostname` for `Service`s of type `ClusterIP` or `LoadBalancer`. diff --git a/source/kong_tcpingress.go b/source/kong_tcpingress.go index f1a264760c..d317868bef 100644 --- a/source/kong_tcpingress.go +++ b/source/kong_tcpingress.go @@ -47,16 +47,17 @@ var kongGroupdVersionResource = schema.GroupVersionResource{ // kongTCPIngressSource is an implementation of Source for Kong TCPIngress objects. type kongTCPIngressSource struct { - annotationFilter string - dynamicKubeClient dynamic.Interface - kongTCPIngressInformer informers.GenericInformer - kubeClient kubernetes.Interface - namespace string - unstructuredConverter *unstructuredConverter + annotationFilter string + ignoreHostnameAnnotation bool + dynamicKubeClient dynamic.Interface + kongTCPIngressInformer informers.GenericInformer + kubeClient kubernetes.Interface + namespace string + unstructuredConverter *unstructuredConverter } // NewKongTCPIngressSource creates a new kongTCPIngressSource with the given config. -func NewKongTCPIngressSource(ctx context.Context, dynamicKubeClient dynamic.Interface, kubeClient kubernetes.Interface, namespace string, annotationFilter string) (Source, error) { +func NewKongTCPIngressSource(ctx context.Context, dynamicKubeClient dynamic.Interface, kubeClient kubernetes.Interface, namespace string, annotationFilter string, ignoreHostnameAnnotation bool) (Source, error) { var err error // Use shared informer to listen for add/update/delete of Host in the specified namespace. @@ -85,12 +86,13 @@ func NewKongTCPIngressSource(ctx context.Context, dynamicKubeClient dynamic.Inte } return &kongTCPIngressSource{ - annotationFilter: annotationFilter, - dynamicKubeClient: dynamicKubeClient, - kongTCPIngressInformer: kongTCPIngressInformer, - kubeClient: kubeClient, - namespace: namespace, - unstructuredConverter: uc, + annotationFilter: annotationFilter, + ignoreHostnameAnnotation: ignoreHostnameAnnotation, + dynamicKubeClient: dynamicKubeClient, + kongTCPIngressInformer: kongTCPIngressInformer, + kubeClient: kubeClient, + namespace: namespace, + unstructuredConverter: uc, }, nil } @@ -213,9 +215,11 @@ func (sc *kongTCPIngressSource) endpointsFromTCPIngress(tcpIngress *TCPIngress, resource := fmt.Sprintf("tcpingress/%s/%s", tcpIngress.Namespace, tcpIngress.Name) - hostnameList := getHostnamesFromAnnotations(tcpIngress.Annotations) - for _, hostname := range hostnameList { - endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...) + if !sc.ignoreHostnameAnnotation { + hostnameList := getHostnamesFromAnnotations(tcpIngress.Annotations) + for _, hostname := range hostnameList { + endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...) + } } if tcpIngress.Spec.Rules != nil { diff --git a/source/kong_tcpingress_test.go b/source/kong_tcpingress_test.go index bb3db2c657..8f8100e3db 100644 --- a/source/kong_tcpingress_test.go +++ b/source/kong_tcpingress_test.go @@ -40,9 +40,10 @@ func TestKongTCPIngressEndpoints(t *testing.T) { t.Parallel() for _, ti := range []struct { - title string - tcpProxy TCPIngress - expected []*endpoint.Endpoint + title string + tcpProxy TCPIngress + ignoreHostnameAnnotation bool + expected []*endpoint.Endpoint }{ { title: "TCPIngress with hostname annotation", @@ -220,6 +221,67 @@ func TestKongTCPIngressEndpoints(t *testing.T) { }, }, }, + { + title: "TCPIngress ignoring hostname annotation", + tcpProxy: TCPIngress{ + TypeMeta: metav1.TypeMeta{ + APIVersion: kongGroupdVersionResource.GroupVersion().String(), + Kind: "TCPIngress", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "tcp-ingress-both", + Namespace: defaultKongNamespace, + Annotations: map[string]string{ + "external-dns.alpha.kubernetes.io/hostname": "d.example.com", + "kubernetes.io/ingress.class": "kong", + }, + }, + Spec: tcpIngressSpec{ + Rules: []tcpIngressRule{ + { + Port: 30004, + Host: "e.example.com", + }, + { + Port: 30005, + Host: "f.example.com", + }, + }, + }, + Status: tcpIngressStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + Hostname: "a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com", + }, + }, + }, + }, + }, + ignoreHostnameAnnotation: true, + expected: []*endpoint.Endpoint{ + { + DNSName: "e.example.com", + Targets: []string{"a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "tcpingress/kong/tcp-ingress-both", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + { + DNSName: "f.example.com", + Targets: []string{"a12e71861a4303f063456769a314a3bd-1291189659.us-east-1.elb.amazonaws.com"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "tcpingress/kong/tcp-ingress-both", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + }, + }, { title: "TCPIngress with target annotation", tcpProxy: TCPIngress{ @@ -300,7 +362,7 @@ func TestKongTCPIngressEndpoints(t *testing.T) { _, err = fakeDynamicClient.Resource(kongGroupdVersionResource).Namespace(defaultKongNamespace).Create(context.Background(), &tcpi, metav1.CreateOptions{}) assert.NoError(t, err) - source, err := NewKongTCPIngressSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultKongNamespace, "kubernetes.io/ingress.class=kong") + source, err := NewKongTCPIngressSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultKongNamespace, "kubernetes.io/ingress.class=kong", ti.ignoreHostnameAnnotation) assert.NoError(t, err) assert.NotNil(t, source) @@ -312,7 +374,7 @@ func TestKongTCPIngressEndpoints(t *testing.T) { endpoints, err := source.Endpoints(context.Background()) assert.NoError(t, err) assert.Len(t, endpoints, len(ti.expected)) - assert.Equal(t, endpoints, ti.expected) + assert.Equal(t, ti.expected, endpoints) }) } } diff --git a/source/store.go b/source/store.go index 3599390e85..5f6b9dc35e 100644 --- a/source/store.go +++ b/source/store.go @@ -300,7 +300,7 @@ func BuildWithConfig(ctx context.Context, source string, p ClientGenerator, cfg if err != nil { return nil, err } - return NewTraefikSource(ctx, dynamicClient, kubernetesClient, cfg.Namespace, cfg.AnnotationFilter) + return NewTraefikSource(ctx, dynamicClient, kubernetesClient, cfg.Namespace, cfg.AnnotationFilter, cfg.IgnoreHostnameAnnotation) case "openshift-route": ocpClient, err := p.OpenShiftClient() if err != nil { @@ -341,7 +341,7 @@ func BuildWithConfig(ctx context.Context, source string, p ClientGenerator, cfg if err != nil { return nil, err } - return NewKongTCPIngressSource(ctx, dynamicClient, kubernetesClient, cfg.Namespace, cfg.AnnotationFilter) + return NewKongTCPIngressSource(ctx, dynamicClient, kubernetesClient, cfg.Namespace, cfg.AnnotationFilter, cfg.IgnoreHostnameAnnotation) case "f5-virtualserver": kubernetesClient, err := p.KubeClient() if err != nil { diff --git a/source/traefik_proxy.go b/source/traefik_proxy.go index c43fa40f8f..d9b7f06eb2 100644 --- a/source/traefik_proxy.go +++ b/source/traefik_proxy.go @@ -80,6 +80,7 @@ var ( type traefikSource struct { annotationFilter string + ignoreHostnameAnnotation bool dynamicKubeClient dynamic.Interface ingressRouteInformer informers.GenericInformer ingressRouteTcpInformer informers.GenericInformer @@ -92,7 +93,7 @@ type traefikSource struct { unstructuredConverter *unstructuredConverter } -func NewTraefikSource(ctx context.Context, dynamicKubeClient dynamic.Interface, kubeClient kubernetes.Interface, namespace string, annotationFilter string) (Source, error) { +func NewTraefikSource(ctx context.Context, dynamicKubeClient dynamic.Interface, kubeClient kubernetes.Interface, namespace string, annotationFilter string, ignoreHostnameAnnotation bool) (Source, error) { // Use shared informer to listen for add/update/delete of Host in the specified namespace. // Set resync period to 0, to prevent processing when nothing has changed. informerFactory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicKubeClient, 0, namespace, nil) @@ -149,6 +150,7 @@ func NewTraefikSource(ctx context.Context, dynamicKubeClient dynamic.Interface, return &traefikSource{ annotationFilter: annotationFilter, + ignoreHostnameAnnotation: ignoreHostnameAnnotation, dynamicKubeClient: dynamicKubeClient, ingressRouteInformer: ingressRouteInformer, ingressRouteTcpInformer: ingressRouteTcpInformer, @@ -656,9 +658,11 @@ func (ts *traefikSource) endpointsFromIngressRoute(ingressRoute *IngressRoute, t resource := fmt.Sprintf("ingressroute/%s/%s", ingressRoute.Namespace, ingressRoute.Name) - hostnameList := getHostnamesFromAnnotations(ingressRoute.Annotations) - for _, hostname := range hostnameList { - endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...) + if !ts.ignoreHostnameAnnotation { + hostnameList := getHostnamesFromAnnotations(ingressRoute.Annotations) + for _, hostname := range hostnameList { + endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...) + } } for _, route := range ingressRoute.Spec.Routes { @@ -693,9 +697,11 @@ func (ts *traefikSource) endpointsFromIngressRouteTCP(ingressRoute *IngressRoute resource := fmt.Sprintf("ingressroutetcp/%s/%s", ingressRoute.Namespace, ingressRoute.Name) - hostnameList := getHostnamesFromAnnotations(ingressRoute.Annotations) - for _, hostname := range hostnameList { - endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...) + if !ts.ignoreHostnameAnnotation { + hostnameList := getHostnamesFromAnnotations(ingressRoute.Annotations) + for _, hostname := range hostnameList { + endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...) + } } for _, route := range ingressRoute.Spec.Routes { @@ -731,9 +737,11 @@ func (ts *traefikSource) endpointsFromIngressRouteUDP(ingressRoute *IngressRoute resource := fmt.Sprintf("ingressrouteudp/%s/%s", ingressRoute.Namespace, ingressRoute.Name) - hostnameList := getHostnamesFromAnnotations(ingressRoute.Annotations) - for _, hostname := range hostnameList { - endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...) + if !ts.ignoreHostnameAnnotation { + hostnameList := getHostnamesFromAnnotations(ingressRoute.Annotations) + for _, hostname := range hostnameList { + endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...) + } } return endpoints, nil diff --git a/source/traefik_proxy_test.go b/source/traefik_proxy_test.go index eb26ed2b31..4905bb0b7d 100644 --- a/source/traefik_proxy_test.go +++ b/source/traefik_proxy_test.go @@ -39,9 +39,10 @@ func TestTraefikProxyIngressRouteEndpoints(t *testing.T) { t.Parallel() for _, ti := range []struct { - title string - ingressRoute IngressRoute - expected []*endpoint.Endpoint + title string + ingressRoute IngressRoute + ignoreHostnameAnnotation bool + expected []*endpoint.Endpoint }{ { title: "IngressRoute with hostname annotation", @@ -248,6 +249,54 @@ func TestTraefikProxyIngressRouteEndpoints(t *testing.T) { }, }, }, + { + title: "IngressRoute ignoring annotation", + ingressRoute: IngressRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: ingressrouteGVR.GroupVersion().String(), + Kind: "IngressRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "ingressroute-multi-host-annotations-match", + Namespace: defaultTraefikNamespace, + Annotations: map[string]string{ + "external-dns.alpha.kubernetes.io/hostname": "f.example.com", + "external-dns.alpha.kubernetes.io/target": "target.domain.tld", + "kubernetes.io/ingress.class": "traefik", + }, + }, + Spec: traefikIngressRouteSpec{ + Routes: []traefikRoute{ + { + Match: "Host(`g.example.com`, `h.example.com`)", + }, + }, + }, + }, + ignoreHostnameAnnotation: true, + expected: []*endpoint.Endpoint{ + { + DNSName: "g.example.com", + Targets: []string{"target.domain.tld"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "ingressroute/traefik/ingressroute-multi-host-annotations-match", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + { + DNSName: "h.example.com", + Targets: []string{"target.domain.tld"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "ingressroute/traefik/ingressroute-multi-host-annotations-match", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + }, + }, { title: "IngressRoute omit wildcard", ingressRoute: IngressRoute{ @@ -299,7 +348,7 @@ func TestTraefikProxyIngressRouteEndpoints(t *testing.T) { _, err = fakeDynamicClient.Resource(ingressrouteGVR).Namespace(defaultTraefikNamespace).Create(context.Background(), &ir, metav1.CreateOptions{}) assert.NoError(t, err) - source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik") + source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik", ti.ignoreHostnameAnnotation) assert.NoError(t, err) assert.NotNil(t, source) @@ -311,7 +360,7 @@ func TestTraefikProxyIngressRouteEndpoints(t *testing.T) { endpoints, err := source.Endpoints(context.Background()) assert.NoError(t, err) assert.Len(t, endpoints, len(ti.expected)) - assert.Equal(t, endpoints, ti.expected) + assert.Equal(t, ti.expected, endpoints) }) } } @@ -320,9 +369,10 @@ func TestTraefikProxyIngressRouteTCPEndpoints(t *testing.T) { t.Parallel() for _, ti := range []struct { - title string - ingressRouteTCP IngressRouteTCP - expected []*endpoint.Endpoint + title string + ingressRouteTCP IngressRouteTCP + ignoreHostnameAnnotation bool + expected []*endpoint.Endpoint }{ { title: "IngressRouteTCP with hostname annotation", @@ -493,6 +543,54 @@ func TestTraefikProxyIngressRouteTCPEndpoints(t *testing.T) { }, }, }, + { + title: "IngressRouteTCP ignoring annotation", + ingressRouteTCP: IngressRouteTCP{ + TypeMeta: metav1.TypeMeta{ + APIVersion: ingressrouteTCPGVR.GroupVersion().String(), + Kind: "IngressRouteTCP", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "ingressroutetcp-multi-host-annotations-match", + Namespace: defaultTraefikNamespace, + Annotations: map[string]string{ + "external-dns.alpha.kubernetes.io/hostname": "f.example.com", + "external-dns.alpha.kubernetes.io/target": "target.domain.tld", + "kubernetes.io/ingress.class": "traefik", + }, + }, + Spec: traefikIngressRouteTCPSpec{ + Routes: []traefikRouteTCP{ + { + Match: "HostSNI(`g.example.com`, `h.example.com`)", + }, + }, + }, + }, + ignoreHostnameAnnotation: true, + expected: []*endpoint.Endpoint{ + { + DNSName: "g.example.com", + Targets: []string{"target.domain.tld"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "ingressroutetcp/traefik/ingressroutetcp-multi-host-annotations-match", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + { + DNSName: "h.example.com", + Targets: []string{"target.domain.tld"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "ingressroutetcp/traefik/ingressroutetcp-multi-host-annotations-match", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + }, + }, { title: "IngressRouteTCP omit wildcard host sni", ingressRouteTCP: IngressRouteTCP{ @@ -544,7 +642,7 @@ func TestTraefikProxyIngressRouteTCPEndpoints(t *testing.T) { _, err = fakeDynamicClient.Resource(ingressrouteTCPGVR).Namespace(defaultTraefikNamespace).Create(context.Background(), &ir, metav1.CreateOptions{}) assert.NoError(t, err) - source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik") + source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik", ti.ignoreHostnameAnnotation) assert.NoError(t, err) assert.NotNil(t, source) @@ -556,7 +654,7 @@ func TestTraefikProxyIngressRouteTCPEndpoints(t *testing.T) { endpoints, err := source.Endpoints(context.Background()) assert.NoError(t, err) assert.Len(t, endpoints, len(ti.expected)) - assert.Equal(t, endpoints, ti.expected) + assert.Equal(t, ti.expected, endpoints) }) } } @@ -565,9 +663,10 @@ func TestTraefikProxyIngressRouteUDPEndpoints(t *testing.T) { t.Parallel() for _, ti := range []struct { - title string - ingressRouteUDP IngressRouteUDP - expected []*endpoint.Endpoint + title string + ingressRouteUDP IngressRouteUDP + ignoreHostnameAnnotation bool + expected []*endpoint.Endpoint }{ { title: "IngressRouteTCP with hostname annotation", @@ -639,6 +738,26 @@ func TestTraefikProxyIngressRouteUDPEndpoints(t *testing.T) { }, }, }, + { + title: "IngressRouteTCP ignoring hostname annotation", + ingressRouteUDP: IngressRouteUDP{ + TypeMeta: metav1.TypeMeta{ + APIVersion: ingressrouteUDPGVR.GroupVersion().String(), + Kind: "IngressRouteUDP", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "ingressrouteudp-annotation", + Namespace: defaultTraefikNamespace, + Annotations: map[string]string{ + "external-dns.alpha.kubernetes.io/hostname": "a.example.com", + "external-dns.alpha.kubernetes.io/target": "target.domain.tld", + "kubernetes.io/ingress.class": "traefik", + }, + }, + }, + ignoreHostnameAnnotation: true, + expected: nil, + }, } { ti := ti t.Run(ti.title, func(t *testing.T) { @@ -665,7 +784,7 @@ func TestTraefikProxyIngressRouteUDPEndpoints(t *testing.T) { _, err = fakeDynamicClient.Resource(ingressrouteUDPGVR).Namespace(defaultTraefikNamespace).Create(context.Background(), &ir, metav1.CreateOptions{}) assert.NoError(t, err) - source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik") + source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik", ti.ignoreHostnameAnnotation) assert.NoError(t, err) assert.NotNil(t, source) @@ -677,7 +796,7 @@ func TestTraefikProxyIngressRouteUDPEndpoints(t *testing.T) { endpoints, err := source.Endpoints(context.Background()) assert.NoError(t, err) assert.Len(t, endpoints, len(ti.expected)) - assert.Equal(t, endpoints, ti.expected) + assert.Equal(t, ti.expected, endpoints) }) } } @@ -686,9 +805,10 @@ func TestTraefikProxyOldIngressRouteEndpoints(t *testing.T) { t.Parallel() for _, ti := range []struct { - title string - ingressRoute IngressRoute - expected []*endpoint.Endpoint + title string + ingressRoute IngressRoute + ignoreHostnameAnnotation bool + expected []*endpoint.Endpoint }{ { title: "IngressRoute with hostname annotation", @@ -895,6 +1015,54 @@ func TestTraefikProxyOldIngressRouteEndpoints(t *testing.T) { }, }, }, + { + title: "IngressRoute ignoring annotation", + ingressRoute: IngressRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: oldIngressrouteGVR.GroupVersion().String(), + Kind: "IngressRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "ingressroute-multi-host-annotations-match", + Namespace: defaultTraefikNamespace, + Annotations: map[string]string{ + "external-dns.alpha.kubernetes.io/hostname": "f.example.com", + "external-dns.alpha.kubernetes.io/target": "target.domain.tld", + "kubernetes.io/ingress.class": "traefik", + }, + }, + Spec: traefikIngressRouteSpec{ + Routes: []traefikRoute{ + { + Match: "Host(`g.example.com`, `h.example.com`)", + }, + }, + }, + }, + ignoreHostnameAnnotation: true, + expected: []*endpoint.Endpoint{ + { + DNSName: "g.example.com", + Targets: []string{"target.domain.tld"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "ingressroute/traefik/ingressroute-multi-host-annotations-match", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + { + DNSName: "h.example.com", + Targets: []string{"target.domain.tld"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "ingressroute/traefik/ingressroute-multi-host-annotations-match", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + }, + }, { title: "IngressRoute omit wildcard", ingressRoute: IngressRoute{ @@ -946,7 +1114,7 @@ func TestTraefikProxyOldIngressRouteEndpoints(t *testing.T) { _, err = fakeDynamicClient.Resource(oldIngressrouteGVR).Namespace(defaultTraefikNamespace).Create(context.Background(), &ir, metav1.CreateOptions{}) assert.NoError(t, err) - source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik") + source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik", ti.ignoreHostnameAnnotation) assert.NoError(t, err) assert.NotNil(t, source) @@ -958,7 +1126,7 @@ func TestTraefikProxyOldIngressRouteEndpoints(t *testing.T) { endpoints, err := source.Endpoints(context.Background()) assert.NoError(t, err) assert.Len(t, endpoints, len(ti.expected)) - assert.Equal(t, endpoints, ti.expected) + assert.Equal(t, ti.expected, endpoints) }) } } @@ -967,9 +1135,10 @@ func TestTraefikProxyOldIngressRouteTCPEndpoints(t *testing.T) { t.Parallel() for _, ti := range []struct { - title string - ingressRouteTCP IngressRouteTCP - expected []*endpoint.Endpoint + title string + ingressRouteTCP IngressRouteTCP + ignoreHostnameAnnotation bool + expected []*endpoint.Endpoint }{ { title: "IngressRouteTCP with hostname annotation", @@ -1140,6 +1309,54 @@ func TestTraefikProxyOldIngressRouteTCPEndpoints(t *testing.T) { }, }, }, + { + title: "IngressRouteTCP ignoring annotation", + ingressRouteTCP: IngressRouteTCP{ + TypeMeta: metav1.TypeMeta{ + APIVersion: oldIngressrouteTCPGVR.GroupVersion().String(), + Kind: "IngressRouteTCP", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "ingressroutetcp-multi-host-annotations-match", + Namespace: defaultTraefikNamespace, + Annotations: map[string]string{ + "external-dns.alpha.kubernetes.io/hostname": "f.example.com", + "external-dns.alpha.kubernetes.io/target": "target.domain.tld", + "kubernetes.io/ingress.class": "traefik", + }, + }, + Spec: traefikIngressRouteTCPSpec{ + Routes: []traefikRouteTCP{ + { + Match: "HostSNI(`g.example.com`, `h.example.com`)", + }, + }, + }, + }, + ignoreHostnameAnnotation: true, + expected: []*endpoint.Endpoint{ + { + DNSName: "g.example.com", + Targets: []string{"target.domain.tld"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "ingressroutetcp/traefik/ingressroutetcp-multi-host-annotations-match", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + { + DNSName: "h.example.com", + Targets: []string{"target.domain.tld"}, + RecordType: endpoint.RecordTypeCNAME, + RecordTTL: 0, + Labels: endpoint.Labels{ + "resource": "ingressroutetcp/traefik/ingressroutetcp-multi-host-annotations-match", + }, + ProviderSpecific: endpoint.ProviderSpecific{}, + }, + }, + }, { title: "IngressRouteTCP omit wildcard host sni", ingressRouteTCP: IngressRouteTCP{ @@ -1191,7 +1408,7 @@ func TestTraefikProxyOldIngressRouteTCPEndpoints(t *testing.T) { _, err = fakeDynamicClient.Resource(oldIngressrouteTCPGVR).Namespace(defaultTraefikNamespace).Create(context.Background(), &ir, metav1.CreateOptions{}) assert.NoError(t, err) - source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik") + source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik", ti.ignoreHostnameAnnotation) assert.NoError(t, err) assert.NotNil(t, source) @@ -1203,7 +1420,7 @@ func TestTraefikProxyOldIngressRouteTCPEndpoints(t *testing.T) { endpoints, err := source.Endpoints(context.Background()) assert.NoError(t, err) assert.Len(t, endpoints, len(ti.expected)) - assert.Equal(t, endpoints, ti.expected) + assert.Equal(t, ti.expected, endpoints) }) } } @@ -1212,9 +1429,10 @@ func TestTraefikProxyOldIngressRouteUDPEndpoints(t *testing.T) { t.Parallel() for _, ti := range []struct { - title string - ingressRouteUDP IngressRouteUDP - expected []*endpoint.Endpoint + title string + ingressRouteUDP IngressRouteUDP + ignoreHostnameAnnotation bool + expected []*endpoint.Endpoint }{ { title: "IngressRouteTCP with hostname annotation", @@ -1286,6 +1504,26 @@ func TestTraefikProxyOldIngressRouteUDPEndpoints(t *testing.T) { }, }, }, + { + title: "IngressRouteTCP ignoring hostname annotation", + ingressRouteUDP: IngressRouteUDP{ + TypeMeta: metav1.TypeMeta{ + APIVersion: oldIngressrouteUDPGVR.GroupVersion().String(), + Kind: "IngressRouteUDP", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "ingressrouteudp-annotation", + Namespace: defaultTraefikNamespace, + Annotations: map[string]string{ + "external-dns.alpha.kubernetes.io/hostname": "a.example.com", + "external-dns.alpha.kubernetes.io/target": "target.domain.tld", + "kubernetes.io/ingress.class": "traefik", + }, + }, + }, + ignoreHostnameAnnotation: true, + expected: nil, + }, } { ti := ti t.Run(ti.title, func(t *testing.T) { @@ -1312,7 +1550,7 @@ func TestTraefikProxyOldIngressRouteUDPEndpoints(t *testing.T) { _, err = fakeDynamicClient.Resource(oldIngressrouteUDPGVR).Namespace(defaultTraefikNamespace).Create(context.Background(), &ir, metav1.CreateOptions{}) assert.NoError(t, err) - source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik") + source, err := NewTraefikSource(context.TODO(), fakeDynamicClient, fakeKubernetesClient, defaultTraefikNamespace, "kubernetes.io/ingress.class=traefik", ti.ignoreHostnameAnnotation) assert.NoError(t, err) assert.NotNil(t, source) @@ -1324,7 +1562,7 @@ func TestTraefikProxyOldIngressRouteUDPEndpoints(t *testing.T) { endpoints, err := source.Endpoints(context.Background()) assert.NoError(t, err) assert.Len(t, endpoints, len(ti.expected)) - assert.Equal(t, endpoints, ti.expected) + assert.Equal(t, ti.expected, endpoints) }) } }