1
0
Fork 0

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

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