Reintroduce dropped v2 dynamic config
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
This commit is contained in:
parent
18203f57d2
commit
40de310927
53 changed files with 880 additions and 392 deletions
|
@ -1,196 +0,0 @@
|
|||
package crd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
|
||||
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
)
|
||||
|
||||
var _ Client = (*clientMock)(nil)
|
||||
|
||||
func init() {
|
||||
// required by k8s.MustParseYaml
|
||||
err := traefikv1alpha1.AddToScheme(kscheme.Scheme)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type clientMock struct {
|
||||
services []*corev1.Service
|
||||
secrets []*corev1.Secret
|
||||
endpoints []*corev1.Endpoints
|
||||
|
||||
apiServiceError error
|
||||
apiSecretError error
|
||||
apiEndpointsError error
|
||||
|
||||
ingressRoutes []*traefikv1alpha1.IngressRoute
|
||||
ingressRouteTCPs []*traefikv1alpha1.IngressRouteTCP
|
||||
ingressRouteUDPs []*traefikv1alpha1.IngressRouteUDP
|
||||
middlewares []*traefikv1alpha1.Middleware
|
||||
middlewareTCPs []*traefikv1alpha1.MiddlewareTCP
|
||||
tlsOptions []*traefikv1alpha1.TLSOption
|
||||
tlsStores []*traefikv1alpha1.TLSStore
|
||||
traefikServices []*traefikv1alpha1.TraefikService
|
||||
serversTransports []*traefikv1alpha1.ServersTransport
|
||||
serversTransportTCPs []*traefikv1alpha1.ServersTransportTCP
|
||||
|
||||
watchChan chan interface{}
|
||||
}
|
||||
|
||||
func newClientMock(paths ...string) clientMock {
|
||||
var c clientMock
|
||||
|
||||
for _, path := range paths {
|
||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
k8sObjects := k8s.MustParseYaml(yamlContent)
|
||||
for _, obj := range k8sObjects {
|
||||
switch o := obj.(type) {
|
||||
case *corev1.Service:
|
||||
c.services = append(c.services, o)
|
||||
case *corev1.Endpoints:
|
||||
c.endpoints = append(c.endpoints, o)
|
||||
case *traefikv1alpha1.IngressRoute:
|
||||
c.ingressRoutes = append(c.ingressRoutes, o)
|
||||
case *traefikv1alpha1.IngressRouteTCP:
|
||||
c.ingressRouteTCPs = append(c.ingressRouteTCPs, o)
|
||||
case *traefikv1alpha1.IngressRouteUDP:
|
||||
c.ingressRouteUDPs = append(c.ingressRouteUDPs, o)
|
||||
case *traefikv1alpha1.Middleware:
|
||||
c.middlewares = append(c.middlewares, o)
|
||||
case *traefikv1alpha1.MiddlewareTCP:
|
||||
c.middlewareTCPs = append(c.middlewareTCPs, o)
|
||||
case *traefikv1alpha1.TraefikService:
|
||||
c.traefikServices = append(c.traefikServices, o)
|
||||
case *traefikv1alpha1.TLSOption:
|
||||
c.tlsOptions = append(c.tlsOptions, o)
|
||||
case *traefikv1alpha1.ServersTransport:
|
||||
c.serversTransports = append(c.serversTransports, o)
|
||||
case *traefikv1alpha1.ServersTransportTCP:
|
||||
c.serversTransportTCPs = append(c.serversTransportTCPs, o)
|
||||
case *traefikv1alpha1.TLSStore:
|
||||
c.tlsStores = append(c.tlsStores, o)
|
||||
case *corev1.Secret:
|
||||
c.secrets = append(c.secrets, o)
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c clientMock) GetIngressRoutes() []*traefikv1alpha1.IngressRoute {
|
||||
return c.ingressRoutes
|
||||
}
|
||||
|
||||
func (c clientMock) GetIngressRouteTCPs() []*traefikv1alpha1.IngressRouteTCP {
|
||||
return c.ingressRouteTCPs
|
||||
}
|
||||
|
||||
func (c clientMock) GetIngressRouteUDPs() []*traefikv1alpha1.IngressRouteUDP {
|
||||
return c.ingressRouteUDPs
|
||||
}
|
||||
|
||||
func (c clientMock) GetMiddlewares() []*traefikv1alpha1.Middleware {
|
||||
return c.middlewares
|
||||
}
|
||||
|
||||
func (c clientMock) GetMiddlewareTCPs() []*traefikv1alpha1.MiddlewareTCP {
|
||||
return c.middlewareTCPs
|
||||
}
|
||||
|
||||
func (c clientMock) GetTraefikService(namespace, name string) (*traefikv1alpha1.TraefikService, bool, error) {
|
||||
for _, svc := range c.traefikServices {
|
||||
if svc.Namespace == namespace && svc.Name == name {
|
||||
return svc, true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
func (c clientMock) GetTraefikServices() []*traefikv1alpha1.TraefikService {
|
||||
return c.traefikServices
|
||||
}
|
||||
|
||||
func (c clientMock) GetTLSOptions() []*traefikv1alpha1.TLSOption {
|
||||
return c.tlsOptions
|
||||
}
|
||||
|
||||
func (c clientMock) GetTLSStores() []*traefikv1alpha1.TLSStore {
|
||||
return c.tlsStores
|
||||
}
|
||||
|
||||
func (c clientMock) GetServersTransports() []*traefikv1alpha1.ServersTransport {
|
||||
return c.serversTransports
|
||||
}
|
||||
|
||||
func (c clientMock) GetServersTransportTCPs() []*traefikv1alpha1.ServersTransportTCP {
|
||||
return c.serversTransportTCPs
|
||||
}
|
||||
|
||||
func (c clientMock) GetTLSOption(namespace, name string) (*traefikv1alpha1.TLSOption, bool, error) {
|
||||
for _, option := range c.tlsOptions {
|
||||
if option.Namespace == namespace && option.Name == name {
|
||||
return option, true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
func (c clientMock) GetService(namespace, name string) (*corev1.Service, bool, error) {
|
||||
if c.apiServiceError != nil {
|
||||
return nil, false, c.apiServiceError
|
||||
}
|
||||
|
||||
for _, service := range c.services {
|
||||
if service.Namespace == namespace && service.Name == name {
|
||||
return service, true, nil
|
||||
}
|
||||
}
|
||||
return nil, false, c.apiServiceError
|
||||
}
|
||||
|
||||
func (c clientMock) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) {
|
||||
if c.apiEndpointsError != nil {
|
||||
return nil, false, c.apiEndpointsError
|
||||
}
|
||||
|
||||
for _, endpoints := range c.endpoints {
|
||||
if endpoints.Namespace == namespace && endpoints.Name == name {
|
||||
return endpoints, true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return &corev1.Endpoints{}, false, nil
|
||||
}
|
||||
|
||||
func (c clientMock) GetSecret(namespace, name string) (*corev1.Secret, bool, error) {
|
||||
if c.apiSecretError != nil {
|
||||
return nil, false, c.apiSecretError
|
||||
}
|
||||
|
||||
for _, secret := range c.secrets {
|
||||
if secret.Namespace == namespace && secret.Name == name {
|
||||
return secret, true, nil
|
||||
}
|
||||
}
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
func (c clientMock) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) {
|
||||
return c.watchChan, nil
|
||||
}
|
|
@ -166,7 +166,7 @@ subsets:
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: external-svc
|
||||
name: external-svc-tcp
|
||||
namespace: default
|
||||
spec:
|
||||
externalName: external.domain
|
||||
|
@ -176,7 +176,7 @@ spec:
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: external.service.with.port
|
||||
name: external.service.with.port.tcp
|
||||
namespace: default
|
||||
spec:
|
||||
externalName: external.domain
|
||||
|
@ -186,19 +186,6 @@ spec:
|
|||
protocol: TCP
|
||||
port: 80
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: external.service.without.port
|
||||
namespace: default
|
||||
spec:
|
||||
externalName: external.domain
|
||||
type: ExternalName
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
|
@ -266,7 +253,7 @@ metadata:
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: native-svc
|
||||
name: native-svc-tcp
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
|
|
|
@ -11,5 +11,5 @@ spec:
|
|||
routes:
|
||||
- match: HostSNI(`foo.com`)
|
||||
services:
|
||||
- name: external-svc
|
||||
- name: external-svc-tcp
|
||||
port: 8000
|
||||
|
|
|
@ -11,5 +11,5 @@ spec:
|
|||
routes:
|
||||
- match: HostSNI(`foo.com`)
|
||||
services:
|
||||
- name: external.service.with.port
|
||||
- name: external.service.with.port.tcp
|
||||
port: 80
|
||||
|
|
|
@ -11,4 +11,4 @@ spec:
|
|||
routes:
|
||||
- match: HostSNI(`foo.com`)
|
||||
services:
|
||||
- name: external-svc
|
||||
- name: external-svc-tcp
|
||||
|
|
|
@ -11,6 +11,6 @@ spec:
|
|||
routes:
|
||||
- match: HostSNI(`foo.com`)
|
||||
services:
|
||||
- name: native-svc
|
||||
- name: native-svc-tcp
|
||||
port: 8000
|
||||
nativeLB: true
|
||||
|
|
|
@ -150,7 +150,7 @@ spec:
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: external-svc
|
||||
name: external-svc-udp
|
||||
namespace: default
|
||||
spec:
|
||||
externalName: external.domain
|
||||
|
@ -160,7 +160,7 @@ spec:
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: external.service.with.port
|
||||
name: external.service.with.port.udp
|
||||
namespace: default
|
||||
spec:
|
||||
externalName: external.domain
|
||||
|
@ -170,19 +170,6 @@ spec:
|
|||
protocol: TCP
|
||||
port: 80
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: external.service.without.port
|
||||
namespace: default
|
||||
spec:
|
||||
externalName: external.domain
|
||||
type: ExternalName
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
kind: Endpoints
|
||||
apiVersion: v1
|
||||
|
@ -225,7 +212,7 @@ metadata:
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: native-svc
|
||||
name: native-svc-udp
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
|
|
|
@ -10,5 +10,5 @@ spec:
|
|||
|
||||
routes:
|
||||
- services:
|
||||
- name: external-svc
|
||||
- name: external-svc-udp
|
||||
port: 8000
|
||||
|
|
|
@ -10,5 +10,5 @@ spec:
|
|||
|
||||
routes:
|
||||
- services:
|
||||
- name: external.service.with.port
|
||||
- name: external.service.with.port.udp
|
||||
port: 80
|
||||
|
|
|
@ -10,5 +10,5 @@ spec:
|
|||
|
||||
routes:
|
||||
- services:
|
||||
- name: external.service.with.port
|
||||
- name: external.service.with.port.udp
|
||||
port: 80
|
||||
|
|
|
@ -10,4 +10,4 @@ spec:
|
|||
|
||||
routes:
|
||||
- services:
|
||||
- name: external-svc
|
||||
- name: external-svc-udp
|
||||
|
|
|
@ -10,6 +10,6 @@ spec:
|
|||
|
||||
routes:
|
||||
- services:
|
||||
- name: native-svc
|
||||
- name: native-svc-udp
|
||||
port: 8000
|
||||
nativeLB: true
|
||||
|
|
|
@ -40,7 +40,7 @@ spec:
|
|||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: test.route
|
||||
name: test.route.default
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
|
|
|
@ -23,7 +23,7 @@ data:
|
|||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: test.route
|
||||
name: test.route.default
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
|
|
|
@ -735,7 +735,7 @@ func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *traef
|
|||
return forwardAuth, nil
|
||||
}
|
||||
|
||||
forwardAuth.TLS = &types.ClientTLS{
|
||||
forwardAuth.TLS = &dynamic.ClientTLS{
|
||||
InsecureSkipVerify: auth.TLS.InsecureSkipVerify,
|
||||
}
|
||||
|
||||
|
@ -756,6 +756,8 @@ func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *traef
|
|||
forwardAuth.TLS.Key = authSecretKey
|
||||
}
|
||||
|
||||
forwardAuth.TLS.CAOptional = auth.TLS.CAOptional
|
||||
|
||||
return forwardAuth, nil
|
||||
}
|
||||
|
||||
|
@ -1008,8 +1010,9 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options
|
|||
CAFiles: clientCAs,
|
||||
ClientAuthType: tlsOption.Spec.ClientAuth.ClientAuthType,
|
||||
},
|
||||
SniStrict: tlsOption.Spec.SniStrict,
|
||||
ALPNProtocols: alpnProtocols,
|
||||
SniStrict: tlsOption.Spec.SniStrict,
|
||||
ALPNProtocols: alpnProtocols,
|
||||
PreferServerCipherSuites: tlsOption.Spec.PreferServerCipherSuites,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -204,6 +204,10 @@ func (p *Provider) createLoadBalancerServerTCP(client Client, parentNamespace st
|
|||
}
|
||||
}
|
||||
|
||||
if service.ServersTransport == "" && service.TerminationDelay != nil {
|
||||
tcpService.LoadBalancer.TerminationDelay = service.TerminationDelay
|
||||
}
|
||||
|
||||
if service.ServersTransport != "" {
|
||||
tcpService.LoadBalancer.ServersTransport, err = p.makeTCPServersTransportKey(parentNamespace, service.ServersTransport)
|
||||
if err != nil {
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
kubefake "k8s.io/client-go/kubernetes/fake"
|
||||
kscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
)
|
||||
|
||||
var _ provider.Provider = (*Provider)(nil)
|
||||
|
@ -30,6 +31,14 @@ var _ provider.Provider = (*Provider)(nil)
|
|||
func Int(v int) *int { return &v }
|
||||
func Bool(v bool) *bool { return &v }
|
||||
|
||||
func init() {
|
||||
// required by k8s.MustParseYaml
|
||||
err := traefikv1alpha1.AddToScheme(kscheme.Scheme)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
|
@ -1035,6 +1044,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
|||
Services: map[string]*dynamic.TCPService{
|
||||
"default-test.route-fdd3e9338e47a45efefc": {
|
||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||
TerminationDelay: Int(500),
|
||||
Servers: []dynamic.TCPServer{
|
||||
{
|
||||
Address: "10.10.0.1:8000",
|
||||
|
@ -1568,6 +1578,23 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||
|
||||
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||
|
||||
client := newClientImpl(kubeClient, crdClient)
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
|
||||
eventCh, err := client.WatchAll(nil, stopCh)
|
||||
require.NoError(t, err)
|
||||
|
||||
if k8sObjects != nil || crdObjects != nil {
|
||||
// just wait for the first event
|
||||
<-eventCh
|
||||
}
|
||||
|
||||
p := Provider{
|
||||
IngressClass: test.ingressClass,
|
||||
AllowCrossNamespace: true,
|
||||
|
@ -1575,8 +1602,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
|||
AllowEmptyServices: test.allowEmptyServices,
|
||||
}
|
||||
|
||||
clientMock := newClientMock(test.paths...)
|
||||
conf := p.loadConfigurationFromCRD(context.Background(), clientMock)
|
||||
conf := p.loadConfigurationFromCRD(context.Background(), client)
|
||||
assert.Equal(t, test.expected, conf)
|
||||
})
|
||||
}
|
||||
|
@ -3063,6 +3089,15 @@ func TestLoadIngressRoutes(t *testing.T) {
|
|||
Options: "default-foo",
|
||||
},
|
||||
},
|
||||
"default-test-route-default-6b204d94623b3df4370c": {
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "default-test-route-default-6b204d94623b3df4370c",
|
||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||
Priority: 12,
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "default-foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{
|
||||
|
@ -3082,6 +3117,22 @@ func TestLoadIngressRoutes(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
"default-test-route-default-6b204d94623b3df4370c": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://10.10.0.1:80",
|
||||
},
|
||||
{
|
||||
URL: "http://10.10.0.2:80",
|
||||
},
|
||||
},
|
||||
PassHostHeader: Bool(true),
|
||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
||||
},
|
||||
|
@ -3602,7 +3653,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
|||
"default-forwardauth": {
|
||||
ForwardAuth: &dynamic.ForwardAuth{
|
||||
Address: "test.com",
|
||||
TLS: &types.ClientTLS{
|
||||
TLS: &dynamic.ClientTLS{
|
||||
CA: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
|
||||
Cert: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
|
||||
Key: "-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----",
|
||||
|
@ -4017,6 +4068,13 @@ func TestLoadIngressRoutes(t *testing.T) {
|
|||
Priority: 12,
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
"default-test-route-default-6b204d94623b3df4370c": {
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "default-test-route-default-6b204d94623b3df4370c",
|
||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||
Priority: 12,
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{
|
||||
|
@ -4036,6 +4094,22 @@ func TestLoadIngressRoutes(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
"default-test-route-default-6b204d94623b3df4370c": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://10.10.0.1:80",
|
||||
},
|
||||
{
|
||||
URL: "http://10.10.0.2:80",
|
||||
},
|
||||
},
|
||||
PassHostHeader: Bool(true),
|
||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
||||
},
|
||||
|
@ -4521,6 +4595,23 @@ func TestLoadIngressRoutes(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||
|
||||
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||
|
||||
client := newClientImpl(kubeClient, crdClient)
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
|
||||
eventCh, err := client.WatchAll(nil, stopCh)
|
||||
require.NoError(t, err)
|
||||
|
||||
if k8sObjects != nil || crdObjects != nil {
|
||||
// just wait for the first event
|
||||
<-eventCh
|
||||
}
|
||||
|
||||
p := Provider{
|
||||
IngressClass: test.ingressClass,
|
||||
AllowCrossNamespace: test.allowCrossNamespace,
|
||||
|
@ -4528,8 +4619,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
|||
AllowEmptyServices: test.allowEmptyServices,
|
||||
}
|
||||
|
||||
clientMock := newClientMock(test.paths...)
|
||||
conf := p.loadConfigurationFromCRD(context.Background(), clientMock)
|
||||
conf := p.loadConfigurationFromCRD(context.Background(), client)
|
||||
assert.Equal(t, test.expected, conf)
|
||||
})
|
||||
}
|
||||
|
@ -5016,6 +5106,23 @@ func TestLoadIngressRouteUDPs(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||
|
||||
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||
|
||||
client := newClientImpl(kubeClient, crdClient)
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
|
||||
eventCh, err := client.WatchAll(nil, stopCh)
|
||||
require.NoError(t, err)
|
||||
|
||||
if k8sObjects != nil || crdObjects != nil {
|
||||
// just wait for the first event
|
||||
<-eventCh
|
||||
}
|
||||
|
||||
p := Provider{
|
||||
IngressClass: test.ingressClass,
|
||||
AllowCrossNamespace: true,
|
||||
|
@ -5023,8 +5130,7 @@ func TestLoadIngressRouteUDPs(t *testing.T) {
|
|||
AllowEmptyServices: test.allowEmptyServices,
|
||||
}
|
||||
|
||||
clientMock := newClientMock(test.paths...)
|
||||
conf := p.loadConfigurationFromCRD(context.Background(), clientMock)
|
||||
conf := p.loadConfigurationFromCRD(context.Background(), client)
|
||||
assert.Equal(t, test.expected, conf)
|
||||
})
|
||||
}
|
||||
|
@ -6435,43 +6541,7 @@ func TestCrossNamespace(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var k8sObjects []runtime.Object
|
||||
var crdObjects []runtime.Object
|
||||
for _, path := range test.paths {
|
||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
objects := k8s.MustParseYaml(yamlContent)
|
||||
for _, obj := range objects {
|
||||
switch o := obj.(type) {
|
||||
case *corev1.Service, *corev1.Endpoints, *corev1.Secret:
|
||||
k8sObjects = append(k8sObjects, o)
|
||||
case *traefikv1alpha1.IngressRoute:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.IngressRouteTCP:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.IngressRouteUDP:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.Middleware:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.MiddlewareTCP:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.TraefikService:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.TLSOption:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.TLSStore:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.ServersTransport:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.ServersTransportTCP:
|
||||
crdObjects = append(crdObjects, o)
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||
|
||||
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||
|
@ -6742,37 +6812,7 @@ func TestExternalNameService(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var k8sObjects []runtime.Object
|
||||
var crdObjects []runtime.Object
|
||||
for _, path := range test.paths {
|
||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
objects := k8s.MustParseYaml(yamlContent)
|
||||
for _, obj := range objects {
|
||||
switch o := obj.(type) {
|
||||
case *corev1.Service, *corev1.Endpoints, *corev1.Secret:
|
||||
k8sObjects = append(k8sObjects, o)
|
||||
case *traefikv1alpha1.IngressRoute:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.IngressRouteTCP:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.IngressRouteUDP:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.Middleware:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.TraefikService:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.TLSOption:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.TLSStore:
|
||||
crdObjects = append(crdObjects, o)
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||
|
||||
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||
|
@ -6955,37 +6995,7 @@ func TestNativeLB(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var k8sObjects []runtime.Object
|
||||
var crdObjects []runtime.Object
|
||||
for _, path := range test.paths {
|
||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
objects := k8s.MustParseYaml(yamlContent)
|
||||
for _, obj := range objects {
|
||||
switch o := obj.(type) {
|
||||
case *corev1.Service, *corev1.Endpoints, *corev1.Secret:
|
||||
k8sObjects = append(k8sObjects, o)
|
||||
case *traefikv1alpha1.IngressRoute:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.IngressRouteTCP:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.IngressRouteUDP:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.Middleware:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.TraefikService:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.TLSOption:
|
||||
crdObjects = append(crdObjects, o)
|
||||
case *traefikv1alpha1.TLSStore:
|
||||
crdObjects = append(crdObjects, o)
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||
|
||||
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||
|
@ -7071,3 +7081,28 @@ func TestCreateBasicAuthCredentials(t *testing.T) {
|
|||
assert.Equal(t, "$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", hashedPassword)
|
||||
assert.True(t, auth.CheckSecret("test2", hashedPassword))
|
||||
}
|
||||
|
||||
func readResources(t *testing.T, paths []string) ([]runtime.Object, []runtime.Object) {
|
||||
t.Helper()
|
||||
|
||||
var k8sObjects []runtime.Object
|
||||
var crdObjects []runtime.Object
|
||||
for _, path := range paths {
|
||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
objects := k8s.MustParseYaml(yamlContent)
|
||||
for _, obj := range objects {
|
||||
switch obj.GetObjectKind().GroupVersionKind().Group {
|
||||
case "traefik.io":
|
||||
crdObjects = append(crdObjects, obj)
|
||||
default:
|
||||
k8sObjects = append(k8sObjects, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return k8sObjects, crdObjects
|
||||
}
|
||||
|
|
|
@ -72,6 +72,13 @@ type ServiceTCP struct {
|
|||
Port intstr.IntOrString `json:"port"`
|
||||
// Weight defines the weight used when balancing requests between multiple Kubernetes Service.
|
||||
Weight *int `json:"weight,omitempty"`
|
||||
// TerminationDelay defines the deadline that the proxy sets, after one of its connected peers indicates
|
||||
// it has closed the writing capability of its connection, to close the reading capability as well,
|
||||
// hence fully terminating the connection.
|
||||
// It is a duration in milliseconds, defaulting to 100.
|
||||
// A negative value means an infinite deadline (i.e. the reading capability is never closed).
|
||||
// Deprecated: TerminationDelay is not supported APIVersion traefik.io/v1, please use ServersTransport to configure the TerminationDelay instead.
|
||||
TerminationDelay *int `json:"terminationDelay,omitempty"`
|
||||
// ProxyProtocol defines the PROXY protocol configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v3.0/routing/services/#proxy-protocol
|
||||
ProxyProtocol *dynamic.ProxyProtocol `json:"proxyProtocol,omitempty"`
|
||||
|
|
|
@ -171,6 +171,9 @@ type ClientTLS struct {
|
|||
CertSecret string `json:"certSecret,omitempty"`
|
||||
// InsecureSkipVerify defines whether the server certificates should be validated.
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
|
||||
|
||||
// Deprecated: TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634).
|
||||
CAOptional *bool `json:"caOptional,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
|
|
@ -26,9 +26,13 @@ type MiddlewareTCPSpec struct {
|
|||
// InFlightConn defines the InFlightConn middleware configuration.
|
||||
InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"`
|
||||
// IPWhiteList defines the IPWhiteList middleware configuration.
|
||||
// This middleware accepts/refuses connections based on the client IP.
|
||||
// Deprecated: please use IPAllowList instead.
|
||||
// More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipwhitelist/
|
||||
IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"`
|
||||
// IPAllowList defines the IPAllowList middleware configuration.
|
||||
// This middleware accepts/refuses connections based on the client IP.
|
||||
// More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipallowlist/
|
||||
IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,11 @@ type TLSOptionSpec struct {
|
|||
// ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference.
|
||||
// More info: https://doc.traefik.io/traefik/v3.0/https/tls/#alpn-protocols
|
||||
ALPNProtocols []string `json:"alpnProtocols,omitempty"`
|
||||
|
||||
// PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
|
||||
// It is enabled automatically when minVersion or maxVersion is set.
|
||||
// Deprecated: https://github.com/golang/go/issues/45430
|
||||
PreferServerCipherSuites *bool `json:"preferServerCipherSuites,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
|
|
@ -146,6 +146,11 @@ func (in *ClientAuth) DeepCopy() *ClientAuth {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClientTLS) DeepCopyInto(out *ClientTLS) {
|
||||
*out = *in
|
||||
if in.CAOptional != nil {
|
||||
in, out := &in.CAOptional, &out.CAOptional
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -213,7 +218,7 @@ func (in *ForwardAuth) DeepCopyInto(out *ForwardAuth) {
|
|||
if in.TLS != nil {
|
||||
in, out := &in.TLS, &out.TLS
|
||||
*out = new(ClientTLS)
|
||||
**out = **in
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.AddAuthCookiesToResponse != nil {
|
||||
in, out := &in.AddAuthCookiesToResponse, &out.AddAuthCookiesToResponse
|
||||
|
@ -777,7 +782,7 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) {
|
|||
if in.ContentType != nil {
|
||||
in, out := &in.ContentType, &out.ContentType
|
||||
*out = new(dynamic.ContentType)
|
||||
**out = **in
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.GrpcWeb != nil {
|
||||
in, out := &in.GrpcWeb, &out.GrpcWeb
|
||||
|
@ -1318,6 +1323,11 @@ func (in *ServiceTCP) DeepCopyInto(out *ServiceTCP) {
|
|||
*out = new(int)
|
||||
**out = **in
|
||||
}
|
||||
if in.TerminationDelay != nil {
|
||||
in, out := &in.TerminationDelay, &out.TerminationDelay
|
||||
*out = new(int)
|
||||
**out = **in
|
||||
}
|
||||
if in.ProxyProtocol != nil {
|
||||
in, out := &in.ProxyProtocol, &out.ProxyProtocol
|
||||
*out = new(dynamic.ProxyProtocol)
|
||||
|
@ -1517,6 +1527,11 @@ func (in *TLSOptionSpec) DeepCopyInto(out *TLSOptionSpec) {
|
|||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.PreferServerCipherSuites != nil {
|
||||
in, out := &in.PreferServerCipherSuites, &out.PreferServerCipherSuites
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue