Add UDP support in kubernetesCRD provider

Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
This commit is contained in:
Jean-Baptiste Doumenjou 2020-02-26 12:28:05 +01:00 committed by GitHub
parent 98f304f8b0
commit 665aeb34b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 2041 additions and 366 deletions

View file

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

View file

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

View file

@ -35,6 +35,7 @@ rules:
- ingressroutes
- traefikservices
- ingressroutetcps
- ingressrouteudps
- tlsoptions
verbs:
- get

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,6 +10,8 @@
[entryPoints]
[entryPoints.footcp]
address = ":8093"
[entryPoints.fooudp]
address = ":8090/udp"
[entryPoints.web]
address = ":8000"

View file

@ -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"
]
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -30,6 +30,8 @@ type IngressRouteExpansion interface{}
type IngressRouteTCPExpansion interface{}
type IngressRouteUDPExpansion interface{}
type MiddlewareExpansion interface{}
type TLSOptionExpansion interface{}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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"`
}

View file

@ -37,6 +37,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&IngressRouteList{},
&IngressRouteTCP{},
&IngressRouteTCPList{},
&IngressRouteUDP{},
&IngressRouteUDPList{},
&Middleware{},
&MiddlewareList{},
&TLSOption{},

View file

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

View file

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