From 665aeb34b25afea89321bd8311a978089942df3a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Doumenjou Date: Wed, 26 Feb 2020 12:28:05 +0100 Subject: [PATCH] Add UDP support in kubernetesCRD provider Co-authored-by: Mathieu Lonjaret --- .../kubernetes-crd-definition.yml | 15 + ...ernetes-crd-ingressroutetcp-definition.yml | 13 - .../kubernetes-crd-rbac.yml | 1 + .../kubernetes-crd-resource.yml | 15 + .../dynamic-configuration/kubernetes-crd.yml | 271 --------- .../routing/providers/crd_ingress_route.yml | 28 - .../routing/providers/crd_middlewares.yml | 13 - .../routing/providers/crd_tls_option.yml | 13 - .../routing/providers/crd_traefikservice.yml | 13 - .../routing/providers/kubernetes-crd.md | 226 ++++++- integration/fixtures/k8s/01-crd.yml | 15 + integration/fixtures/k8s/02-services.yml | 44 ++ .../fixtures/k8s/05-ingressrouteudp.yml | 14 + integration/fixtures/k8s_crd.toml | 2 + integration/testdata/rawdata-crd.json | 30 + pkg/provider/kubernetes/crd/client.go | 16 + .../kubernetes/crd/client_mock_test.go | 7 + .../fixtures/tcp/with_two_identical_rules.yml | 19 + .../kubernetes/crd/fixtures/udp/services.yml | 103 ++++ .../kubernetes/crd/fixtures/udp/simple.yml | 14 + .../udp/with_different_services_ns.yml | 30 + .../crd/fixtures/udp/with_two_routes.yml | 17 + .../crd/fixtures/udp/with_two_services.yml | 18 + .../v1alpha1/fake/fake_ingressrouteudp.go | 136 +++++ .../v1alpha1/fake/fake_traefik_client.go | 4 + .../traefik/v1alpha1/generated_expansion.go | 2 + .../typed/traefik/v1alpha1/ingressrouteudp.go | 182 ++++++ .../typed/traefik/v1alpha1/traefik_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../traefik/v1alpha1/ingressrouteudp.go | 97 +++ .../traefik/v1alpha1/interface.go | 7 + .../traefik/v1alpha1/expansion_generated.go | 8 + .../traefik/v1alpha1/ingressrouteudp.go | 102 ++++ pkg/provider/kubernetes/crd/kubernetes.go | 1 + .../kubernetes/crd/kubernetes_test.go | 561 ++++++++++++++++++ pkg/provider/kubernetes/crd/kubernetes_udp.go | 161 +++++ .../crd/traefik/v1alpha1/ingressrouteudp.go | 50 ++ .../crd/traefik/v1alpha1/register.go | 2 + .../traefik/v1alpha1/zz_generated.deepcopy.go | 148 +++++ pkg/provider/kubernetes/k8s/parser.go | 2 +- 40 files changed, 2041 insertions(+), 366 deletions(-) delete mode 100644 docs/content/reference/dynamic-configuration/kubernetes-crd-ingressroutetcp-definition.yml delete mode 100644 docs/content/reference/dynamic-configuration/kubernetes-crd.yml delete mode 100644 docs/content/routing/providers/crd_ingress_route.yml delete mode 100644 docs/content/routing/providers/crd_middlewares.yml delete mode 100644 docs/content/routing/providers/crd_tls_option.yml delete mode 100644 docs/content/routing/providers/crd_traefikservice.yml create mode 100644 integration/fixtures/k8s/05-ingressrouteudp.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/tcp/with_two_identical_rules.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/udp/services.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/udp/simple.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/udp/with_different_services_ns.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/udp/with_two_routes.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/udp/with_two_services.yml create mode 100644 pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go create mode 100644 pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go create mode 100644 pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go create mode 100644 pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go create mode 100644 pkg/provider/kubernetes/crd/kubernetes_udp.go create mode 100644 pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressrouteudp.go diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition.yml index 35c6029a2..9b589da72 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition.yml @@ -42,6 +42,21 @@ spec: singular: ingressroutetcp scope: Namespaced +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: ingressrouteudps.traefik.containo.us + +spec: + group: traefik.containo.us + version: v1alpha1 + names: + kind: IngressRouteUDP + plural: ingressrouteudps + singular: ingressrouteudp + scope: Namespaced + --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-ingressroutetcp-definition.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-ingressroutetcp-definition.yml deleted file mode 100644 index 36b202ae3..000000000 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-ingressroutetcp-definition.yml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: ingressroutetcps.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: IngressRouteTCP - plural: ingressroutetcps - singular: ingressroutetcp - scope: Namespaced diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml index 9b56464d7..c31cfc508 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml @@ -35,6 +35,7 @@ rules: - ingressroutes - traefikservices - ingressroutetcps + - ingressrouteudps - tlsoptions verbs: - get diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml index 04b9d0f74..fd6e4ce79 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml @@ -156,6 +156,21 @@ spec: name: myTLSOption namespace: default +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteUDP +metadata: + name: ingressrouteudp.crd + namespace: default + +spec: + entryPoints: + - footcp + routes: + - services: + - name: whoamiudp + port: 8080 + --- apiVersion: traefik.containo.us/v1alpha1 kind: TLSOption diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd.yml deleted file mode 100644 index 58f5f6bb4..000000000 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd.yml +++ /dev/null @@ -1,271 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: ingressroutes.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: IngressRoute - plural: ingressroutes - singular: ingressroute - scope: Namespaced - ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: middlewares.traefik.containo.us -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: Middleware - plural: middlewares - singular: middleware - scope: Namespaced - ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: tlsoptions.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: TLSOption - plural: tlsoptions - singular: tlsoption - scope: Namespaced - ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: tlsstores.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: TLSStore - plural: tlsstores - singular: tlsstore - scope: Namespaced - ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: ingressroutetcps.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: IngressRouteTCP - plural: ingressroutetcps - singular: ingressroutetcp - scope: Namespaced - ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: traefikservices.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: TraefikService - plural: traefikservices - singular: traefikservice - scope: Namespaced - ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: TraefikService -metadata: - name: wrr2 - namespace: default - -spec: - weighted: - services: - - name: s1 - weight: 1 - port: 80 - # Optional, as it is the default value - kind: Service - - name: s3 - weight: 1 - port: 80 - ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: TraefikService -metadata: - name: wrr1 - namespace: default - -spec: - weighted: - services: - - name: wrr2 - kind: TraefikService - weight: 1 - - name: s3 - weight: 1 - port: 80 - ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: TraefikService -metadata: - name: mirror1 - namespace: default - -spec: - mirroring: - name: s1 - port: 80 - mirrors: - - name: s3 - percent: 20 - port: 80 - - name: mirror2 - kind: TraefikService - percent: 20 - ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: TraefikService -metadata: - name: mirror2 - namespace: default - -spec: - mirroring: - name: wrr2 - kind: TraefikService - mirrors: - - name: s2 - # Optional, as it is the default value - kind: Service - percent: 20 - port: 80 - ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: IngressRoute -metadata: - name: ingressroute -spec: - entryPoints: - - web - - websecure - routes: - - match: Host(`foo.com`) && PathPrefix(`/bar`) - kind: Rule - priority: 12 - # defining several services is possible and allowed, but for now the servers of - # all the services (for a given route) get merged altogether under the same - # load-balancing strategy. - services: - - name: s1 - port: 80 - healthCheck: - path: /health - host: baz.com - intervalSeconds: 7 - timeoutSeconds: 60 - # strategy defines the load balancing strategy between the servers. It defaults - # to Round Robin, and for now only Round Robin is supported anyway. - strategy: RoundRobin - - name: s2 - port: 433 - healthCheck: - path: /health - host: baz.com - intervalSeconds: 7 - timeoutSeconds: 60 - - match: PathPrefix(`/misc`) - services: - - name: s3 - port: 80 - middlewares: - - name: stripprefix - - name: addprefix - - match: PathPrefix(`/misc`) - services: - - name: s3 - # Optional, as it is the default value - kind: Service - port: 8443 - # scheme allow to override the scheme for the service. (ex: https or h2c) - scheme: https - - match: PathPrefix(`/lb`) - services: - - name: wrr1 - kind: TraefikService - - match: PathPrefix(`/mirrored`) - services: - - name: mirror1 - kind: TraefikService - # use an empty tls object for TLS with Let's Encrypt - tls: - secretName: supersecret - options: - name: myTLSOption - namespace: default - ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: IngressRouteTCP -metadata: - name: ingressroutetcp.crd - namespace: default - -spec: - entryPoints: - - footcp - routes: - - match: HostSNI(`bar.com`) - services: - - name: whoamitcp - namespace: default - port: 8080 - tls: - secretName: foosecret - passthrough: false - options: - name: myTLSOption - namespace: default - ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: TLSOption -metadata: - name: tlsoption - namespace: default - -spec: - minVersion: foobar - maxVersion: foobar - cipherSuites: - - foobar - - foobar - curvePreferences: - - foobar - - foobar - clientAuth: - caFiles: - - foobar - - foobar - clientAuthType: foobar - sniStrict: true - preferServerCipherSuites: true diff --git a/docs/content/routing/providers/crd_ingress_route.yml b/docs/content/routing/providers/crd_ingress_route.yml deleted file mode 100644 index b40f22527..000000000 --- a/docs/content/routing/providers/crd_ingress_route.yml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: ingressroutes.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: IngressRoute - plural: ingressroutes - singular: ingressroute - scope: Namespaced - ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: ingressroutetcps.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: IngressRouteTCP - plural: ingressroutetcps - singular: ingressroutetcp - scope: Namespaced diff --git a/docs/content/routing/providers/crd_middlewares.yml b/docs/content/routing/providers/crd_middlewares.yml deleted file mode 100644 index d1ae35f79..000000000 --- a/docs/content/routing/providers/crd_middlewares.yml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: middlewares.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: Middleware - plural: middlewares - singular: middleware - scope: Namespaced diff --git a/docs/content/routing/providers/crd_tls_option.yml b/docs/content/routing/providers/crd_tls_option.yml deleted file mode 100644 index 1495e0d0b..000000000 --- a/docs/content/routing/providers/crd_tls_option.yml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: tlsoptions.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: TLSOption - plural: tlsoptions - singular: tlsoption - scope: Namespaced diff --git a/docs/content/routing/providers/crd_traefikservice.yml b/docs/content/routing/providers/crd_traefikservice.yml deleted file mode 100644 index 9d151625a..000000000 --- a/docs/content/routing/providers/crd_traefikservice.yml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - name: traefikservices.traefik.containo.us - -spec: - group: traefik.containo.us - version: v1alpha1 - names: - kind: TraefikService - plural: traefikservices - singular: traefikservice - scope: Namespaced diff --git a/docs/content/routing/providers/kubernetes-crd.md b/docs/content/routing/providers/kubernetes-crd.md index 9b51b8070..6252f6bc4 100644 --- a/docs/content/routing/providers/kubernetes-crd.md +++ b/docs/content/routing/providers/kubernetes-crd.md @@ -49,12 +49,18 @@ The Kubernetes Ingress Controller, The Custom Resource Way. - --api - --api.insecure - --entrypoints.web.address=:80 + - --entrypoints.tcpep.address=:8000 + - --entrypoints.udpep.address=:9000/udp - --providers.kubernetescrd ports: - name: web containerPort: 80 - name: admin containerPort: 8080 + - name: tcpep + containerPort: 8000 + - name: udpep + containerPort: 9000 --- apiVersion: v1 @@ -74,6 +80,25 @@ The Kubernetes Ingress Controller, The Custom Resource Way. port: 8080 name: admin targetPort: 8080 + - protocol: TCP + port: 8000 + name: tcpep + targetPort: 8000 + + --- + apiVersion: v1 + kind: Service + metadata: + name: traefikudp + spec: + type: LoadBalancer + selector: + app: traefik + ports: + - protocol: UDP + port: 9000 + name: udpep + targetPort: 9000 ``` ```yaml tab="IngressRoute" @@ -93,8 +118,41 @@ The Kubernetes Ingress Controller, The Custom Resource Way. services: - name: whoami port: 80 + + --- + apiVersion: traefik.containo.us/v1alpha1 + kind: IngressRouteTCP + metadata: + name: ingressroute.tcp + namespace: default + + spec: + entryPoints: + - tcpep + routes: + - match: HostSNI(`bar`) + kind: Rule + services: + - name: whoamitcp + port: 8080 + + --- + apiVersion: traefik.containo.us/v1alpha1 + kind: IngressRouteUDP + metadata: + name: ingressroute.udp + namespace: default + + spec: + entryPoints: + - fooudp + routes: + - kind: Rule + services: + - name: whoamiudp + port: 8080 ``` - + ```yaml tab="Whoami" kind: Deployment apiVersion: apps/v1 @@ -137,6 +195,91 @@ The Kubernetes Ingress Controller, The Custom Resource Way. selector: app: containous task: whoami + + --- + kind: Deployment + apiVersion: apps/v1 + metadata: + name: whoamitcp + namespace: default + labels: + app: containous + name: whoamitcp + + spec: + replicas: 2 + selector: + matchLabels: + app: containous + task: whoamitcp + template: + metadata: + labels: + app: containous + task: whoamitcp + spec: + containers: + - name: containouswhoamitcp + image: containous/whoamitcp + ports: + - containerPort: 8080 + + --- + apiVersion: v1 + kind: Service + metadata: + name: whoamitcp + namespace: default + + spec: + ports: + - protocol: TCP + port: 8080 + selector: + app: containous + task: whoamitcp + + --- + kind: Deployment + apiVersion: apps/v1 + metadata: + name: whoamiudp + namespace: default + labels: + app: containous + name: whoamiudp + + spec: + replicas: 2 + selector: + matchLabels: + app: containous + task: whoamiudp + template: + metadata: + labels: + app: containous + task: whoamiudp + spec: + containers: + - name: containouswhoamiudp + image: containous/whoamiudp:dev + ports: + - containerPort: 8080 + + --- + apiVersion: v1 + kind: Service + metadata: + name: whoamiudp + namespace: default + + spec: + ports: + - port: 8080 + selector: + app: containous + task: whoamiudp ``` ## Routing Configuration @@ -155,13 +298,14 @@ You can find an excerpt of the available custom resources in the table below: | [Middleware](#kind-middleware) | Tweaks the HTTP requests before they are sent to your service | [HTTP Middlewares](../../middlewares/overview.md) | | [TraefikService](#kind-traefikservice) | Abstraction for HTTP loadbalancing/mirroring | [HTTP service](../services/index.md#configuring-http-services) | | [IngressRouteTCP](#kind-ingressroutetcp) | TCP Routing | [TCP router](../routers/index.md#configuring-tcp-routers) | +| [IngressRouteUDP](#kind-ingressrouteudp) | UDP Routing | [UDP router](../routers/index.md#configuring-udp-routers) | | [TLSOptions](#kind-tlsoption) | Allows to configure some parameters of the TLS connection | [TLSOptions](../../https/tls.md#tls-options) | ### Kind: `IngressRoute` `IngressRoute` is the CRD implementation of a [Traefik HTTP router](../routers/index.md#configuring-http-routers). -Register the `IngressRoute` kind in the Kubernetes cluster before creating `IngressRoute` objects. +Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kubernetes-crd.md#definitions) in the Kubernetes cluster before creating `IngressRoute` objects. !!! info "IngressRoute Attributes" @@ -212,8 +356,8 @@ Register the `IngressRoute` kind in the Kubernetes cluster before creating `Ingr | Ref | Attribute | Purpose | |------|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [1] | `entryPoints` | List of [entry points](../routers/index.md#entrypoints) name | -| [2] | `routes` | List of route | +| [1] | `entryPoints` | List of [entry points](../routers/index.md#entrypoints) names | +| [2] | `routes` | List of routes | | [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule) corresponding to an underlying router. | | [4] | `routes[n].priority` | [Disambiguate](../routers/index.md#priority) rules of the same length, for route matching | | [5] | `routes[n].middlewares` | List of reference to [Middleware](#kind-middleware) | @@ -317,7 +461,7 @@ Register the `IngressRoute` kind in the Kubernetes cluster before creating `Ingr `Middleware` is the CRD implementation of a [Traefik middleware](../../middlewares/overview.md). -Register the `Middleware` kind in the Kubernetes cluster before creating `Middleware` objects or referencing middlewares in the [`IngressRoute`](#kind-ingressroute) objects. +Register the `Middleware` [kind](../../reference/dynamic-configuration/kubernetes-crd.md#definitions) in the Kubernetes cluster before creating `Middleware` objects or referencing middlewares in the [`IngressRoute`](#kind-ingressroute) objects. ??? "Declaring and Referencing a Middleware" @@ -367,8 +511,8 @@ More information about available middlewares in the dedicated [middlewares secti `TraefikService` is the CRD implementation of a ["Traefik Service"](../services/index.md). -Register the `TraefikService` kind in the Kubernetes cluster before creating `TraefikService` objects, -referencing services in the [`IngressRoute`](#kind-ingressroute)/[`IngressRouteTCP`](#kind-ingressroutetcp) objects or recursively in others `TraefikService` objects. +Register the `TraefikService` [kind](../../reference/dynamic-configuration/kubernetes-crd.md#definitions) in the Kubernetes cluster before creating `TraefikService` objects, +referencing services in the [`IngressRoute`](#kind-ingressroute) objects, or recursively in others `TraefikService` objects. !!! info "Disambiguate Traefik and Kubernetes Services " @@ -659,7 +803,7 @@ More information in the dedicated [mirroring](../services/index.md#mirroring-ser `IngressRouteTCP` is the CRD implementation of a [Traefik TCP router](../routers/index.md#configuring-tcp-routers). -Register the `IngressRouteTCP` kind in the Kubernetes cluster before creating `IngressRouteTCP` objects. +Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kubernetes-crd.md#definitions) in the Kubernetes cluster before creating `IngressRouteTCP` objects. !!! info "IngressRouteTCP Attributes" @@ -695,10 +839,10 @@ Register the `IngressRouteTCP` kind in the Kubernetes cluster before creating `I | Ref | Attribute | Purpose | |------|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [1] | `entryPoints` | List of [entrypoints](../routers/index.md#entrypoints_1) name | -| [2] | `routes` | List of route | -| [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule_1) corresponding to an underlying router. | -| [4] | `routes[n].services` | List of any combination of [TraefikService](#kind-traefikservice) and reference to a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) | +| [1] | `entryPoints` | List of [entrypoints](../routers/index.md#entrypoints_1) names | +| [2] | `routes` | List of routes | +| [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule_1) corresponding to an underlying router | +| [4] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions | | [5] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) | | [6] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) | | [7] | `services[n].weight` | Defines the weight to apply to the server load balancing | @@ -708,7 +852,7 @@ Register the `IngressRouteTCP` kind in the Kubernetes cluster before creating `I | [11] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) | | [12] | `options.name` | Defines the [TLSOption](#kind-tlsoption) name | | [13] | `options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace | -| [14] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver_1) | +| [14] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver_1) | | [15] | `tls.domains` | List of [domains](../routers/index.md#domains_1) | | [16] | `domains[n].main` | Defines the main domain name | | [17] | `domains[n].sans` | List of SANs (alternative domains) | @@ -773,11 +917,65 @@ Register the `IngressRouteTCP` kind in the Kubernetes cluster before creating `I tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= ``` +### Kind `IngressRouteUDP` + +`IngressRouteUDP` is the CRD implementation of a [Traefik UDP router](../routers/index.md#configuring-udp-routers). + +Register the `IngressRouteUDP` [kind](../../reference/dynamic-configuration/kubernetes-crd.md#definitions) in the Kubernetes cluster before creating `IngressRouteUDP` objects. + +!!! info "IngressRouteUDP Attributes" + + ```yaml + apiVersion: traefik.containo.us/v1alpha1 + kind: IngressRouteUDP + metadata: + name: ingressrouteudpfoo + + spec: + entryPoints: # [1] + - fooudp + routes: # [2] + - services: # [3] + - name: foo # [4] + port: 8080 # [5] + weight: 10 # [6] + ``` + +| Ref | Attribute | Purpose | +|------|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [1] | `entryPoints` | List of [entrypoints](../routers/index.md#entrypoints_1) names | +| [2] | `routes` | List of routes | +| [3] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions | +| [4] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) | +| [6] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) | +| [7] | `services[n].weight` | Defines the weight to apply to the server load balancing | + +??? example "Declaring an IngressRouteUDP" + + ```yaml + apiVersion: traefik.containo.us/v1alpha1 + kind: IngressRouteUDP + metadata: + name: ingressrouteudpfoo + + spec: + entryPoints: + - fooudp + routes: + - services: + - name: foo + port: 8080 + weight: 10 + - name: bar + port: 8081 + weight: 10 + ``` + ### Kind: `TLSOption` `TLSOption` is the CRD implementation of a [Traefik "TLS Option"](../../https/tls.md#tls-options). -Register the `TLSOption` kind in the Kubernetes cluster before creating `TLSOption` objects +Register the `TLSOption` [kind](../../reference/dynamic-configuration/kubernetes-crd.md#definitions) in the Kubernetes cluster before creating `TLSOption` objects or referencing TLS options in the [`IngressRoute`](#kind-ingressroute) / [`IngressRouteTCP`](#kind-ingressroutetcp) objects. !!! info "TLSOption Attributes" diff --git a/integration/fixtures/k8s/01-crd.yml b/integration/fixtures/k8s/01-crd.yml index f96f95c09..71a64b196 100644 --- a/integration/fixtures/k8s/01-crd.yml +++ b/integration/fixtures/k8s/01-crd.yml @@ -42,6 +42,21 @@ spec: singular: ingressroutetcp scope: Namespaced +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: ingressrouteudps.traefik.containo.us + +spec: + group: traefik.containo.us + version: v1alpha1 + names: + kind: IngressRouteUDP + plural: ingressrouteudps + singular: ingressrouteudp + scope: Namespaced + --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition diff --git a/integration/fixtures/k8s/02-services.yml b/integration/fixtures/k8s/02-services.yml index 4c3d933b6..e02661c7c 100644 --- a/integration/fixtures/k8s/02-services.yml +++ b/integration/fixtures/k8s/02-services.yml @@ -82,3 +82,47 @@ spec: selector: app: containous task: whoamitcp + +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: whoamiudp + namespace: default + labels: + app: containous + name: whoamiudp + +spec: + replicas: 2 + selector: + matchLabels: + app: containous + task: whoamiudp + template: + metadata: + labels: + app: containous + task: whoamiudp + spec: + containers: + - name: containouswhoamiudp + image: containous/whoamiudp:dev + ports: + - containerPort: 8090 + +--- +apiVersion: v1 +kind: Service +metadata: + name: whoamiudp + namespace: default + +spec: + ports: + - protocol: UDP + name: fooudp + port: 8090 + selector: + app: containous + task: whoamiudp diff --git a/integration/fixtures/k8s/05-ingressrouteudp.yml b/integration/fixtures/k8s/05-ingressrouteudp.yml new file mode 100644 index 000000000..535a9e4d4 --- /dev/null +++ b/integration/fixtures/k8s/05-ingressrouteudp.yml @@ -0,0 +1,14 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteUDP +metadata: + name: test3.route + namespace: default + +spec: + entryPoints: + - fooudp + routes: + - services: + - name: whoamiudp + namespace: default + port: 8090 diff --git a/integration/fixtures/k8s_crd.toml b/integration/fixtures/k8s_crd.toml index 21bfa9855..1f85c7822 100644 --- a/integration/fixtures/k8s_crd.toml +++ b/integration/fixtures/k8s_crd.toml @@ -10,6 +10,8 @@ [entryPoints] [entryPoints.footcp] address = ":8093" + [entryPoints.fooudp] + address = ":8090/udp" [entryPoints.web] address = ":8000" diff --git a/integration/testdata/rawdata-crd.json b/integration/testdata/rawdata-crd.json index 3aee24836..dcbfd135d 100644 --- a/integration/testdata/rawdata-crd.json +++ b/integration/testdata/rawdata-crd.json @@ -208,5 +208,35 @@ "default-test3.route-673acf455cb2dab0b43a@kubernetescrd" ] } + }, + "udpRouters": { + "default-test3.route-0@kubernetescrd": { + "entryPoints": [ + "fooudp" + ], + "service": "default-test3.route-0", + "status": "enabled", + "using": [ + "fooudp" + ] + } + }, + "udpServices": { + "default-test3.route-0@kubernetescrd": { + "loadBalancer": { + "servers": [ + { + "address": "10.42.0.4:8090" + }, + { + "address": "10.42.0.6:8090" + } + ] + }, + "status": "enabled", + "usedBy": [ + "default-test3.route-0@kubernetescrd" + ] + } } } \ No newline at end of file diff --git a/pkg/provider/kubernetes/crd/client.go b/pkg/provider/kubernetes/crd/client.go index b244643ea..de3be82c5 100644 --- a/pkg/provider/kubernetes/crd/client.go +++ b/pkg/provider/kubernetes/crd/client.go @@ -47,6 +47,7 @@ type Client interface { GetIngressRoutes() []*v1alpha1.IngressRoute GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP + GetIngressRouteUDPs() []*v1alpha1.IngressRouteUDP GetMiddlewares() []*v1alpha1.Middleware GetTraefikService(namespace, name string) (*v1alpha1.TraefikService, bool, error) GetTraefikServices() []*v1alpha1.TraefikService @@ -159,6 +160,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (< factoryCrd.Traefik().V1alpha1().IngressRoutes().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().Middlewares().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().IngressRouteTCPs().Informer().AddEventHandler(eventHandler) + factoryCrd.Traefik().V1alpha1().IngressRouteUDPs().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().TLSOptions().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().TLSStores().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().TraefikServices().Informer().AddEventHandler(eventHandler) @@ -231,6 +233,20 @@ func (c *clientWrapper) GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP { return result } +func (c *clientWrapper) GetIngressRouteUDPs() []*v1alpha1.IngressRouteUDP { + var result []*v1alpha1.IngressRouteUDP + + for ns, factory := range c.factoriesCrd { + ings, err := factory.Traefik().V1alpha1().IngressRouteUDPs().Lister().List(c.labelSelector) + if err != nil { + log.Errorf("Failed to list udp ingress routes in namespace %s: %v", ns, err) + } + result = append(result, ings...) + } + + return result +} + func (c *clientWrapper) GetMiddlewares() []*v1alpha1.Middleware { var result []*v1alpha1.Middleware diff --git a/pkg/provider/kubernetes/crd/client_mock_test.go b/pkg/provider/kubernetes/crd/client_mock_test.go index 8eb0538bf..5097120a3 100644 --- a/pkg/provider/kubernetes/crd/client_mock_test.go +++ b/pkg/provider/kubernetes/crd/client_mock_test.go @@ -32,6 +32,7 @@ type clientMock struct { ingressRoutes []*v1alpha1.IngressRoute ingressRouteTCPs []*v1alpha1.IngressRouteTCP + ingressRouteUDPs []*v1alpha1.IngressRouteUDP middlewares []*v1alpha1.Middleware tlsOptions []*v1alpha1.TLSOption tlsStores []*v1alpha1.TLSStore @@ -60,6 +61,8 @@ func newClientMock(paths ...string) clientMock { c.ingressRoutes = append(c.ingressRoutes, o) case *v1alpha1.IngressRouteTCP: c.ingressRouteTCPs = append(c.ingressRouteTCPs, o) + case *v1alpha1.IngressRouteUDP: + c.ingressRouteUDPs = append(c.ingressRouteUDPs, o) case *v1alpha1.Middleware: c.middlewares = append(c.middlewares, o) case *v1alpha1.TraefikService: @@ -87,6 +90,10 @@ func (c clientMock) GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP { return c.ingressRouteTCPs } +func (c clientMock) GetIngressRouteUDPs() []*v1alpha1.IngressRouteUDP { + return c.ingressRouteUDPs +} + func (c clientMock) GetMiddlewares() []*v1alpha1.Middleware { return c.middlewares } diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_identical_rules.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_identical_rules.yml new file mode 100644 index 000000000..b6e6108cd --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_identical_rules.yml @@ -0,0 +1,19 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteTCP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: HostSNI(`foo.com`) + services: + - name: whoamitcp + port: 8000 + - match: HostSNI(`foo.com`) + services: + - name: whoamitcp + port: 8000 diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/services.yml b/pkg/provider/kubernetes/crd/fixtures/udp/services.yml new file mode 100644 index 000000000..e29b194d4 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/udp/services.yml @@ -0,0 +1,103 @@ +apiVersion: v1 +kind: Service +metadata: + name: whoamiudp + namespace: default + +spec: + ports: + - name: myapp + port: 8000 + selector: + app: containous + task: whoamiudp + +--- +kind: Endpoints +apiVersion: v1 +metadata: + name: whoamiudp + namespace: default + +subsets: + - addresses: + - ip: 10.10.0.1 + - ip: 10.10.0.2 + ports: + - name: myapp + port: 8000 + +--- +apiVersion: v1 +kind: Service +metadata: + name: whoamiudp2 + namespace: default + +spec: + ports: + - name: myapp2 + port: 8080 + selector: + app: containous + task: whoamiudp2 + +--- +kind: Endpoints +apiVersion: v1 +metadata: + name: whoamiudp2 + namespace: default + +subsets: + - addresses: + - ip: 10.10.0.3 + - ip: 10.10.0.4 + ports: + - name: myapp2 + port: 8080 + +--- +apiVersion: v1 +kind: Service +metadata: + name: whoamiudp3 + namespace: ns3 + +spec: + ports: + - name: myapp3 + port: 8083 + selector: + app: containous + task: whoamiudp3 + +--- +kind: Endpoints +apiVersion: v1 +metadata: + name: whoamiudp3 + namespace: ns3 + +subsets: + - addresses: + - ip: 10.10.0.7 + - ip: 10.10.0.8 + ports: + - name: myapp3 + port: 8083 + +--- +kind: Endpoints +apiVersion: v1 +metadata: + name: whoamiudp3 + namespace: ns4 + +subsets: + - addresses: + - ip: 10.10.0.9 + - ip: 10.10.0.10 + ports: + - name: myapp4 + port: 8084 diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/simple.yml b/pkg/provider/kubernetes/crd/fixtures/udp/simple.yml new file mode 100644 index 000000000..f514d78a5 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/udp/simple.yml @@ -0,0 +1,14 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteUDP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - services: + - name: whoamiudp + port: 8000 diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_different_services_ns.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_different_services_ns.yml new file mode 100644 index 000000000..2943a9238 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_different_services_ns.yml @@ -0,0 +1,30 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteUDP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - services: + # without namespace + - name: whoamiudp + port: 8000 + weight: 2 + # with default namespace + - name: whoamiudp2 + namespace: default + port: 8080 + weight: 3 + # with custom namespace + - name: whoamiudp3 + namespace: ns3 + port: 8083 + weight: 4 + # with unknown namespace + - name: whoamiudp + namespace: unknwonns + port: 8080 diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_two_routes.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_two_routes.yml new file mode 100644 index 000000000..9abffc0d8 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_two_routes.yml @@ -0,0 +1,17 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteUDP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - services: + - name: whoamiudp + port: 8000 + - services: + - name: whoamiudp2 + port: 8080 diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_two_services.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_two_services.yml new file mode 100644 index 000000000..46bae5d8c --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_two_services.yml @@ -0,0 +1,18 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteUDP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - services: + - name: whoamiudp + port: 8000 + weight: 2 + - name: whoamiudp2 + port: 8080 + weight: 3 diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go new file mode 100644 index 000000000..efdbf8bc1 --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go @@ -0,0 +1,136 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeIngressRouteUDPs implements IngressRouteUDPInterface +type FakeIngressRouteUDPs struct { + Fake *FakeTraefikV1alpha1 + ns string +} + +var ingressrouteudpsResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "ingressrouteudps"} + +var ingressrouteudpsKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "IngressRouteUDP"} + +// Get takes name of the ingressRouteUDP, and returns the corresponding ingressRouteUDP object, and an error if there is any. +func (c *FakeIngressRouteUDPs) Get(name string, options v1.GetOptions) (result *v1alpha1.IngressRouteUDP, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(ingressrouteudpsResource, c.ns, name), &v1alpha1.IngressRouteUDP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IngressRouteUDP), err +} + +// List takes label and field selectors, and returns the list of IngressRouteUDPs that match those selectors. +func (c *FakeIngressRouteUDPs) List(opts v1.ListOptions) (result *v1alpha1.IngressRouteUDPList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(ingressrouteudpsResource, ingressrouteudpsKind, c.ns, opts), &v1alpha1.IngressRouteUDPList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.IngressRouteUDPList{ListMeta: obj.(*v1alpha1.IngressRouteUDPList).ListMeta} + for _, item := range obj.(*v1alpha1.IngressRouteUDPList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested ingressRouteUDPs. +func (c *FakeIngressRouteUDPs) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(ingressrouteudpsResource, c.ns, opts)) + +} + +// Create takes the representation of a ingressRouteUDP and creates it. Returns the server's representation of the ingressRouteUDP, and an error, if there is any. +func (c *FakeIngressRouteUDPs) Create(ingressRouteUDP *v1alpha1.IngressRouteUDP) (result *v1alpha1.IngressRouteUDP, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(ingressrouteudpsResource, c.ns, ingressRouteUDP), &v1alpha1.IngressRouteUDP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IngressRouteUDP), err +} + +// Update takes the representation of a ingressRouteUDP and updates it. Returns the server's representation of the ingressRouteUDP, and an error, if there is any. +func (c *FakeIngressRouteUDPs) Update(ingressRouteUDP *v1alpha1.IngressRouteUDP) (result *v1alpha1.IngressRouteUDP, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(ingressrouteudpsResource, c.ns, ingressRouteUDP), &v1alpha1.IngressRouteUDP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IngressRouteUDP), err +} + +// Delete takes name of the ingressRouteUDP and deletes it. Returns an error if one occurs. +func (c *FakeIngressRouteUDPs) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(ingressrouteudpsResource, c.ns, name), &v1alpha1.IngressRouteUDP{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeIngressRouteUDPs) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(ingressrouteudpsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.IngressRouteUDPList{}) + return err +} + +// Patch applies the patch and returns the patched ingressRouteUDP. +func (c *FakeIngressRouteUDPs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IngressRouteUDP, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(ingressrouteudpsResource, c.ns, name, pt, data, subresources...), &v1alpha1.IngressRouteUDP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IngressRouteUDP), err +} diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go index f07c74323..ff0fdea49 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go @@ -44,6 +44,10 @@ func (c *FakeTraefikV1alpha1) IngressRouteTCPs(namespace string) v1alpha1.Ingres return &FakeIngressRouteTCPs{c, namespace} } +func (c *FakeTraefikV1alpha1) IngressRouteUDPs(namespace string) v1alpha1.IngressRouteUDPInterface { + return &FakeIngressRouteUDPs{c, namespace} +} + func (c *FakeTraefikV1alpha1) Middlewares(namespace string) v1alpha1.MiddlewareInterface { return &FakeMiddlewares{c, namespace} } diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go index 10c2f1332..4568ff0ef 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go @@ -30,6 +30,8 @@ type IngressRouteExpansion interface{} type IngressRouteTCPExpansion interface{} +type IngressRouteUDPExpansion interface{} + type MiddlewareExpansion interface{} type TLSOptionExpansion interface{} diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go new file mode 100644 index 000000000..053b3e010 --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go @@ -0,0 +1,182 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + scheme "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// IngressRouteUDPsGetter has a method to return a IngressRouteUDPInterface. +// A group's client should implement this interface. +type IngressRouteUDPsGetter interface { + IngressRouteUDPs(namespace string) IngressRouteUDPInterface +} + +// IngressRouteUDPInterface has methods to work with IngressRouteUDP resources. +type IngressRouteUDPInterface interface { + Create(*v1alpha1.IngressRouteUDP) (*v1alpha1.IngressRouteUDP, error) + Update(*v1alpha1.IngressRouteUDP) (*v1alpha1.IngressRouteUDP, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.IngressRouteUDP, error) + List(opts v1.ListOptions) (*v1alpha1.IngressRouteUDPList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IngressRouteUDP, err error) + IngressRouteUDPExpansion +} + +// ingressRouteUDPs implements IngressRouteUDPInterface +type ingressRouteUDPs struct { + client rest.Interface + ns string +} + +// newIngressRouteUDPs returns a IngressRouteUDPs +func newIngressRouteUDPs(c *TraefikV1alpha1Client, namespace string) *ingressRouteUDPs { + return &ingressRouteUDPs{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the ingressRouteUDP, and returns the corresponding ingressRouteUDP object, and an error if there is any. +func (c *ingressRouteUDPs) Get(name string, options v1.GetOptions) (result *v1alpha1.IngressRouteUDP, err error) { + result = &v1alpha1.IngressRouteUDP{} + err = c.client.Get(). + Namespace(c.ns). + Resource("ingressrouteudps"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of IngressRouteUDPs that match those selectors. +func (c *ingressRouteUDPs) List(opts v1.ListOptions) (result *v1alpha1.IngressRouteUDPList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.IngressRouteUDPList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("ingressrouteudps"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested ingressRouteUDPs. +func (c *ingressRouteUDPs) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("ingressrouteudps"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a ingressRouteUDP and creates it. Returns the server's representation of the ingressRouteUDP, and an error, if there is any. +func (c *ingressRouteUDPs) Create(ingressRouteUDP *v1alpha1.IngressRouteUDP) (result *v1alpha1.IngressRouteUDP, err error) { + result = &v1alpha1.IngressRouteUDP{} + err = c.client.Post(). + Namespace(c.ns). + Resource("ingressrouteudps"). + Body(ingressRouteUDP). + Do(). + Into(result) + return +} + +// Update takes the representation of a ingressRouteUDP and updates it. Returns the server's representation of the ingressRouteUDP, and an error, if there is any. +func (c *ingressRouteUDPs) Update(ingressRouteUDP *v1alpha1.IngressRouteUDP) (result *v1alpha1.IngressRouteUDP, err error) { + result = &v1alpha1.IngressRouteUDP{} + err = c.client.Put(). + Namespace(c.ns). + Resource("ingressrouteudps"). + Name(ingressRouteUDP.Name). + Body(ingressRouteUDP). + Do(). + Into(result) + return +} + +// Delete takes name of the ingressRouteUDP and deletes it. Returns an error if one occurs. +func (c *ingressRouteUDPs) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("ingressrouteudps"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *ingressRouteUDPs) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("ingressrouteudps"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched ingressRouteUDP. +func (c *ingressRouteUDPs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IngressRouteUDP, err error) { + result = &v1alpha1.IngressRouteUDP{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("ingressrouteudps"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go index f9063c83a..42bba3996 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go @@ -36,6 +36,7 @@ type TraefikV1alpha1Interface interface { RESTClient() rest.Interface IngressRoutesGetter IngressRouteTCPsGetter + IngressRouteUDPsGetter MiddlewaresGetter TLSOptionsGetter TLSStoresGetter @@ -55,6 +56,10 @@ func (c *TraefikV1alpha1Client) IngressRouteTCPs(namespace string) IngressRouteT return newIngressRouteTCPs(c, namespace) } +func (c *TraefikV1alpha1Client) IngressRouteUDPs(namespace string) IngressRouteUDPInterface { + return newIngressRouteUDPs(c, namespace) +} + func (c *TraefikV1alpha1Client) Middlewares(namespace string) MiddlewareInterface { return newMiddlewares(c, namespace) } diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go index 13c31bbb4..0513a3dff 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go @@ -65,6 +65,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().IngressRoutes().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("ingressroutetcps"): return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().IngressRouteTCPs().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("ingressrouteudps"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().IngressRouteUDPs().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("middlewares"): return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().Middlewares().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("tlsoptions"): diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go new file mode 100644 index 000000000..acc91b043 --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go @@ -0,0 +1,97 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + versioned "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1" + traefikv1alpha1 "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// IngressRouteUDPInformer provides access to a shared informer and lister for +// IngressRouteUDPs. +type IngressRouteUDPInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.IngressRouteUDPLister +} + +type ingressRouteUDPInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewIngressRouteUDPInformer constructs a new informer for IngressRouteUDP type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewIngressRouteUDPInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredIngressRouteUDPInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredIngressRouteUDPInformer constructs a new informer for IngressRouteUDP type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredIngressRouteUDPInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TraefikV1alpha1().IngressRouteUDPs(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TraefikV1alpha1().IngressRouteUDPs(namespace).Watch(options) + }, + }, + &traefikv1alpha1.IngressRouteUDP{}, + resyncPeriod, + indexers, + ) +} + +func (f *ingressRouteUDPInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredIngressRouteUDPInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *ingressRouteUDPInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&traefikv1alpha1.IngressRouteUDP{}, f.defaultInformer) +} + +func (f *ingressRouteUDPInformer) Lister() v1alpha1.IngressRouteUDPLister { + return v1alpha1.NewIngressRouteUDPLister(f.Informer().GetIndexer()) +} diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go index 13fb193a4..31d683e23 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go @@ -36,6 +36,8 @@ type Interface interface { IngressRoutes() IngressRouteInformer // IngressRouteTCPs returns a IngressRouteTCPInformer. IngressRouteTCPs() IngressRouteTCPInformer + // IngressRouteUDPs returns a IngressRouteUDPInformer. + IngressRouteUDPs() IngressRouteUDPInformer // Middlewares returns a MiddlewareInformer. Middlewares() MiddlewareInformer // TLSOptions returns a TLSOptionInformer. @@ -67,6 +69,11 @@ func (v *version) IngressRouteTCPs() IngressRouteTCPInformer { return &ingressRouteTCPInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// IngressRouteUDPs returns a IngressRouteUDPInformer. +func (v *version) IngressRouteUDPs() IngressRouteUDPInformer { + return &ingressRouteUDPInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // Middlewares returns a MiddlewareInformer. func (v *version) Middlewares() MiddlewareInformer { return &middlewareInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go index d42d1051a..f1137d956 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go @@ -42,6 +42,14 @@ type IngressRouteTCPListerExpansion interface{} // IngressRouteTCPNamespaceLister. type IngressRouteTCPNamespaceListerExpansion interface{} +// IngressRouteUDPListerExpansion allows custom methods to be added to +// IngressRouteUDPLister. +type IngressRouteUDPListerExpansion interface{} + +// IngressRouteUDPNamespaceListerExpansion allows custom methods to be added to +// IngressRouteUDPNamespaceLister. +type IngressRouteUDPNamespaceListerExpansion interface{} + // MiddlewareListerExpansion allows custom methods to be added to // MiddlewareLister. type MiddlewareListerExpansion interface{} diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go new file mode 100644 index 000000000..0d9eef69f --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go @@ -0,0 +1,102 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// IngressRouteUDPLister helps list IngressRouteUDPs. +type IngressRouteUDPLister interface { + // List lists all IngressRouteUDPs in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.IngressRouteUDP, err error) + // IngressRouteUDPs returns an object that can list and get IngressRouteUDPs. + IngressRouteUDPs(namespace string) IngressRouteUDPNamespaceLister + IngressRouteUDPListerExpansion +} + +// ingressRouteUDPLister implements the IngressRouteUDPLister interface. +type ingressRouteUDPLister struct { + indexer cache.Indexer +} + +// NewIngressRouteUDPLister returns a new IngressRouteUDPLister. +func NewIngressRouteUDPLister(indexer cache.Indexer) IngressRouteUDPLister { + return &ingressRouteUDPLister{indexer: indexer} +} + +// List lists all IngressRouteUDPs in the indexer. +func (s *ingressRouteUDPLister) List(selector labels.Selector) (ret []*v1alpha1.IngressRouteUDP, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.IngressRouteUDP)) + }) + return ret, err +} + +// IngressRouteUDPs returns an object that can list and get IngressRouteUDPs. +func (s *ingressRouteUDPLister) IngressRouteUDPs(namespace string) IngressRouteUDPNamespaceLister { + return ingressRouteUDPNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// IngressRouteUDPNamespaceLister helps list and get IngressRouteUDPs. +type IngressRouteUDPNamespaceLister interface { + // List lists all IngressRouteUDPs in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.IngressRouteUDP, err error) + // Get retrieves the IngressRouteUDP from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.IngressRouteUDP, error) + IngressRouteUDPNamespaceListerExpansion +} + +// ingressRouteUDPNamespaceLister implements the IngressRouteUDPNamespaceLister +// interface. +type ingressRouteUDPNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all IngressRouteUDPs in the indexer for a given namespace. +func (s ingressRouteUDPNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.IngressRouteUDP, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.IngressRouteUDP)) + }) + return ret, err +} + +// Get retrieves the IngressRouteUDP from the indexer for a given namespace and name. +func (s ingressRouteUDPNamespaceLister) Get(name string) (*v1alpha1.IngressRouteUDP, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("ingressrouteudp"), name) + } + return obj.(*v1alpha1.IngressRouteUDP), nil +} diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 148acb307..7820336e4 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -168,6 +168,7 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) conf := &dynamic.Configuration{ HTTP: p.loadIngressRouteConfiguration(ctx, client, tlsConfigs), TCP: p.loadIngressRouteTCPConfiguration(ctx, client, tlsConfigs), + UDP: p.loadIngressRouteUDPConfiguration(ctx, client), TLS: &dynamic.TLSConfiguration{ Certificates: getTLSConfig(tlsConfigs), Options: buildTLSOptions(ctx, client), diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go index 63e56d84c..376057bfc 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_test.go +++ b/pkg/provider/kubernetes/crd/kubernetes_test.go @@ -25,6 +25,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { { desc: "Empty", expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -41,6 +45,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "Simple Ingress Route, with foo entrypoint", paths: []string{"tcp/services.yml", "tcp/simple.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, Middlewares: map[string]*dynamic.Middleware{}, @@ -78,6 +86,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "One ingress Route with two different rules", paths: []string{"tcp/services.yml", "tcp/with_two_rules.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ "default-test.route-fdd3e9338e47a45efefc": { @@ -130,10 +142,55 @@ func TestLoadIngressRouteTCPs(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "One ingress Route with two identical rules", + paths: []string{"tcp/services.yml", "tcp/with_two_identical_rules.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-test.route-fdd3e9338e47a45efefc": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-fdd3e9338e47a45efefc", + Rule: "HostSNI(`foo.com`)", + }, + }, + Services: map[string]*dynamic.TCPService{ + "default-test.route-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + Port: "", + }, + { + Address: "10.10.0.2:8000", + Port: "", + }, + }, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, { desc: "One ingress Route with two different services", paths: []string{"tcp/services.yml", "tcp/with_two_services.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ "default-test.route-fdd3e9338e47a45efefc": { @@ -195,6 +252,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "One ingress Route with different services namespaces", paths: []string{"tcp/services.yml", "tcp/with_different_services_ns.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ "default-test.route-fdd3e9338e47a45efefc": { @@ -273,6 +334,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { paths: []string{"tcp/services.yml", "tcp/simple.yml"}, ingressClass: "tchouk", expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -289,6 +354,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "Route with empty rule value is ignored", paths: []string{"tcp/services.yml", "tcp/with_no_rule_value.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -305,6 +374,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "check rule quoting validity", paths: []string{"tcp/services.yml", "tcp/with_bad_host_rule.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -321,6 +394,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS", paths: []string{"tcp/services.yml", "tcp/with_tls.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Certificates: []*tls.CertAndStores{ { @@ -368,6 +445,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with passthrough", paths: []string{"tcp/services.yml", "tcp/with_tls_passthrough.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ "default-test.route-fdd3e9338e47a45efefc": { @@ -408,6 +489,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with tls options", paths: []string{"tcp/services.yml", "tcp/with_tls_options.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "default-foo": { @@ -467,6 +552,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with tls options and specific namespace", paths: []string{"tcp/services.yml", "tcp/with_tls_options_and_specific_namespace.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "myns-foo": { @@ -525,6 +614,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with bad tls options", paths: []string{"tcp/services.yml", "tcp/with_bad_tls_options.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "default-foo": { @@ -582,6 +675,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with unknown tls options", paths: []string{"tcp/services.yml", "tcp/with_unknown_tls_options.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "default-foo": { @@ -628,6 +725,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with unknown tls options namespace", paths: []string{"tcp/services.yml", "tcp/with_unknown_tls_options_namespace.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "default-foo": { @@ -674,6 +775,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with ACME", paths: []string{"tcp/services.yml", "tcp/with_tls_acme.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ "default-test.route-fdd3e9338e47a45efefc": { @@ -713,6 +818,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { paths: []string{"tcp/services.yml", "tcp/with_termination_delay.yml"}, expected: &dynamic.Configuration{ TLS: &dynamic.TLSConfiguration{}, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ "default-test.route-fdd3e9338e47a45efefc": { @@ -786,6 +895,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, Middlewares: map[string]*dynamic.Middleware{}, @@ -822,6 +935,10 @@ func TestLoadIngressRoutes(t *testing.T) { { desc: "Empty", expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -838,6 +955,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Simple Ingress Route, with foo entrypoint", paths: []string{"services.yml", "simple.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -875,6 +996,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Simple Ingress Route with middleware", paths: []string{"services.yml", "with_middleware.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -924,6 +1049,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Simple Ingress Route with middleware crossprovider", paths: []string{"services.yml", "with_middleware_crossprovider.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -973,6 +1102,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "One ingress Route with two different rules", paths: []string{"services.yml", "with_two_rules.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -1029,6 +1162,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "One ingress Route with two different services", paths: []string{"services.yml", "with_two_services.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1093,6 +1230,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "one kube service (== servers lb) in a services wrr", paths: []string{"with_services_lb0.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1140,6 +1281,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "traefik service without ingress route", paths: []string{"with_services_only.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1180,6 +1325,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "One ingress Route with two different services, each with two services, balancing servers nested", paths: []string{"with_services_lb1.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1298,6 +1447,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "one wrr and one kube service (== servers lb) in a wrr", paths: []string{"with_services_lb2.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1359,6 +1512,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "services lb, servers lb, and mirror service, all in a wrr", paths: []string{"with_services_lb3.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1445,6 +1602,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "services lb, servers lb, and mirror service, all in a wrr with different namespaces", paths: []string{"with_namespaces.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1617,6 +1778,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "one kube service (== servers lb) in a mirroring", paths: []string{"with_mirroring.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1675,6 +1840,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "weighted services in a mirroring", paths: []string{"with_mirroring2.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1753,6 +1922,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "One ingress Route with two different services, with weights", paths: []string{"services.yml", "with_two_services_weight.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1818,6 +1991,10 @@ func TestLoadIngressRoutes(t *testing.T) { paths: []string{"services.yml", "simple.yml"}, ingressClass: "tchouk", expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1834,6 +2011,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Route with empty rule value is ignored", paths: []string{"services.yml", "with_no_rule_value.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1850,6 +2031,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Route with kind not of a rule type (empty kind) is ignored", paths: []string{"services.yml", "with_wrong_rule_kind.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1866,6 +2051,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "check rule quoting validity", paths: []string{"services.yml", "with_bad_host_rule.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -1882,6 +2071,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS", paths: []string{"services.yml", "with_tls.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Certificates: []*tls.CertAndStores{ { @@ -1929,6 +2122,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with tls options", paths: []string{"services.yml", "with_tls_options.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "default-foo": { @@ -1988,6 +2185,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with two default tls options", paths: []string{"services.yml", "with_default_tls_options.yml", "with_default_tls_options_default_namespace.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{}, }, @@ -2050,6 +2251,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, }, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -2089,6 +2294,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with tls options and specific namespace", paths: []string{"services.yml", "with_tls_options_and_specific_namespace.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "myns-foo": { @@ -2147,6 +2356,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with bad tls options", paths: []string{"services.yml", "with_bad_tls_options.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "default-foo": { @@ -2204,6 +2417,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with unknown tls options", paths: []string{"services.yml", "with_unknown_tls_options.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "default-foo": { @@ -2250,6 +2467,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with unknown tls options namespace", paths: []string{"services.yml", "with_unknown_tls_options_namespace.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ "default-foo": { @@ -2296,6 +2517,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with ACME", paths: []string{"services.yml", "with_tls_acme.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -2334,6 +2559,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Simple Ingress Route, defaulting to https for servers", paths: []string{"services.yml", "with_https_default.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -2371,6 +2600,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Simple Ingress Route, explicit https scheme", paths: []string{"services.yml", "with_https_scheme.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -2408,6 +2641,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Simple Ingress Route, with basic auth middleware", paths: []string{"services.yml", "with_auth.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -2445,6 +2682,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Simple Ingress Route, with error page middleware", paths: []string{"services.yml", "with_error_page.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, @@ -2483,6 +2724,10 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Simple Ingress Route, with options", paths: []string{"services.yml", "with_options.yml"}, expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -2531,6 +2776,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, }, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -2571,6 +2820,10 @@ func TestLoadIngressRoutes(t *testing.T) { TLS: &dynamic.TLSConfiguration{ Stores: map[string]tls.Store{}, }, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}, @@ -2625,3 +2878,311 @@ func TestLoadIngressRoutes(t *testing.T) { }) } } + +func TestLoadIngressRouteUDPs(t *testing.T) { + testCases := []struct { + desc string + ingressClass string + paths []string + expected *dynamic.Configuration + }{ + { + desc: "Empty", + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "Simple Ingress Route, with foo entrypoint", + paths: []string{"udp/services.yml", "udp/simple.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{ + "default-test.route-0": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-0", + }, + }, + Services: map[string]*dynamic.UDPService{ + "default-test.route-0": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.1:8000", + Port: "", + }, + { + Address: "10.10.0.2:8000", + Port: "", + }, + }, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Services: map[string]*dynamic.TCPService{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "One ingress Route with two different routes", + paths: []string{"udp/services.yml", "udp/with_two_routes.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{ + "default-test.route-0": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-0", + }, + "default-test.route-1": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-1", + }, + }, + Services: map[string]*dynamic.UDPService{ + "default-test.route-0": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.1:8000", + Port: "", + }, + { + Address: "10.10.0.2:8000", + Port: "", + }, + }, + }, + }, + "default-test.route-1": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.3:8080", + Port: "", + }, + { + Address: "10.10.0.4:8080", + Port: "", + }, + }, + }, + }, + }, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "One ingress Route with two different services", + paths: []string{"udp/services.yml", "udp/with_two_services.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{ + "default-test.route-0": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-0", + }, + }, + Services: map[string]*dynamic.UDPService{ + "default-test.route-0": { + Weighted: &dynamic.UDPWeightedRoundRobin{ + Services: []dynamic.UDPWRRService{ + { + Name: "default-test.route-0-whoamiudp-8000", + Weight: func(i int) *int { return &i }(2), + }, + { + Name: "default-test.route-0-whoamiudp2-8080", + Weight: func(i int) *int { return &i }(3), + }, + }, + }, + }, + "default-test.route-0-whoamiudp-8000": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + }, + }, + "default-test.route-0-whoamiudp2-8080": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.3:8080", + }, + { + Address: "10.10.0.4:8080", + }, + }, + }, + }, + }, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "One ingress Route with different services namespaces", + paths: []string{"udp/services.yml", "udp/with_different_services_ns.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{ + "default-test.route-0": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-0", + }, + }, + Services: map[string]*dynamic.UDPService{ + "default-test.route-0": { + Weighted: &dynamic.UDPWeightedRoundRobin{ + Services: []dynamic.UDPWRRService{ + { + Name: "default-test.route-0-whoamiudp-8000", + Weight: func(i int) *int { return &i }(2), + }, + { + Name: "default-test.route-0-whoamiudp2-8080", + Weight: func(i int) *int { return &i }(3), + }, + { + Name: "default-test.route-0-whoamiudp3-8083", + Weight: func(i int) *int { return &i }(4), + }, + }, + }, + }, + "default-test.route-0-whoamiudp-8000": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + }, + }, + "default-test.route-0-whoamiudp2-8080": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.3:8080", + }, + { + Address: "10.10.0.4:8080", + }, + }, + }, + }, + "default-test.route-0-whoamiudp3-8083": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.7:8083", + }, + { + Address: "10.10.0.8:8083", + }, + }, + }, + }, + }, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "Ingress class does not match", + paths: []string{"udp/services.yml", "udp/simple.yml"}, + ingressClass: "tchouk", + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + } + + for _, test := range testCases { + test := test + + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + if test.expected == nil { + return + } + + p := Provider{IngressClass: test.ingressClass} + conf := p.loadConfigurationFromCRD(context.Background(), newClientMock(test.paths...)) + assert.Equal(t, test.expected, conf) + }) + } +} diff --git a/pkg/provider/kubernetes/crd/kubernetes_udp.go b/pkg/provider/kubernetes/crd/kubernetes_udp.go new file mode 100644 index 000000000..9ff4706ec --- /dev/null +++ b/pkg/provider/kubernetes/crd/kubernetes_udp.go @@ -0,0 +1,161 @@ +package crd + +import ( + "context" + "errors" + "fmt" + + "github.com/containous/traefik/v2/pkg/config/dynamic" + "github.com/containous/traefik/v2/pkg/log" + "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + corev1 "k8s.io/api/core/v1" +) + +func (p *Provider) loadIngressRouteUDPConfiguration(ctx context.Context, client Client) *dynamic.UDPConfiguration { + conf := &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + } + + for _, ingressRouteUDP := range client.GetIngressRouteUDPs() { + logger := log.FromContext(log.With(ctx, log.Str("ingress", ingressRouteUDP.Name), log.Str("namespace", ingressRouteUDP.Namespace))) + + if !shouldProcessIngress(p.IngressClass, ingressRouteUDP.Annotations[annotationKubernetesIngressClass]) { + continue + } + + ingressName := ingressRouteUDP.Name + if len(ingressName) == 0 { + ingressName = ingressRouteUDP.GenerateName + } + + for i, route := range ingressRouteUDP.Spec.Routes { + key := fmt.Sprintf("%s-%d", ingressName, i) + serviceName := makeID(ingressRouteUDP.Namespace, key) + + for _, service := range route.Services { + balancerServerUDP, err := createLoadBalancerServerUDP(client, ingressRouteUDP.Namespace, service) + if err != nil { + logger. + WithField("serviceName", service.Name). + WithField("servicePort", service.Port). + Errorf("Cannot create service: %v", err) + continue + } + + // If there is only one service defined, we skip the creation of the load balancer of services, + // i.e. the service on top is directly a load balancer of servers. + if len(route.Services) == 1 { + conf.Services[serviceName] = balancerServerUDP + break + } + + serviceKey := fmt.Sprintf("%s-%s-%d", serviceName, service.Name, service.Port) + conf.Services[serviceKey] = balancerServerUDP + + srv := dynamic.UDPWRRService{Name: serviceKey} + srv.SetDefaults() + if service.Weight != nil { + srv.Weight = service.Weight + } + + if conf.Services[serviceName] == nil { + conf.Services[serviceName] = &dynamic.UDPService{Weighted: &dynamic.UDPWeightedRoundRobin{}} + } + conf.Services[serviceName].Weighted.Services = append(conf.Services[serviceName].Weighted.Services, srv) + } + + conf.Routers[serviceName] = &dynamic.UDPRouter{ + EntryPoints: ingressRouteUDP.Spec.EntryPoints, + Service: serviceName, + } + } + } + + return conf +} + +func createLoadBalancerServerUDP(client Client, namespace string, service v1alpha1.ServiceUDP) (*dynamic.UDPService, error) { + ns := namespace + if len(service.Namespace) > 0 { + ns = service.Namespace + } + + servers, err := loadUDPServers(client, ns, service) + if err != nil { + return nil, err + } + + udpService := &dynamic.UDPService{ + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: servers, + }, + } + + return udpService, nil +} + +func loadUDPServers(client Client, namespace string, svc v1alpha1.ServiceUDP) ([]dynamic.UDPServer, error) { + service, exists, err := client.GetService(namespace, svc.Name) + if err != nil { + return nil, err + } + + if !exists { + return nil, errors.New("service not found") + } + + var portSpec *corev1.ServicePort + for _, p := range service.Spec.Ports { + if svc.Port == p.Port { + portSpec = &p + break + } + } + + if portSpec == nil { + return nil, errors.New("service port not found") + } + + var servers []dynamic.UDPServer + if service.Spec.Type == corev1.ServiceTypeExternalName { + servers = append(servers, dynamic.UDPServer{ + Address: fmt.Sprintf("%s:%d", service.Spec.ExternalName, portSpec.Port), + }) + } else { + endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, svc.Name) + if endpointsErr != nil { + return nil, endpointsErr + } + + if !endpointsExists { + return nil, errors.New("endpoints not found") + } + + if len(endpoints.Subsets) == 0 { + return nil, errors.New("subset not found") + } + + var port int32 + for _, subset := range endpoints.Subsets { + for _, p := range subset.Ports { + if portSpec.Name == p.Name { + port = p.Port + break + } + } + + if port == 0 { + return nil, errors.New("cannot define a port") + } + + for _, addr := range subset.Addresses { + servers = append(servers, dynamic.UDPServer{ + Address: fmt.Sprintf("%s:%d", addr.IP, port), + }) + } + } + } + + return servers, nil +} diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressrouteudp.go new file mode 100644 index 000000000..509de5b3c --- /dev/null +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressrouteudp.go @@ -0,0 +1,50 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// IngressRouteUDPSpec is a specification for a IngressRouteUDPSpec resource. +type IngressRouteUDPSpec struct { + Routes []RouteUDP `json:"routes"` + EntryPoints []string `json:"entryPoints"` +} + +// RouteUDP contains the set of routes. +type RouteUDP struct { + Services []ServiceUDP `json:"services,omitempty"` +} + +// TLSOptionUDPRef is a ref to the TLSOption resources. +type TLSOptionUDPRef struct { + Name string `json:"name"` + Namespace string `json:"namespace"` +} + +// ServiceUDP defines an upstream to proxy traffic. +type ServiceUDP struct { + Name string `json:"name"` + Namespace string `json:"namespace"` + Port int32 `json:"port"` + Weight *int `json:"weight,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// IngressRouteUDP is an Ingress CRD specification. +type IngressRouteUDP struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + + Spec IngressRouteUDPSpec `json:"spec"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// IngressRouteUDPList is a list of IngressRoutes. +type IngressRouteUDPList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []IngressRouteUDP `json:"items"` +} diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go index b8de2058b..79c796129 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go @@ -37,6 +37,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &IngressRouteList{}, &IngressRouteTCP{}, &IngressRouteTCPList{}, + &IngressRouteUDP{}, + &IngressRouteUDPList{}, &Middleware{}, &MiddlewareList{}, &TLSOption{}, diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go index 5590ee372..b1d58417a 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go @@ -397,6 +397,94 @@ func (in *IngressRouteTCPSpec) DeepCopy() *IngressRouteTCPSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IngressRouteUDP) DeepCopyInto(out *IngressRouteUDP) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteUDP. +func (in *IngressRouteUDP) DeepCopy() *IngressRouteUDP { + if in == nil { + return nil + } + out := new(IngressRouteUDP) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IngressRouteUDP) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IngressRouteUDPList) DeepCopyInto(out *IngressRouteUDPList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]IngressRouteUDP, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteUDPList. +func (in *IngressRouteUDPList) DeepCopy() *IngressRouteUDPList { + if in == nil { + return nil + } + out := new(IngressRouteUDPList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IngressRouteUDPList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IngressRouteUDPSpec) DeepCopyInto(out *IngressRouteUDPSpec) { + *out = *in + if in.Routes != nil { + in, out := &in.Routes, &out.Routes + *out = make([]RouteUDP, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EntryPoints != nil { + in, out := &in.EntryPoints, &out.EntryPoints + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressRouteUDPSpec. +func (in *IngressRouteUDPSpec) DeepCopy() *IngressRouteUDPSpec { + if in == nil { + return nil + } + out := new(IngressRouteUDPSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancerSpec) DeepCopyInto(out *LoadBalancerSpec) { *out = *in @@ -732,6 +820,29 @@ func (in *RouteTCP) DeepCopy() *RouteTCP { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteUDP) DeepCopyInto(out *RouteUDP) { + *out = *in + if in.Services != nil { + in, out := &in.Services, &out.Services + *out = make([]ServiceUDP, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteUDP. +func (in *RouteUDP) DeepCopy() *RouteUDP { + if in == nil { + return nil + } + out := new(RouteUDP) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Service) DeepCopyInto(out *Service) { *out = *in @@ -801,6 +912,27 @@ func (in *ServiceTCP) DeepCopy() *ServiceTCP { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceUDP) DeepCopyInto(out *ServiceUDP) { + *out = *in + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(int) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceUDP. +func (in *ServiceUDP) DeepCopy() *ServiceUDP { + if in == nil { + return nil + } + out := new(ServiceUDP) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLS) DeepCopyInto(out *TLS) { *out = *in @@ -953,6 +1085,22 @@ func (in *TLSOptionTCPRef) DeepCopy() *TLSOptionTCPRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSOptionUDPRef) DeepCopyInto(out *TLSOptionUDPRef) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSOptionUDPRef. +func (in *TLSOptionUDPRef) DeepCopy() *TLSOptionUDPRef { + if in == nil { + return nil + } + out := new(TLSOptionUDPRef) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSStore) DeepCopyInto(out *TLSStore) { *out = *in diff --git a/pkg/provider/kubernetes/k8s/parser.go b/pkg/provider/kubernetes/k8s/parser.go index f3aa25666..e0d662b5e 100644 --- a/pkg/provider/kubernetes/k8s/parser.go +++ b/pkg/provider/kubernetes/k8s/parser.go @@ -12,7 +12,7 @@ import ( // MustParseYaml parses a YAML to objects. func MustParseYaml(content []byte) []runtime.Object { - acceptedK8sTypes := regexp.MustCompile(`^(Deployment|Endpoints|Service|Ingress|IngressRoute|IngressRouteTCP|Middleware|Secret|TLSOption|TLSStore|TraefikService)$`) + acceptedK8sTypes := regexp.MustCompile(`^(Deployment|Endpoints|Service|Ingress|IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|Secret|TLSOption|TLSStore|TraefikService)$`) files := strings.Split(string(content), "---") retVal := make([]runtime.Object, 0, len(files))