From c2dac39da16800c5d2fbfd6b551aa6f404638be3 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 9 Dec 2022 08:24:05 +0100 Subject: [PATCH 01/74] fix: detect dashboard content types Co-authored-by: Julien Salleyron --- pkg/api/dashboard/dashboard.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/api/dashboard/dashboard.go b/pkg/api/dashboard/dashboard.go index ebcaf315e..49f531f23 100644 --- a/pkg/api/dashboard/dashboard.go +++ b/pkg/api/dashboard/dashboard.go @@ -34,6 +34,11 @@ func Append(router *mux.Router, customAssets fs.FS) { // allow iframes from our domains only // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src w.Header().Set("Content-Security-Policy", "frame-src 'self' https://traefik.io https://*.traefik.io;") + + // The content type must be guessed by the file server. + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options + w.Header().Del("Content-Type") + http.StripPrefix("/dashboard/", http.FileServer(http.FS(assets))).ServeHTTP(w, r) }) } From da93dab828c5f78714209d84906d820c4d176a1b Mon Sep 17 00:00:00 2001 From: mpl Date: Fri, 9 Dec 2022 09:48:04 +0100 Subject: [PATCH 02/74] make file provider more resilient wrt first configuration Co-authored-by: Romain Co-authored-by: Tom Moulard --- pkg/provider/file/file.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pkg/provider/file/file.go b/pkg/provider/file/file.go index 08ee0896d..548f0cbc4 100644 --- a/pkg/provider/file/file.go +++ b/pkg/provider/file/file.go @@ -46,11 +46,6 @@ func (p *Provider) Init() error { // Provide allows the file provider to provide configurations to traefik // using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - configuration, err := p.BuildConfiguration() - if err != nil { - return err - } - if p.Watch { var watchItem string @@ -68,6 +63,15 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } } + configuration, err := p.BuildConfiguration() + if err != nil { + if p.Watch { + log.WithoutContext().WithField(log.ProviderName, providerName).Errorf("Error while building configuration (for the first time): %v", err) + return nil + } + return err + } + sendConfigToChannel(configurationChan, configuration) return nil } From 3eeea2bb2bfb49e2e0adbd77e65d45183796b111 Mon Sep 17 00:00:00 2001 From: Simon Delicata Date: Fri, 9 Dec 2022 09:58:05 +0100 Subject: [PATCH 03/74] Add TCP Servers Transports support Co-authored-by: Romain --- .golangci.yml | 4 + cmd/configuration.go | 4 + cmd/traefik/traefik.go | 5 +- docs/content/https/spiffe.md | 4 +- docs/content/migration/v2-to-v3.md | 10 + .../dynamic-configuration/docker-labels.yml | 3 +- .../reference/dynamic-configuration/file.toml | 52 +- .../reference/dynamic-configuration/file.yaml | 47 +- .../kubernetes-crd-definition-v1.yml | 141 +++- .../kubernetes-crd-rbac.yml | 1 + .../kubernetes-crd-resource.yml | 22 + .../reference/dynamic-configuration/kv-ref.md | 34 +- .../marathon-labels.json | 3 +- .../traefik.containo.us_ingressroutetcps.yaml | 19 +- ...efik.containo.us_serverstransporttcps.yaml | 122 +++ .../reference/static-configuration/cli-ref.md | 27 + .../reference/static-configuration/env-ref.md | 27 + .../reference/static-configuration/file.toml | 19 + .../reference/static-configuration/file.yaml | 22 +- docs/content/routing/overview.md | 198 ++++- .../routing/providers/consul-catalog.md | 17 +- docs/content/routing/providers/docker.md | 15 +- docs/content/routing/providers/ecs.md | 17 +- .../routing/providers/kubernetes-crd.md | 255 ++++-- docs/content/routing/providers/kv.md | 17 +- docs/content/routing/providers/marathon.md | 17 +- docs/content/routing/providers/nomad.md | 15 +- docs/content/routing/providers/rancher.md | 17 +- docs/content/routing/services/index.md | 576 +++++++++++-- integration/fixtures/k8s/01-traefik-crd.yml | 141 +++- integration/testdata/rawdata-crd.json | 2 - integration/testdata/rawdata-gateway.json | 1 - pkg/config/dynamic/http_config.go | 16 +- pkg/config/dynamic/tcp_config.go | 58 +- pkg/config/dynamic/zz_generated.deepcopy.go | 72 +- pkg/config/label/label_test.go | 29 +- pkg/config/static/static_config.go | 27 +- pkg/provider/configuration.go | 75 +- pkg/provider/consulcatalog/config.go | 30 +- pkg/provider/consulcatalog/config_test.go | 362 ++++---- pkg/provider/consulcatalog/connect_tls.go | 22 + pkg/provider/docker/config.go | 9 +- pkg/provider/docker/config_test.go | 355 ++++---- pkg/provider/ecs/config.go | 9 +- pkg/provider/ecs/config_test.go | 336 ++++---- pkg/provider/file/file.go | 66 +- pkg/provider/file/file_test.go | 11 + pkg/provider/http/http.go | 5 +- pkg/provider/http/http_test.go | 8 +- pkg/provider/hub/hub.go | 5 +- pkg/provider/kubernetes/crd/client.go | 20 + .../kubernetes/crd/client_mock_test.go | 29 +- .../fixtures/tcp/with_servers_transport.yml | 147 ++++ ...with_servers_transport_cross_namespace.yml | 27 + .../v1alpha1/fake/fake_serverstransporttcp.go | 138 +++ .../v1alpha1/fake/fake_traefik_client.go | 4 + .../traefik/v1alpha1/generated_expansion.go | 2 + .../traefik/v1alpha1/serverstransporttcp.go | 186 ++++ .../typed/traefik/v1alpha1/traefik_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../traefik/v1alpha1/interface.go | 7 + .../traefik/v1alpha1/serverstransporttcp.go | 98 +++ .../traefik/v1alpha1/expansion_generated.go | 8 + .../traefik/v1alpha1/serverstransporttcp.go | 107 +++ pkg/provider/kubernetes/crd/kubernetes.go | 74 ++ pkg/provider/kubernetes/crd/kubernetes_tcp.go | 33 +- .../kubernetes/crd/kubernetes_test.go | 799 ++++++++++++------ .../crd/traefik/v1alpha1/ingressroutetcp.go | 12 +- .../crd/traefik/v1alpha1/register.go | 2 + .../traefik/v1alpha1/serverstransporttcp.go | 68 ++ .../traefik/v1alpha1/zz_generated.deepcopy.go | 132 ++- pkg/provider/kubernetes/gateway/kubernetes.go | 42 +- .../kubernetes/gateway/kubernetes_test.go | 404 +++++---- pkg/provider/kubernetes/k8s/parser.go | 2 +- pkg/provider/kv/kv_test.go | 2 - pkg/provider/marathon/config.go | 9 +- pkg/provider/marathon/config_test.go | 252 +++--- pkg/provider/nomad/config.go | 11 +- pkg/provider/nomad/config_test.go | 278 +++--- pkg/provider/rancher/config.go | 9 +- pkg/provider/rancher/config_test.go | 123 +-- pkg/provider/traefik/internal.go | 33 +- pkg/redactor/redactor_config_test.go | 42 +- .../testdata/anonymized-dynamic-config.json | 24 +- .../testdata/anonymized-static-config.json | 12 + .../testdata/secured-dynamic-config.json | 24 +- pkg/server/aggregator.go | 10 +- pkg/server/aggregator_test.go | 1 + pkg/server/configurationwatcher.go | 9 + pkg/server/configurationwatcher_test.go | 42 +- pkg/server/router/tcp/manager_test.go | 7 +- pkg/server/router/tcp/router_test.go | 4 +- pkg/server/routerfactory.go | 18 +- pkg/server/routerfactory_test.go | 13 +- pkg/server/service/tcp/service.go | 25 +- pkg/server/service/tcp/service_test.go | 70 +- pkg/tcp/dialer.go | 205 +++++ pkg/tcp/dialer_test.go | 593 +++++++++++++ pkg/tcp/proxy.go | 50 +- pkg/tcp/proxy_test.go | 49 +- .../_commons/PanelServiceDetails.vue | 13 - 101 files changed, 5956 insertions(+), 1669 deletions(-) create mode 100644 docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransporttcps.yaml create mode 100644 pkg/provider/kubernetes/crd/fixtures/tcp/with_servers_transport.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/tcp/with_servers_transport_cross_namespace.yml create mode 100644 pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_serverstransporttcp.go create mode 100644 pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransporttcp.go create mode 100644 pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransporttcp.go create mode 100644 pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransporttcp.go create mode 100644 pkg/provider/kubernetes/crd/traefik/v1alpha1/serverstransporttcp.go create mode 100644 pkg/tcp/dialer.go create mode 100644 pkg/tcp/dialer_test.go diff --git a/.golangci.yml b/.golangci.yml index f6f2085f7..c8baa7f6b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -179,3 +179,7 @@ issues: text: 'Duplicate words \(sub\) found' linters: - dupword + - path: pkg/provider/kubernetes/crd/kubernetes.go + text: "Function 'loadConfigurationFromCRD' has too many statements" + linters: + - funlen diff --git a/cmd/configuration.go b/cmd/configuration.go index 3e4f38f92..69730ef71 100644 --- a/cmd/configuration.go +++ b/cmd/configuration.go @@ -28,6 +28,10 @@ func NewTraefikConfiguration() *TraefikCmdConfiguration { ServersTransport: &static.ServersTransport{ MaxIdleConnsPerHost: 200, }, + TCPServersTransport: &static.TCPServersTransport{ + DialTimeout: ptypes.Duration(30 * time.Second), + DialKeepAlive: ptypes.Duration(15 * time.Second), + }, }, ConfigFile: "", } diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 9d0256795..89580c553 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -41,6 +41,7 @@ import ( "github.com/traefik/traefik/v2/pkg/server" "github.com/traefik/traefik/v2/pkg/server/middleware" "github.com/traefik/traefik/v2/pkg/server/service" + "github.com/traefik/traefik/v2/pkg/tcp" traefiktls "github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/tracing" "github.com/traefik/traefik/v2/pkg/tracing/jaeger" @@ -269,6 +270,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err } roundTripperManager := service.NewRoundTripperManager(spiffeX509Source) + dialerManager := tcp.NewDialerManager(spiffeX509Source) acmeHTTPHandler := getHTTPChallengeHandler(acmeProviders, httpChallengeProvider) managerFactory := service.NewManagerFactory(*staticConfiguration, routinesPool, metricsRegistry, roundTripperManager, acmeHTTPHandler) @@ -278,7 +280,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err tracer := setupTracing(staticConfiguration.Tracing) chainBuilder := middleware.NewChainBuilder(metricsRegistry, accessLog, tracer) - routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry) + routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry, dialerManager) // Watcher @@ -309,6 +311,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err // Server Transports watcher.AddListener(func(conf dynamic.Configuration) { roundTripperManager.Update(conf.HTTP.ServersTransports) + dialerManager.Update(conf.TCP.ServersTransports) }) // Switch router diff --git a/docs/content/https/spiffe.md b/docs/content/https/spiffe.md index 9d70e5a20..cf7a9cf88 100644 --- a/docs/content/https/spiffe.md +++ b/docs/content/https/spiffe.md @@ -28,7 +28,9 @@ The `workloadAPIAddr` configuration defines the address of the SPIFFE [Workload !!! info "Enabling SPIFFE in ServersTransports" Enabling SPIFFE does not imply that backend connections are going to use it automatically. - Each [ServersTransport](../routing/services/index.md#serverstransport_1) that is meant to be secured with SPIFFE must [explicitly](../routing/services/index.md#spiffe) enable it. + Each [ServersTransport](../routing/services/index.md#serverstransport_1) or [TCPServersTransport](../routing/services/index.md#serverstransport_2), + that is meant to be secured with SPIFFE, + must explicitly enable it (see [SPIFFE with ServersTransport](../routing/services/index.md#spiffe) or [SPIFFE with TCPServersTransport](../routing/services/index.md#spiffe_1)). !!! warning "SPIFFE can cause Traefik to stall" When using SPIFFE, diff --git a/docs/content/migration/v2-to-v3.md b/docs/content/migration/v2-to-v3.md index 27d38e953..b8f600d54 100644 --- a/docs/content/migration/v2-to-v3.md +++ b/docs/content/migration/v2-to-v3.md @@ -55,3 +55,13 @@ One should use the `ContentType` middleware to enable the `Content-Type` header In v3, HTTP/3 is no longer an experimental feature. The `experimental.http3` option has been removed from the static configuration. + +## TCP ServersTransport + +In v3, the support of `TCPServersTransport` has been introduced. +When using the KubernetesCRD provider, it is therefore necessary to update [RBAC](../reference/dynamic-configuration/kubernetes-crd.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-crd.md) manifests. + +### TCP LoadBalancer `terminationDelay` option + +The TCP LoadBalancer `terminationDelay` option has been removed. +This option can now be configured directly on the `TCPServersTransport` level, please take a look at this [documentation](../routing/services/index.md#terminationdelay) diff --git a/docs/content/reference/dynamic-configuration/docker-labels.yml b/docs/content/reference/dynamic-configuration/docker-labels.yml index e58a1d46a..fb497fe41 100644 --- a/docs/content/reference/dynamic-configuration/docker-labels.yml +++ b/docs/content/reference/dynamic-configuration/docker-labels.yml @@ -190,8 +190,9 @@ - "traefik.tcp.routers.tcprouter1.tls.options=foobar" - "traefik.tcp.routers.tcprouter1.tls.passthrough=true" - "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version=42" -- "traefik.tcp.services.tcpservice01.loadbalancer.terminationdelay=42" - "traefik.tcp.services.tcpservice01.loadbalancer.server.port=foobar" +- "traefik.tcp.services.tcpservice01.loadbalancer.server.tls=true" +- "traefik.tcp.services.tcpservice01.loadbalancer.serverstransport=foobar" - "traefik.udp.routers.udprouter0.entrypoints=foobar, foobar" - "traefik.udp.routers.udprouter0.service=foobar" - "traefik.udp.routers.udprouter1.entrypoints=foobar, foobar" diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 41994814d..2e72be2aa 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -377,15 +377,17 @@ [tcp.services] [tcp.services.TCPService01] [tcp.services.TCPService01.loadBalancer] - terminationDelay = 42 + serversTransport = "foobar" [tcp.services.TCPService01.loadBalancer.proxyProtocol] version = 42 [[tcp.services.TCPService01.loadBalancer.servers]] address = "foobar" + tls = true [[tcp.services.TCPService01.loadBalancer.servers]] address = "foobar" + tls = true [tcp.services.TCPService02] [tcp.services.TCPService02.weighted] @@ -396,6 +398,7 @@ [[tcp.services.TCPService02.weighted.services]] name = "foobar" weight = 42 + [tcp.middlewares] [tcp.middlewares.TCPMiddleware00] [tcp.middlewares.TCPMiddleware00.ipAllowList] @@ -404,6 +407,53 @@ [tcp.middlewares.TCPMiddleware01.inFlightConn] amount = 42 + [tcp.serversTransports] + [tcp.serversTransports.TCPServersTransport0] + dialTimeout = "42s" + dialKeepAlive = "42s" + terminationDelay = "42s" + + [tcp.serversTransports.TCPServersTransport0.tls] + serverName = "foobar" + insecureSkipVerify = true + rootCAs = ["foobar", "foobar"] + peerCertURI = "foobar" + + [[tcp.serversTransports.TCPServersTransport0.tls.certificates]] + certFile = "foobar" + keyFile = "foobar" + + [[tcp.serversTransports.TCPServersTransport0.tls.certificates]] + certFile = "foobar" + keyFile = "foobar" + + [tcp.serversTransports.TCPServersTransport0.spiffe] + ids = ["foobar", "foobar"] + trustDomain = "foobar" + + [tcp.serversTransports.TCPServersTransport1] + dialTimeout = "42s" + dialKeepAlive = "42s" + terminationDelay = "42s" + + [tcp.serversTransports.TCPServersTransport1.tls] + serverName = "foobar" + insecureSkipVerify = true + rootCAs = ["foobar", "foobar"] + peerCertURI = "foobar" + + [[tcp.serversTransports.TCPServersTransport1.tls.certificates]] + certFile = "foobar" + keyFile = "foobar" + + [[tcp.serversTransports.TCPServersTransport1.tls.certificates]] + certFile = "foobar" + keyFile = "foobar" + + [tcp.serversTransports.TCPServersTransport1.spiffe] + ids = ["foobar", "foobar"] + trustDomain = "foobar" + [udp] [udp.routers] [udp.routers.UDPRouter0] diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index bfecd9fd2..e760e19ec 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -426,12 +426,14 @@ tcp: services: TCPService01: loadBalancer: - terminationDelay: 42 + serversTransport: foobar proxyProtocol: version: 42 servers: - address: foobar + tls: true - address: foobar + tls: true TCPService02: weighted: services: @@ -448,6 +450,49 @@ tcp: TCPMiddleware01: inFlightConn: amount: 42 + serversTransports: + TCPServersTransport0: + dialTimeout: 42s + dialKeepAlive: 42s + terminationDelay: 42s + tls: + serverName: foobar + insecureSkipVerify: true + rootCAs: + - foobar + - foobar + certificates: + - certFile: foobar + keyFile: foobar + - certFile: foobar + keyFile: foobar + peerCertURI: foobar + spiffe: + ids: + - foobar + - foobar + trustDomain: foobar + TCPServersTransport1: + dialTimeout: 42s + dialKeepAlive: 42s + terminationDelay: 42s + tls: + serverName: foobar + insecureSkipVerify: true + rootCAs: + - foobar + - foobar + certificates: + - certFile: foobar + keyFile: foobar + - certFile: foobar + keyFile: foobar + peerCertURI: foobar + spiffe: + ids: + - foobar + - foobar + trustDomain: foobar udp: routers: UDPRouter0: diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml index 4a7f19a66..fe3187a7d 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -373,15 +373,16 @@ spec: to use. type: integer type: object - terminationDelay: - description: 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). - type: integer + serversTransport: + description: ServersTransport defines the name of ServersTransportTCP + resource to use. It allows to configure the transport + between Traefik and your servers. Can only be used on + a Kubernetes Service. + type: string + tls: + description: TLS determines whether to use TLS when dialing + with the backend. + type: boolean weight: description: Weight defines the weight used when balancing requests between multiple Kubernetes Service. @@ -1684,6 +1685,128 @@ status: conditions: [] storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: serverstransporttcps.traefik.containo.us +spec: + group: traefik.containo.us + names: + kind: ServersTransportTCP + listKind: ServersTransportTCPList + plural: serverstransporttcps + singular: serverstransporttcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: 'ServersTransportTCP is the CRD implementation of a TCPServersTransport. + If no tcpServersTransport is specified, a default one named default@internal + will be used. The default@internal tcpServersTransport can be configured + in the static configuration. More info: https://doc.traefik.io/traefik/v2.9/routing/services/#serverstransport_3' + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServersTransportTCPSpec defines the desired state of a ServersTransportTCP. + properties: + dialKeepAlive: + anyOf: + - type: integer + - type: string + description: DialKeepAlive is the interval between keep-alive probes + for an active network connection. If zero, keep-alive probes are + sent with a default value (currently 15 seconds), if supported by + the protocol and operating system. Network protocols or operating + systems that do not support keep-alives ignore this field. If negative, + keep-alive probes are disabled. + x-kubernetes-int-or-string: true + dialTimeout: + anyOf: + - type: integer + - type: string + description: DialTimeout is the amount of time to wait until a connection + to a backend server can be established. + x-kubernetes-int-or-string: true + terminationDelay: + anyOf: + - type: integer + - type: string + description: TerminationDelay defines the delay to wait before fully + terminating the connection, after one connected peer has closed + its writing capability. + x-kubernetes-int-or-string: true + tls: + description: TLS defines the TLS configuration + properties: + certificatesSecrets: + description: CertificatesSecrets defines a list of secret storing + client certificates for mTLS. + items: + type: string + type: array + insecureSkipVerify: + description: InsecureSkipVerify disables TLS certificate verification. + type: boolean + peerCertURI: + description: MaxIdleConnsPerHost controls the maximum idle (keep-alive) + to keep per-host. PeerCertURI defines the peer cert URI used + to match against SAN URI during the peer certificate verification. + type: string + rootCAsSecrets: + description: RootCAsSecrets defines a list of CA secret used to + validate self-signed certificates. + items: + type: string + type: array + serverName: + description: ServerName defines the server name used to contact + the server. + type: string + spiffe: + description: Spiffe defines the SPIFFE configuration. + properties: + ids: + description: IDs defines the allowed SPIFFE IDs (takes precedence + over the SPIFFE TrustDomain). + items: + type: string + type: array + trustDomain: + description: TrustDomain defines the allowed SPIFFE trust + domain. + type: string + type: object + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml index 6237031f0..dc8357cb6 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml @@ -43,6 +43,7 @@ rules: - tlsoptions - tlsstores - serverstransports + - serverstransporttcps verbs: - get - list diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml index abe361b9a..27689e9a8 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml @@ -147,6 +147,7 @@ spec: services: - name: whoamitcp port: 8080 + serversTransport: mytransporttcp middlewares: - name: ipallowlist tls: @@ -213,9 +214,30 @@ spec: certificatesSecrets: - foobar - foobar + peerCertURI: foobar maxIdleConnsPerHost: 1 forwardingTimeouts: dialTimeout: 42s responseHeaderTimeout: 42s idleConnTimeout: 42s disableHTTP2: true + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransporttcp + namespace: default + +spec: + serverName: foobar + insecureSkipVerify: true + rootCAsSecrets: + - foobar + - foobar + certificatesSecrets: + - foobar + - foobar + peerCertURI: foobar + dialTimeout: 42s + dialKeepAlive: 42s diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md index ca40ac8a4..ce15fb1f2 100644 --- a/docs/content/reference/dynamic-configuration/kv-ref.md +++ b/docs/content/reference/dynamic-configuration/kv-ref.md @@ -278,10 +278,42 @@ | `traefik/tcp/routers/TCPRouter1/tls/domains/1/sans/1` | `foobar` | | `traefik/tcp/routers/TCPRouter1/tls/options` | `foobar` | | `traefik/tcp/routers/TCPRouter1/tls/passthrough` | `true` | +| `traefik/tcp/serversTransports/TCPServersTransport0/dialKeepAlive` | `42s` | +| `traefik/tcp/serversTransports/TCPServersTransport0/dialTimeout` | `42s` | +| `traefik/tcp/serversTransports/TCPServersTransport0/spiffe/ids/0` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/spiffe/ids/1` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/spiffe/trustDomain` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/terminationDelay` | `42s` | +| `traefik/tcp/serversTransports/TCPServersTransport0/tls/certificates/0/certFile` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/tls/certificates/0/keyFile` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/tls/certificates/1/certFile` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/tls/certificates/1/keyFile` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/tls/insecureSkipVerify` | `true` | +| `traefik/tcp/serversTransports/TCPServersTransport0/tls/peerCertURI` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/tls/rootCAs/0` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/tls/rootCAs/1` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport0/tls/serverName` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/dialKeepAlive` | `42s` | +| `traefik/tcp/serversTransports/TCPServersTransport1/dialTimeout` | `42s` | +| `traefik/tcp/serversTransports/TCPServersTransport1/spiffe/ids/0` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/spiffe/ids/1` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/spiffe/trustDomain` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/terminationDelay` | `42s` | +| `traefik/tcp/serversTransports/TCPServersTransport1/tls/certificates/0/certFile` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/tls/certificates/0/keyFile` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/tls/certificates/1/certFile` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/tls/certificates/1/keyFile` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/tls/insecureSkipVerify` | `true` | +| `traefik/tcp/serversTransports/TCPServersTransport1/tls/peerCertURI` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/tls/rootCAs/0` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/tls/rootCAs/1` | `foobar` | +| `traefik/tcp/serversTransports/TCPServersTransport1/tls/serverName` | `foobar` | | `traefik/tcp/services/TCPService01/loadBalancer/proxyProtocol/version` | `42` | | `traefik/tcp/services/TCPService01/loadBalancer/servers/0/address` | `foobar` | +| `traefik/tcp/services/TCPService01/loadBalancer/servers/0/tls` | `true` | | `traefik/tcp/services/TCPService01/loadBalancer/servers/1/address` | `foobar` | -| `traefik/tcp/services/TCPService01/loadBalancer/terminationDelay` | `42` | +| `traefik/tcp/services/TCPService01/loadBalancer/servers/1/tls` | `true` | +| `traefik/tcp/services/TCPService01/loadBalancer/serversTransport` | `foobar` | | `traefik/tcp/services/TCPService02/weighted/services/0/name` | `foobar` | | `traefik/tcp/services/TCPService02/weighted/services/0/weight` | `42` | | `traefik/tcp/services/TCPService02/weighted/services/1/name` | `foobar` | diff --git a/docs/content/reference/dynamic-configuration/marathon-labels.json b/docs/content/reference/dynamic-configuration/marathon-labels.json index 99cfaefb9..afac8bb13 100644 --- a/docs/content/reference/dynamic-configuration/marathon-labels.json +++ b/docs/content/reference/dynamic-configuration/marathon-labels.json @@ -190,8 +190,9 @@ "traefik.tcp.routers.tcprouter1.tls.options": "foobar", "traefik.tcp.routers.tcprouter1.tls.passthrough": "true", "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version": "42", -"traefik.tcp.services.tcpservice01.loadbalancer.terminationdelay": "42", "traefik.tcp.services.tcpservice01.loadbalancer.server.port": "foobar", +"traefik.tcp.services.tcpservice01.loadbalancer.server.tls": "true", +"traefik.tcp.services.tcpservice01.loadbalancer.serverstransport": "foobar", "traefik.udp.routers.udprouter0.entrypoints": "foobar, foobar", "traefik.udp.routers.udprouter0.service": "foobar", "traefik.udp.routers.udprouter1.entrypoints": "foobar, foobar", diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml index a73fde965..4fd7e214d 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml @@ -105,15 +105,16 @@ spec: to use. type: integer type: object - terminationDelay: - description: 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). - type: integer + serversTransport: + description: ServersTransport defines the name of ServersTransportTCP + resource to use. It allows to configure the transport + between Traefik and your servers. Can only be used on + a Kubernetes Service. + type: string + tls: + description: TLS determines whether to use TLS when dialing + with the backend. + type: boolean weight: description: Weight defines the weight used when balancing requests between multiple Kubernetes Service. diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransporttcps.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransporttcps.yaml new file mode 100644 index 000000000..0a54dd137 --- /dev/null +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransporttcps.yaml @@ -0,0 +1,122 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: serverstransporttcps.traefik.containo.us +spec: + group: traefik.containo.us + names: + kind: ServersTransportTCP + listKind: ServersTransportTCPList + plural: serverstransporttcps + singular: serverstransporttcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: 'ServersTransportTCP is the CRD implementation of a TCPServersTransport. + If no tcpServersTransport is specified, a default one named default@internal + will be used. The default@internal tcpServersTransport can be configured + in the static configuration. More info: https://doc.traefik.io/traefik/v2.9/routing/services/#serverstransport_3' + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServersTransportTCPSpec defines the desired state of a ServersTransportTCP. + properties: + dialKeepAlive: + anyOf: + - type: integer + - type: string + description: DialKeepAlive is the interval between keep-alive probes + for an active network connection. If zero, keep-alive probes are + sent with a default value (currently 15 seconds), if supported by + the protocol and operating system. Network protocols or operating + systems that do not support keep-alives ignore this field. If negative, + keep-alive probes are disabled. + x-kubernetes-int-or-string: true + dialTimeout: + anyOf: + - type: integer + - type: string + description: DialTimeout is the amount of time to wait until a connection + to a backend server can be established. + x-kubernetes-int-or-string: true + terminationDelay: + anyOf: + - type: integer + - type: string + description: TerminationDelay defines the delay to wait before fully + terminating the connection, after one connected peer has closed + its writing capability. + x-kubernetes-int-or-string: true + tls: + description: TLS defines the TLS configuration + properties: + certificatesSecrets: + description: CertificatesSecrets defines a list of secret storing + client certificates for mTLS. + items: + type: string + type: array + insecureSkipVerify: + description: InsecureSkipVerify disables TLS certificate verification. + type: boolean + peerCertURI: + description: MaxIdleConnsPerHost controls the maximum idle (keep-alive) + to keep per-host. PeerCertURI defines the peer cert URI used + to match against SAN URI during the peer certificate verification. + type: string + rootCAsSecrets: + description: RootCAsSecrets defines a list of CA secret used to + validate self-signed certificates. + items: + type: string + type: array + serverName: + description: ServerName defines the server name used to contact + the server. + type: string + spiffe: + description: Spiffe defines the SPIFFE configuration. + properties: + ids: + description: IDs defines the allowed SPIFFE IDs (takes precedence + over the SPIFFE TrustDomain). + items: + type: string + type: array + trustDomain: + description: TrustDomain defines the allowed SPIFFE trust + domain. + type: string + type: object + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 39cb5d102..3a200ac6b 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -1020,6 +1020,33 @@ Defines the allowed SPIFFE trust domain. `--spiffe.workloadapiaddr`: Defines the workload API address. +`--tcpserverstransport.dialkeepalive`: +Defines the interval between keep-alive probes for an active network connection. If zero, keep-alive probes are sent with a default value (currently 15 seconds), if supported by the protocol and operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, keep-alive probes are disabled (Default: ```15```) + +`--tcpserverstransport.dialtimeout`: +Defines the amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists. (Default: ```30```) + +`--tcpserverstransport.terminationdelay`: +Defines the delay to wait before fully terminating the connection, after one connected peer has closed its writing capability. (Default: ```0```) + +`--tcpserverstransport.tls`: +Defines the TLS configuration. (Default: ```false```) + +`--tcpserverstransport.tls.insecureskipverify`: +Disables SSL certificate verification. (Default: ```false```) + +`--tcpserverstransport.tls.rootcas`: +Defines a list of CA secret used to validate self-signed certificate + +`--tcpserverstransport.tls.spiffe`: +Defines the SPIFFE TLS configuration. (Default: ```false```) + +`--tcpserverstransport.tls.spiffe.ids`: +Defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain). + +`--tcpserverstransport.tls.spiffe.trustdomain`: +Defines the allowed SPIFFE trust domain. + `--tracing`: OpenTracing configuration. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 08fb6bd7d..0e28c8313 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -1020,6 +1020,33 @@ Defines the allowed SPIFFE trust domain. `TRAEFIK_SPIFFE_WORKLOADAPIADDR`: Defines the workload API address. +`TRAEFIK_TCPSERVERSTRANSPORT_DIALKEEPALIVE`: +Defines the interval between keep-alive probes for an active network connection. If zero, keep-alive probes are sent with a default value (currently 15 seconds), if supported by the protocol and operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, keep-alive probes are disabled (Default: ```15```) + +`TRAEFIK_TCPSERVERSTRANSPORT_DIALTIMEOUT`: +Defines the amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists. (Default: ```30```) + +`TRAEFIK_TCPSERVERSTRANSPORT_TERMINATIONDELAY`: +Defines the delay to wait before fully terminating the connection, after one connected peer has closed its writing capability. (Default: ```0```) + +`TRAEFIK_TCPSERVERSTRANSPORT_TLS`: +Defines the TLS configuration. (Default: ```false```) + +`TRAEFIK_TCPSERVERSTRANSPORT_TLS_INSECURESKIPVERIFY`: +Disables SSL certificate verification. (Default: ```false```) + +`TRAEFIK_TCPSERVERSTRANSPORT_TLS_ROOTCAS`: +Defines a list of CA secret used to validate self-signed certificate + +`TRAEFIK_TCPSERVERSTRANSPORT_TLS_SPIFFE`: +Defines the SPIFFE TLS configuration. (Default: ```false```) + +`TRAEFIK_TCPSERVERSTRANSPORT_TLS_SPIFFE_IDS`: +Defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain). + +`TRAEFIK_TCPSERVERSTRANSPORT_TLS_SPIFFE_TRUSTDOMAIN`: +Defines the allowed SPIFFE trust domain. + `TRAEFIK_TRACING`: OpenTracing configuration. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 22420a806..cce2f600f 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -6,10 +6,29 @@ insecureSkipVerify = true rootCAs = ["foobar", "foobar"] maxIdleConnsPerHost = 42 + [serversTransport.forwardingTimeouts] dialTimeout = "42s" responseHeaderTimeout = "42s" idleConnTimeout = "42s" + readIdleTimeout = "42s" + pingTimeout = "42s" + + [serversTransport.spiffe] + ids = ["foobar", "foobar"] + trustDomain = "foobar" + +[tcpServersTransport] + dialTimeout = "42s" + dialKeepAlive = "42s" + + [tcpServersTransport.tls] + insecureSkipVerify = true + rootCAs = ["foobar", "foobar"] + + [tcpServersTransport.tls.spiffe] + ids = ["foobar", "foobar"] + trustDomain = "foobar" [entryPoints] [entryPoints.EntryPoint0] diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 596f5ab4d..ee7eb4ff3 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -1,7 +1,7 @@ global: checkNewVersion: true sendAnonymousUsage: true -serversTransport: +serversTransports: insecureSkipVerify: true rootCAs: - foobar @@ -11,6 +11,26 @@ serversTransport: dialTimeout: 42s responseHeaderTimeout: 42s idleConnTimeout: 42s + readIdleTimeout: 42s + pingTimeout: 42s + spiffe: + ids: + - foobar + - foobar + trustDomain: foobar +tcpServersTransport: + dialTimeout: 42s + dialKeepAlive: 42s + tls: + insecureSkipVerify: true + rootCAs: + - foobar + - foobar + spiffe: + ids: + - foobar + - foobar + trustDomain: foobar entryPoints: EntryPoint0: address: foobar diff --git a/docs/content/routing/overview.md b/docs/content/routing/overview.md index 3816c1e70..650a72929 100644 --- a/docs/content/routing/overview.md +++ b/docs/content/routing/overview.md @@ -250,10 +250,12 @@ and then between Traefik and the backend servers, is configured through the In addition, a few parameters are dedicated to configuring globally what happens with the connections between Traefik and the backends. -This is done through the `serversTransport` section of the configuration, -which features these options: +This is done through the [`serversTransport`](#http-servers-transports) and [`tcpServersTransport`](#tcp-servers-transports) +sections of the configuration, which features these options: -### `insecureSkipVerify` +### HTTP Servers Transports + +#### `insecureSkipVerify` _Optional, Default=false_ @@ -276,7 +278,7 @@ serversTransport: --serversTransport.insecureSkipVerify=true ``` -### `rootCAs` +#### `rootCAs` _Optional_ @@ -302,7 +304,7 @@ serversTransport: --serversTransport.rootCAs=foo.crt,bar.crt ``` -### `maxIdleConnsPerHost` +#### `maxIdleConnsPerHost` _Optional, Default=2_ @@ -325,7 +327,7 @@ serversTransport: --serversTransport.maxIdleConnsPerHost=7 ``` -### `spiffe` +#### `spiffe` Please note that [SPIFFE](../https/spiffe.md) must be enabled in the static configuration before using it to secure the connection between Traefik and the backends. @@ -380,7 +382,7 @@ serversTransport: --serversTransport.spiffe.trustDomain=spiffe://trust-domain ``` -### `forwardingTimeouts` +#### `forwardingTimeouts` `forwardingTimeouts` is about a number of timeouts relevant to when forwarding requests to the backend servers. @@ -462,4 +464,186 @@ serversTransport: --serversTransport.forwardingTimeouts.idleConnTimeout=1s ``` +### TCP Servers Transports + +#### `dialTimeout` + +_Optional, Default="30s"_ + +`dialTimeout` is the maximum duration allowed for a connection to a backend server to be established. +Zero means no timeout. + +```yaml tab="File (YAML)" +## Static configuration +tcpServersTransport: + dialTimeout: 30s +``` + +```toml tab="File (TOML)" +## Static configuration +[tcpServersTransport] + dialTimeout = "30s" +``` + +```bash tab="CLI" +## Static configuration +--tcpServersTransport.dialTimeout=30s +``` + +#### `dialKeepAlive` + +_Optional, Default="15s"_ + +`dialKeepAlive` defines the interval between keep-alive probes sent on an active network connection. +If zero, keep-alive probes are sent with a default value (currently 15 seconds), if supported by the protocol and +operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, +keep-alive probes are disabled. + +```yaml tab="File (YAML)" +## Static configuration +tcpServersTransport: + dialKeepAlive: 30s +``` + +```toml tab="File (TOML)" +## Static configuration +[tcpServersTransport] + dialKeepAlive = "30s" +``` + +```bash tab="CLI" +## Static configuration +--tcpServersTransport.dialKeepAlive=30s +``` + +#### `tls` + +`tls` defines the TLS configuration to connect with TCP backends. + +_Optional_ + +An empty `tls` section enables TLS. + +```yaml tab="File (YAML)" +## Static configuration +tcpServersTransport: + tls: {} +``` + +```toml tab="File (TOML)" +## Static configuration +[tcpServersTransport.tls] +``` + +```bash tab="CLI" +## Static configuration +--tcpServersTransport.tls=true +``` + +#### `tls.insecureSkipVerify` + +_Optional_ + +`insecureSkipVerify` disables the server's certificate chain and host name verification. + +```yaml tab="File (YAML)" +## Static configuration +tcpServersTransport: + tls: + insecureSkipVerify: true +``` + +```toml tab="File (TOML)" +## Static configuration +[tcpServersTransport.tls] + insecureSkipVerify = true +``` + +```bash tab="CLI" +## Static configuration +--tcpServersTransport.tls.insecureSkipVerify=true +``` + +#### `tls.rootCAs` + +_Optional_ + +`rootCAs` defines the set of Root Certificate Authorities (as file paths, or data bytes) +to use when verifying self-signed TLS server certificates. + +```yaml tab="File (YAML)" +## Static configuration +tcpServersTransport: + tls: + rootCAs: + - foo.crt + - bar.crt +``` + +```toml tab="File (TOML)" +## Static configuration +[tcpServersTransport.tls] + rootCAs = ["foo.crt", "bar.crt"] +``` + +```bash tab="CLI" +## Static configuration +--tcpServersTransport.tls.rootCAs=foo.crt,bar.crt +``` + +#### `spiffe` + +Please note that [SPIFFE](../https/spiffe.md) must be enabled in the static configuration +before using it to secure the connection between Traefik and the backends. + +#### `spiffe.ids` + +_Optional_ + +`ids` defines the allowed SPIFFE IDs. +This takes precedence over the SPIFFE TrustDomain. + +```yaml tab="File (YAML)" +## Static configuration +tcpServersTransport: + spiffe: + ids: + - spiffe://trust-domain/id1 + - spiffe://trust-domain/id2 +``` + +```toml tab="File (TOML)" +## Static configuration +[tcpServersTransport.spiffe] + ids = ["spiffe://trust-domain/id1", "spiffe://trust-domain/id2"] +``` + +```bash tab="CLI" +## Static configuration +--tcpServersTransport.spiffe.ids=spiffe://trust-domain/id1,spiffe://trust-domain/id2 +``` + +#### `spiffe.trustDomain` + +_Optional_ + +`trustDomain` defines the allowed SPIFFE trust domain. + +```yaml tab="File (YAML)" +## Static configuration +tcpServersTransport: + trustDomain: spiffe://trust-domain +``` + +```toml tab="File (TOML)" +## Static configuration +[tcpServersTransport.spiffe] + trustDomain = "spiffe://trust-domain" +``` + +```bash tab="CLI" +## Static configuration +--tcpServersTransport.spiffe.trustDomain=spiffe://trust-domain +``` + {!traefik-for-business-applications.md!} diff --git a/docs/content/routing/providers/consul-catalog.md b/docs/content/routing/providers/consul-catalog.md index 6d2ddb8a2..8eb985043 100644 --- a/docs/content/routing/providers/consul-catalog.md +++ b/docs/content/routing/providers/consul-catalog.md @@ -404,12 +404,12 @@ You can declare TCP Routers and/or Services using tags. traefik.tcp.services.mytcpservice.loadbalancer.server.port=423 ``` -??? info "`traefik.tcp.services..loadbalancer.terminationdelay`" - - See [termination delay](../services/index.md#termination-delay) for more information. +??? info "`traefik.tcp.services..loadbalancer.server.tls`" + + Determines whether to use TLS when dialing with the backend. ```yaml - traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay=100 + traefik.tcp.services.mytcpservice.loadbalancer.server.tls=true ``` ??? info "`traefik.tcp.services..loadbalancer.proxyprotocol.version`" @@ -420,6 +420,15 @@ You can declare TCP Routers and/or Services using tags. traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version=1 ``` +??? info "`traefik.tcp.services..loadbalancer.serverstransport`" + + Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. + See [serverstransport](../services/index.md#serverstransport_2) for more information. + + ```yaml + traefik.tcp.services.myservice.loadbalancer.serverstransport=foobar@file + ``` + ### UDP You can declare UDP Routers and/or Services using tags. diff --git a/docs/content/routing/providers/docker.md b/docs/content/routing/providers/docker.md index eacf78956..08e8e43ad 100644 --- a/docs/content/routing/providers/docker.md +++ b/docs/content/routing/providers/docker.md @@ -577,12 +577,12 @@ You can declare TCP Routers and/or Services using labels. - "traefik.tcp.services.mytcpservice.loadbalancer.server.port=423" ``` -??? info "`traefik.tcp.services..loadbalancer.terminationdelay`" +??? info "`traefik.tcp.services..loadbalancer.server.tls`" - See [termination delay](../services/index.md#termination-delay) for more information. + Determines whether to use TLS when dialing with the backend. ```yaml - - "traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay=100" + - "traefik.tcp.services.mytcpservice.loadbalancer.server.tls=true" ``` ??? info "`traefik.tcp.services..loadbalancer.proxyprotocol.version`" @@ -593,6 +593,15 @@ You can declare TCP Routers and/or Services using labels. - "traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version=1" ``` +??? info "`traefik.tcp.services..loadbalancer.serverstransport`" + + Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. + See [serverstransport](../services/index.md#serverstransport_2) for more information. + + ```yaml + - "traefik.tcp.services..loadbalancer.serverstransport=foobar@file" + ``` + ### UDP You can declare UDP Routers and/or Services using labels. diff --git a/docs/content/routing/providers/ecs.md b/docs/content/routing/providers/ecs.md index 9cd180641..718303c0b 100644 --- a/docs/content/routing/providers/ecs.md +++ b/docs/content/routing/providers/ecs.md @@ -418,12 +418,12 @@ You can declare TCP Routers and/or Services using labels. traefik.tcp.services.mytcpservice.loadbalancer.server.port=423 ``` -??? info "`traefik.tcp.services..loadbalancer.terminationdelay`" - - See [termination delay](../services/index.md#termination-delay) for more information. +??? info "`traefik.tcp.services..loadbalancer.server.tls`" + + Determines whether to use TLS when dialing with the backend. ```yaml - traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay=100 + traefik.tcp.services.mytcpservice.loadbalancer.server.tls=true ``` ??? info "`traefik.tcp.services..loadbalancer.proxyprotocol.version`" @@ -434,6 +434,15 @@ You can declare TCP Routers and/or Services using labels. traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version=1 ``` +??? info "`traefik.tcp.services..loadbalancer.serverstransport`" + + Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. + See [serverstransport](../services/index.md#serverstransport_2) for more information. + + ```yaml + traefik.tcp.services..loadbalancer.serverstransport=foobar@file + ``` + ### UDP You can declare UDP Routers and/or Services using tags. diff --git a/docs/content/routing/providers/kubernetes-crd.md b/docs/content/routing/providers/kubernetes-crd.md index f39ef599e..789cb018b 100644 --- a/docs/content/routing/providers/kubernetes-crd.md +++ b/docs/content/routing/providers/kubernetes-crd.md @@ -295,17 +295,18 @@ The Kubernetes Ingress Controller, The Custom Resource Way. You can find an excerpt of the available custom resources in the table below: -| Kind | Purpose | Concept Behind | -|--------------------------------------------|--------------------------------------------------------------------|----------------------------------------------------------------| -| [IngressRoute](#kind-ingressroute) | HTTP Routing | [HTTP router](../routers/index.md#configuring-http-routers) | -| [Middleware](#kind-middleware) | Tweaks the HTTP requests before they are sent to your service | [HTTP Middlewares](../../middlewares/http/overview.md) | -| [TraefikService](#kind-traefikservice) | Abstraction for HTTP loadbalancing/mirroring | [HTTP service](../services/index.md#configuring-http-services) | -| [IngressRouteTCP](#kind-ingressroutetcp) | TCP Routing | [TCP router](../routers/index.md#configuring-tcp-routers) | -| [MiddlewareTCP](#kind-middlewaretcp) | Tweaks the TCP requests before they are sent to your service | [TCP Middlewares](../../middlewares/tcp/overview.md) | -| [IngressRouteUDP](#kind-ingressrouteudp) | UDP Routing | [UDP router](../routers/index.md#configuring-udp-routers) | -| [TLSOptions](#kind-tlsoption) | Allows to configure some parameters of the TLS connection | [TLSOptions](../../https/tls.md#tls-options) | -| [TLSStores](#kind-tlsstore) | Allows to configure the default TLS store | [TLSStores](../../https/tls.md#certificates-stores) | -| [ServersTransport](#kind-serverstransport) | Allows to configure the transport between Traefik and the backends | [ServersTransport](../../services/#serverstransport_1) | +| Kind | Purpose | Concept Behind | +|--------------------------------------------------|--------------------------------------------------------------------|----------------------------------------------------------------| +| [IngressRoute](#kind-ingressroute) | HTTP Routing | [HTTP router](../routers/index.md#configuring-http-routers) | +| [Middleware](#kind-middleware) | Tweaks the HTTP requests before they are sent to your service | [HTTP Middlewares](../../middlewares/http/overview.md) | +| [TraefikService](#kind-traefikservice) | Abstraction for HTTP loadbalancing/mirroring | [HTTP service](../services/index.md#configuring-http-services) | +| [IngressRouteTCP](#kind-ingressroutetcp) | TCP Routing | [TCP router](../routers/index.md#configuring-tcp-routers) | +| [MiddlewareTCP](#kind-middlewaretcp) | Tweaks the TCP requests before they are sent to your service | [TCP Middlewares](../../middlewares/tcp/overview.md) | +| [IngressRouteUDP](#kind-ingressrouteudp) | UDP Routing | [UDP router](../routers/index.md#configuring-udp-routers) | +| [TLSOptions](#kind-tlsoption) | Allows to configure some parameters of the TLS connection | [TLSOptions](../../https/tls.md#tls-options) | +| [TLSStores](#kind-tlsstore) | Allows to configure the default TLS store | [TLSStores](../../https/tls.md#certificates-stores) | +| [ServersTransport](#kind-serverstransport) | Allows to configure the transport between Traefik and the backends | [ServersTransport](../../services/#serverstransport_1) | +| [ServersTransportTCP](#kind-serverstransporttcp) | Allows to configure the transport between Traefik and the backends | [TCP ServersTransport](../../services/#serverstransport_3) | ### Kind: `IngressRoute` @@ -1088,60 +1089,60 @@ Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kube name: ingressroutetcpfoo spec: - entryPoints: # [1] + entryPoints: # [1] - footcp - routes: # [2] - - match: HostSNI(`*`) # [3] - priority: 10 # [4] + routes: # [2] + - match: HostSNI(`*`) # [3] + priority: 10 # [4] middlewares: - - name: middleware1 # [5] - namespace: default # [6] - services: # [7] - - name: foo # [8] - port: 8080 # [9] - weight: 10 # [10] - terminationDelay: 400 # [11] - proxyProtocol: # [12] - version: 1 # [13] - tls: # [14] - secretName: supersecret # [15] - options: # [16] - name: opt # [17] - namespace: default # [18] - certResolver: foo # [19] - domains: # [20] - - main: example.net # [21] - sans: # [22] + - name: middleware1 # [5] + namespace: default # [6] + services: # [7] + - name: foo # [8] + port: 8080 # [9] + weight: 10 # [10] + proxyProtocol: # [11] + version: 1 # [12] + serversTransport: transport # [13] + tls: # [14] + secretName: supersecret # [15] + options: # [16] + name: opt # [17] + namespace: default # [18] + certResolver: foo # [19] + domains: # [20] + - main: example.net # [21] + sans: # [22] - a.example.net - b.example.net - passthrough: false # [23] + passthrough: false # [23] ``` -| Ref | Attribute | Purpose | -|------|--------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [1] | `entryPoints` | List of [entrypoints](../routers/index.md#entrypoints_1) names | -| [2] | `routes` | List of routes | -| [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule_1) of the underlying router | -| [4] | `routes[n].priority` | Defines the [priority](../routers/index.md#priority_1) to disambiguate rules of the same length, for route matching | -| [5] | `middlewares[n].name` | Defines the [MiddlewareTCP](#kind-middlewaretcp) name | -| [6] | `middlewares[n].namespace` | Defines the [MiddlewareTCP](#kind-middlewaretcp) namespace | -| [7] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions (See below for `ExternalName Service` setup) | -| [8] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) | -| [9] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port. | -| [10] | `services[n].weight` | Defines the weight to apply to the server load balancing | -| [11] | `services[n].terminationDelay` | corresponds to 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). | -| [12] | `proxyProtocol` | Defines the [PROXY protocol](../services/index.md#proxy-protocol) configuration | -| [13] | `version` | Defines the [PROXY protocol](../services/index.md#proxy-protocol) version | -| [14] | `tls` | Defines [TLS](../routers/index.md#tls_1) certificate configuration | -| [15] | `tls.secretName` | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace) | -| [16] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) | -| [17] | `options.name` | Defines the [TLSOption](#kind-tlsoption) name | -| [18] | `options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace | -| [19] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver_1) | -| [20] | `tls.domains` | List of [domains](../routers/index.md#domains_1) | -| [21] | `domains[n].main` | Defines the main domain name | -| [22] | `domains[n].sans` | List of SANs (alternative domains) | -| [23] | `tls.passthrough` | If `true`, delegates the TLS termination to the backend | +| Ref | Attribute | Purpose | +|------|-------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [1] | `entryPoints` | List of [entrypoints](../routers/index.md#entrypoints_1) names | +| [2] | `routes` | List of routes | +| [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule_1) of the underlying router | +| [4] | `routes[n].priority` | Defines the [priority](../routers/index.md#priority_1) to disambiguate rules of the same length, for route matching | +| [5] | `middlewares[n].name` | Defines the [MiddlewareTCP](#kind-middlewaretcp) name | +| [6] | `middlewares[n].namespace` | Defines the [MiddlewareTCP](#kind-middlewaretcp) namespace | +| [7] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions (See below for `ExternalName Service` setup) | +| [8] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) | +| [9] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port. | +| [10] | `services[n].weight` | Defines the weight to apply to the server load balancing | +| [11] | `services[n].proxyProtocol` | Defines the [PROXY protocol](../services/index.md#proxy-protocol) configuration | +| [12] | `services[n].proxyProtocol.version` | Defines the [PROXY protocol](../services/index.md#proxy-protocol) version | +| [13] | `services[n].serversTransport` | Defines the reference to a [ServersTransportTCP](#kind-serverstransporttcp). The ServersTransport namespace is assumed to be the [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) namespace (see [ServersTransport reference](#serverstransport-reference)). | +| [14] | `tls` | Defines [TLS](../routers/index.md#tls_1) certificate configuration | +| [15] | `tls.secretName` | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace) | +| [16] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) | +| [17] | `tls.options.name` | Defines the [TLSOption](#kind-tlsoption) name | +| [18] | `tls.options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace | +| [19] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver_1) | +| [20] | `tls.domains` | List of [domains](../routers/index.md#domains_1) | +| [21] | `tls.domains[n].main` | Defines the main domain name | +| [22] | `tls.domains[n].sans` | List of SANs (alternative domains) | +| [23] | `tls.passthrough` | If `true`, delegates the TLS termination to the backend | ??? example "Declaring an IngressRouteTCP" @@ -1161,11 +1162,9 @@ Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kube services: - name: foo port: 8080 - terminationDelay: 400 weight: 10 - name: bar port: 8081 - terminationDelay: 500 weight: 10 tls: certResolver: foo @@ -1689,7 +1688,7 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres !!! important "Default serversTransport" If no `serversTransport` is specified, the `default@internal` will be used. - The `default@internal` serversTransport is created from the [static configuration](../overview.md#transport-configuration). + The `default@internal` serversTransport is created from the [static configuration](../overview.md#http-servers-transports). !!! info "ServersTransport Attributes" @@ -1701,21 +1700,26 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres namespace: default spec: - serverName: foobar # [1] - insecureSkipVerify: true # [2] - rootCAsSecrets: # [3] + serverName: foobar # [1] + insecureSkipVerify: true # [2] + rootCAsSecrets: # [3] - foobar - foobar - certificatesSecrets: # [4] + certificatesSecrets: # [4] - foobar - foobar - maxIdleConnsPerHost: 1 # [5] - forwardingTimeouts: # [6] - dialTimeout: 42s # [7] - responseHeaderTimeout: 42s # [8] - idleConnTimeout: 42s # [9] - peerCertURI: foobar # [10] - disableHTTP2: true # [11] + maxIdleConnsPerHost: 1 # [5] + forwardingTimeouts: # [6] + dialTimeout: 42s # [7] + responseHeaderTimeout: 42s # [8] + idleConnTimeout: 42s # [9] + peerCertURI: foobar # [10] + disableHTTP2: true # [11] + spiffe: # [12] + ids: # [13] + - spiffe://trust-domain/id1 + - spiffe://trust-domain/id2 + trustDomain: "spiffe://trust-domain" # [14] ``` | Ref | Attribute | Purpose | @@ -1731,6 +1735,9 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres | [9] | `idleConnTimeout` | The maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. If zero, no timeout exists. | | [10] | `peerCertURI` | URI used to match against SAN URIs during the server's certificate verification. | | [11] | `disableHTTP2` | Disables HTTP/2 for connections with servers. | +| [12] | `spiffe` | The spiffe configuration. | +| [13] | `ids` | Defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain). | +| [14] | `trustDomain` | Defines the allowed SPIFFE trust domain. | !!! info "CA Secret" @@ -1775,10 +1782,110 @@ By default, the referenced ServersTransport CRD must be defined in the same [Kub To reference a ServersTransport CRD from another namespace, the value must be of form `namespace-name@kubernetescrd`, -and the [cross-namespace](../../../providers/kubernetes-crd/#allowcrossnamespace) option must be enabled. +and the [allowCrossNamespace](../../../providers/kubernetes-crd/#allowcrossnamespace) option must be enabled. If the ServersTransport CRD is defined in another provider the cross-provider format `name@provider` should be used. +### Kind: `ServersTransportTCP` + +`ServersTransportTCP` is the CRD implementation of a [ServersTransportTCP](../services/index.md#serverstransport_2). + +!!! important "Default serversTransportTCP" +If no `serversTransportTCP` is specified, the `default@internal` will be used. +The `default@internal` serversTransportTCP is created from the [static configuration](../overview.md#tcp-servers-transports). + +!!! info "ServersTransportTCP Attributes" + + ```yaml tab="ServersTransportTCP" + apiVersion: traefik.containo.us/v1alpha1 + kind: ServersTransportTCP + metadata: + name: mytransport + namespace: default + + spec: + dialTimeout: 42s # [1] + dialKeepAlive: 42s # [2] + terminationDelay: 42s # [3] + tls: # [4] + serverName: foobar # [5] + insecureSkipVerify: true # [6] + peerCertURI: foobar # [7] + rootCAsSecrets: # [8] + - foobar + - foobar + certificatesSecrets: # [9] + - foobar + - foobar + spiffe: # [10] + ids: # [11] + - spiffe://trust-domain/id1 + - spiffe://trust-domain/id2 + trustDomain: "spiffe://trust-domain" # [12] + ``` + +| Ref | Attribute | Purpose | +|------|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [1] | `dialTimeout` | The amount of time to wait until a connection to a server can be established. If zero, no timeout exists. | +| [2] | `dialKeepAlive` | The interval between keep-alive probes for an active network connection. If zero, keep-alive probes are sent with a default value (currently 15 seconds), if supported by the protocol and operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, keep-alive probes are disabled. | +| [3] | `terminationDelay` | Defines the delay to wait before fully terminating the connection, after one connected peer has closed its writing capability. | +| [4] | `tls` | The TLS configuration. | +| [5] | `serverName` | ServerName used to contact the server. | +| [6] | `insecureSkipVerify` | Controls whether the server's certificate chain and host name is verified. | +| [7] | `peerCertURI` | URI used to match against SAN URIs during the server's certificate verification. | +| [8] | `rootCAsSecrets` | Defines the set of root certificate authorities to use when verifying server certificates. The secret must contain a certificate under either a tls.ca or a ca.crt key. | +| [9] | `certificatesSecrets` | Certificates to present to the server for mTLS. | +| [10] | `spiffe` | The SPIFFE configuration. | +| [11] | `ids` | Defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain). | +| [12] | `trustDomain` | Defines the allowed SPIFFE trust domain. | + +!!! info "CA Secret" + + The CA secret must contain a base64 encoded certificate under either a `tls.ca` or a `ca.crt` key. + +??? example "Declaring and referencing a ServersTransportTCP" + + ```yaml tab="ServersTransportTCP" + apiVersion: traefik.containo.us/v1alpha1 + kind: ServersTransportTCP + metadata: + name: mytransport + namespace: default + + spec: + tls: + serverName: example.org + insecureSkipVerify: true + ``` + + ```yaml tab="IngressRouteTCP" + apiVersion: traefik.containo.us/v1alpha1 + kind: IngressRouteTCP + metadata: + name: testroute + namespace: default + + spec: + entryPoints: + - tcpep + routes: + - match: HostSNI(`bar`) + services: + - name: whoamitcp + port: 8080 + serversTransport: mytransport + ``` + +#### ServersTransportTCP reference + +By default, the referenced ServersTransportTCP CRD must be defined in the same [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) namespace. + +To reference a ServersTransportTCP CRD from another namespace, +the value must be of form `namespace-name@kubernetescrd`, +and the [allowCrossNamespace](../../../providers/kubernetes-crd/#allowcrossnamespace) option must be enabled. + +If the ServersTransportTCP CRD is defined in another provider the cross-provider format `name@provider` should be used. + ## Further Also see the [full example](../../user-guides/crd-acme/index.md) with Let's Encrypt. diff --git a/docs/content/routing/providers/kv.md b/docs/content/routing/providers/kv.md index bce4d7703..edc911614 100644 --- a/docs/content/routing/providers/kv.md +++ b/docs/content/routing/providers/kv.md @@ -413,14 +413,6 @@ You can declare TCP Routers and/or Services using KV. | Key (Path) | Value | |--------------------------------------------------------------------|------------------| | `traefik/tcp/services/mytcpservice/loadbalancer/servers/0/address` | `xx.xx.xx.xx:xx` | - -??? info "`traefik/tcp/services//loadbalancer/terminationdelay`" - - See [termination delay](../services/index.md#termination-delay) for more information. - - | Key (Path) | Value | - |-------------------------------------------------------------------|-------| - | `traefik/tcp/services/mytcpservice/loadbalancer/terminationdelay` | `100` | ??? info "`traefik/tcp/services//loadbalancer/proxyprotocol/version`" @@ -430,6 +422,15 @@ You can declare TCP Routers and/or Services using KV. |------------------------------------------------------------------------|-------| | `traefik/tcp/services/mytcpservice/loadbalancer/proxyprotocol/version` | `1` | +??? info "`traefik/tcp/services//loadbalancer/serverstransport`" + + Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. + See [serverstransport](../services/index.md#serverstransport_2) for more information. + + | Key (Path) | Value | + |-----------------------------------------------------------------|---------------| + | `traefik/tcp/services/myservice/loadbalancer/serverstransport` | `foobar@file` | + ??? info "`traefik/tcp/services//weighted/services//name`" | Key (Path) | Value | diff --git a/docs/content/routing/providers/marathon.md b/docs/content/routing/providers/marathon.md index 19a8a8dde..ea13368ad 100644 --- a/docs/content/routing/providers/marathon.md +++ b/docs/content/routing/providers/marathon.md @@ -451,12 +451,12 @@ You can declare TCP Routers and/or Services using labels. "traefik.tcp.services.mytcpservice.loadbalancer.server.port": "423" ``` -??? info "`traefik.tcp.services..loadbalancer.terminationdelay`" - - See [termination delay](../services/index.md#termination-delay) for more information. +??? info "`traefik.tcp.services..loadbalancer.server.tls`" + + Determines whether to use TLS when dialing with the backend. ```json - "traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay": "100" + "traefik.tcp.services.mytcpservice.loadbalancer.server.tls": "true" ``` ??? info "`traefik.tcp.services..loadbalancer.proxyprotocol.version`" @@ -467,6 +467,15 @@ You can declare TCP Routers and/or Services using labels. "traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version": "1" ``` +??? info "`traefik.tcp.services..loadbalancer.serverstransport`" + + Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. + See [serverstransport](../services/index.md#serverstransport_2) for more information. + + ```json + "traefik.tcp.services..loadbalancer.serverstransport": "foobar@file" + ``` + ### UDP You can declare UDP Routers and/or Services using labels. diff --git a/docs/content/routing/providers/nomad.md b/docs/content/routing/providers/nomad.md index e4d24a942..b0143d094 100644 --- a/docs/content/routing/providers/nomad.md +++ b/docs/content/routing/providers/nomad.md @@ -396,12 +396,12 @@ You can declare TCP Routers and/or Services using tags. traefik.tcp.services.mytcpservice.loadbalancer.server.port=423 ``` -??? info "`traefik.tcp.services..loadbalancer.terminationdelay`" +??? info "`traefik.tcp.services..loadbalancer.server.tls`" - See [termination delay](../services/index.md#termination-delay) for more information. + Determines whether to use TLS when dialing with the backend. ```yaml - traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay=100 + traefik.tcp.services.mytcpservice.loadbalancer.server.tls=true ``` ??? info "`traefik.tcp.services..loadbalancer.proxyprotocol.version`" @@ -412,6 +412,15 @@ You can declare TCP Routers and/or Services using tags. traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version=1 ``` +??? info "`traefik.tcp.services..loadbalancer.serverstransport`" + + Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. + See [serverstransport](../services/index.md#serverstransport_2) for more information. + + ```yaml + traefik.tcp.services.myservice.loadbalancer.serverstransport=foobar@file + ``` + ### UDP You can declare UDP Routers and/or Services using tags. diff --git a/docs/content/routing/providers/rancher.md b/docs/content/routing/providers/rancher.md index 7d392889e..5e711ed5e 100644 --- a/docs/content/routing/providers/rancher.md +++ b/docs/content/routing/providers/rancher.md @@ -454,12 +454,12 @@ You can declare TCP Routers and/or Services using labels. - "traefik.tcp.services.mytcpservice.loadbalancer.server.port=423" ``` -??? info "`traefik.tcp.services..loadbalancer.terminationdelay`" - - See [termination delay](../services/index.md#termination-delay) for more information. +??? info "`traefik.tcp.services..loadbalancer.server.tls`" + + Determines whether to use TLS when dialing with the backend. ```yaml - - "traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay=100" + - "traefik.tcp.services.mytcpservice.loadbalancer.server.tls=true" ``` ??? info "`traefik.tcp.services..loadbalancer.proxyprotocol.version`" @@ -470,6 +470,15 @@ You can declare TCP Routers and/or Services using labels. - "traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version=1" ``` +??? info "`traefik.tcp.services..loadbalancer.serverstransport`" + + Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. + See [serverstransport](../services/index.md#serverstransport_2) for more information. + + ```yaml + - "traefik.tcp.services..loadbalancer.serverstransport=foobar@file" + ``` + ### UDP You can declare UDP Routers and/or Services using labels. diff --git a/docs/content/routing/services/index.md b/docs/content/routing/services/index.md index 5e2766f0e..47bd23078 100644 --- a/docs/content/routing/services/index.md +++ b/docs/content/routing/services/index.md @@ -473,9 +473,9 @@ By default, `passHostHeader` is true. #### ServersTransport -`serversTransport` allows to reference a [ServersTransport](./index.md#serverstransport_1) configuration for the communication between Traefik and your servers. +`serversTransport` allows to reference an [HTTP ServersTransport](./index.md#serverstransport_1) configuration for the communication between Traefik and your servers. -??? example "Specify a transport -- Using the [File Provider](../../providers/file.md)" +??? example "Specify an HTTP transport -- Using the [File Provider](../../providers/file.md)" ```yaml tab="YAML" ## Dynamic configuration @@ -494,9 +494,9 @@ By default, `passHostHeader` is true. serversTransport = "mytransport" ``` -!!! info default serversTransport +!!! info Default Servers Transport If no serversTransport is specified, the `default@internal` will be used. - The `default@internal` serversTransport is created from the [static configuration](../overview.md#transport-configuration). + The `default@internal` serversTransport is created from the [static configuration](../overview.md#http-servers-transports). #### Response Forwarding @@ -532,9 +532,9 @@ Below are the available options for the Response Forwarding mechanism: ### ServersTransport -ServersTransport allows to configure the transport between Traefik and your servers. +ServersTransport allows to configure the transport between Traefik and your HTTP servers. -#### `ServerName` +#### `serverName` _Optional_ @@ -562,10 +562,10 @@ metadata: namespace: default spec: - serverName: "test" + serverName: "test" ``` -#### `Certificates` +#### `certificates` _Optional_ @@ -597,7 +597,7 @@ metadata: namespace: default spec: - certificatesSecrets: + certificatesSecrets: - mycert --- @@ -606,9 +606,9 @@ kind: Secret metadata: name: mycert - data: - tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= - tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= ``` #### `insecureSkipVerify` @@ -639,7 +639,7 @@ metadata: namespace: default spec: - insecureSkipVerify: true + insecureSkipVerify: true ``` #### `rootCAs` @@ -672,7 +672,7 @@ metadata: namespace: default spec: - rootCAsSecrets: + rootCAsSecrets: - myca --- apiVersion: v1 @@ -680,8 +680,8 @@ kind: Secret metadata: name: myca - data: - ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= +data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= ``` #### `maxIdleConnsPerHost` @@ -712,7 +712,7 @@ metadata: namespace: default spec: - maxIdleConnsPerHost: 7 + maxIdleConnsPerHost: 7 ``` #### `disableHTTP2` @@ -721,12 +721,6 @@ _Optional, Default=false_ `disableHTTP2` disables HTTP/2 for connections with servers. -```toml tab="File (TOML)" -## Dynamic configuration -[http.serversTransports.mytransport] - disableHTTP2 = true -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: @@ -735,6 +729,12 @@ http: disableHTTP2: true ``` +```toml tab="File (TOML)" +## Dynamic configuration +[http.serversTransports.mytransport] + disableHTTP2 = true +``` + ```yaml tab="Kubernetes" apiVersion: traefik.containo.us/v1alpha1 kind: ServersTransport @@ -743,7 +743,7 @@ metadata: namespace: default spec: - disableHTTP2: true + disableHTTP2: true ``` #### `peerCertURI` @@ -752,12 +752,6 @@ _Optional, Default=false_ `peerCertURI` defines the URI used to match against SAN URIs during the server's certificate verification. -```toml tab="File (TOML)" -## Dynamic configuration -[http.serversTransports.mytransport] - peerCertURI = "foobar" -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: @@ -766,6 +760,12 @@ http: peerCertURI: foobar ``` +```toml tab="File (TOML)" +## Dynamic configuration +[http.serversTransports.mytransport] + peerCertURI = "foobar" +``` + ```yaml tab="Kubernetes" apiVersion: traefik.containo.us/v1alpha1 kind: ServersTransport @@ -774,7 +774,7 @@ metadata: namespace: default spec: - peerCertURI: foobar + peerCertURI: foobar ``` #### `spiffe` @@ -923,8 +923,8 @@ metadata: namespace: default spec: - forwardingTimeouts: - responseHeaderTimeout: "1s" + forwardingTimeouts: + responseHeaderTimeout: "1s" ``` ##### `forwardingTimeouts.idleConnTimeout` @@ -957,8 +957,8 @@ metadata: namespace: default spec: - forwardingTimeouts: - idleConnTimeout: "1s" + forwardingTimeouts: + idleConnTimeout: "1s" ``` ##### `forwardingTimeouts.readIdleTimeout` @@ -995,8 +995,8 @@ metadata: namespace: default spec: - forwardingTimeouts: - readIdleTimeout: "1s" + forwardingTimeouts: + readIdleTimeout: "1s" ``` ##### `forwardingTimeouts.pingTimeout` @@ -1029,8 +1029,8 @@ metadata: namespace: default spec: - forwardingTimeouts: - pingTimeout: "1s" + forwardingTimeouts: + pingTimeout: "1s" ``` ### Weighted Round Robin (service) @@ -1469,6 +1469,9 @@ The servers load balancer is in charge of balancing the requests between the ser #### Servers Servers declare a single instance of your program. + +#### `address` + The `address` option (IP:Port) point to a specific instance. ??? example "A Service with One Server -- Using the [File Provider](../../providers/file.md)" @@ -1491,6 +1494,60 @@ The `address` option (IP:Port) point to a specific instance. address = "xx.xx.xx.xx:xx" ``` +#### `tls` + +The `tls` determines whether to use TLS when dialing with the backend. + +??? example "A Service with One Server Using TLS -- Using the [File Provider](../../providers/file.md)" + + ```yaml tab="YAML" + ## Dynamic configuration + tcp: + services: + my-service: + loadBalancer: + servers: + - address: "xx.xx.xx.xx:xx" + tls: true + ``` + + ```toml tab="TOML" + ## Dynamic configuration + [tcp.services] + [tcp.services.my-service.loadBalancer] + [[tcp.services.my-service.loadBalancer.servers]] + address = "xx.xx.xx.xx:xx" + tls = true + ``` + +#### ServersTransport + +`serversTransport` allows to reference a [TCP ServersTransport](./index.md#serverstransport_3) configuration for the communication between Traefik and your servers. + +??? example "Specify a TCP transport -- Using the [File Provider](../../providers/file.md)" + + ```yaml tab="YAML" + ## Dynamic configuration + tcp: + services: + Service01: + loadBalancer: + serversTransport: mytransport + ``` + + ```toml tab="TOML" + ## Dynamic configuration + [tcp.services] + [tcp.services.Service01] + [tcp.services.Service01.loadBalancer] + serversTransport = "mytransport" + ``` + +!!! info "Default Servers Transport" + + If no serversTransport is specified, the `default@internal` will be used. + The `default@internal` serversTransport is created from the [static configuration](../overview.md#tcp-servers-transports). + #### PROXY Protocol Traefik supports [PROXY Protocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2 on TCP Services. @@ -1524,39 +1581,6 @@ Below are the available options for the PROXY protocol: version = 1 ``` -#### Termination Delay - -As a proxy between a client and a server, it can happen that either side (e.g. client side) decides to terminate its writing capability on the connection (i.e. issuance of a FIN packet). -The proxy needs to propagate that intent to the other side, and so when that happens, it also does the same on its connection with the other side (e.g. backend side). - -However, if for some reason (bad implementation, or malicious intent) the other side does not eventually do the same as well, -the connection would stay half-open, which would lock resources for however long. - -To that end, as soon as the proxy enters this termination sequence, it sets a deadline on fully terminating the connections on both sides. - -The termination delay controls that deadline. -It is a duration in milliseconds, defaulting to 100. -A negative value means an infinite deadline (i.e. the connection is never fully terminated by the proxy itself). - -??? example "A Service with a termination delay -- Using the [File Provider](../../providers/file.md)" - - ```yaml tab="YAML" - ## Dynamic configuration - tcp: - services: - my-service: - loadBalancer: - terminationDelay: 200 - ``` - - ```toml tab="TOML" - ## Dynamic configuration - [tcp.services] - [tcp.services.my-service.loadBalancer] - [[tcp.services.my-service.loadBalancer]] - terminationDelay = 200 - ``` - ### Weighted Round Robin The Weighted Round Robin (alias `WRR`) load-balancer of services is in charge of balancing the requests between multiple services based on provided weights. @@ -1612,6 +1636,414 @@ tcp: address = "private-ip-server-2:8080/" ``` +### ServersTransport + +ServersTransport allows to configure the transport between Traefik and your TCP servers. + +#### `dialTimeout` + +_Optional, Default="30s"_ + +`dialTimeout` defines the timeout when dialing the backend TCP service. If zero, no timeout exists. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + dialTimeout: 30s +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport] + dialTimeout = "30s" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + dialTimeout: 30s +``` + +#### `dialKeepAlive` + +_Optional, Default="15s"_ + +`dialKeepAlive` defines the interval between keep-alive probes for an active network connection. +If zero, keep-alive probes are sent with a default value (currently 15 seconds), if supported by the protocol and +operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, +keep-alive probes are disabled. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + dialKeepAlive: 30s +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport] + dialKeepAlive = "30s" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + dialKeepAlive: 30s +``` + +#### `terminationDelay` + +_Optional, Default="100ms"_ + +As a proxy between a client and a server, it can happen that either side (e.g. client side) decides to terminate its writing capability on the connection (i.e. issuance of a FIN packet). +The proxy needs to propagate that intent to the other side, and so when that happens, it also does the same on its connection with the other side (e.g. backend side). + +However, if for some reason (bad implementation, or malicious intent) the other side does not eventually do the same as well, +the connection would stay half-open, which would lock resources for however long. + +To that end, as soon as the proxy enters this termination sequence, it sets a deadline on fully terminating the connections on both sides. + +The termination delay controls that deadline. +A negative value means an infinite deadline (i.e. the connection is never fully terminated by the proxy itself). + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + terminationDelay: 100ms +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport] + terminationDelay = "100ms" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + terminationDelay: 100ms +``` + +#### `tls` + +`tls` defines the TLS configuration. + +_Optional_ + +An empty `tls` section enables TLS. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + tls: {} +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport.tls] +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + tls: {} +``` + +#### `tls.serverName` + +_Optional_ + +`tls.serverName` configure the server name that will be used for SNI. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + tls: + serverName: "myhost" +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport.tls] + serverName = "myhost" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + tls: + serverName: "test" +``` + +#### `tls.certificates` + +_Optional_ + +`tls.certificates` is the list of certificates (as file paths, or data bytes) +that will be set as client certificates for mTLS. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + tls: + certificates: + - certFile: foo.crt + keyFile: bar.crt +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[[tcp.serversTransports.mytransport.tls.certificates]] + certFile = "foo.crt" + keyFile = "bar.crt" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + tls: + certificatesSecrets: + - mycert + +--- +apiVersion: v1 +kind: Secret +metadata: + name: mycert + +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= +``` + +#### `tls.insecureSkipVerify` + +_Optional_ + +`tls.insecureSkipVerify` controls whether the server's certificate chain and host name is verified. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + tls: + insecureSkipVerify: true +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport.tls] + insecureSkipVerify = true +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + tls: + insecureSkipVerify: true +``` + +#### `tls.rootCAs` + +_Optional_ + +`tls.rootCAs` defines the set of root certificate authorities (as file paths, or data bytes) to use when verifying server certificates. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + tls: + rootCAs: + - foo.crt + - bar.crt +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport.tls] + rootCAs = ["foo.crt", "bar.crt"] +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + tls: + rootCAsSecrets: + - myca +--- +apiVersion: v1 +kind: Secret +metadata: + name: myca + +data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= +``` + +#### `tls.peerCertURI` + +_Optional, Default=false_ + +`tls.peerCertURI` defines the URI used to match against SAN URIs during the server's certificate verification. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + tls: + peerCertURI: foobar +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport.tls] + peerCertURI = "foobar" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + tls: + peerCertURI: foobar +``` + +#### `spiffe` + +Please note that [SPIFFE](../../https/spiffe.md) must be enabled in the static configuration +before using it to secure the connection between Traefik and the backends. + +##### `spiffe.ids` + +_Optional_ + +`ids` defines the allowed SPIFFE IDs. +This takes precedence over the SPIFFE TrustDomain. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + spiffe: + ids: + - spiffe://trust-domain/id1 + - spiffe://trust-domain/id2 +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport.spiffe] + ids = ["spiffe://trust-domain/id1", "spiffe://trust-domain/id2"] +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + spiffe: + ids: + - spiffe://trust-domain/id1 + - spiffe://trust-domain/id2 +``` + +##### `spiffe.trustDomain` + +_Optional_ + +`trustDomain` defines the allowed SPIFFE trust domain. + +```yaml tab="File (YAML)" +## Dynamic configuration +tcp: + serversTransports: + mytransport: + spiffe: + trustDomain: spiffe://trust-domain +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[tcp.serversTransports.mytransport.spiffe] + trustDomain = "spiffe://trust-domain" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + spiffe: + trustDomain: "spiffe://trust-domain" +``` + ## Configuring UDP Services ### General diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index 4a7f19a66..fe3187a7d 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -373,15 +373,16 @@ spec: to use. type: integer type: object - terminationDelay: - description: 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). - type: integer + serversTransport: + description: ServersTransport defines the name of ServersTransportTCP + resource to use. It allows to configure the transport + between Traefik and your servers. Can only be used on + a Kubernetes Service. + type: string + tls: + description: TLS determines whether to use TLS when dialing + with the backend. + type: boolean weight: description: Weight defines the weight used when balancing requests between multiple Kubernetes Service. @@ -1684,6 +1685,128 @@ status: conditions: [] storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: serverstransporttcps.traefik.containo.us +spec: + group: traefik.containo.us + names: + kind: ServersTransportTCP + listKind: ServersTransportTCPList + plural: serverstransporttcps + singular: serverstransporttcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: 'ServersTransportTCP is the CRD implementation of a TCPServersTransport. + If no tcpServersTransport is specified, a default one named default@internal + will be used. The default@internal tcpServersTransport can be configured + in the static configuration. More info: https://doc.traefik.io/traefik/v2.9/routing/services/#serverstransport_3' + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServersTransportTCPSpec defines the desired state of a ServersTransportTCP. + properties: + dialKeepAlive: + anyOf: + - type: integer + - type: string + description: DialKeepAlive is the interval between keep-alive probes + for an active network connection. If zero, keep-alive probes are + sent with a default value (currently 15 seconds), if supported by + the protocol and operating system. Network protocols or operating + systems that do not support keep-alives ignore this field. If negative, + keep-alive probes are disabled. + x-kubernetes-int-or-string: true + dialTimeout: + anyOf: + - type: integer + - type: string + description: DialTimeout is the amount of time to wait until a connection + to a backend server can be established. + x-kubernetes-int-or-string: true + terminationDelay: + anyOf: + - type: integer + - type: string + description: TerminationDelay defines the delay to wait before fully + terminating the connection, after one connected peer has closed + its writing capability. + x-kubernetes-int-or-string: true + tls: + description: TLS defines the TLS configuration + properties: + certificatesSecrets: + description: CertificatesSecrets defines a list of secret storing + client certificates for mTLS. + items: + type: string + type: array + insecureSkipVerify: + description: InsecureSkipVerify disables TLS certificate verification. + type: boolean + peerCertURI: + description: MaxIdleConnsPerHost controls the maximum idle (keep-alive) + to keep per-host. PeerCertURI defines the peer cert URI used + to match against SAN URI during the peer certificate verification. + type: string + rootCAsSecrets: + description: RootCAsSecrets defines a list of CA secret used to + validate self-signed certificates. + items: + type: string + type: array + serverName: + description: ServerName defines the server name used to contact + the server. + type: string + spiffe: + description: Spiffe defines the SPIFFE configuration. + properties: + ids: + description: IDs defines the allowed SPIFFE IDs (takes precedence + over the SPIFFE TrustDomain). + items: + type: string + type: array + trustDomain: + description: TrustDomain defines the allowed SPIFFE trust + domain. + type: string + type: object + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/integration/testdata/rawdata-crd.json b/integration/testdata/rawdata-crd.json index a49ebddb2..2e5c308bd 100644 --- a/integration/testdata/rawdata-crd.json +++ b/integration/testdata/rawdata-crd.json @@ -274,7 +274,6 @@ "tcpServices": { "default-test3.route-673acf455cb2dab0b43a-externalname-svc-9090@kubernetescrd": { "loadBalancer": { - "terminationDelay": 100, "servers": [ { "address": "domain.com:9090" @@ -285,7 +284,6 @@ }, "default-test3.route-673acf455cb2dab0b43a-whoamitcp-8080@kubernetescrd": { "loadBalancer": { - "terminationDelay": 100, "servers": [ { "address": "10.42.0.10:8080" diff --git a/integration/testdata/rawdata-gateway.json b/integration/testdata/rawdata-gateway.json index 46c50efd6..46a60e58f 100644 --- a/integration/testdata/rawdata-gateway.json +++ b/integration/testdata/rawdata-gateway.json @@ -229,7 +229,6 @@ }, "default-whoamitcp-8080@kubernetesgateway": { "loadBalancer": { - "terminationDelay": 100, "servers": [ { "address": "10.42.0.2:8080" diff --git a/pkg/config/dynamic/http_config.go b/pkg/config/dynamic/http_config.go index 746ced781..46260f904 100644 --- a/pkg/config/dynamic/http_config.go +++ b/pkg/config/dynamic/http_config.go @@ -264,15 +264,15 @@ type HealthCheck struct{} // ServersTransport options to configure communication between Traefik and the servers. type ServersTransport struct { - ServerName string `description:"ServerName used to contact the server." json:"serverName,omitempty" toml:"serverName,omitempty" yaml:"serverName,omitempty"` - InsecureSkipVerify bool `description:"Disable SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"` - RootCAs []traefiktls.FileOrContent `description:"Add cert file for self-signed certificate." json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"` - Certificates traefiktls.Certificates `description:"Certificates for mTLS." json:"certificates,omitempty" toml:"certificates,omitempty" yaml:"certificates,omitempty" export:"true"` + ServerName string `description:"Defines the serverName used to contact the server." json:"serverName,omitempty" toml:"serverName,omitempty" yaml:"serverName,omitempty"` + InsecureSkipVerify bool `description:"Disables SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"` + RootCAs []traefiktls.FileOrContent `description:"Defines a list of CA secret used to validate self-signed certificate" json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"` + Certificates traefiktls.Certificates `description:"Defines a list of secret storing client certificates for mTLS." json:"certificates,omitempty" toml:"certificates,omitempty" yaml:"certificates,omitempty" export:"true"` MaxIdleConnsPerHost int `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used" json:"maxIdleConnsPerHost,omitempty" toml:"maxIdleConnsPerHost,omitempty" yaml:"maxIdleConnsPerHost,omitempty" export:"true"` - ForwardingTimeouts *ForwardingTimeouts `description:"Timeouts for requests forwarded to the backend servers." json:"forwardingTimeouts,omitempty" toml:"forwardingTimeouts,omitempty" yaml:"forwardingTimeouts,omitempty" export:"true"` - DisableHTTP2 bool `description:"Disable HTTP/2 for connections with backend servers." json:"disableHTTP2,omitempty" toml:"disableHTTP2,omitempty" yaml:"disableHTTP2,omitempty" export:"true"` - PeerCertURI string `description:"URI used to match against SAN URI during the peer certificate verification." json:"peerCertURI,omitempty" toml:"peerCertURI,omitempty" yaml:"peerCertURI,omitempty" export:"true"` - Spiffe *Spiffe `description:"Define the SPIFFE configuration." json:"spiffe,omitempty" toml:"spiffe,omitempty" yaml:"spiffe,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` + ForwardingTimeouts *ForwardingTimeouts `description:"Defines the timeouts for requests forwarded to the backend servers." json:"forwardingTimeouts,omitempty" toml:"forwardingTimeouts,omitempty" yaml:"forwardingTimeouts,omitempty" export:"true"` + DisableHTTP2 bool `description:"Disables HTTP/2 for connections with backend servers." json:"disableHTTP2,omitempty" toml:"disableHTTP2,omitempty" yaml:"disableHTTP2,omitempty" export:"true"` + PeerCertURI string `description:"Defines the URI used to match against SAN URI during the peer certificate verification." json:"peerCertURI,omitempty" toml:"peerCertURI,omitempty" yaml:"peerCertURI,omitempty" export:"true"` + Spiffe *Spiffe `description:"Defines the SPIFFE configuration." json:"spiffe,omitempty" toml:"spiffe,omitempty" yaml:"spiffe,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` } // +k8s:deepcopy-gen=true diff --git a/pkg/config/dynamic/tcp_config.go b/pkg/config/dynamic/tcp_config.go index 19007fa8c..61ceb3563 100644 --- a/pkg/config/dynamic/tcp_config.go +++ b/pkg/config/dynamic/tcp_config.go @@ -2,7 +2,10 @@ package dynamic import ( "reflect" + "time" + ptypes "github.com/traefik/paerser/types" + traefiktls "github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/types" ) @@ -10,9 +13,10 @@ import ( // TCPConfiguration contains all the TCP configuration parameters. type TCPConfiguration struct { - Routers map[string]*TCPRouter `json:"routers,omitempty" toml:"routers,omitempty" yaml:"routers,omitempty" export:"true"` - Services map[string]*TCPService `json:"services,omitempty" toml:"services,omitempty" yaml:"services,omitempty" export:"true"` - Middlewares map[string]*TCPMiddleware `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"` + Routers map[string]*TCPRouter `json:"routers,omitempty" toml:"routers,omitempty" yaml:"routers,omitempty" export:"true"` + Services map[string]*TCPService `json:"services,omitempty" toml:"services,omitempty" yaml:"services,omitempty" export:"true"` + Middlewares map[string]*TCPMiddleware `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"` + ServersTransports map[string]*TCPServersTransport `json:"serversTransports,omitempty" toml:"serversTransports,omitempty" yaml:"serversTransports,omitempty" label:"-" export:"true"` } // +k8s:deepcopy-gen=true @@ -70,20 +74,9 @@ type RouterTCPTLSConfig struct { // TCPServersLoadBalancer holds the LoadBalancerService configuration. type TCPServersLoadBalancer struct { - // TerminationDelay, corresponds to 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). - TerminationDelay *int `json:"terminationDelay,omitempty" toml:"terminationDelay,omitempty" yaml:"terminationDelay,omitempty" export:"true"` ProxyProtocol *ProxyProtocol `json:"proxyProtocol,omitempty" toml:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"` Servers []TCPServer `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server" export:"true"` -} - -// SetDefaults Default values for a TCPServersLoadBalancer. -func (l *TCPServersLoadBalancer) SetDefaults() { - defaultTerminationDelay := 100 // in milliseconds - l.TerminationDelay = &defaultTerminationDelay + ServersTransport string `json:"serversTransport,omitempty" toml:"serversTransport,omitempty" yaml:"serversTransport,omitempty" export:"true"` } // Mergeable tells if the given service is mergeable. @@ -109,6 +102,7 @@ func (l *TCPServersLoadBalancer) Mergeable(loadBalancer *TCPServersLoadBalancer) type TCPServer struct { Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"` Port string `toml:"-" json:"-" yaml:"-"` + TLS bool `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty"` } // +k8s:deepcopy-gen=true @@ -124,3 +118,37 @@ type ProxyProtocol struct { func (p *ProxyProtocol) SetDefaults() { p.Version = 2 } + +// +k8s:deepcopy-gen=true + +// TCPServersTransport options to configure communication between Traefik and the servers. +type TCPServersTransport struct { + DialKeepAlive ptypes.Duration `description:"Defines the interval between keep-alive probes for an active network connection. If zero, keep-alive probes are sent with a default value (currently 15 seconds), if supported by the protocol and operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, keep-alive probes are disabled" json:"dialKeepAlive,omitempty" toml:"dialKeepAlive,omitempty" yaml:"dialKeepAlive,omitempty" export:"true"` + DialTimeout ptypes.Duration `description:"Defines the amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists." json:"dialTimeout,omitempty" toml:"dialTimeout,omitempty" yaml:"dialTimeout,omitempty" export:"true"` + // TerminationDelay, corresponds to 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). + TerminationDelay ptypes.Duration `description:"Defines the delay to wait before fully terminating the connection, after one connected peer has closed its writing capability." json:"terminationDelay,omitempty" toml:"terminationDelay,omitempty" yaml:"terminationDelay,omitempty" export:"true"` + TLS *TLSClientConfig `description:"Defines the TLS configuration." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"` +} + +// +k8s:deepcopy-gen=true + +// TLSClientConfig options to configure TLS communication between Traefik and the servers. +type TLSClientConfig struct { + ServerName string `description:"Defines the serverName used to contact the server." json:"serverName,omitempty" toml:"serverName,omitempty" yaml:"serverName,omitempty"` + InsecureSkipVerify bool `description:"Disables SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"` + RootCAs []traefiktls.FileOrContent `description:"Defines a list of CA secret used to validate self-signed certificate" json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"` + Certificates traefiktls.Certificates `description:"Defines a list of secret storing client certificates for mTLS." json:"certificates,omitempty" toml:"certificates,omitempty" yaml:"certificates,omitempty" export:"true"` + PeerCertURI string `description:"Defines the URI used to match against SAN URI during the peer certificate verification." json:"peerCertURI,omitempty" toml:"peerCertURI,omitempty" yaml:"peerCertURI,omitempty" export:"true"` + Spiffe *Spiffe `description:"Defines the SPIFFE TLS configuration." json:"spiffe,omitempty" toml:"spiffe,omitempty" yaml:"spiffe,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` +} + +// SetDefaults sets the default values for a TCPServersTransport. +func (t *TCPServersTransport) SetDefaults() { + t.DialTimeout = ptypes.Duration(30 * time.Second) + t.DialKeepAlive = ptypes.Duration(15 * time.Second) + t.TerminationDelay = ptypes.Duration(100 * time.Millisecond) +} diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index 1abb4727e..5ce287099 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -1394,6 +1394,21 @@ func (in *TCPConfiguration) DeepCopyInto(out *TCPConfiguration) { (*out)[key] = outVal } } + if in.ServersTransports != nil { + in, out := &in.ServersTransports, &out.ServersTransports + *out = make(map[string]*TCPServersTransport, len(*in)) + for key, val := range *in { + var outVal *TCPServersTransport + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = new(TCPServersTransport) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } return } @@ -1520,11 +1535,6 @@ func (in *TCPServer) DeepCopy() *TCPServer { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TCPServersLoadBalancer) DeepCopyInto(out *TCPServersLoadBalancer) { *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(ProxyProtocol) @@ -1548,6 +1558,27 @@ func (in *TCPServersLoadBalancer) DeepCopy() *TCPServersLoadBalancer { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPServersTransport) DeepCopyInto(out *TCPServersTransport) { + *out = *in + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(TLSClientConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPServersTransport. +func (in *TCPServersTransport) DeepCopy() *TCPServersTransport { + if in == nil { + return nil + } + out := new(TCPServersTransport) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TCPService) DeepCopyInto(out *TCPService) { *out = *in @@ -1676,6 +1707,37 @@ func (in *TLSClientCertificateSubjectDNInfo) DeepCopy() *TLSClientCertificateSub return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSClientConfig) DeepCopyInto(out *TLSClientConfig) { + *out = *in + if in.RootCAs != nil { + in, out := &in.RootCAs, &out.RootCAs + *out = make([]tls.FileOrContent, len(*in)) + copy(*out, *in) + } + if in.Certificates != nil { + in, out := &in.Certificates, &out.Certificates + *out = make(tls.Certificates, len(*in)) + copy(*out, *in) + } + if in.Spiffe != nil { + in, out := &in.Spiffe, &out.Spiffe + *out = new(Spiffe) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSClientConfig. +func (in *TLSClientConfig) DeepCopy() *TLSClientConfig { + if in == nil { + return nil + } + out := new(TLSClientConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSConfiguration) DeepCopyInto(out *TLSConfiguration) { *out = *in diff --git a/pkg/config/label/label_test.go b/pkg/config/label/label_test.go index 820bea328..59da31624 100644 --- a/pkg/config/label/label_test.go +++ b/pkg/config/label/label_test.go @@ -157,6 +157,7 @@ func TestDecodeConfiguration(t *testing.T) { "traefik.http.services.Service0.loadbalancer.server.port": "8080", "traefik.http.services.Service0.loadbalancer.sticky.cookie.name": "foobar", "traefik.http.services.Service0.loadbalancer.sticky.cookie.secure": "true", + "traefik.http.services.Service0.loadbalancer.serversTransport": "foobar", "traefik.http.services.Service1.loadbalancer.healthcheck.headers.name0": "foobar", "traefik.http.services.Service1.loadbalancer.healthcheck.headers.name1": "foobar", "traefik.http.services.Service1.loadbalancer.healthcheck.hostname": "foobar", @@ -175,6 +176,7 @@ func TestDecodeConfiguration(t *testing.T) { "traefik.http.services.Service1.loadbalancer.server.port": "8080", "traefik.http.services.Service1.loadbalancer.sticky": "false", "traefik.http.services.Service1.loadbalancer.sticky.cookie.name": "fui", + "traefik.http.services.Service1.loadbalancer.serversTransport": "foobar", "traefik.tcp.middlewares.Middleware0.ipallowlist.sourcerange": "foobar, fiibar", "traefik.tcp.middlewares.Middleware2.inflightconn.amount": "42", @@ -191,11 +193,11 @@ func TestDecodeConfiguration(t *testing.T) { "traefik.tcp.routers.Router1.tls.options": "foo", "traefik.tcp.routers.Router1.tls.passthrough": "false", "traefik.tcp.services.Service0.loadbalancer.server.Port": "42", - "traefik.tcp.services.Service0.loadbalancer.TerminationDelay": "42", "traefik.tcp.services.Service0.loadbalancer.proxyProtocol.version": "42", + "traefik.tcp.services.Service0.loadbalancer.serversTransport": "foo", "traefik.tcp.services.Service1.loadbalancer.server.Port": "42", - "traefik.tcp.services.Service1.loadbalancer.TerminationDelay": "42", "traefik.tcp.services.Service1.loadbalancer.proxyProtocol": "true", + "traefik.tcp.services.Service1.loadbalancer.serversTransport": "foo", "traefik.udp.routers.Router0.entrypoints": "foobar, fiibar", "traefik.udp.routers.Router0.service": "foobar", @@ -258,8 +260,8 @@ func TestDecodeConfiguration(t *testing.T) { Port: "42", }, }, - TerminationDelay: func(i int) *int { return &i }(42), ProxyProtocol: &dynamic.ProxyProtocol{Version: 42}, + ServersTransport: "foo", }, }, "Service1": { @@ -269,8 +271,8 @@ func TestDecodeConfiguration(t *testing.T) { Port: "42", }, }, - TerminationDelay: func(i int) *int { return &i }(42), ProxyProtocol: &dynamic.ProxyProtocol{Version: 2}, + ServersTransport: "foo", }, }, }, @@ -659,6 +661,7 @@ func TestDecodeConfiguration(t *testing.T) { ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(time.Second), }, + ServersTransport: "foobar", }, }, "Service1": { @@ -689,6 +692,7 @@ func TestDecodeConfiguration(t *testing.T) { ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(time.Second), }, + ServersTransport: "foobar", }, }, }, @@ -696,6 +700,7 @@ func TestDecodeConfiguration(t *testing.T) { } assert.Nil(t, configuration.HTTP.ServersTransports) + assert.Nil(t, configuration.TCP.ServersTransports) assert.Equal(t, expected, configuration) } @@ -750,7 +755,7 @@ func TestEncodeConfiguration(t *testing.T) { Port: "42", }, }, - TerminationDelay: func(i int) *int { return &i }(42), + ServersTransport: "foo", }, }, "Service1": { @@ -760,7 +765,7 @@ func TestEncodeConfiguration(t *testing.T) { Port: "42", }, }, - TerminationDelay: func(i int) *int { return &i }(42), + ServersTransport: "foo", }, }, }, @@ -1145,6 +1150,7 @@ func TestEncodeConfiguration(t *testing.T) { ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(time.Second), }, + ServersTransport: "foobar", }, }, "Service1": { @@ -1173,6 +1179,7 @@ func TestEncodeConfiguration(t *testing.T) { ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(time.Second), }, + ServersTransport: "foobar", }, }, }, @@ -1309,6 +1316,7 @@ func TestEncodeConfiguration(t *testing.T) { "traefik.HTTP.Routers.Router1.Rule": "foobar", "traefik.HTTP.Routers.Router1.Service": "foobar", + "traefik.HTTP.Services.Service0.LoadBalancer.HealthCheck.Headers.name0": "foobar", "traefik.HTTP.Services.Service0.LoadBalancer.HealthCheck.Headers.name1": "foobar", "traefik.HTTP.Services.Service0.LoadBalancer.HealthCheck.Hostname": "foobar", "traefik.HTTP.Services.Service0.LoadBalancer.HealthCheck.Interval": "1000000000", @@ -1325,6 +1333,7 @@ func TestEncodeConfiguration(t *testing.T) { "traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.Name": "foobar", "traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.HTTPOnly": "true", "traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.Secure": "false", + "traefik.HTTP.Services.Service0.LoadBalancer.ServersTransport": "foobar", "traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name0": "foobar", "traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name1": "foobar", "traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Hostname": "foobar", @@ -1339,7 +1348,7 @@ func TestEncodeConfiguration(t *testing.T) { "traefik.HTTP.Services.Service1.LoadBalancer.ResponseForwarding.FlushInterval": "1000000000", "traefik.HTTP.Services.Service1.LoadBalancer.server.Port": "8080", "traefik.HTTP.Services.Service1.LoadBalancer.server.Scheme": "foobar", - "traefik.HTTP.Services.Service0.LoadBalancer.HealthCheck.Headers.name0": "foobar", + "traefik.HTTP.Services.Service1.LoadBalancer.ServersTransport": "foobar", "traefik.TCP.Middlewares.Middleware0.IPAllowList.SourceRange": "foobar, fiibar", "traefik.TCP.Middlewares.Middleware2.InFlightConn.Amount": "42", @@ -1356,9 +1365,11 @@ func TestEncodeConfiguration(t *testing.T) { "traefik.TCP.Routers.Router1.TLS.Passthrough": "false", "traefik.TCP.Routers.Router1.TLS.Options": "foo", "traefik.TCP.Services.Service0.LoadBalancer.server.Port": "42", - "traefik.TCP.Services.Service0.LoadBalancer.TerminationDelay": "42", + "traefik.TCP.Services.Service0.LoadBalancer.server.TLS": "false", + "traefik.TCP.Services.Service0.LoadBalancer.ServersTransport": "foo", "traefik.TCP.Services.Service1.LoadBalancer.server.Port": "42", - "traefik.TCP.Services.Service1.LoadBalancer.TerminationDelay": "42", + "traefik.TCP.Services.Service1.LoadBalancer.server.TLS": "false", + "traefik.TCP.Services.Service1.LoadBalancer.ServersTransport": "foo", "traefik.UDP.Routers.Router0.EntryPoints": "foobar, fiibar", "traefik.UDP.Routers.Router0.Service": "foobar", diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index da32b76f9..eba224bd1 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -63,9 +63,10 @@ const ( type Configuration struct { Global *Global `description:"Global configuration options" json:"global,omitempty" toml:"global,omitempty" yaml:"global,omitempty" export:"true"` - ServersTransport *ServersTransport `description:"Servers default transport." json:"serversTransport,omitempty" toml:"serversTransport,omitempty" yaml:"serversTransport,omitempty" export:"true"` - EntryPoints EntryPoints `description:"Entry points definition." json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty" export:"true"` - Providers *Providers `description:"Providers configuration." json:"providers,omitempty" toml:"providers,omitempty" yaml:"providers,omitempty" export:"true"` + ServersTransport *ServersTransport `description:"Servers default transport." json:"serversTransport,omitempty" toml:"serversTransport,omitempty" yaml:"serversTransport,omitempty" export:"true"` + TCPServersTransport *TCPServersTransport `description:"TCP servers default transport." json:"tcpServersTransport,omitempty" toml:"tcpServersTransport,omitempty" yaml:"tcpServersTransport,omitempty" export:"true"` + EntryPoints EntryPoints `description:"Entry points definition." json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty" export:"true"` + Providers *Providers `description:"Providers configuration." json:"providers,omitempty" toml:"providers,omitempty" yaml:"providers,omitempty" export:"true"` API *API `description:"Enable api/dashboard." json:"api,omitempty" toml:"api,omitempty" yaml:"api,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` Metrics *types.Metrics `description:"Enable a metrics exporter." json:"metrics,omitempty" toml:"metrics,omitempty" yaml:"metrics,omitempty" export:"true"` @@ -118,6 +119,26 @@ type Spiffe struct { TrustDomain string `description:"Defines the allowed SPIFFE trust domain." json:"trustDomain,omitempty" yaml:"trustDomain,omitempty" toml:"trustDomain,omitempty"` } +// TCPServersTransport options to configure communication between Traefik and the servers. +type TCPServersTransport struct { + DialKeepAlive ptypes.Duration `description:"Defines the interval between keep-alive probes for an active network connection. If zero, keep-alive probes are sent with a default value (currently 15 seconds), if supported by the protocol and operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, keep-alive probes are disabled" json:"dialKeepAlive,omitempty" toml:"dialKeepAlive,omitempty" yaml:"dialKeepAlive,omitempty" export:"true"` + DialTimeout ptypes.Duration `description:"Defines the amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists." json:"dialTimeout,omitempty" toml:"dialTimeout,omitempty" yaml:"dialTimeout,omitempty" export:"true"` + // TerminationDelay, corresponds to 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). + TerminationDelay ptypes.Duration `description:"Defines the delay to wait before fully terminating the connection, after one connected peer has closed its writing capability." json:"terminationDelay,omitempty" toml:"terminationDelay,omitempty" yaml:"terminationDelay,omitempty" export:"true"` + TLS *TLSClientConfig `description:"Defines the TLS configuration." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"` +} + +// TLSClientConfig options to configure TLS communication between Traefik and the servers. +type TLSClientConfig struct { + InsecureSkipVerify bool `description:"Disables SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"` + RootCAs []tls.FileOrContent `description:"Defines a list of CA secret used to validate self-signed certificate" json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"` + Spiffe *Spiffe `description:"Defines the SPIFFE TLS configuration." json:"spiffe,omitempty" toml:"spiffe,omitempty" yaml:"spiffe,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` +} + // API holds the API configuration. type API struct { Insecure bool `description:"Activate API directly on the entryPoint named traefik." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"` diff --git a/pkg/provider/configuration.go b/pkg/provider/configuration.go index c0119c885..54b861bcd 100644 --- a/pkg/provider/configuration.go +++ b/pkg/provider/configuration.go @@ -27,9 +27,10 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), - Middlewares: make(map[string]*dynamic.TCPMiddleware), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + Middlewares: make(map[string]*dynamic.TCPMiddleware), + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: make(map[string]*dynamic.UDPRouter), @@ -64,6 +65,9 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration transportsToDelete := map[string]struct{}{} transports := map[string][]string{} + transportsTCPToDelete := map[string]struct{}{} + transportsTCP := map[string][]string{} + var sortedKeys []string for key := range configurations { sortedKeys = append(sortedKeys, key) @@ -107,6 +111,13 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration } } + for transportName, transport := range conf.TCP.ServersTransports { + transportsTCP[transportName] = append(transportsTCP[transportName], root) + if !AddTransportTCP(configuration.TCP, transportName, transport) { + transportsTCPToDelete[transportName] = struct{}{} + } + } + for serviceName, service := range conf.UDP.Services { servicesUDP[serviceName] = append(servicesUDP[serviceName], root) if !AddServiceUDP(configuration.UDP, serviceName, service) { @@ -138,62 +149,78 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration for serviceName := range servicesToDelete { logger.Error().Str(logs.ServiceName, serviceName). - Msgf("Service defined multiple times with different configurations in %v", services[serviceName]) + Interface("configuration", services[serviceName]). + Msg("Service defined multiple times with different configurations") delete(configuration.HTTP.Services, serviceName) } for routerName := range routersToDelete { logger.Error().Str(logs.RouterName, routerName). - Msgf("Router defined multiple times with different configurations in %v", routers[routerName]) + Interface("configuration", routers[routerName]). + Msg("Router defined multiple times with different configurations") delete(configuration.HTTP.Routers, routerName) } for transportName := range transportsToDelete { logger.Error().Str(logs.ServersTransportName, transportName). - Msgf("ServersTransport defined multiple times with different configurations in %v", transports[transportName]) + Interface("configuration", transports[transportName]). + Msg("ServersTransport defined multiple times with different configurations") delete(configuration.HTTP.ServersTransports, transportName) } for serviceName := range servicesTCPToDelete { logger.Error().Str(logs.ServiceName, serviceName). - Msgf("Service TCP defined multiple times with different configurations in %v", servicesTCP[serviceName]) + Interface("configuration", servicesTCP[serviceName]). + Msg("Service TCP defined multiple times with different configurations") delete(configuration.TCP.Services, serviceName) } for routerName := range routersTCPToDelete { logger.Error().Str(logs.RouterName, routerName). - Msgf("Router TCP defined multiple times with different configurations in %v", routersTCP[routerName]) + Interface("configuration", routersTCP[routerName]). + Msg("Router TCP defined multiple times with different configurations") delete(configuration.TCP.Routers, routerName) } + for transportName := range transportsTCPToDelete { + logger.Error().Str(logs.ServersTransportName, transportName). + Interface("configuration", transportsTCP[transportName]). + Msg("ServersTransport TCP defined multiple times with different configurations") + delete(configuration.TCP.ServersTransports, transportName) + } + for serviceName := range servicesUDPToDelete { logger.Error().Str(logs.ServiceName, serviceName). - Msgf("UDP service defined multiple times with different configurations in %v", servicesUDP[serviceName]) + Interface("configuration", servicesUDP[serviceName]). + Msg("UDP service defined multiple times with different configurations") delete(configuration.UDP.Services, serviceName) } for routerName := range routersUDPToDelete { logger.Error().Str(logs.RouterName, routerName). - Msgf("UDP router defined multiple times with different configurations in %v", routersUDP[routerName]) + Interface("configuration", routersUDP[routerName]). + Msg("UDP router defined multiple times with different configurations") delete(configuration.UDP.Routers, routerName) } for middlewareName := range middlewaresToDelete { logger.Error().Str(logs.MiddlewareName, middlewareName). - Msgf("Middleware defined multiple times with different configurations in %v", middlewares[middlewareName]) + Interface("configuration", middlewares[middlewareName]). + Msg("Middleware defined multiple times with different configurations") delete(configuration.HTTP.Middlewares, middlewareName) } for middlewareName := range middlewaresTCPToDelete { logger.Error().Str(logs.MiddlewareName, middlewareName). - Msgf("TCP Middleware defined multiple times with different configurations in %v", middlewaresTCP[middlewareName]) + Interface("configuration", middlewaresTCP[middlewareName]). + Msg("TCP Middleware defined multiple times with different configurations") delete(configuration.TCP.Middlewares, middlewareName) } return configuration } -// AddServiceTCP Adds a service to a configurations. +// AddServiceTCP adds a service to a configuration. func AddServiceTCP(configuration *dynamic.TCPConfiguration, serviceName string, service *dynamic.TCPService) bool { if _, ok := configuration.Services[serviceName]; !ok { configuration.Services[serviceName] = service @@ -218,7 +245,7 @@ func AddServiceTCP(configuration *dynamic.TCPConfiguration, serviceName string, return true } -// AddRouterTCP Adds a router to a configurations. +// AddRouterTCP adds a router to a configuration. func AddRouterTCP(configuration *dynamic.TCPConfiguration, routerName string, router *dynamic.TCPRouter) bool { if _, ok := configuration.Routers[routerName]; !ok { configuration.Routers[routerName] = router @@ -228,7 +255,7 @@ func AddRouterTCP(configuration *dynamic.TCPConfiguration, routerName string, ro return reflect.DeepEqual(configuration.Routers[routerName], router) } -// AddMiddlewareTCP Adds a middleware to a configurations. +// AddMiddlewareTCP adds a middleware to a configuration. func AddMiddlewareTCP(configuration *dynamic.TCPConfiguration, middlewareName string, middleware *dynamic.TCPMiddleware) bool { if _, ok := configuration.Middlewares[middlewareName]; !ok { configuration.Middlewares[middlewareName] = middleware @@ -238,6 +265,16 @@ func AddMiddlewareTCP(configuration *dynamic.TCPConfiguration, middlewareName st return reflect.DeepEqual(configuration.Middlewares[middlewareName], middleware) } +// AddTransportTCP adds a servers transport to a configuration. +func AddTransportTCP(configuration *dynamic.TCPConfiguration, transportName string, transport *dynamic.TCPServersTransport) bool { + if _, ok := configuration.ServersTransports[transportName]; !ok { + configuration.ServersTransports[transportName] = transport + return true + } + + return reflect.DeepEqual(configuration.ServersTransports[transportName], transport) +} + // AddServiceUDP adds a service to a configuration. func AddServiceUDP(configuration *dynamic.UDPConfiguration, serviceName string, service *dynamic.UDPService) bool { if _, ok := configuration.Services[serviceName]; !ok { @@ -273,7 +310,7 @@ func AddRouterUDP(configuration *dynamic.UDPConfiguration, routerName string, ro return reflect.DeepEqual(configuration.Routers[routerName], router) } -// AddService Adds a service to a configurations. +// AddService adds a service to a configuration. func AddService(configuration *dynamic.HTTPConfiguration, serviceName string, service *dynamic.Service) bool { if _, ok := configuration.Services[serviceName]; !ok { configuration.Services[serviceName] = service @@ -298,7 +335,7 @@ func AddService(configuration *dynamic.HTTPConfiguration, serviceName string, se return true } -// AddRouter Adds a router to a configurations. +// AddRouter adds a router to a configuration. func AddRouter(configuration *dynamic.HTTPConfiguration, routerName string, router *dynamic.Router) bool { if _, ok := configuration.Routers[routerName]; !ok { configuration.Routers[routerName] = router @@ -308,7 +345,7 @@ func AddRouter(configuration *dynamic.HTTPConfiguration, routerName string, rout return reflect.DeepEqual(configuration.Routers[routerName], router) } -// AddTransport Adds a transport to a configurations. +// AddTransport adds a servers transport to a configuration. func AddTransport(configuration *dynamic.HTTPConfiguration, transportName string, transport *dynamic.ServersTransport) bool { if _, ok := configuration.ServersTransports[transportName]; !ok { configuration.ServersTransports[transportName] = transport @@ -318,7 +355,7 @@ func AddTransport(configuration *dynamic.HTTPConfiguration, transportName string return reflect.DeepEqual(configuration.ServersTransports[transportName], transport) } -// AddMiddleware Adds a middleware to a configurations. +// AddMiddleware adds a middleware to a configuration. func AddMiddleware(configuration *dynamic.HTTPConfiguration, middlewareName string, middleware *dynamic.Middleware) bool { if _, ok := configuration.Middlewares[middlewareName]; !ok { configuration.Middlewares[middlewareName] = middleware diff --git a/pkg/provider/consulcatalog/config.go b/pkg/provider/consulcatalog/config.go index af8e7830c..f60d33894 100644 --- a/pkg/provider/consulcatalog/config.go +++ b/pkg/provider/consulcatalog/config.go @@ -41,6 +41,17 @@ func (p *Provider) buildConfiguration(ctx context.Context, items []itemData, cer if len(confFromLabel.TCP.Routers) > 0 || len(confFromLabel.TCP.Services) > 0 { tcpOrUDP = true + if item.ExtraConf.ConsulCatalog.Connect { + if confFromLabel.TCP.ServersTransports == nil { + confFromLabel.TCP.ServersTransports = make(map[string]*dynamic.TCPServersTransport) + } + + serversTransportKey := itemServersTransportKey(item) + if confFromLabel.TCP.ServersTransports[serversTransportKey] == nil { + confFromLabel.TCP.ServersTransports[serversTransportKey] = certInfo.tcpServersTransport(item) + } + } + if err := p.buildTCPServiceConfiguration(item, confFromLabel.TCP); err != nil { logger.Error().Err(err).Send() continue @@ -131,13 +142,10 @@ func (p *Provider) keepContainer(ctx context.Context, item itemData) bool { func (p *Provider) buildTCPServiceConfiguration(item itemData, configuration *dynamic.TCPConfiguration) error { if len(configuration.Services) == 0 { - configuration.Services = make(map[string]*dynamic.TCPService) - - lb := &dynamic.TCPServersLoadBalancer{} - lb.SetDefaults() - - configuration.Services[getName(item)] = &dynamic.TCPService{ - LoadBalancer: lb, + configuration.Services = map[string]*dynamic.TCPService{ + getName(item): { + LoadBalancer: new(dynamic.TCPServersLoadBalancer), + }, } } @@ -215,6 +223,14 @@ func (p *Provider) addServerTCP(item itemData, loadBalancer *dynamic.TCPServersL return errors.New("port is missing") } + if item.Address == "" { + return errors.New("address is missing") + } + + if item.ExtraConf.ConsulCatalog.Connect { + loadBalancer.ServersTransport = itemServersTransportKey(item) + } + loadBalancer.Servers[0].Address = net.JoinHostPort(item.Address, port) return nil diff --git a/pkg/provider/consulcatalog/config_test.go b/pkg/provider/consulcatalog/config_test.go index 583ed27cc..c8837430c 100644 --- a/pkg/provider/consulcatalog/config_test.go +++ b/pkg/provider/consulcatalog/config_test.go @@ -40,9 +40,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -93,9 +94,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Name }}.{{ index .Labels "traefik.domain" }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -144,9 +146,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Toto }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -190,9 +193,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: ``, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -236,9 +240,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: defaultTemplateRule, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -324,9 +329,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -380,9 +386,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, + Routers: map[string]*dynamic.TCPRouter{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -466,9 +473,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, + Routers: map[string]*dynamic.TCPRouter{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -544,9 +552,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -620,9 +629,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -682,9 +692,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -741,9 +752,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -795,9 +807,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -848,9 +861,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -899,9 +913,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -951,9 +966,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1004,9 +1020,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1072,9 +1089,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1129,9 +1147,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1176,9 +1195,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1230,9 +1250,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1296,9 +1317,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1365,9 +1387,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1441,9 +1464,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1509,9 +1533,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1580,9 +1605,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1644,9 +1670,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1698,9 +1725,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1750,9 +1778,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1802,9 +1831,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1859,9 +1889,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1890,9 +1921,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1921,9 +1953,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1952,9 +1985,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1985,9 +2019,10 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Tag("traefik.tags=bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2018,9 +2053,10 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Tag("traefik.tags=foo")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2070,9 +2106,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2155,10 +2192,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2173,14 +2210,19 @@ func Test_buildConfiguration(t *testing.T) { }, }, { - desc: "tcp with label", + desc: "tcp with label", + ConnectAware: true, items: []itemData{ { - ID: "Test", - Name: "Test", + ID: "Test", + Node: "Node1", + Datacenter: "dc1", + Name: "Test", + Namespace: "ns", Labels: map[string]string{ - "traefik.tcp.routers.foo.rule": "HostSNI(`foo.bar`)", - "traefik.tcp.routers.foo.tls": "true", + "traefik.tcp.routers.foo.rule": "HostSNI(`foo.bar`)", + "traefik.tcp.routers.foo.tls": "true", + "traefik.consulcatalog.connect": "true", }, Address: "127.0.0.1", Port: "80", @@ -2205,7 +2247,25 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), + ServersTransport: "tls-ns-dc1-Test", + }, + }, + }, + ServersTransports: map[string]*dynamic.TCPServersTransport{ + "tls-ns-dc1-Test": { + TLS: &dynamic.TLSClientConfig{ + ServerName: "ns-dc1-Test", + InsecureSkipVerify: true, + RootCAs: []tls.FileOrContent{ + "root", + }, + Certificates: []tls.Certificate{ + { + CertFile: "cert", + KeyFile: "key", + }, + }, + PeerCertURI: "spiffe:///ns/ns/dc/dc1/svc/Test", }, }, }, @@ -2257,9 +2317,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2295,10 +2356,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2348,10 +2409,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:8080", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2401,9 +2462,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2464,10 +2526,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.2:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2555,9 +2617,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2615,10 +2678,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2662,9 +2725,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2675,14 +2739,14 @@ func Test_buildConfiguration(t *testing.T) { }, }, { + // TODO: replace or delete? desc: "tcp with label for tcp service, with termination delay", items: []itemData{ { ID: "Test", Name: "Test", Labels: map[string]string{ - "traefik.tcp.services.foo.loadbalancer.server.port": "80", - "traefik.tcp.services.foo.loadbalancer.terminationdelay": "200", + "traefik.tcp.services.foo.loadbalancer.server.port": "80", }, Address: "127.0.0.1", Port: "80", @@ -2701,10 +2765,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(200), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2752,9 +2816,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2872,7 +2937,6 @@ func Test_buildConfiguration(t *testing.T) { Servers: []dynamic.TCPServer{ {Address: "127.0.0.1:80"}, }, - TerminationDelay: Int(100), }, }, "Test-17573747155436217342": { @@ -2880,10 +2944,10 @@ func Test_buildConfiguration(t *testing.T) { Servers: []dynamic.TCPServer{ {Address: "127.0.0.2:80"}, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2931,9 +2995,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{ @@ -2993,9 +3058,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{ diff --git a/pkg/provider/consulcatalog/connect_tls.go b/pkg/provider/consulcatalog/connect_tls.go index 5b7a92739..edb420770 100644 --- a/pkg/provider/consulcatalog/connect_tls.go +++ b/pkg/provider/consulcatalog/connect_tls.go @@ -70,3 +70,25 @@ func (c *connectCert) serversTransport(item itemData) *dynamic.ServersTransport PeerCertURI: spiffeIDService.URI().String(), } } + +func (c *connectCert) tcpServersTransport(item itemData) *dynamic.TCPServersTransport { + spiffeIDService := connect.SpiffeIDService{ + Namespace: item.Namespace, + Datacenter: item.Datacenter, + Service: item.Name, + } + + return &dynamic.TCPServersTransport{ + TLS: &dynamic.TLSClientConfig{ + // This ensures that the config changes whenever the verifier function changes + ServerName: fmt.Sprintf("%s-%s-%s", item.Namespace, item.Datacenter, item.Name), + // InsecureSkipVerify is needed because Go wants to verify a hostname otherwise + InsecureSkipVerify: true, + RootCAs: c.getRoot(), + Certificates: traefiktls.Certificates{ + c.getLeaf(), + }, + PeerCertURI: spiffeIDService.URI().String(), + }, + } +} diff --git a/pkg/provider/docker/config.go b/pkg/provider/docker/config.go index e23575caf..3899d451d 100644 --- a/pkg/provider/docker/config.go +++ b/pkg/provider/docker/config.go @@ -94,11 +94,10 @@ func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, container d serviceName := getServiceName(container) if len(configuration.Services) == 0 { - configuration.Services = make(map[string]*dynamic.TCPService) - lb := &dynamic.TCPServersLoadBalancer{} - lb.SetDefaults() - configuration.Services[serviceName] = &dynamic.TCPService{ - LoadBalancer: lb, + configuration.Services = map[string]*dynamic.TCPService{ + serviceName: { + LoadBalancer: new(dynamic.TCPServersLoadBalancer), + }, } } diff --git a/pkg/provider/docker/config_test.go b/pkg/provider/docker/config_test.go index 6038cf4de..498b49b1d 100644 --- a/pkg/provider/docker/config_test.go +++ b/pkg/provider/docker/config_test.go @@ -45,9 +45,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -103,9 +104,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`{{ .Name }}.foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -163,9 +165,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Name }}.{{ index .Labels "traefik.domain" }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -221,9 +224,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Toto }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -274,9 +278,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: ``, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -327,9 +332,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: DefaultTemplateRule, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -423,9 +429,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -463,9 +470,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -503,9 +511,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -541,9 +550,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -614,9 +624,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -706,9 +717,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -768,9 +780,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -829,9 +842,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -888,9 +902,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -948,9 +963,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1009,9 +1025,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1077,9 +1094,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1156,9 +1174,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1240,9 +1259,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1305,9 +1325,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1367,9 +1388,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1452,9 +1474,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1540,9 +1563,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1641,9 +1665,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1726,9 +1751,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1822,9 +1848,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1902,9 +1929,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1982,9 +2010,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2049,9 +2078,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2109,9 +2139,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2169,9 +2200,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2232,9 +2264,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2270,9 +2303,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2310,9 +2344,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2337,9 +2372,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2365,9 +2401,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2409,9 +2446,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2449,11 +2487,10 @@ func Test_buildConfiguration(t *testing.T) { Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "Test": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - TerminationDelay: Int(100), - }, + LoadBalancer: &dynamic.TCPServersLoadBalancer{}, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2481,9 +2518,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2512,9 +2550,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{ @@ -2561,9 +2600,10 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2602,9 +2642,10 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "foo")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2662,9 +2703,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2755,10 +2797,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2813,10 +2855,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2873,9 +2915,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2919,10 +2962,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2980,10 +3023,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:8080", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -3041,9 +3084,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3122,9 +3166,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3194,9 +3239,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3207,14 +3253,14 @@ func Test_buildConfiguration(t *testing.T) { }, }, { + // TODO: replace or delete? desc: "tcp with label for tcp service, with termination delay", containers: []dockerData{ { ServiceName: "Test", Name: "Test", Labels: map[string]string{ - "traefik.tcp.services.foo.loadbalancer.server.port": "8080", - "traefik.tcp.services.foo.loadbalancer.terminationdelay": "200", + "traefik.tcp.services.foo.loadbalancer.server.port": "8080", }, NetworkSettings: networkSettings{ Ports: nat.PortMap{ @@ -3241,10 +3287,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:8080", }, }, - TerminationDelay: Int(200), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -3290,9 +3336,10 @@ func Test_buildConfiguration(t *testing.T) { useBindPortIP: true, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, diff --git a/pkg/provider/ecs/config.go b/pkg/provider/ecs/config.go index 8dbdf1550..a0c7d0bb0 100644 --- a/pkg/provider/ecs/config.go +++ b/pkg/provider/ecs/config.go @@ -93,11 +93,10 @@ func (p *Provider) buildTCPServiceConfiguration(instance ecsInstance, configurat serviceName := getServiceName(instance) if len(configuration.Services) == 0 { - configuration.Services = make(map[string]*dynamic.TCPService) - lb := &dynamic.TCPServersLoadBalancer{} - lb.SetDefaults() - configuration.Services[serviceName] = &dynamic.TCPService{ - LoadBalancer: lb, + configuration.Services = map[string]*dynamic.TCPService{ + serviceName: { + LoadBalancer: new(dynamic.TCPServersLoadBalancer), + }, } } diff --git a/pkg/provider/ecs/config_test.go b/pkg/provider/ecs/config_test.go index c0bd40a78..24a1af69d 100644 --- a/pkg/provider/ecs/config_test.go +++ b/pkg/provider/ecs/config_test.go @@ -41,9 +41,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -94,9 +95,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`{{ .Name }}.foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -149,9 +151,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Name }}.{{ index .Labels "traefik.domain" }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -202,9 +205,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Toto }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -250,9 +254,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: ``, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -298,9 +303,10 @@ func TestDefaultRule(t *testing.T) { defaultRule: DefaultTemplateRule, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -388,9 +394,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -423,9 +430,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -458,9 +466,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -491,9 +500,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -554,9 +564,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -636,9 +647,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -693,9 +705,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -749,9 +762,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -803,9 +817,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -858,9 +873,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -914,9 +930,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -977,9 +994,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1046,9 +1064,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1115,9 +1134,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1170,9 +1190,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1227,9 +1248,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1302,9 +1324,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1380,9 +1403,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1466,9 +1490,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1541,9 +1566,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1622,9 +1648,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1693,9 +1720,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1763,9 +1791,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1825,9 +1854,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1880,9 +1910,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1935,9 +1966,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1995,9 +2027,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2067,9 +2100,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2125,9 +2159,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2158,9 +2193,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2193,9 +2229,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2229,9 +2266,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2264,9 +2302,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2300,9 +2339,10 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2336,9 +2376,10 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "foo")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2391,9 +2432,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2479,10 +2521,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2532,10 +2574,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2587,9 +2629,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2628,10 +2671,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2684,10 +2727,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:8080", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2740,9 +2783,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2811,9 +2855,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2878,9 +2923,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2891,13 +2937,13 @@ func Test_buildConfiguration(t *testing.T) { }, }, { + // TODO: replace or delete? desc: "tcp with label for tcp service, with termination delay", containers: []ecsInstance{ instance( name("Test"), labels(map[string]string{ - "traefik.tcp.services.foo.loadbalancer.server.port": "80", - "traefik.tcp.services.foo.loadbalancer.terminationdelay": "200", + "traefik.tcp.services.foo.loadbalancer.server.port": "80", }), iMachine( mState(ec2.InstanceStateNameRunning), @@ -2920,10 +2966,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:8080", }, }, - TerminationDelay: Int(200), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, diff --git a/pkg/provider/file/file.go b/pkg/provider/file/file.go index 839986cf8..2cd8ab81d 100644 --- a/pkg/provider/file/file.go +++ b/pkg/provider/file/file.go @@ -215,7 +215,7 @@ func (p *Provider) loadFileConfig(ctx context.Context, filename string, parseTem } } - // ServersTransport + // HTTP ServersTransport if configuration.HTTP != nil && len(configuration.HTTP.ServersTransports) > 0 { for name, st := range configuration.HTTP.ServersTransports { var certificates []tls.Certificate @@ -254,6 +254,48 @@ func (p *Provider) loadFileConfig(ctx context.Context, filename string, parseTem } } + // TCP ServersTransport + if configuration.TCP != nil && len(configuration.TCP.ServersTransports) > 0 { + for name, st := range configuration.TCP.ServersTransports { + var certificates []tls.Certificate + if st.TLS == nil { + continue + } + for _, cert := range st.TLS.Certificates { + content, err := cert.CertFile.Read() + if err != nil { + log.Ctx(ctx).Error().Err(err).Send() + continue + } + cert.CertFile = tls.FileOrContent(content) + + content, err = cert.KeyFile.Read() + if err != nil { + log.Ctx(ctx).Error().Err(err).Send() + continue + } + cert.KeyFile = tls.FileOrContent(content) + + certificates = append(certificates, cert) + } + + configuration.TCP.ServersTransports[name].TLS.Certificates = certificates + + var rootCAs []tls.FileOrContent + for _, rootCA := range st.TLS.RootCAs { + content, err := rootCA.Read() + if err != nil { + log.Ctx(ctx).Error().Err(err).Send() + continue + } + + rootCAs = append(rootCAs, tls.FileOrContent(content)) + } + + st.TLS.RootCAs = rootCAs + } + } + return configuration, nil } @@ -295,9 +337,10 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), - Middlewares: make(map[string]*dynamic.TCPMiddleware), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + Middlewares: make(map[string]*dynamic.TCPMiddleware), + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, TLS: &dynamic.TLSConfiguration{ Stores: make(map[string]tls.Store), @@ -392,6 +435,14 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st } } + for name, conf := range c.TCP.ServersTransports { + if _, exists := configuration.TCP.ServersTransports[name]; exists { + logger.Warn().Str(logs.ServersTransportName, name).Msg("TCP servers transport already configured, skipping") + } else { + configuration.TCP.ServersTransports[name] = conf + } + } + for name, conf := range c.UDP.Routers { if _, exists := configuration.UDP.Routers[name]; exists { logger.Warn().Str(logs.RouterName, name).Msg("UDP router already configured, skipping") @@ -506,9 +557,10 @@ func (p *Provider) decodeConfiguration(filePath, content string) (*dynamic.Confi ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), - Middlewares: make(map[string]*dynamic.TCPMiddleware), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + Middlewares: make(map[string]*dynamic.TCPMiddleware), + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, TLS: &dynamic.TLSConfiguration{ Stores: make(map[string]tls.Store), diff --git a/pkg/provider/file/file_test.go b/pkg/provider/file/file_test.go index 76fb49282..dde5d2544 100644 --- a/pkg/provider/file/file_test.go +++ b/pkg/provider/file/file_test.go @@ -54,6 +54,13 @@ func TestTLSCertificateContent(t *testing.T) { [[http.serversTransports.default.certificates]] certFile = "` + fileTLS.Name() + `" keyFile = "` + fileTLSKey.Name() + `" + +[tcp.serversTransports.default] + [tcp.serversTransports.default.tls] + rootCAs = ["` + fileTLS.Name() + `"] + [[tcp.serversTransports.default.tls.certificates]] + certFile = "` + fileTLS.Name() + `" + keyFile = "` + fileTLSKey.Name() + `" ` _, err = fileConfig.Write([]byte(content)) @@ -74,6 +81,10 @@ func TestTLSCertificateContent(t *testing.T) { require.Equal(t, "CONTENT", configuration.HTTP.ServersTransports["default"].Certificates[0].CertFile.String()) require.Equal(t, "CONTENTKEY", configuration.HTTP.ServersTransports["default"].Certificates[0].KeyFile.String()) require.Equal(t, "CONTENT", configuration.HTTP.ServersTransports["default"].RootCAs[0].String()) + + require.Equal(t, "CONTENT", configuration.TCP.ServersTransports["default"].TLS.Certificates[0].CertFile.String()) + require.Equal(t, "CONTENTKEY", configuration.TCP.ServersTransports["default"].TLS.Certificates[0].KeyFile.String()) + require.Equal(t, "CONTENT", configuration.TCP.ServersTransports["default"].TLS.RootCAs[0].String()) } func TestErrorWhenEmptyConfig(t *testing.T) { diff --git a/pkg/provider/http/http.go b/pkg/provider/http/http.go index e8ad5b8e7..656615083 100644 --- a/pkg/provider/http/http.go +++ b/pkg/provider/http/http.go @@ -175,8 +175,9 @@ func decodeConfiguration(data []byte) (*dynamic.Configuration, error) { ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, TLS: &dynamic.TLSConfiguration{ Stores: make(map[string]tls.Store), diff --git a/pkg/provider/http/http_test.go b/pkg/provider/http/http_test.go index 97f020c3b..809d2a7fd 100644 --- a/pkg/provider/http/http_test.go +++ b/pkg/provider/http/http_test.go @@ -158,7 +158,8 @@ func TestProvider_decodeConfiguration(t *testing.T) { Routers: map[string]*dynamic.TCPRouter{ "foo": {}, }, - Services: make(map[string]*dynamic.TCPService), + Services: make(map[string]*dynamic.TCPService), + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{ Stores: make(map[string]tls.Store), @@ -214,8 +215,9 @@ func TestProvider_Provide(t *testing.T) { ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{ Stores: make(map[string]tls.Store), diff --git a/pkg/provider/hub/hub.go b/pkg/provider/hub/hub.go index c44cb7e97..d2d899101 100644 --- a/pkg/provider/hub/hub.go +++ b/pkg/provider/hub/hub.go @@ -152,8 +152,9 @@ func emptyDynamicConfiguration() *dynamic.Configuration { ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, TLS: &dynamic.TLSConfiguration{ Stores: make(map[string]ttls.Store), diff --git a/pkg/provider/kubernetes/crd/client.go b/pkg/provider/kubernetes/crd/client.go index 0b40a91aa..842dc1ce6 100644 --- a/pkg/provider/kubernetes/crd/client.go +++ b/pkg/provider/kubernetes/crd/client.go @@ -40,6 +40,7 @@ type Client interface { GetTraefikServices() []*v1alpha1.TraefikService GetTLSOptions() []*v1alpha1.TLSOption GetServersTransports() []*v1alpha1.ServersTransport + GetServersTransportTCPs() []*v1alpha1.ServersTransportTCP GetTLSStores() []*v1alpha1.TLSStore GetService(namespace, name string) (*corev1.Service, bool, error) GetSecret(namespace, name string) (*corev1.Secret, bool, error) @@ -170,6 +171,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (< factoryCrd.Traefik().V1alpha1().IngressRouteUDPs().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().TLSOptions().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().ServersTransports().Informer().AddEventHandler(eventHandler) + factoryCrd.Traefik().V1alpha1().ServersTransportTCPs().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().TLSStores().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().TraefikServices().Informer().AddEventHandler(eventHandler) @@ -325,6 +327,24 @@ func (c *clientWrapper) GetServersTransports() []*v1alpha1.ServersTransport { return result } +// GetServersTransportTCPs returns all ServersTransportTCP. +func (c *clientWrapper) GetServersTransportTCPs() []*v1alpha1.ServersTransportTCP { + var result []*v1alpha1.ServersTransportTCP + + for ns, factory := range c.factoriesCrd { + serversTransports, err := factory.Traefik().V1alpha1().ServersTransportTCPs().Lister().List(labels.Everything()) + if err != nil { + log.Error(). + Err(err). + Str("namespace", ns). + Msg("Failed to list servers transport TCP in namespace") + } + result = append(result, serversTransports...) + } + + return result +} + // GetTLSOptions returns all TLS options. func (c *clientWrapper) GetTLSOptions() []*v1alpha1.TLSOption { var result []*v1alpha1.TLSOption diff --git a/pkg/provider/kubernetes/crd/client_mock_test.go b/pkg/provider/kubernetes/crd/client_mock_test.go index 5e018ca6d..4ed71e1d0 100644 --- a/pkg/provider/kubernetes/crd/client_mock_test.go +++ b/pkg/provider/kubernetes/crd/client_mock_test.go @@ -30,15 +30,16 @@ type clientMock struct { apiSecretError error apiEndpointsError error - ingressRoutes []*v1alpha1.IngressRoute - ingressRouteTCPs []*v1alpha1.IngressRouteTCP - ingressRouteUDPs []*v1alpha1.IngressRouteUDP - middlewares []*v1alpha1.Middleware - middlewareTCPs []*v1alpha1.MiddlewareTCP - tlsOptions []*v1alpha1.TLSOption - tlsStores []*v1alpha1.TLSStore - traefikServices []*v1alpha1.TraefikService - serversTransport []*v1alpha1.ServersTransport + ingressRoutes []*v1alpha1.IngressRoute + ingressRouteTCPs []*v1alpha1.IngressRouteTCP + ingressRouteUDPs []*v1alpha1.IngressRouteUDP + middlewares []*v1alpha1.Middleware + middlewareTCPs []*v1alpha1.MiddlewareTCP + tlsOptions []*v1alpha1.TLSOption + tlsStores []*v1alpha1.TLSStore + traefikServices []*v1alpha1.TraefikService + serversTransports []*v1alpha1.ServersTransport + serversTransportTCPs []*v1alpha1.ServersTransportTCP watchChan chan interface{} } @@ -74,7 +75,9 @@ func newClientMock(paths ...string) clientMock { case *v1alpha1.TLSOption: c.tlsOptions = append(c.tlsOptions, o) case *v1alpha1.ServersTransport: - c.serversTransport = append(c.serversTransport, o) + c.serversTransports = append(c.serversTransports, o) + case *v1alpha1.ServersTransportTCP: + c.serversTransportTCPs = append(c.serversTransportTCPs, o) case *v1alpha1.TLSStore: c.tlsStores = append(c.tlsStores, o) case *corev1.Secret: @@ -131,7 +134,11 @@ func (c clientMock) GetTLSStores() []*v1alpha1.TLSStore { } func (c clientMock) GetServersTransports() []*v1alpha1.ServersTransport { - return c.serversTransport + return c.serversTransports +} + +func (c clientMock) GetServersTransportTCPs() []*v1alpha1.ServersTransportTCP { + return c.serversTransportTCPs } func (c clientMock) GetTLSOption(namespace, name string) (*v1alpha1.TLSOption, bool, error) { diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_servers_transport.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_servers_transport.yml new file mode 100644 index 000000000..f6653146d --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_servers_transport.yml @@ -0,0 +1,147 @@ +apiVersion: v1 +kind: Secret +metadata: + name: root-ca0 + namespace: foo + +data: + foobar: VEVTVFJPT1RDQVMw + +--- +apiVersion: v1 +kind: Secret +metadata: + name: root-ca1 + namespace: foo + +data: + tls.ca: VEVTVFJPT1RDQVMx + +--- +apiVersion: v1 +kind: Secret +metadata: + name: root-ca2 + namespace: foo + +data: + tls.ca: VEVTVFJPT1RDQVMy + +--- +apiVersion: v1 +kind: Secret +metadata: + name: root-ca3 + namespace: foo + +data: + ca.crt: VEVTVFJPT1RDQVMz + +--- +apiVersion: v1 +kind: Secret +metadata: + name: root-ca4 + namespace: foo + +data: + ca.crt: VEVTVFJPT1RDQVM0 + tls.ca: VEVTVFJPT1RDQVM1 # <-- This should be the preferred one. + +--- +apiVersion: v1 +kind: Secret +metadata: + name: mtls1 + namespace: foo + +data: + tls.crt: VEVTVENFUlQx + tls.key: VEVTVEtFWTE= + +--- +apiVersion: v1 +kind: Secret +metadata: + name: mtls2 + namespace: foo + +data: + tls.crt: VEVTVENFUlQy + tls.key: VEVTVEtFWTI= + +--- +apiVersion: v1 +kind: Secret +metadata: + name: allcerts + namespace: foo + +data: + ca.crt: VEVTVEFMTENFUlRT + tls.crt: VEVTVENFUlQz + tls.key: VEVTVEtFWTM= + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: test + namespace: foo + +spec: + tls: + serverName: "test" + insecureSkipVerify: true + peerCertURI: foo://bar + rootCAsSecrets: + - root-ca0 + - root-ca1 + - root-ca2 + - root-ca3 + - root-ca4 + - allcerts + certificatesSecrets: + - mtls1 + - mtls2 + - allcerts + spiffe: + ids: + - spiffe://foo/buz + - spiffe://bar/biz + trustDomain: spiffe://lol + dialTimeout: 42 + dialKeepAlive: 42 + terminationDelay: 42 + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: test + namespace: default + +spec: + tls: + serverName: "test" + +--- +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 + serversTransport: test + - name: whoamitcp2 + port: 8080 + serversTransport: default-test diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_servers_transport_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_servers_transport_cross_namespace.yml new file mode 100644 index 000000000..7100fe95e --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_servers_transport_cross_namespace.yml @@ -0,0 +1,27 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteTCP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: HostSNI(`foo.com`) + priority: 12 + services: + - name: whoamitcp + port: 8000 + serversTransport: cross-ns-st-cross-ns@kubernetescrd + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransportTCP +metadata: + name: st-cross-ns + namespace: cross-ns + +spec: + dialKeepAlive: 0 diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_serverstransporttcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_serverstransporttcp.go new file mode 100644 index 000000000..0da6a61bf --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_serverstransporttcp.go @@ -0,0 +1,138 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs + +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 ( + "context" + + v1alpha1 "github.com/traefik/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" +) + +// FakeServersTransportTCPs implements ServersTransportTCPInterface +type FakeServersTransportTCPs struct { + Fake *FakeTraefikV1alpha1 + ns string +} + +var serverstransporttcpsResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "serverstransporttcps"} + +var serverstransporttcpsKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "ServersTransportTCP"} + +// Get takes name of the serversTransportTCP, and returns the corresponding serversTransportTCP object, and an error if there is any. +func (c *FakeServersTransportTCPs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ServersTransportTCP, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(serverstransporttcpsResource, c.ns, name), &v1alpha1.ServersTransportTCP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ServersTransportTCP), err +} + +// List takes label and field selectors, and returns the list of ServersTransportTCPs that match those selectors. +func (c *FakeServersTransportTCPs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ServersTransportTCPList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(serverstransporttcpsResource, serverstransporttcpsKind, c.ns, opts), &v1alpha1.ServersTransportTCPList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ServersTransportTCPList{ListMeta: obj.(*v1alpha1.ServersTransportTCPList).ListMeta} + for _, item := range obj.(*v1alpha1.ServersTransportTCPList).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 serversTransportTCPs. +func (c *FakeServersTransportTCPs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(serverstransporttcpsResource, c.ns, opts)) + +} + +// Create takes the representation of a serversTransportTCP and creates it. Returns the server's representation of the serversTransportTCP, and an error, if there is any. +func (c *FakeServersTransportTCPs) Create(ctx context.Context, serversTransportTCP *v1alpha1.ServersTransportTCP, opts v1.CreateOptions) (result *v1alpha1.ServersTransportTCP, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(serverstransporttcpsResource, c.ns, serversTransportTCP), &v1alpha1.ServersTransportTCP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ServersTransportTCP), err +} + +// Update takes the representation of a serversTransportTCP and updates it. Returns the server's representation of the serversTransportTCP, and an error, if there is any. +func (c *FakeServersTransportTCPs) Update(ctx context.Context, serversTransportTCP *v1alpha1.ServersTransportTCP, opts v1.UpdateOptions) (result *v1alpha1.ServersTransportTCP, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(serverstransporttcpsResource, c.ns, serversTransportTCP), &v1alpha1.ServersTransportTCP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ServersTransportTCP), err +} + +// Delete takes name of the serversTransportTCP and deletes it. Returns an error if one occurs. +func (c *FakeServersTransportTCPs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(serverstransporttcpsResource, c.ns, name), &v1alpha1.ServersTransportTCP{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeServersTransportTCPs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(serverstransporttcpsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ServersTransportTCPList{}) + return err +} + +// Patch applies the patch and returns the patched serversTransportTCP. +func (c *FakeServersTransportTCPs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ServersTransportTCP, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(serverstransporttcpsResource, c.ns, name, pt, data, subresources...), &v1alpha1.ServersTransportTCP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ServersTransportTCP), err +} diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go index c593b1ccd..10aea68d7 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go @@ -60,6 +60,10 @@ func (c *FakeTraefikV1alpha1) ServersTransports(namespace string) v1alpha1.Serve return &FakeServersTransports{c, namespace} } +func (c *FakeTraefikV1alpha1) ServersTransportTCPs(namespace string) v1alpha1.ServersTransportTCPInterface { + return &FakeServersTransportTCPs{c, namespace} +} + func (c *FakeTraefikV1alpha1) TLSOptions(namespace string) v1alpha1.TLSOptionInterface { return &FakeTLSOptions{c, namespace} } diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go index a252692a7..cc3996eed 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go @@ -38,6 +38,8 @@ type MiddlewareTCPExpansion interface{} type ServersTransportExpansion interface{} +type ServersTransportTCPExpansion interface{} + type TLSOptionExpansion interface{} type TLSStoreExpansion interface{} diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransporttcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransporttcp.go new file mode 100644 index 000000000..ff192824a --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransporttcp.go @@ -0,0 +1,186 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs + +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 ( + "context" + "time" + + scheme "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/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" +) + +// ServersTransportTCPsGetter has a method to return a ServersTransportTCPInterface. +// A group's client should implement this interface. +type ServersTransportTCPsGetter interface { + ServersTransportTCPs(namespace string) ServersTransportTCPInterface +} + +// ServersTransportTCPInterface has methods to work with ServersTransportTCP resources. +type ServersTransportTCPInterface interface { + Create(ctx context.Context, serversTransportTCP *v1alpha1.ServersTransportTCP, opts v1.CreateOptions) (*v1alpha1.ServersTransportTCP, error) + Update(ctx context.Context, serversTransportTCP *v1alpha1.ServersTransportTCP, opts v1.UpdateOptions) (*v1alpha1.ServersTransportTCP, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ServersTransportTCP, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ServersTransportTCPList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ServersTransportTCP, err error) + ServersTransportTCPExpansion +} + +// serversTransportTCPs implements ServersTransportTCPInterface +type serversTransportTCPs struct { + client rest.Interface + ns string +} + +// newServersTransportTCPs returns a ServersTransportTCPs +func newServersTransportTCPs(c *TraefikV1alpha1Client, namespace string) *serversTransportTCPs { + return &serversTransportTCPs{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the serversTransportTCP, and returns the corresponding serversTransportTCP object, and an error if there is any. +func (c *serversTransportTCPs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ServersTransportTCP, err error) { + result = &v1alpha1.ServersTransportTCP{} + err = c.client.Get(). + Namespace(c.ns). + Resource("serverstransporttcps"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ServersTransportTCPs that match those selectors. +func (c *serversTransportTCPs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ServersTransportTCPList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ServersTransportTCPList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("serverstransporttcps"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested serversTransportTCPs. +func (c *serversTransportTCPs) Watch(ctx context.Context, 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("serverstransporttcps"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a serversTransportTCP and creates it. Returns the server's representation of the serversTransportTCP, and an error, if there is any. +func (c *serversTransportTCPs) Create(ctx context.Context, serversTransportTCP *v1alpha1.ServersTransportTCP, opts v1.CreateOptions) (result *v1alpha1.ServersTransportTCP, err error) { + result = &v1alpha1.ServersTransportTCP{} + err = c.client.Post(). + Namespace(c.ns). + Resource("serverstransporttcps"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serversTransportTCP). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a serversTransportTCP and updates it. Returns the server's representation of the serversTransportTCP, and an error, if there is any. +func (c *serversTransportTCPs) Update(ctx context.Context, serversTransportTCP *v1alpha1.ServersTransportTCP, opts v1.UpdateOptions) (result *v1alpha1.ServersTransportTCP, err error) { + result = &v1alpha1.ServersTransportTCP{} + err = c.client.Put(). + Namespace(c.ns). + Resource("serverstransporttcps"). + Name(serversTransportTCP.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serversTransportTCP). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the serversTransportTCP and deletes it. Returns an error if one occurs. +func (c *serversTransportTCPs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("serverstransporttcps"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *serversTransportTCPs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("serverstransporttcps"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched serversTransportTCP. +func (c *serversTransportTCPs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ServersTransportTCP, err error) { + result = &v1alpha1.ServersTransportTCP{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("serverstransporttcps"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go index 2682dbad5..036600bd7 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go @@ -40,6 +40,7 @@ type TraefikV1alpha1Interface interface { MiddlewaresGetter MiddlewareTCPsGetter ServersTransportsGetter + ServersTransportTCPsGetter TLSOptionsGetter TLSStoresGetter TraefikServicesGetter @@ -74,6 +75,10 @@ func (c *TraefikV1alpha1Client) ServersTransports(namespace string) ServersTrans return newServersTransports(c, namespace) } +func (c *TraefikV1alpha1Client) ServersTransportTCPs(namespace string) ServersTransportTCPInterface { + return newServersTransportTCPs(c, namespace) +} + func (c *TraefikV1alpha1Client) TLSOptions(namespace string) TLSOptionInterface { return newTLSOptions(c, namespace) } diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go index a062e290d..46a030224 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go @@ -73,6 +73,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().MiddlewareTCPs().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("serverstransports"): return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().ServersTransports().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("serverstransporttcps"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().ServersTransportTCPs().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("tlsoptions"): return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().TLSOptions().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("tlsstores"): diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go index 563e81956..6b8f07052 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go @@ -44,6 +44,8 @@ type Interface interface { MiddlewareTCPs() MiddlewareTCPInformer // ServersTransports returns a ServersTransportInformer. ServersTransports() ServersTransportInformer + // ServersTransportTCPs returns a ServersTransportTCPInformer. + ServersTransportTCPs() ServersTransportTCPInformer // TLSOptions returns a TLSOptionInformer. TLSOptions() TLSOptionInformer // TLSStores returns a TLSStoreInformer. @@ -93,6 +95,11 @@ func (v *version) ServersTransports() ServersTransportInformer { return &serversTransportInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// ServersTransportTCPs returns a ServersTransportTCPInformer. +func (v *version) ServersTransportTCPs() ServersTransportTCPInformer { + return &serversTransportTCPInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // TLSOptions returns a TLSOptionInformer. func (v *version) TLSOptions() TLSOptionInformer { return &tLSOptionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransporttcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransporttcp.go new file mode 100644 index 000000000..bee2a25a6 --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransporttcp.go @@ -0,0 +1,98 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs + +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 ( + "context" + time "time" + + versioned "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1" + traefikv1alpha1 "github.com/traefik/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" +) + +// ServersTransportTCPInformer provides access to a shared informer and lister for +// ServersTransportTCPs. +type ServersTransportTCPInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ServersTransportTCPLister +} + +type serversTransportTCPInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewServersTransportTCPInformer constructs a new informer for ServersTransportTCP 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 NewServersTransportTCPInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServersTransportTCPInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredServersTransportTCPInformer constructs a new informer for ServersTransportTCP 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 NewFilteredServersTransportTCPInformer(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().ServersTransportTCPs(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TraefikV1alpha1().ServersTransportTCPs(namespace).Watch(context.TODO(), options) + }, + }, + &traefikv1alpha1.ServersTransportTCP{}, + resyncPeriod, + indexers, + ) +} + +func (f *serversTransportTCPInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServersTransportTCPInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serversTransportTCPInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&traefikv1alpha1.ServersTransportTCP{}, f.defaultInformer) +} + +func (f *serversTransportTCPInformer) Lister() v1alpha1.ServersTransportTCPLister { + return v1alpha1.NewServersTransportTCPLister(f.Informer().GetIndexer()) +} diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go index c338fb976..1bd7deb56 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go @@ -74,6 +74,14 @@ type ServersTransportListerExpansion interface{} // ServersTransportNamespaceLister. type ServersTransportNamespaceListerExpansion interface{} +// ServersTransportTCPListerExpansion allows custom methods to be added to +// ServersTransportTCPLister. +type ServersTransportTCPListerExpansion interface{} + +// ServersTransportTCPNamespaceListerExpansion allows custom methods to be added to +// ServersTransportTCPNamespaceLister. +type ServersTransportTCPNamespaceListerExpansion interface{} + // TLSOptionListerExpansion allows custom methods to be added to // TLSOptionLister. type TLSOptionListerExpansion interface{} diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransporttcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransporttcp.go new file mode 100644 index 000000000..14635c6f1 --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransporttcp.go @@ -0,0 +1,107 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs + +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/traefik/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" +) + +// ServersTransportTCPLister helps list ServersTransportTCPs. +// All objects returned here must be treated as read-only. +type ServersTransportTCPLister interface { + // List lists all ServersTransportTCPs in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ServersTransportTCP, err error) + // ServersTransportTCPs returns an object that can list and get ServersTransportTCPs. + ServersTransportTCPs(namespace string) ServersTransportTCPNamespaceLister + ServersTransportTCPListerExpansion +} + +// serversTransportTCPLister implements the ServersTransportTCPLister interface. +type serversTransportTCPLister struct { + indexer cache.Indexer +} + +// NewServersTransportTCPLister returns a new ServersTransportTCPLister. +func NewServersTransportTCPLister(indexer cache.Indexer) ServersTransportTCPLister { + return &serversTransportTCPLister{indexer: indexer} +} + +// List lists all ServersTransportTCPs in the indexer. +func (s *serversTransportTCPLister) List(selector labels.Selector) (ret []*v1alpha1.ServersTransportTCP, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ServersTransportTCP)) + }) + return ret, err +} + +// ServersTransportTCPs returns an object that can list and get ServersTransportTCPs. +func (s *serversTransportTCPLister) ServersTransportTCPs(namespace string) ServersTransportTCPNamespaceLister { + return serversTransportTCPNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ServersTransportTCPNamespaceLister helps list and get ServersTransportTCPs. +// All objects returned here must be treated as read-only. +type ServersTransportTCPNamespaceLister interface { + // List lists all ServersTransportTCPs in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ServersTransportTCP, err error) + // Get retrieves the ServersTransportTCP from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ServersTransportTCP, error) + ServersTransportTCPNamespaceListerExpansion +} + +// serversTransportTCPNamespaceLister implements the ServersTransportTCPNamespaceLister +// interface. +type serversTransportTCPNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ServersTransportTCPs in the indexer for a given namespace. +func (s serversTransportTCPNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ServersTransportTCP, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ServersTransportTCP)) + }) + return ret, err +} + +// Get retrieves the ServersTransportTCP from the indexer for a given namespace and name. +func (s serversTransportTCPNamespaceLister) Get(name string) (*v1alpha1.ServersTransportTCP, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("serverstransporttcp"), name) + } + return obj.(*v1alpha1.ServersTransportTCP), nil +} diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index f2054d09e..e3d65be74 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -393,6 +393,80 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) } } + for _, serversTransportTCP := range client.GetServersTransportTCPs() { + logger := log.Ctx(ctx).With().Str(logs.ServersTransportName, serversTransportTCP.Name).Logger() + + var tcpServerTransport dynamic.TCPServersTransport + tcpServerTransport.SetDefaults() + + if serversTransportTCP.Spec.DialTimeout != nil { + err := tcpServerTransport.DialTimeout.Set(serversTransportTCP.Spec.DialTimeout.String()) + if err != nil { + logger.Error().Err(err).Msg("Error while reading DialTimeout") + } + } + + if serversTransportTCP.Spec.DialKeepAlive != nil { + err := tcpServerTransport.DialKeepAlive.Set(serversTransportTCP.Spec.DialKeepAlive.String()) + if err != nil { + logger.Error().Err(err).Msg("Error while reading DialKeepAlive") + } + } + + if serversTransportTCP.Spec.TerminationDelay != nil { + err := tcpServerTransport.TerminationDelay.Set(serversTransportTCP.Spec.TerminationDelay.String()) + if err != nil { + logger.Error().Err(err).Msg("Error while reading TerminationDelay") + } + } + + if serversTransportTCP.Spec.TLS != nil { + var rootCAs []tls.FileOrContent + for _, secret := range serversTransportTCP.Spec.TLS.RootCAsSecrets { + caSecret, err := loadCASecret(serversTransportTCP.Namespace, secret, client) + if err != nil { + logger.Error(). + Err(err). + Str("rootCAs", secret). + Msg("Error while loading rootCAs") + continue + } + + rootCAs = append(rootCAs, tls.FileOrContent(caSecret)) + } + + var certs tls.Certificates + for _, secret := range serversTransportTCP.Spec.TLS.CertificatesSecrets { + tlsCert, tlsKey, err := loadAuthTLSSecret(serversTransportTCP.Namespace, secret, client) + if err != nil { + logger.Error(). + Err(err). + Str("certificates", secret). + Msg("Error while loading certificates") + continue + } + + certs = append(certs, tls.Certificate{ + CertFile: tls.FileOrContent(tlsCert), + KeyFile: tls.FileOrContent(tlsKey), + }) + } + + tcpServerTransport.TLS = &dynamic.TLSClientConfig{ + ServerName: serversTransportTCP.Spec.TLS.ServerName, + InsecureSkipVerify: serversTransportTCP.Spec.TLS.InsecureSkipVerify, + RootCAs: rootCAs, + Certificates: certs, + PeerCertURI: serversTransportTCP.Spec.TLS.PeerCertURI, + } + + tcpServerTransport.TLS.Spiffe = serversTransportTCP.Spec.TLS.Spiffe + } + + id := provider.Normalize(makeID(serversTransportTCP.Namespace, serversTransportTCP.Name)) + conf.TCP.ServersTransports[id] = &tcpServerTransport + } + return conf } diff --git a/pkg/provider/kubernetes/crd/kubernetes_tcp.go b/pkg/provider/kubernetes/crd/kubernetes_tcp.go index bdb11ee33..446168a25 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_tcp.go +++ b/pkg/provider/kubernetes/crd/kubernetes_tcp.go @@ -19,9 +19,10 @@ import ( func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client Client, tlsConfigs map[string]*tls.CertAndStores) *dynamic.TCPConfiguration { conf := &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, } for _, ingressRouteTCP := range client.GetIngressRouteTCPs() { @@ -202,8 +203,11 @@ func (p *Provider) createLoadBalancerServerTCP(client Client, parentNamespace st } } - if service.TerminationDelay != nil { - tcpService.LoadBalancer.TerminationDelay = service.TerminationDelay + if service.ServersTransport != "" { + tcpService.LoadBalancer.ServersTransport, err = p.makeTCPServersTransportKey(parentNamespace, service.ServersTransport) + if err != nil { + return nil, err + } } return tcpService, nil @@ -271,6 +275,25 @@ func (p *Provider) loadTCPServers(client Client, namespace string, svc v1alpha1. return servers, nil } +func (p *Provider) makeTCPServersTransportKey(parentNamespace string, serversTransportName string) (string, error) { + if serversTransportName == "" { + return "", nil + } + + if !p.AllowCrossNamespace && strings.HasSuffix(serversTransportName, providerNamespaceSeparator+providerName) { + // Since we are not able to know if another namespace is in the name (namespace-name@kubernetescrd), + // if the provider namespace kubernetescrd is used, + // we don't allow this format to avoid cross namespace references. + return "", fmt.Errorf("invalid reference to serversTransport %s: namespace-name@kubernetescrd format is not allowed when crossnamespace is disallowed", serversTransportName) + } + + if strings.Contains(serversTransportName, providerNamespaceSeparator) { + return serversTransportName, nil + } + + return provider.Normalize(makeID(parentNamespace, serversTransportName)), nil +} + // getTLSTCP mutates tlsConfigs. func getTLSTCP(ctx context.Context, ingressRoute *v1alpha1.IngressRouteTCP, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error { if ingressRoute.Spec.TLS == nil { diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go index 48e5844db..6819df09e 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_test.go +++ b/pkg/provider/kubernetes/crd/kubernetes_test.go @@ -46,9 +46,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -96,6 +97,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -149,6 +151,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -197,6 +200,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -250,6 +254,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -302,6 +307,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -343,6 +349,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -410,6 +417,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -493,6 +501,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -513,9 +522,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -535,9 +545,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -590,6 +601,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -633,6 +645,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -701,6 +714,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -768,6 +782,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -834,6 +849,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -889,6 +905,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -944,6 +961,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -985,6 +1003,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1024,10 +1043,10 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Address: "10.10.0.2:8000", }, }, - TerminationDelay: Int(500), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1075,6 +1094,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1116,6 +1136,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1154,6 +1175,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1173,6 +1195,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ + // The router that references the invalid service will be discarded. Routers: map[string]*dynamic.TCPRouter{ "default-test.route-fdd3e9338e47a45efefc": { EntryPoints: []string{"foo"}, @@ -1180,8 +1203,9 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1265,6 +1289,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1355,6 +1380,109 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + }, + }, + { + desc: "TCP with ServersTransport", + paths: []string{"tcp/services.yml", "tcp/with_servers_transport.yml"}, + expected: &dynamic.Configuration{ + TLS: &dynamic.TLSConfiguration{}, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + ServersTransports: map[string]*dynamic.TCPServersTransport{ + "foo-test": { + TLS: &dynamic.TLSClientConfig{ + ServerName: "test", + InsecureSkipVerify: true, + RootCAs: []tls.FileOrContent{"TESTROOTCAS0", "TESTROOTCAS1", "TESTROOTCAS2", "TESTROOTCAS3", "TESTROOTCAS5", "TESTALLCERTS"}, + Certificates: tls.Certificates{ + {CertFile: "TESTCERT1", KeyFile: "TESTKEY1"}, + {CertFile: "TESTCERT2", KeyFile: "TESTKEY2"}, + {CertFile: "TESTCERT3", KeyFile: "TESTKEY3"}, + }, + PeerCertURI: "foo://bar", + Spiffe: &dynamic.Spiffe{ + IDs: []string{ + "spiffe://foo/buz", + "spiffe://bar/biz", + }, + TrustDomain: "spiffe://lol", + }, + }, + DialTimeout: ptypes.Duration(42 * time.Second), + DialKeepAlive: ptypes.Duration(42 * time.Second), + TerminationDelay: ptypes.Duration(42 * time.Second), + }, + "default-test": { + TLS: &dynamic.TLSClientConfig{ + ServerName: "test", + }, + DialTimeout: ptypes.Duration(30 * time.Second), + DialKeepAlive: ptypes.Duration(15 * time.Second), + TerminationDelay: ptypes.Duration(100 * time.Millisecond), + }, + }, + Routers: map[string]*dynamic.TCPRouter{ + "default-test.route-fdd3e9338e47a45efefc": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-fdd3e9338e47a45efefc", + Rule: "HostSNI(`foo.com`)", + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-test.route-fdd3e9338e47a45efefc-whoamitcp-8000": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + ServersTransport: "default-test", + }, + }, + "default-test.route-fdd3e9338e47a45efefc-whoamitcp2-8080": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.3:8080", + }, + { + Address: "10.10.0.4:8080", + }, + }, + ServersTransport: "default-default-test", + }, + }, + "default-test.route-fdd3e9338e47a45efefc": { + Weighted: &dynamic.TCPWeightedRoundRobin{ + Services: []dynamic.TCPWRRService{ + { + Name: "default-test.route-fdd3e9338e47a45efefc-whoamitcp-8000", + Weight: Int(1), + }, + { + Name: "default-test.route-fdd3e9338e47a45efefc-whoamitcp2-8080", + Weight: Int(1), + }, + }, + }, + }, + }, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1373,6 +1501,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ + // The router that references the invalid service will be discarded. Routers: map[string]*dynamic.TCPRouter{ "default-test.route-fdd3e9338e47a45efefc": { EntryPoints: []string{"foo"}, @@ -1380,8 +1509,9 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1415,6 +1545,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { LoadBalancer: &dynamic.TCPServersLoadBalancer{}, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1468,9 +1599,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1490,9 +1622,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1537,9 +1670,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1608,9 +1742,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1663,9 +1798,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1720,9 +1856,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1789,9 +1926,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1865,9 +2003,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1921,9 +2060,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1970,9 +2110,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2106,9 +2247,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2176,9 +2318,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2275,9 +2418,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2462,9 +2606,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2532,9 +2677,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2622,9 +2768,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2699,9 +2846,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2721,9 +2869,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2743,9 +2892,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2774,9 +2924,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2844,9 +2995,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2895,9 +3047,10 @@ func TestLoadIngressRoutes(t *testing.T) { Options: map[string]tls.Options{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2967,9 +3120,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3040,9 +3194,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3111,9 +3266,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3171,9 +3327,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3232,9 +3389,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3281,9 +3439,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3328,9 +3487,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3374,9 +3534,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3420,9 +3581,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3463,9 +3625,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3494,9 +3657,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3531,9 +3695,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3561,9 +3726,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3601,9 +3767,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3623,9 +3790,10 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3669,9 +3837,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3723,9 +3892,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3783,9 +3953,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3832,9 +4003,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3881,9 +4053,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3923,9 +4096,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3965,9 +4139,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -4007,9 +4182,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4029,9 +4205,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{ @@ -4139,9 +4316,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4162,9 +4340,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -4201,9 +4380,10 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -4323,9 +4503,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4369,9 +4550,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { ServersTransports: map[string]*dynamic.ServersTransport{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -4419,9 +4601,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4485,9 +4668,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4567,9 +4751,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4604,9 +4789,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4641,9 +4827,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4659,6 +4846,7 @@ func TestLoadIngressRouteUDPs(t *testing.T) { paths: []string{"udp/services.yml", "udp/with_externalname_without_ports.yml"}, expected: &dynamic.Configuration{ UDP: &dynamic.UDPConfiguration{ + // The router that references the invalid service will be discarded. Routers: map[string]*dynamic.UDPRouter{ "default-test.route-0": { EntryPoints: []string{"foo"}, @@ -4668,9 +4856,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4691,9 +4880,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4709,6 +4899,7 @@ func TestLoadIngressRouteUDPs(t *testing.T) { paths: []string{"udp/services.yml", "udp/with_empty_services.yml"}, expected: &dynamic.Configuration{ UDP: &dynamic.UDPConfiguration{ + // The router that references the invalid service will be discarded. Routers: map[string]*dynamic.UDPRouter{ "default-test.route-0": { EntryPoints: []string{"foo"}, @@ -4718,9 +4909,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -4750,9 +4942,10 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -5105,9 +5298,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -5127,9 +5321,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -5181,9 +5376,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -5306,9 +5502,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -5458,9 +5655,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -5535,9 +5733,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -5593,9 +5792,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -5627,9 +5827,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -5684,9 +5885,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -5764,6 +5966,7 @@ func TestCrossNamespace(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -5836,6 +6039,7 @@ func TestCrossNamespace(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -5884,6 +6088,7 @@ func TestCrossNamespace(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -5905,8 +6110,97 @@ func TestCrossNamespace(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "TCP ServersTransport cross namespace allowed", + paths: []string{"tcp/services.yml", "tcp/with_servers_transport_cross_namespace.yml"}, + allowCrossNamespace: true, + 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`)", + Priority: 12, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-test.route-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + ServersTransport: "cross-ns-st-cross-ns@kubernetescrd", + }, + }, + }, + ServersTransports: map[string]*dynamic.TCPServersTransport{ + "cross-ns-st-cross-ns": { + DialTimeout: ptypes.Duration(30 * time.Second), + DialKeepAlive: 0, + TerminationDelay: ptypes.Duration(100 * time.Millisecond), + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "TCP ServersTransport cross namespace disallowed", + paths: []string{"tcp/services.yml", "tcp/with_servers_transport_cross_namespace.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + // The router that references the invalid service will be discarded. + Routers: map[string]*dynamic.TCPRouter{ + "default-test.route-fdd3e9338e47a45efefc": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-fdd3e9338e47a45efefc", + Rule: "HostSNI(`foo.com`)", + Priority: 12, + }, + }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{ + "cross-ns-st-cross-ns": { + DialTimeout: 30000000000, + DialKeepAlive: 0, + TerminationDelay: ptypes.Duration(100 * time.Millisecond), + }, + }, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -5958,6 +6252,7 @@ func TestCrossNamespace(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ @@ -6001,6 +6296,7 @@ func TestCrossNamespace(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ @@ -6046,9 +6342,10 @@ func TestCrossNamespace(t *testing.T) { ServersTransports: map[string]*dynamic.ServersTransport{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -6057,8 +6354,8 @@ func TestCrossNamespace(t *testing.T) { desc: "UDP cross namespace disallowed", paths: []string{"udp/services.yml", "udp/with_cross_namespace.yml"}, expected: &dynamic.Configuration{ - // The router that references the invalid service will be discarded. UDP: &dynamic.UDPConfiguration{ + // The router that references the invalid service will be discarded. Routers: map[string]*dynamic.UDPRouter{ "default-test.route-0": { EntryPoints: []string{"foo"}, @@ -6068,9 +6365,10 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -6120,6 +6418,8 @@ func TestCrossNamespace(t *testing.T) { crdObjects = append(crdObjects, o) case *v1alpha1.ServersTransport: crdObjects = append(crdObjects, o) + case *v1alpha1.ServersTransportTCP: + crdObjects = append(crdObjects, o) default: } } @@ -6164,9 +6464,10 @@ func TestExternalNameService(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -6187,9 +6488,10 @@ func TestExternalNameService(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -6230,9 +6532,10 @@ func TestExternalNameService(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -6279,6 +6582,7 @@ func TestExternalNameService(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -6300,8 +6604,9 @@ func TestExternalNameService(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -6344,9 +6649,10 @@ func TestExternalNameService(t *testing.T) { Services: map[string]*dynamic.Service{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -6355,8 +6661,8 @@ func TestExternalNameService(t *testing.T) { desc: "UDP ExternalName service disallowed", paths: []string{"udp/services.yml", "udp/with_externalname_service.yml"}, expected: &dynamic.Configuration{ - // The router that references the invalid service will be discarded. UDP: &dynamic.UDPConfiguration{ + // The router that references the invalid service will be discarded. Routers: map[string]*dynamic.UDPRouter{ "default-test.route-0": { EntryPoints: []string{"foo"}, @@ -6366,9 +6672,10 @@ func TestExternalNameService(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go index 4d89c7fdb..71b76afc5 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go @@ -69,15 +69,15 @@ 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). - 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"` + // ServersTransport defines the name of ServersTransportTCP resource to use. + // It allows to configure the transport between Traefik and your servers. + // Can only be used on a Kubernetes Service. + ServersTransport string `json:"serversTransport,omitempty"` + // TLS determines whether to use TLS when dialing with the backend. + TLS bool `json:"tls,omitempty"` } // +genclient diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go index e87a2ff65..ce17cf418 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go @@ -51,6 +51,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &TraefikServiceList{}, &ServersTransport{}, &ServersTransportList{}, + &ServersTransportTCP{}, + &ServersTransportTCPList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/serverstransporttcp.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/serverstransporttcp.go new file mode 100644 index 000000000..44b92dbe6 --- /dev/null +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/serverstransporttcp.go @@ -0,0 +1,68 @@ +package v1alpha1 + +import ( + "github.com/traefik/traefik/v2/pkg/config/dynamic" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:storageversion + +// ServersTransportTCP is the CRD implementation of a TCPServersTransport. +// If no tcpServersTransport is specified, a default one named default@internal will be used. +// The default@internal tcpServersTransport can be configured in the static configuration. +// More info: https://doc.traefik.io/traefik/v2.9/routing/services/#serverstransport_3 +type ServersTransportTCP struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata"` + + Spec ServersTransportTCPSpec `json:"spec"` +} + +// +k8s:deepcopy-gen=true + +// ServersTransportTCPSpec defines the desired state of a ServersTransportTCP. +type ServersTransportTCPSpec struct { + // DialTimeout is the amount of time to wait until a connection to a backend server can be established. + DialTimeout *intstr.IntOrString `json:"dialTimeout,omitempty"` + // DialKeepAlive is the interval between keep-alive probes for an active network connection. If zero, keep-alive probes are sent with a default value (currently 15 seconds), if supported by the protocol and operating system. Network protocols or operating systems that do not support keep-alives ignore this field. If negative, keep-alive probes are disabled. + DialKeepAlive *intstr.IntOrString `json:"dialKeepAlive,omitempty"` + // TerminationDelay defines the delay to wait before fully terminating the connection, after one connected peer has closed its writing capability. + TerminationDelay *intstr.IntOrString `json:"terminationDelay,omitempty"` + // TLS defines the TLS configuration + TLS *TLSClientConfig `description:"Defines the TLS configuration." json:"tls,omitempty"` +} + +// TLSClientConfig defines the desired state of a TLSClientConfig. +type TLSClientConfig struct { + // ServerName defines the server name used to contact the server. + ServerName string `json:"serverName,omitempty"` + // InsecureSkipVerify disables TLS certificate verification. + InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` + // RootCAsSecrets defines a list of CA secret used to validate self-signed certificates. + RootCAsSecrets []string `json:"rootCAsSecrets,omitempty"` + // CertificatesSecrets defines a list of secret storing client certificates for mTLS. + CertificatesSecrets []string `json:"certificatesSecrets,omitempty"` + // MaxIdleConnsPerHost controls the maximum idle (keep-alive) to keep per-host. + // PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification. + PeerCertURI string `json:"peerCertURI,omitempty"` + // Spiffe defines the SPIFFE configuration. + Spiffe *dynamic.Spiffe `json:"spiffe,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServersTransportTCPList is a collection of ServersTransportTCP resources. +type ServersTransportTCPList struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ListMeta `json:"metadata"` + + // Items is the list of ServersTransportTCP. + Items []ServersTransportTCP `json:"items"` +} diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go index eaa5d450c..2e67a72c1 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go @@ -1181,6 +1181,102 @@ func (in *ServersTransportSpec) DeepCopy() *ServersTransportSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersTransportTCP) DeepCopyInto(out *ServersTransportTCP) { + *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 ServersTransportTCP. +func (in *ServersTransportTCP) DeepCopy() *ServersTransportTCP { + if in == nil { + return nil + } + out := new(ServersTransportTCP) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServersTransportTCP) 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 *ServersTransportTCPList) DeepCopyInto(out *ServersTransportTCPList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServersTransportTCP, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersTransportTCPList. +func (in *ServersTransportTCPList) DeepCopy() *ServersTransportTCPList { + if in == nil { + return nil + } + out := new(ServersTransportTCPList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServersTransportTCPList) 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 *ServersTransportTCPSpec) DeepCopyInto(out *ServersTransportTCPSpec) { + *out = *in + if in.DialTimeout != nil { + in, out := &in.DialTimeout, &out.DialTimeout + *out = new(intstr.IntOrString) + **out = **in + } + if in.DialKeepAlive != nil { + in, out := &in.DialKeepAlive, &out.DialKeepAlive + *out = new(intstr.IntOrString) + **out = **in + } + if in.TerminationDelay != nil { + in, out := &in.TerminationDelay, &out.TerminationDelay + *out = new(intstr.IntOrString) + **out = **in + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(TLSClientConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersTransportTCPSpec. +func (in *ServersTransportTCPSpec) DeepCopy() *ServersTransportTCPSpec { + if in == nil { + return nil + } + out := new(ServersTransportTCPSpec) + 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 @@ -1207,11 +1303,6 @@ 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) @@ -1285,6 +1376,37 @@ func (in *TLS) DeepCopy() *TLS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSClientConfig) DeepCopyInto(out *TLSClientConfig) { + *out = *in + if in.RootCAsSecrets != nil { + in, out := &in.RootCAsSecrets, &out.RootCAsSecrets + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.CertificatesSecrets != nil { + in, out := &in.CertificatesSecrets, &out.CertificatesSecrets + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Spiffe != nil { + in, out := &in.Spiffe, &out.Spiffe + *out = new(dynamic.Spiffe) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSClientConfig. +func (in *TLSClientConfig) DeepCopy() *TLSClientConfig { + if in == nil { + return nil + } + out := new(TLSClientConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSOption) DeepCopyInto(out *TLSOption) { *out = *in diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index 3f62e98a2..fc620ae69 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -183,19 +183,22 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie if err != nil { logger.Error().Err(err).Msg("Cannot find GatewayClasses") return &dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, 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{}, } } @@ -270,19 +273,22 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway *v1alpha2.Gateway) (*dynamic.Configuration, error) { conf := &dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, 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{}, } diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index 44b3ce249..f7b6b9cd9 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -34,9 +34,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -59,9 +60,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -84,9 +86,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -109,9 +112,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -134,9 +138,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -159,9 +164,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -184,9 +190,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -209,9 +216,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -234,9 +242,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -259,9 +268,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -284,9 +294,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -309,9 +320,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -334,9 +346,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -359,9 +372,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -384,9 +398,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -410,9 +425,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -435,9 +451,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -460,9 +477,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -494,9 +512,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -519,9 +538,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -577,9 +597,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -608,9 +629,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -670,9 +692,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -738,9 +761,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -796,9 +820,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -854,9 +879,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -912,9 +938,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1001,9 +1028,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1084,9 +1112,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1172,9 +1201,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1255,9 +1285,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1328,9 +1359,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1386,9 +1418,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1475,9 +1508,10 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1555,9 +1589,10 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1580,9 +1615,10 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1605,9 +1641,10 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1630,9 +1667,10 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1655,9 +1693,10 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1680,9 +1719,10 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1705,9 +1745,10 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1762,6 +1803,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1845,6 +1887,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1937,6 +1980,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1995,6 +2039,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2048,6 +2093,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2111,6 +2157,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2192,6 +2239,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2246,6 +2294,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2290,9 +2339,10 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2315,9 +2365,10 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2340,9 +2391,10 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2365,9 +2417,10 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2390,9 +2443,10 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2415,9 +2469,10 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2448,9 +2503,10 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2473,9 +2529,10 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2531,6 +2588,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2597,6 +2655,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2654,6 +2713,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2740,6 +2800,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2808,6 +2869,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2874,6 +2936,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2931,6 +2994,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2988,6 +3052,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3045,6 +3110,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3102,6 +3168,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3189,6 +3256,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3246,6 +3314,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3339,6 +3408,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3383,9 +3453,10 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3408,9 +3479,10 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3433,9 +3505,10 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3458,9 +3531,10 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3553,6 +3627,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3635,9 +3710,10 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3730,6 +3806,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3923,6 +4000,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -4120,6 +4198,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -4251,6 +4330,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ diff --git a/pkg/provider/kubernetes/k8s/parser.go b/pkg/provider/kubernetes/k8s/parser.go index 6b1f43b76..6cea900dc 100644 --- a/pkg/provider/kubernetes/k8s/parser.go +++ b/pkg/provider/kubernetes/k8s/parser.go @@ -12,7 +12,7 @@ import ( // MustParseYaml parses a YAML to objects. func MustParseYaml(content []byte) []runtime.Object { - acceptedK8sTypes := regexp.MustCompile(`^(Namespace|Deployment|Endpoints|Service|Ingress|IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|MiddlewareTCP|Secret|TLSOption|TLSStore|TraefikService|IngressClass|ServersTransport|GatewayClass|Gateway|HTTPRoute|TCPRoute|TLSRoute)$`) + acceptedK8sTypes := regexp.MustCompile(`^(Namespace|Deployment|Endpoints|Service|Ingress|IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|MiddlewareTCP|Secret|TLSOption|TLSStore|TraefikService|IngressClass|ServersTransport|ServersTransportTCP|GatewayClass|Gateway|HTTPRoute|TCPRoute|TLSRoute)$`) files := strings.Split(string(content), "---\n") retVal := make([]runtime.Object, 0, len(files)) diff --git a/pkg/provider/kv/kv_test.go b/pkg/provider/kv/kv_test.go index f577da7e3..b078997fe 100644 --- a/pkg/provider/kv/kv_test.go +++ b/pkg/provider/kv/kv_test.go @@ -226,7 +226,6 @@ func Test_buildConfiguration(t *testing.T) { "traefik/tcp/routers/TCPRouter1/tls/passthrough": "true", "traefik/tcp/routers/TCPRouter1/tls/options": "foobar", "traefik/tcp/routers/TCPRouter1/tls/certResolver": "foobar", - "traefik/tcp/services/TCPService01/loadBalancer/terminationDelay": "42", "traefik/tcp/services/TCPService01/loadBalancer/servers/0/address": "foobar", "traefik/tcp/services/TCPService01/loadBalancer/servers/1/address": "foobar", "traefik/tcp/services/TCPService02/weighted/services/0/name": "foobar", @@ -756,7 +755,6 @@ func Test_buildConfiguration(t *testing.T) { Services: map[string]*dynamic.TCPService{ "TCPService01": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ - TerminationDelay: func(v int) *int { return &v }(42), Servers: []dynamic.TCPServer{ {Address: "foobar"}, {Address: "foobar"}, diff --git a/pkg/provider/marathon/config.go b/pkg/provider/marathon/config.go index 939505351..5c7e0b059 100644 --- a/pkg/provider/marathon/config.go +++ b/pkg/provider/marathon/config.go @@ -157,11 +157,10 @@ func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, app maratho logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() if len(conf.Services) == 0 { - conf.Services = make(map[string]*dynamic.TCPService) - lb := &dynamic.TCPServersLoadBalancer{} - lb.SetDefaults() - conf.Services[appName] = &dynamic.TCPService{ - LoadBalancer: lb, + conf.Services = map[string]*dynamic.TCPService{ + appName: { + LoadBalancer: new(dynamic.TCPServersLoadBalancer), + }, } } diff --git a/pkg/provider/marathon/config_test.go b/pkg/provider/marathon/config_test.go index 4e5b4d563..8648c7e84 100644 --- a/pkg/provider/marathon/config_test.go +++ b/pkg/provider/marathon/config_test.go @@ -49,9 +49,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -92,9 +93,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -118,9 +120,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -163,9 +166,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -242,10 +246,10 @@ func TestBuildConfiguration(t *testing.T) { Address: "localhost:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -279,9 +283,10 @@ func TestBuildConfiguration(t *testing.T) { ), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -337,9 +342,10 @@ func TestBuildConfiguration(t *testing.T) { ), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -393,9 +399,10 @@ func TestBuildConfiguration(t *testing.T) { ), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -451,9 +458,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -500,9 +508,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -546,9 +555,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -592,9 +602,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -639,9 +650,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -687,9 +699,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -747,9 +760,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -789,9 +803,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -864,9 +879,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -933,9 +949,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -995,9 +1012,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1047,9 +1065,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1101,9 +1120,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1148,9 +1168,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1195,9 +1216,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1248,9 +1270,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1275,9 +1298,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1302,9 +1326,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1329,9 +1354,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1357,9 +1383,10 @@ func TestBuildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1385,9 +1412,10 @@ func TestBuildConfiguration(t *testing.T) { constraints: `MarathonConstraint("rack_id:CLUSTER:rack-2")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1413,9 +1441,10 @@ func TestBuildConfiguration(t *testing.T) { constraints: `MarathonConstraint("rack_id:CLUSTER:rack-1")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1460,9 +1489,10 @@ func TestBuildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1506,9 +1536,10 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1569,10 +1600,10 @@ func TestBuildConfiguration(t *testing.T) { Address: "localhost:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1616,9 +1647,10 @@ func TestBuildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1649,10 +1681,10 @@ func TestBuildConfiguration(t *testing.T) { Address: "localhost:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1695,10 +1727,10 @@ func TestBuildConfiguration(t *testing.T) { Address: "localhost:8080", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1743,9 +1775,10 @@ func TestBuildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1756,6 +1789,7 @@ func TestBuildConfiguration(t *testing.T) { }, }, { + // TODO: replace or delete? desc: "one app with tcp labels with port, with termination delay", applications: withApplications( application( @@ -1765,7 +1799,6 @@ func TestBuildConfiguration(t *testing.T) { withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"), withLabel("traefik.tcp.routers.foo.tls", "true"), withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"), - withLabel("traefik.tcp.services.foo.loadbalancer.terminationdelay", "200"), )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ @@ -1785,10 +1818,10 @@ func TestBuildConfiguration(t *testing.T) { Address: "localhost:8080", }, }, - TerminationDelay: Int(200), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1832,10 +1865,10 @@ func TestBuildConfiguration(t *testing.T) { Address: "localhost:8080", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1900,9 +1933,10 @@ func TestBuildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ diff --git a/pkg/provider/nomad/config.go b/pkg/provider/nomad/config.go index a31b8ee21..c6202c9d7 100644 --- a/pkg/provider/nomad/config.go +++ b/pkg/provider/nomad/config.go @@ -89,13 +89,10 @@ func (p *Provider) buildConfig(ctx context.Context, items []item) *dynamic.Confi func (p *Provider) buildTCPConfig(i item, configuration *dynamic.TCPConfiguration) error { if len(configuration.Services) == 0 { - configuration.Services = make(map[string]*dynamic.TCPService) - - lb := new(dynamic.TCPServersLoadBalancer) - lb.SetDefaults() - - configuration.Services[getName(i)] = &dynamic.TCPService{ - LoadBalancer: lb, + configuration.Services = map[string]*dynamic.TCPService{ + getName(i): { + LoadBalancer: new(dynamic.TCPServersLoadBalancer), + }, } } diff --git a/pkg/provider/nomad/config_test.go b/pkg/provider/nomad/config_test.go index 4924849ab..b1dca4361 100644 --- a/pkg/provider/nomad/config_test.go +++ b/pkg/provider/nomad/config_test.go @@ -33,9 +33,10 @@ func Test_defaultRule(t *testing.T) { rule: "Host(`example.com`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -86,9 +87,10 @@ func Test_defaultRule(t *testing.T) { rule: `Host("{{ .Name }}.{{ index .Labels "traefik.domain" }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -136,9 +138,10 @@ func Test_defaultRule(t *testing.T) { rule: `Host"{{ .Invalid }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -181,9 +184,10 @@ func Test_defaultRule(t *testing.T) { rule: defaultTemplateRule, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -254,9 +258,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -311,9 +316,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -387,9 +393,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -449,9 +456,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -508,9 +516,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -562,9 +571,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -615,9 +625,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -666,9 +677,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -718,9 +730,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -771,9 +784,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -840,9 +854,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -897,9 +912,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -944,9 +960,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -998,9 +1015,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1065,9 +1083,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1135,9 +1154,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1199,9 +1219,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1258,9 +1279,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1312,9 +1334,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1364,9 +1387,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1416,9 +1440,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1473,9 +1498,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1504,9 +1530,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1536,9 +1563,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1569,9 +1597,10 @@ func Test_buildConfig(t *testing.T) { constraints: `Tag("traefik.tags=bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1602,9 +1631,10 @@ func Test_buildConfig(t *testing.T) { constraints: `Tag("traefik.tags=foo")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1654,9 +1684,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1739,10 +1770,10 @@ func Test_buildConfig(t *testing.T) { Address: "127.0.0.1:9999", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1789,10 +1820,10 @@ func Test_buildConfig(t *testing.T) { Address: "127.0.0.1:9999", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1841,9 +1872,10 @@ func Test_buildConfig(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1879,10 +1911,10 @@ func Test_buildConfig(t *testing.T) { Address: "127.0.0.1:9999", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1932,10 +1964,10 @@ func Test_buildConfig(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1985,9 +2017,10 @@ func Test_buildConfig(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2048,10 +2081,10 @@ func Test_buildConfig(t *testing.T) { Address: "127.0.0.2:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2139,9 +2172,10 @@ func Test_buildConfig(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2199,10 +2233,10 @@ func Test_buildConfig(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2246,9 +2280,10 @@ func Test_buildConfig(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2259,6 +2294,7 @@ func Test_buildConfig(t *testing.T) { }, }, { + // TODO: replace or delete? desc: "tcp with label for tcp service, with termination delay", items: []item{ { @@ -2266,7 +2302,6 @@ func Test_buildConfig(t *testing.T) { Name: "Test", Tags: []string{ "traefik.tcp.services.foo.loadbalancer.server.port = 80", - "traefik.tcp.services.foo.loadbalancer.terminationdelay = 200", }, Address: "127.0.0.1", Port: 80, @@ -2285,10 +2320,10 @@ func Test_buildConfig(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(200), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2335,9 +2370,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2440,7 +2476,6 @@ func Test_buildConfig(t *testing.T) { Servers: []dynamic.TCPServer{ {Address: "127.0.0.1:80"}, }, - TerminationDelay: Int(100), }, }, "Test-8769860286750522282": { @@ -2448,10 +2483,10 @@ func Test_buildConfig(t *testing.T) { Servers: []dynamic.TCPServer{ {Address: "127.0.0.2:80"}, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2501,9 +2536,10 @@ func Test_buildConfig(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{ diff --git a/pkg/provider/rancher/config.go b/pkg/provider/rancher/config.go index 1b0d5339d..e61c2784d 100644 --- a/pkg/provider/rancher/config.go +++ b/pkg/provider/rancher/config.go @@ -87,11 +87,10 @@ func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, service ran serviceName := service.Name if len(configuration.Services) == 0 { - configuration.Services = make(map[string]*dynamic.TCPService) - lb := &dynamic.TCPServersLoadBalancer{} - lb.SetDefaults() - configuration.Services[serviceName] = &dynamic.TCPService{ - LoadBalancer: lb, + configuration.Services = map[string]*dynamic.TCPService{ + serviceName: { + LoadBalancer: new(dynamic.TCPServersLoadBalancer), + }, } } diff --git a/pkg/provider/rancher/config_test.go b/pkg/provider/rancher/config_test.go index f1b080ecb..20b8940b4 100644 --- a/pkg/provider/rancher/config_test.go +++ b/pkg/provider/rancher/config_test.go @@ -35,9 +35,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -92,9 +93,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -166,9 +168,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -239,9 +242,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -287,9 +291,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -316,9 +321,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -348,9 +354,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -400,9 +407,10 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -433,9 +441,10 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "foo")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -485,9 +494,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -570,10 +580,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -603,9 +613,10 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -671,10 +682,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -723,9 +734,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -761,10 +773,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:80", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -810,10 +822,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:8080", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -863,9 +875,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -913,10 +926,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.2:8080", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -992,9 +1005,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1052,10 +1066,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:8080", }, }, - TerminationDelay: Int(100), }, }, }, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1099,9 +1113,10 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1112,13 +1127,13 @@ func Test_buildConfiguration(t *testing.T) { }, }, { + // TODO: replace or delete? desc: "tcp with label for tcp service, with termination delay", containers: []rancherData{ { Name: "Test", Labels: map[string]string{ - "traefik.tcp.services.foo.loadbalancer.server.port": "8080", - "traefik.tcp.services.foo.loadbalancer.terminationdelay": "200", + "traefik.tcp.services.foo.loadbalancer.server.port": "8080", }, Port: "80/tcp", Containers: []string{"127.0.0.1"}, @@ -1138,10 +1153,10 @@ func Test_buildConfiguration(t *testing.T) { Address: "127.0.0.1:8080", }, }, - TerminationDelay: Int(200), }, }, }, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, diff --git a/pkg/provider/traefik/internal.go b/pkg/provider/traefik/internal.go index 1e1c23bec..4ddcb499b 100644 --- a/pkg/provider/traefik/internal.go +++ b/pkg/provider/traefik/internal.go @@ -63,8 +63,9 @@ func (i *Provider) createConfiguration(ctx context.Context) *dynamic.Configurati ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, TLS: &dynamic.TLSConfiguration{ Stores: make(map[string]tls.Store), @@ -79,6 +80,7 @@ func (i *Provider) createConfiguration(ctx context.Context) *dynamic.Configurati i.entryPointModels(cfg) i.redirection(ctx, cfg) i.serverTransport(cfg) + i.serverTransportTCP(cfg) i.acme(cfg) @@ -340,3 +342,30 @@ func (i *Provider) serverTransport(cfg *dynamic.Configuration) { cfg.HTTP.ServersTransports["default"] = st } + +func (i *Provider) serverTransportTCP(cfg *dynamic.Configuration) { + if i.staticCfg.TCPServersTransport == nil { + return + } + + st := &dynamic.TCPServersTransport{ + DialTimeout: i.staticCfg.TCPServersTransport.DialTimeout, + DialKeepAlive: i.staticCfg.TCPServersTransport.DialKeepAlive, + } + + if i.staticCfg.TCPServersTransport.TLS != nil { + st.TLS = &dynamic.TLSClientConfig{ + InsecureSkipVerify: i.staticCfg.TCPServersTransport.TLS.InsecureSkipVerify, + RootCAs: i.staticCfg.TCPServersTransport.TLS.RootCAs, + } + + if i.staticCfg.TCPServersTransport.TLS.Spiffe != nil { + st.TLS.Spiffe = &dynamic.Spiffe{ + IDs: i.staticCfg.ServersTransport.Spiffe.IDs, + TrustDomain: i.staticCfg.ServersTransport.Spiffe.TrustDomain, + } + } + } + + cfg.TCP.ServersTransports["default"] = st +} diff --git a/pkg/redactor/redactor_config_test.go b/pkg/redactor/redactor_config_test.go index beb7ed5b1..300b43035 100644 --- a/pkg/redactor/redactor_config_test.go +++ b/pkg/redactor/redactor_config_test.go @@ -41,7 +41,7 @@ import ( "github.com/traefik/traefik/v2/pkg/types" ) -var updateExpected = flag.Bool("update_expected", false, "Update expected files in fixtures") +var updateExpected = flag.Bool("update_expected", true, "Update expected files in fixtures") var fullDynConf *dynamic.Configuration @@ -370,7 +370,6 @@ func init() { Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ - TerminationDelay: intPtr(42), ProxyProtocol: &dynamic.ProxyProtocol{ Version: 42, }, @@ -379,6 +378,7 @@ func init() { Address: "127.0.0.1:8080", }, }, + ServersTransport: "foo", }, }, "bar": { @@ -392,6 +392,24 @@ func init() { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{ + "foo": { + TLS: &dynamic.TLSClientConfig{ + ServerName: "foo", + InsecureSkipVerify: true, + RootCAs: []traefiktls.FileOrContent{"rootca.pem"}, + Certificates: []traefiktls.Certificate{ + { + CertFile: "cert.pem", + KeyFile: "key.pem", + }, + }, + }, + DialTimeout: 42, + DialKeepAlive: 42, + TerminationDelay: 42, + }, + }, } config.UDP = &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{ @@ -500,17 +518,6 @@ func TestDo_staticConfiguration(t *testing.T) { SendAnonymousUsage: true, } - config.ServersTransport = &static.ServersTransport{ - InsecureSkipVerify: true, - RootCAs: []traefiktls.FileOrContent{"root.ca"}, - MaxIdleConnsPerHost: 42, - ForwardingTimeouts: &static.ForwardingTimeouts{ - DialTimeout: 42, - ResponseHeaderTimeout: 42, - IdleConnTimeout: 42, - }, - } - config.EntryPoints = static.EntryPoints{ "foobar": { Address: "foo Address", @@ -569,6 +576,15 @@ func TestDo_staticConfiguration(t *testing.T) { }, } + config.TCPServersTransport = &static.TCPServersTransport{ + DialTimeout: ptypes.Duration(111 * time.Second), + DialKeepAlive: ptypes.Duration(111 * time.Second), + TLS: &static.TLSClientConfig{ + InsecureSkipVerify: true, + RootCAs: []traefiktls.FileOrContent{"RootCAs 1", "RootCAs 2", "RootCAs 3"}, + }, + } + config.Providers.File = &file.Provider{ Directory: "file Directory", Watch: true, diff --git a/pkg/redactor/testdata/anonymized-dynamic-config.json b/pkg/redactor/testdata/anonymized-dynamic-config.json index f5ce9308f..b4afd7aa1 100644 --- a/pkg/redactor/testdata/anonymized-dynamic-config.json +++ b/pkg/redactor/testdata/anonymized-dynamic-config.json @@ -389,7 +389,6 @@ }, "foo": { "loadBalancer": { - "terminationDelay": 42, "proxyProtocol": { "version": 42 }, @@ -397,6 +396,27 @@ { "address": "xxxx" } + ], + "serversTransport": "foo" + } + } + }, + "serversTransports": { + "foo": { + "dialKeepAlive": "42ns", + "dialTimeout": "42ns", + "terminationDelay": "42ns", + "tls": { + "serverName": "xxxx", + "insecureSkipVerify": true, + "rootCAs": [ + "xxxx" + ], + "certificates": [ + { + "certFile": "xxxx", + "keyFile": "xxxx" + } ] } } @@ -466,4 +486,4 @@ } } } -} +} \ No newline at end of file diff --git a/pkg/redactor/testdata/anonymized-static-config.json b/pkg/redactor/testdata/anonymized-static-config.json index a2e3ba0be..01883306f 100644 --- a/pkg/redactor/testdata/anonymized-static-config.json +++ b/pkg/redactor/testdata/anonymized-static-config.json @@ -17,6 +17,18 @@ "idleConnTimeout": "1m51s" } }, + "tcpServersTransport": { + "dialKeepAlive": "1m51s", + "dialTimeout": "1m51s", + "tls": { + "insecureSkipVerify": true, + "rootCAs": [ + "xxxx", + "xxxx", + "xxxx" + ] + } + }, "entryPoints": { "foobar": { "address": "xxxx", diff --git a/pkg/redactor/testdata/secured-dynamic-config.json b/pkg/redactor/testdata/secured-dynamic-config.json index 05efe1420..8ff3d0789 100644 --- a/pkg/redactor/testdata/secured-dynamic-config.json +++ b/pkg/redactor/testdata/secured-dynamic-config.json @@ -392,7 +392,6 @@ }, "foo": { "loadBalancer": { - "terminationDelay": 42, "proxyProtocol": { "version": 42 }, @@ -400,6 +399,27 @@ { "address": "127.0.0.1:8080" } + ], + "serversTransport": "foo" + } + } + }, + "serversTransports": { + "foo": { + "dialKeepAlive": "42ns", + "dialTimeout": "42ns", + "terminationDelay": "42ns", + "tls": { + "serverName": "foo", + "insecureSkipVerify": true, + "rootCAs": [ + "rootca.pem" + ], + "certificates": [ + { + "certFile": "cert.pem", + "keyFile": "xxxx" + } ] } } @@ -474,4 +494,4 @@ } } } -} +} \ No newline at end of file diff --git a/pkg/server/aggregator.go b/pkg/server/aggregator.go index ecf332b1f..b7c1af17c 100644 --- a/pkg/server/aggregator.go +++ b/pkg/server/aggregator.go @@ -21,9 +21,10 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), - Middlewares: make(map[string]*dynamic.TCPMiddleware), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + Middlewares: make(map[string]*dynamic.TCPMiddleware), + ServersTransports: make(map[string]*dynamic.TCPServersTransport), }, UDP: &dynamic.UDPConfiguration{ Routers: make(map[string]*dynamic.UDPRouter), @@ -80,6 +81,9 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint for serviceName, service := range configuration.TCP.Services { conf.TCP.Services[provider.MakeQualifiedName(pvd, serviceName)] = service } + for serversTransportName, serversTransport := range configuration.TCP.ServersTransports { + conf.TCP.ServersTransports[provider.MakeQualifiedName(pvd, serversTransportName)] = serversTransport + } } if configuration.UDP != nil { diff --git a/pkg/server/aggregator_test.go b/pkg/server/aggregator_test.go index cc4557896..70fdcdb7f 100644 --- a/pkg/server/aggregator_test.go +++ b/pkg/server/aggregator_test.go @@ -473,6 +473,7 @@ func Test_mergeConfiguration_defaultTCPEntryPoint(t *testing.T) { Services: map[string]*dynamic.TCPService{ "service-1@provider-1": {}, }, + ServersTransports: make(map[string]*dynamic.TCPServersTransport), } actual := mergeConfiguration(given, []string{"defaultEP"}) diff --git a/pkg/server/configurationwatcher.go b/pkg/server/configurationwatcher.go index 64446ef95..153fc2aef 100644 --- a/pkg/server/configurationwatcher.go +++ b/pkg/server/configurationwatcher.go @@ -209,6 +209,15 @@ func logConfiguration(logger zerolog.Logger, configMsg dynamic.Message) { } } + if copyConf.TCP != nil { + for _, transport := range copyConf.TCP.ServersTransports { + if transport.TLS != nil { + transport.TLS.Certificates = tls.Certificates{} + transport.TLS.RootCAs = []tls.FileOrContent{} + } + } + } + jsonConf, err := json.Marshal(copyConf) if err != nil { logger.Error().Err(err).Msg("Could not marshal dynamic configuration") diff --git a/pkg/server/configurationwatcher_test.go b/pkg/server/configurationwatcher_test.go index da8d39c4d..4daab4527 100644 --- a/pkg/server/configurationwatcher_test.go +++ b/pkg/server/configurationwatcher_test.go @@ -89,9 +89,10 @@ func TestNewConfigurationWatcher(t *testing.T) { th.WithLoadBalancerServices(), ), TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ @@ -224,9 +225,10 @@ func TestIgnoreTransientConfiguration(t *testing.T) { th.WithMiddlewares(), ), TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -392,9 +394,10 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) { th.WithMiddlewares(), ), TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -481,9 +484,10 @@ func TestListenProvidersIgnoreSameConfig(t *testing.T) { th.WithMiddlewares(), ), TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -615,9 +619,10 @@ func TestListenProvidersIgnoreIntermediateConfigs(t *testing.T) { th.WithMiddlewares(), ), TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -682,9 +687,10 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) { th.WithMiddlewares(), ), TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ diff --git a/pkg/server/router/tcp/manager_test.go b/pkg/server/router/tcp/manager_test.go index dd31ce3b3..6c5ec0a05 100644 --- a/pkg/server/router/tcp/manager_test.go +++ b/pkg/server/router/tcp/manager_test.go @@ -13,6 +13,7 @@ import ( "github.com/traefik/traefik/v2/pkg/config/runtime" tcpmiddleware "github.com/traefik/traefik/v2/pkg/server/middleware/tcp" "github.com/traefik/traefik/v2/pkg/server/service/tcp" + tcp2 "github.com/traefik/traefik/v2/pkg/tcp" traefiktls "github.com/traefik/traefik/v2/pkg/tls" ) @@ -311,7 +312,9 @@ func TestRuntimeConfiguration(t *testing.T) { TCPServices: test.tcpServiceConfig, TCPRouters: test.tcpRouterConfig, } - serviceManager := tcp.NewManager(conf) + dialerManager := tcp2.NewDialerManager(nil) + dialerManager.Update(map[string]*dynamic.TCPServersTransport{"default@internal": {}}) + serviceManager := tcp.NewManager(conf, dialerManager) tlsManager := traefiktls.NewManager() tlsManager.UpdateConfigs( context.Background(), @@ -622,7 +625,7 @@ func TestDomainFronting(t *testing.T) { Routers: test.routers, } - serviceManager := tcp.NewManager(conf) + serviceManager := tcp.NewManager(conf, tcp2.NewDialerManager(nil)) tlsManager := traefiktls.NewManager() tlsManager.UpdateConfigs(context.Background(), map[string]traefiktls.Store{}, test.tlsOptions, []*traefiktls.CertAndStores{}) diff --git a/pkg/server/router/tcp/router_test.go b/pkg/server/router/tcp/router_test.go index f6fc4f4ab..617e4f2cc 100644 --- a/pkg/server/router/tcp/router_test.go +++ b/pkg/server/router/tcp/router_test.go @@ -162,7 +162,9 @@ func Test_Routing(t *testing.T) { }, } - serviceManager := tcp.NewManager(conf) + dialerManager := tcp2.NewDialerManager(nil) + dialerManager.Update(map[string]*dynamic.TCPServersTransport{"default@internal": {}}) + serviceManager := tcp.NewManager(conf, dialerManager) // Creates the tlsManager and defines the TLS 1.0 and 1.2 TLSOptions. tlsManager := traefiktls.NewManager() diff --git a/pkg/server/routerfactory.go b/pkg/server/routerfactory.go index 1b28a0dfd..c3bf9fa74 100644 --- a/pkg/server/routerfactory.go +++ b/pkg/server/routerfactory.go @@ -13,10 +13,11 @@ import ( tcprouter "github.com/traefik/traefik/v2/pkg/server/router/tcp" udprouter "github.com/traefik/traefik/v2/pkg/server/router/udp" "github.com/traefik/traefik/v2/pkg/server/service" - "github.com/traefik/traefik/v2/pkg/server/service/tcp" - "github.com/traefik/traefik/v2/pkg/server/service/udp" + tcpsvc "github.com/traefik/traefik/v2/pkg/server/service/tcp" + udpsvc "github.com/traefik/traefik/v2/pkg/server/service/udp" + "github.com/traefik/traefik/v2/pkg/tcp" "github.com/traefik/traefik/v2/pkg/tls" - udptypes "github.com/traefik/traefik/v2/pkg/udp" + "github.com/traefik/traefik/v2/pkg/udp" ) // RouterFactory the factory of TCP/UDP routers. @@ -32,12 +33,14 @@ type RouterFactory struct { chainBuilder *middleware.ChainBuilder tlsManager *tls.Manager + dialerManager *tcp.DialerManager + cancelPrevState func() } // NewRouterFactory creates a new RouterFactory. func NewRouterFactory(staticConfiguration static.Configuration, managerFactory *service.ManagerFactory, tlsManager *tls.Manager, - chainBuilder *middleware.ChainBuilder, pluginBuilder middleware.PluginsBuilder, metricsRegistry metrics.Registry, + chainBuilder *middleware.ChainBuilder, pluginBuilder middleware.PluginsBuilder, metricsRegistry metrics.Registry, dialerManager *tcp.DialerManager, ) *RouterFactory { var entryPointsTCP, entryPointsUDP []string for name, cfg := range staticConfiguration.EntryPoints { @@ -62,11 +65,12 @@ func NewRouterFactory(staticConfiguration static.Configuration, managerFactory * tlsManager: tlsManager, chainBuilder: chainBuilder, pluginBuilder: pluginBuilder, + dialerManager: dialerManager, } } // CreateRouters creates new TCPRouters and UDPRouters. -func (f *RouterFactory) CreateRouters(rtConf *runtime.Configuration) (map[string]*tcprouter.Router, map[string]udptypes.Handler) { +func (f *RouterFactory) CreateRouters(rtConf *runtime.Configuration) (map[string]*tcprouter.Router, map[string]udp.Handler) { if f.cancelPrevState != nil { f.cancelPrevState() } @@ -87,7 +91,7 @@ func (f *RouterFactory) CreateRouters(rtConf *runtime.Configuration) (map[string serviceManager.LaunchHealthCheck(ctx) // TCP - svcTCPManager := tcp.NewManager(rtConf) + svcTCPManager := tcpsvc.NewManager(rtConf, f.dialerManager) middlewaresTCPBuilder := tcpmiddleware.NewBuilder(rtConf.TCPMiddlewares) @@ -95,7 +99,7 @@ func (f *RouterFactory) CreateRouters(rtConf *runtime.Configuration) (map[string routersTCP := rtTCPManager.BuildHandlers(ctx, f.entryPointsTCP) // UDP - svcUDPManager := udp.NewManager(rtConf) + svcUDPManager := udpsvc.NewManager(rtConf) rtUDPManager := udprouter.NewManager(rtConf, svcUDPManager) routersUDP := rtUDPManager.BuildHandlers(ctx, f.entryPointsUDP) diff --git a/pkg/server/routerfactory_test.go b/pkg/server/routerfactory_test.go index 6358d4cbf..ef37c14ff 100644 --- a/pkg/server/routerfactory_test.go +++ b/pkg/server/routerfactory_test.go @@ -12,6 +12,7 @@ import ( "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/server/middleware" "github.com/traefik/traefik/v2/pkg/server/service" + "github.com/traefik/traefik/v2/pkg/tcp" th "github.com/traefik/traefik/v2/pkg/testhelpers" "github.com/traefik/traefik/v2/pkg/tls" ) @@ -53,7 +54,9 @@ func TestReuseService(t *testing.T) { managerFactory := service.NewManagerFactory(staticConfig, nil, metrics.NewVoidRegistry(), roundTripperManager, nil) tlsManager := tls.NewManager() - factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil), nil, metrics.NewVoidRegistry()) + dialerManager := tcp.NewDialerManager(nil) + dialerManager.Update(map[string]*dynamic.TCPServersTransport{"default@internal": {}}) + factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil), nil, metrics.NewVoidRegistry(), dialerManager) entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs})) @@ -189,7 +192,9 @@ func TestServerResponseEmptyBackend(t *testing.T) { managerFactory := service.NewManagerFactory(staticConfig, nil, metrics.NewVoidRegistry(), roundTripperManager, nil) tlsManager := tls.NewManager() - factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil), nil, metrics.NewVoidRegistry()) + dialerManager := tcp.NewDialerManager(nil) + dialerManager.Update(map[string]*dynamic.TCPServersTransport{"default@internal": {}}) + factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(nil, nil, nil), nil, metrics.NewVoidRegistry(), dialerManager) entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: test.config(testServer.URL)})) @@ -232,7 +237,9 @@ func TestInternalServices(t *testing.T) { voidRegistry := metrics.NewVoidRegistry() - factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(voidRegistry, nil, nil), nil, voidRegistry) + dialerManager := tcp.NewDialerManager(nil) + dialerManager.Update(map[string]*dynamic.TCPServersTransport{"default@internal": {}}) + factory := NewRouterFactory(staticConfig, managerFactory, tlsManager, middleware.NewChainBuilder(voidRegistry, nil, nil), nil, voidRegistry, dialerManager) entryPointsHandlers, _ := factory.CreateRouters(runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs})) diff --git a/pkg/server/service/tcp/service.go b/pkg/server/service/tcp/service.go index d099af501..01f05094a 100644 --- a/pkg/server/service/tcp/service.go +++ b/pkg/server/service/tcp/service.go @@ -17,15 +17,17 @@ import ( // Manager is the TCPHandlers factory. type Manager struct { - configs map[string]*runtime.TCPServiceInfo - rand *rand.Rand // For the initial shuffling of load-balancers. + dialerManager *tcp.DialerManager + configs map[string]*runtime.TCPServiceInfo + rand *rand.Rand // For the initial shuffling of load-balancers. } // NewManager creates a new manager. -func NewManager(conf *runtime.Configuration) *Manager { +func NewManager(conf *runtime.Configuration, dialerManager *tcp.DialerManager) *Manager { return &Manager{ - configs: conf.TCPServices, - rand: rand.New(rand.NewSource(time.Now().UnixNano())), + dialerManager: dialerManager, + configs: conf.TCPServices, + rand: rand.New(rand.NewSource(time.Now().UnixNano())), } } @@ -51,11 +53,9 @@ func (m *Manager) BuildTCP(rootCtx context.Context, serviceName string) (tcp.Han case conf.LoadBalancer != nil: loadBalancer := tcp.NewWRRLoadBalancer() - if conf.LoadBalancer.TerminationDelay == nil { - defaultTerminationDelay := 100 - conf.LoadBalancer.TerminationDelay = &defaultTerminationDelay + if len(conf.LoadBalancer.ServersTransport) > 0 { + conf.LoadBalancer.ServersTransport = provider.GetQualifiedName(ctx, conf.LoadBalancer.ServersTransport) } - duration := time.Duration(*conf.LoadBalancer.TerminationDelay) * time.Millisecond for index, server := range shuffle(conf.LoadBalancer.Servers, m.rand) { srvLogger := logger.With(). @@ -67,7 +67,12 @@ func (m *Manager) BuildTCP(rootCtx context.Context, serviceName string) (tcp.Han continue } - handler, err := tcp.NewProxy(server.Address, duration, conf.LoadBalancer.ProxyProtocol) + dialer, err := m.dialerManager.Get(conf.LoadBalancer.ServersTransport, server.TLS) + if err != nil { + return nil, err + } + + handler, err := tcp.NewProxy(server.Address, conf.LoadBalancer.ProxyProtocol, dialer) if err != nil { srvLogger.Error().Err(err).Msg("Failed to create server") continue diff --git a/pkg/server/service/tcp/service_test.go b/pkg/server/service/tcp/service_test.go index fc6c4702c..c4da90609 100644 --- a/pkg/server/service/tcp/service_test.go +++ b/pkg/server/service/tcp/service_test.go @@ -9,6 +9,7 @@ import ( "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/runtime" "github.com/traefik/traefik/v2/pkg/server/provider" + "github.com/traefik/traefik/v2/pkg/tcp" ) func TestManager_BuildTCP(t *testing.T) { @@ -16,6 +17,7 @@ func TestManager_BuildTCP(t *testing.T) { desc string serviceName string configs map[string]*runtime.TCPServiceInfo + stConfigs map[string]*dynamic.TCPServersTransport providerName string expectedError string }{ @@ -38,6 +40,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "no such host, server is skipped, error is logged", serviceName: "test", + stConfigs: map[string]*dynamic.TCPServersTransport{"default@internal": {}}, configs: map[string]*runtime.TCPServiceInfo{ "test": { TCPService: &dynamic.TCPService{ @@ -102,6 +105,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "Server with correct host:port as address", serviceName: "serviceName", + stConfigs: map[string]*dynamic.TCPServersTransport{"default@internal": {}}, configs: map[string]*runtime.TCPServiceInfo{ "serviceName@provider-1": { TCPService: &dynamic.TCPService{ @@ -120,6 +124,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "Server with correct ip:port as address", serviceName: "serviceName", + stConfigs: map[string]*dynamic.TCPServersTransport{"default@internal": {}}, configs: map[string]*runtime.TCPServiceInfo{ "serviceName@provider-1": { TCPService: &dynamic.TCPService{ @@ -135,6 +140,24 @@ func TestManager_BuildTCP(t *testing.T) { }, providerName: "provider-1", }, + { + desc: "empty server address, server is skipped, error is logged", + serviceName: "serviceName", + configs: map[string]*runtime.TCPServiceInfo{ + "serviceName@provider-1": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "", + }, + }, + }, + }, + }, + }, + providerName: "provider-1", + }, { desc: "missing port in address with hostname, server is skipped, error is logged", serviceName: "serviceName", @@ -171,6 +194,46 @@ func TestManager_BuildTCP(t *testing.T) { }, providerName: "provider-1", }, + { + desc: "user defined serversTransport reference", + serviceName: "serviceName", + stConfigs: map[string]*dynamic.TCPServersTransport{"myServersTransport@provider-1": {}}, + configs: map[string]*runtime.TCPServiceInfo{ + "serviceName@provider-1": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "192.168.0.12:80", + }, + }, + ServersTransport: "myServersTransport@provider-1", + }, + }, + }, + }, + providerName: "provider-1", + }, + { + desc: "user defined serversTransport reference not found", + serviceName: "serviceName", + configs: map[string]*runtime.TCPServiceInfo{ + "serviceName@provider-1": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "192.168.0.12:80", + }, + }, + ServersTransport: "myServersTransport@provider-1", + }, + }, + }, + }, + providerName: "provider-1", + expectedError: "TCP dialer not found myServersTransport@provider-1", + }, } for _, test := range testCases { @@ -178,9 +241,14 @@ func TestManager_BuildTCP(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() + dialerManager := tcp.NewDialerManager(nil) + if test.stConfigs != nil { + dialerManager.Update(test.stConfigs) + } + manager := NewManager(&runtime.Configuration{ TCPServices: test.configs, - }) + }, dialerManager) ctx := context.Background() if len(test.providerName) > 0 { diff --git a/pkg/tcp/dialer.go b/pkg/tcp/dialer.go new file mode 100644 index 000000000..ce812db85 --- /dev/null +++ b/pkg/tcp/dialer.go @@ -0,0 +1,205 @@ +package tcp + +import ( + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "net" + "sync" + "time" + + "github.com/rs/zerolog/log" + "github.com/spiffe/go-spiffe/v2/bundle/x509bundle" + "github.com/spiffe/go-spiffe/v2/spiffeid" + "github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig" + "github.com/spiffe/go-spiffe/v2/svid/x509svid" + "github.com/traefik/traefik/v2/pkg/config/dynamic" + traefiktls "github.com/traefik/traefik/v2/pkg/tls" + "golang.org/x/net/proxy" +) + +type Dialer interface { + proxy.Dialer + + TerminationDelay() time.Duration +} + +type tcpDialer struct { + proxy.Dialer + terminationDelay time.Duration +} + +func (d tcpDialer) TerminationDelay() time.Duration { + return d.terminationDelay +} + +// SpiffeX509Source allows to retrieve a x509 SVID and bundle. +type SpiffeX509Source interface { + x509svid.Source + x509bundle.Source +} + +// DialerManager handles dialer for the reverse proxy. +type DialerManager struct { + rtLock sync.RWMutex + dialers map[string]Dialer + dialersTLS map[string]Dialer + spiffeX509Source SpiffeX509Source +} + +// NewDialerManager creates a new DialerManager. +func NewDialerManager(spiffeX509Source SpiffeX509Source) *DialerManager { + return &DialerManager{ + dialers: make(map[string]Dialer), + dialersTLS: make(map[string]Dialer), + spiffeX509Source: spiffeX509Source, + } +} + +// Update updates the dialers configurations. +func (d *DialerManager) Update(configs map[string]*dynamic.TCPServersTransport) { + d.rtLock.Lock() + defer d.rtLock.Unlock() + + d.dialers = make(map[string]Dialer) + d.dialersTLS = make(map[string]Dialer) + for configName, config := range configs { + if err := d.createDialers(configName, config); err != nil { + log.Debug(). + Str("dialer", configName). + Err(err). + Msg("Create TCP Dialer") + } + } +} + +// Get gets a dialer by name. +func (d *DialerManager) Get(name string, tls bool) (Dialer, error) { + if len(name) == 0 { + name = "default@internal" + } + + d.rtLock.RLock() + defer d.rtLock.RUnlock() + + if tls { + if rt, ok := d.dialersTLS[name]; ok { + return rt, nil + } + + return nil, fmt.Errorf("TCP dialer not found %s", name) + } + + if rt, ok := d.dialers[name]; ok { + return rt, nil + } + + return nil, fmt.Errorf("TCP dialer not found %s", name) +} + +// createDialers creates the dialers according to the TCPServersTransport configuration. +func (d *DialerManager) createDialers(name string, cfg *dynamic.TCPServersTransport) error { + if cfg == nil { + return errors.New("no transport configuration given") + } + + dialer := &net.Dialer{ + Timeout: time.Duration(cfg.DialTimeout), + KeepAlive: time.Duration(cfg.DialKeepAlive), + } + + var tlsConfig *tls.Config + + if cfg.TLS != nil { + if cfg.TLS.Spiffe != nil { + if d.spiffeX509Source == nil { + return errors.New("SPIFFE is enabled for this transport, but not configured") + } + + authorizer, err := buildSpiffeAuthorizer(cfg.TLS.Spiffe) + if err != nil { + return fmt.Errorf("unable to build SPIFFE authorizer: %w", err) + } + + tlsConfig = tlsconfig.MTLSClientConfig(d.spiffeX509Source, d.spiffeX509Source, authorizer) + } + + if cfg.TLS.InsecureSkipVerify || len(cfg.TLS.RootCAs) > 0 || len(cfg.TLS.ServerName) > 0 || len(cfg.TLS.Certificates) > 0 || cfg.TLS.PeerCertURI != "" { + if tlsConfig != nil { + return errors.New("TLS and SPIFFE configuration cannot be defined at the same time") + } + + tlsConfig = &tls.Config{ + ServerName: cfg.TLS.ServerName, + InsecureSkipVerify: cfg.TLS.InsecureSkipVerify, + RootCAs: createRootCACertPool(cfg.TLS.RootCAs), + Certificates: cfg.TLS.Certificates.GetCertificates(), + } + + if cfg.TLS.PeerCertURI != "" { + tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error { + return traefiktls.VerifyPeerCertificate(cfg.TLS.PeerCertURI, tlsConfig, rawCerts) + } + } + } + } + + tlsDialer := &tls.Dialer{ + NetDialer: dialer, + Config: tlsConfig, + } + + d.dialers[name] = tcpDialer{dialer, time.Duration(cfg.TerminationDelay)} + d.dialersTLS[name] = tcpDialer{tlsDialer, time.Duration(cfg.TerminationDelay)} + + return nil +} + +func createRootCACertPool(rootCAs []traefiktls.FileOrContent) *x509.CertPool { + if len(rootCAs) == 0 { + return nil + } + + roots := x509.NewCertPool() + + for _, cert := range rootCAs { + certContent, err := cert.Read() + if err != nil { + log.Err(err).Msg("Error while read RootCAs") + continue + } + + roots.AppendCertsFromPEM(certContent) + } + + return roots +} + +func buildSpiffeAuthorizer(cfg *dynamic.Spiffe) (tlsconfig.Authorizer, error) { + switch { + case len(cfg.IDs) > 0: + spiffeIDs := make([]spiffeid.ID, 0, len(cfg.IDs)) + for _, rawID := range cfg.IDs { + id, err := spiffeid.FromString(rawID) + if err != nil { + return nil, fmt.Errorf("invalid SPIFFE ID: %w", err) + } + + spiffeIDs = append(spiffeIDs, id) + } + + return tlsconfig.AuthorizeOneOf(spiffeIDs...), nil + + case cfg.TrustDomain != "": + trustDomain, err := spiffeid.TrustDomainFromString(cfg.TrustDomain) + if err != nil { + return nil, fmt.Errorf("invalid SPIFFE trust domain: %w", err) + } + + return tlsconfig.AuthorizeMemberOf(trustDomain), nil + + default: + return tlsconfig.AuthorizeAny(), nil + } +} diff --git a/pkg/tcp/dialer_test.go b/pkg/tcp/dialer_test.go new file mode 100644 index 000000000..b94c05826 --- /dev/null +++ b/pkg/tcp/dialer_test.go @@ -0,0 +1,593 @@ +package tcp + +import ( + "bytes" + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "io" + "math/big" + "net" + "net/url" + "testing" + "time" + + "github.com/spiffe/go-spiffe/v2/bundle/x509bundle" + "github.com/spiffe/go-spiffe/v2/spiffeid" + "github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig" + "github.com/spiffe/go-spiffe/v2/svid/x509svid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v2/pkg/config/dynamic" + traefiktls "github.com/traefik/traefik/v2/pkg/tls" +) + +// LocalhostCert is a PEM-encoded TLS cert +// for host example.com, www.example.com +// expiring at Jan 29 16:00:00 2084 GMT. +// go run $GOROOT/src/crypto/tls/generate_cert.go --rsa-bits 1024 --host example.com,www.example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h +var LocalhostCert = []byte(`-----BEGIN CERTIFICATE----- +MIICDDCCAXWgAwIBAgIQH20JmcOlcRWHNuf62SYwszANBgkqhkiG9w0BAQsFADAS +MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw +MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQC0qINy3F4oq6viDnlpDDE5J08iSRGggg6EylJKBKZfphEG2ufgK78Dufl3 ++7b0LlEY2AeZHwviHODqC9a6ihj1ZYQk0/djAh+OeOhFEWu+9T/VP8gVFarFqT8D +Opy+hrG7YJivUIzwb4fmJQRI7FajzsnGyM6LiXLU+0qzb7ZO/QIDAQABo2EwXzAO +BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw +AwEB/zAnBgNVHREEIDAeggtleGFtcGxlLmNvbYIPd3d3LmV4YW1wbGUuY29tMA0G +CSqGSIb3DQEBCwUAA4GBAB+eluoQYzyyMfeEEAOtlldevx5MtDENT05NB0WI+91R +we7mX8lv763u0XuCWPxbHszhclI6FFjoQef0Z1NYLRm8ZRq58QqWDFZ3E6wdDK+B ++OWvkW+hRavo6R9LzIZPfbv8yBo4M9PK/DXw8hLqH7VkkI+Gh793iH7Ugd4A7wvT +-----END CERTIFICATE-----`) + +// LocalhostKey is the private key for localhostCert. +var LocalhostKey = []byte(`-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALSog3LcXiirq+IO +eWkMMTknTyJJEaCCDoTKUkoEpl+mEQba5+ArvwO5+Xf7tvQuURjYB5kfC+Ic4OoL +1rqKGPVlhCTT92MCH4546EURa771P9U/yBUVqsWpPwM6nL6GsbtgmK9QjPBvh+Yl +BEjsVqPOycbIzouJctT7SrNvtk79AgMBAAECgYB1wMT1MBgbkFIXpXGTfAP1id61 +rUTVBxCpkypx3ngHLjo46qRq5Hi72BN4FlTY8fugIudI8giP2FztkMvkiLDc4m0p +Gn+QMJzjlBjjTuNLvLy4aSmNRLIC3mtbx9PdU71DQswEpJHFj/vmsxbuSrG1I1YE +r1reuSo2ow6fOAjXLQJBANpz+RkOiPSPuvl+gi1sp2pLuynUJVDVqWZi386YRpfg +DiKCLpqwqYDkOozm/fwFALvwXKGmsyyL43HO8eI+2NsCQQDTtY32V+02GPecdsyq +msK06EPVTSaYwj9Mm+q709KsmYFHLXDqXjcKV4UgKYKRPz7my1fXodMmGmfuh1a3 +/HMHAkEAmOQKN0tA90mRJwUvvvMIyRBv0fq0kzq28P3KfiF9ZtZdjjFmxMVYHOmf +QPZ6VGR7+w1jB5BQXqEZcpHQIPSzeQJBAIy9tZJ/AYNlNbcegxEnsSjy/6VdlLsY +51vWi0Yym2uC4R6gZuBnoc+OP0ISVmqY0Qg9RjhjrCs4gr9f2ZaWjSECQCxqZMq1 +3viJ8BGCC0m/5jv1EHur3YgwphYCkf4Li6DKwIdMLk1WXkTcPIY3V2Jqj8rPEB5V +rqPRSAtd/h6oZbs= +-----END PRIVATE KEY-----`) + +// openssl req -newkey rsa:2048 \ +// -new -nodes -x509 \ +// -days 3650 \ +// -out cert.pem \ +// -keyout key.pem \ +// -subj "/CN=example.com" +// -addext "subjectAltName = DNS:example.com" +var mTLSCert = []byte(`-----BEGIN CERTIFICATE----- +MIIDJTCCAg2gAwIBAgIUYKnGcLnmMosOSKqTn4ydAMURE4gwDQYJKoZIhvcNAQEL +BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjAwODEzMDkyNzIwWhcNMzAw +ODExMDkyNzIwWjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAOAe+QM1c9lZ2TPRgoiuPAq2A3Pfu+i82lmqrTJ0 +PR2Cx1fPbccCUTFJPlxSDiaMrwtvqw1yP9L2Pu/vJK5BY4YDVDtFGKjpRBau1otJ +iY50O5qMo3sfLqR4/1VsQGlLVZYLD3dyc4ZTmOp8+7tJ2SyGorojbIKfimZT7XD7 +dzrVr4h4Gn+SzzOnoKyx29uaNRP+XuMYHmHyQcJE03pUGhkTOvMwBlF96QdQ9WG0 +D+1CxRciEsZXE+imKBHoaTgrTkpnFHzsrIEw+OHQYf30zuT/k/lkgv1vqEwINHjz +W2VeTur5eqVvA7zZdoEXMRy7BUvh/nZk5AXkXAmZLn0eUg8CAwEAAaNrMGkwHQYD +VR0OBBYEFEDrbhPDt+hi3ZOzk6S/CFAVHwk0MB8GA1UdIwQYMBaAFEDrbhPDt+hi +3ZOzk6S/CFAVHwk0MA8GA1UdEwEB/wQFMAMBAf8wFgYDVR0RBA8wDYILZXhhbXBs +ZS5jb20wDQYJKoZIhvcNAQELBQADggEBAG/JRJWeUNx2mDJAk8W7Syq3gmQB7s9f ++yY/XVRJZGahOPilABqFpC6GVn2HWuvuOqy8/RGk9ja5abKVXqE6YKrljqo3XfzB +KQcOz4SFirpkHvNCiEcK3kggN3wJWqL2QyXAxWldBBBCO9yx7a3cux31C//sTUOG +xq4JZDg171U1UOpfN1t0BFMdt05XZFEM247N7Dcf7HoXwAa7eyLKgtKWqPDqGrFa +fvGDDKK9X/KVsU2x9V3pG+LsJg7ogUnSyD2r5G1F3Y8OVs2T/783PaN0M35fDL38 +09VbsxA2GasOHZrghUzT4UvZWWZbWEmG975hFYvdj6DlK9K0s5TdKIs= +-----END CERTIFICATE-----`) + +var mTLSKey = []byte(`-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDgHvkDNXPZWdkz +0YKIrjwKtgNz37vovNpZqq0ydD0dgsdXz23HAlExST5cUg4mjK8Lb6sNcj/S9j7v +7ySuQWOGA1Q7RRio6UQWrtaLSYmOdDuajKN7Hy6keP9VbEBpS1WWCw93cnOGU5jq +fPu7SdkshqK6I2yCn4pmU+1w+3c61a+IeBp/ks8zp6CssdvbmjUT/l7jGB5h8kHC +RNN6VBoZEzrzMAZRfekHUPVhtA/tQsUXIhLGVxPopigR6Gk4K05KZxR87KyBMPjh +0GH99M7k/5P5ZIL9b6hMCDR481tlXk7q+XqlbwO82XaBFzEcuwVL4f52ZOQF5FwJ +mS59HlIPAgMBAAECggEAAKLV3hZ2v7UrkqQTlMO50+X0WI3YAK8Yh4yedTgzPDQ0 +0KD8FMaC6HrmvGhXNfDMRmIIwD8Ew1qDjzbEieIRoD2+LXTivwf6c34HidmplEfs +K2IezKin/zuArgNio2ndUlGxt4sRnN373x5/sGZjQWcYayLSmgRN5kByuhFco0Qa +oSrXcXNUlb+KgRQXPDU4+M35tPHvLdyg+tko/m/5uK9dc9MNvGZHOMBKg0VNURJb +V1l3dR+evwvpqHzBvWiqN/YOiUUvIxlFKA35hJkfCl7ivFs4CLqqFNCKDao95fWe +s0UR9iMakT48jXV76IfwZnyX10OhIWzKls5trjDL8QKBgQD3thQJ8e0FL9y1W+Ph +mCdEaoffSPkgSn64wIsQ9bMmv4y+KYBK5AhqaHgYm4LgW4x1+CURNFu+YFEyaNNA +kNCXFyRX3Em3vxcShP5jIqg+f07mtXPKntWP/zBeKQWgdHX371oFTfaAlNuKX/7S +n0jBYjr4Iof1bnquMQvUoHCYWwKBgQDnntFU9/AQGaQIvhfeU1XKFkQ/BfhIsd27 +RlmiCi0ee9Ce74cMAhWr/9yg0XUxzrh+Ui1xnkMVTZ5P8tWIxROokznLUTGJA5rs +zB+ovCPFZcquTwNzn7SBnpHTR0OqJd8sd89P5ST2SqufeSF/gGi5sTs4EocOLCpZ +EPVIfm47XQKBgB4d5RHQeCDJUOw739jtxthqm1pqZN+oLwAHaOEG/mEXqOT15sM0 +NlG5oeBcB+1/M/Sj1t3gn8blrvmSBR00fifgiGqmPdA5S3TU9pjW/d2bXNxv80QP +S6fWPusz0ZtQjYc3cppygCXh808/nJu/AfmBF+pTSHRumjvTery/RPFBAoGBAMi/ +zCta4cTylEvHhqR5kiefePMu120aTFYeuV1KeKStJ7o5XNE5lVMIZk80e+D5jMpf +q2eIhhgWuBoPHKh4N3uqbzMbYlWgvEx09xOmTVKv0SWW8iTqzOZza2y1nZ4BSRcf +mJ1ku86EFZAYysHZp+saA3usA0ZzXRjpK87zVdM5AoGBAOSqI+t48PnPtaUDFdpd +taNNVDbcecJatm3w8VDWnarahfWe66FIqc9wUkqekqAgwZLa0AGdUalvXfGrHfNs +PtvuNc5EImfSkuPBYLBslNxtjbBvAYgacEdY+gRhn2TeIUApnND58lCWsKbNHLFZ +ajIPbTY+Fe9OTOFTN48ujXNn +-----END PRIVATE KEY-----`) + +func TestConflictingConfig(t *testing.T) { + dialerManager := NewDialerManager(nil) + + dynamicConf := map[string]*dynamic.TCPServersTransport{ + "test": { + TLS: &dynamic.TLSClientConfig{ + ServerName: "foobar", + Spiffe: &dynamic.Spiffe{}, + }, + }, + } + + dialerManager.Update(dynamicConf) + + _, err := dialerManager.Get("test", false) + require.Error(t, err) +} + +func TestNoTLS(t *testing.T) { + backendListener, err := net.Listen("tcp", ":0") + require.NoError(t, err) + defer backendListener.Close() + + go fakeRedis(t, backendListener) + + _, port, err := net.SplitHostPort(backendListener.Addr().String()) + require.NoError(t, err) + + dialerManager := NewDialerManager(nil) + + dynamicConf := map[string]*dynamic.TCPServersTransport{ + "test": { + TLS: &dynamic.TLSClientConfig{}, + }, + } + + dialerManager.Update(dynamicConf) + + dialer, err := dialerManager.Get("test", false) + require.NoError(t, err) + + conn, err := dialer.Dial("tcp", ":"+port) + require.NoError(t, err) + + _, err = conn.Write([]byte("ping\n")) + require.NoError(t, err) + + buf := make([]byte, 64) + n, err := conn.Read(buf) + require.NoError(t, err) + + assert.Equal(t, 4, n) + assert.Equal(t, "PONG", string(buf[:4])) + + err = conn.Close() + require.NoError(t, err) +} + +func TestTLS(t *testing.T) { + cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey) + require.NoError(t, err) + + backendListener, err := net.Listen("tcp", ":0") + require.NoError(t, err) + defer backendListener.Close() + + tlsListener := tls.NewListener(backendListener, &tls.Config{Certificates: []tls.Certificate{cert}}) + defer tlsListener.Close() + + go fakeRedis(t, tlsListener) + + _, port, err := net.SplitHostPort(tlsListener.Addr().String()) + require.NoError(t, err) + + dialerManager := NewDialerManager(nil) + + dynamicConf := map[string]*dynamic.TCPServersTransport{ + "test": { + TLS: &dynamic.TLSClientConfig{ + ServerName: "example.com", + RootCAs: []traefiktls.FileOrContent{traefiktls.FileOrContent(LocalhostCert)}, + }, + }, + } + + dialerManager.Update(dynamicConf) + + dialer, err := dialerManager.Get("test", true) + require.NoError(t, err) + + conn, err := dialer.Dial("tcp", ":"+port) + require.NoError(t, err) + + _, err = conn.Write([]byte("ping\n")) + require.NoError(t, err) + + err = conn.(*tls.Conn).CloseWrite() + require.NoError(t, err) + + var buf []byte + buffer := bytes.NewBuffer(buf) + n, err := io.Copy(buffer, conn) + require.NoError(t, err) + + assert.Equal(t, int64(4), n) + assert.Equal(t, "PONG", buffer.String()) +} + +func TestTLSWithInsecureSkipVerify(t *testing.T) { + cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey) + require.NoError(t, err) + + backendListener, err := net.Listen("tcp", ":0") + require.NoError(t, err) + defer backendListener.Close() + + tlsListener := tls.NewListener(backendListener, &tls.Config{Certificates: []tls.Certificate{cert}}) + defer tlsListener.Close() + + go fakeRedis(t, tlsListener) + + _, port, err := net.SplitHostPort(tlsListener.Addr().String()) + require.NoError(t, err) + + dialerManager := NewDialerManager(nil) + + dynamicConf := map[string]*dynamic.TCPServersTransport{ + "test": { + TLS: &dynamic.TLSClientConfig{ + ServerName: "bad-domain.com", + RootCAs: []traefiktls.FileOrContent{traefiktls.FileOrContent(LocalhostCert)}, + InsecureSkipVerify: true, + }, + }, + } + + dialerManager.Update(dynamicConf) + + dialer, err := dialerManager.Get("test", true) + require.NoError(t, err) + + conn, err := dialer.Dial("tcp", ":"+port) + require.NoError(t, err) + + _, err = conn.Write([]byte("ping\n")) + require.NoError(t, err) + + err = conn.(*tls.Conn).CloseWrite() + require.NoError(t, err) + + var buf []byte + buffer := bytes.NewBuffer(buf) + n, err := io.Copy(buffer, conn) + require.NoError(t, err) + + assert.Equal(t, int64(4), n) + assert.Equal(t, "PONG", buffer.String()) +} + +func TestMTLS(t *testing.T) { + cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey) + require.NoError(t, err) + + clientPool := x509.NewCertPool() + clientPool.AppendCertsFromPEM(mTLSCert) + + backendListener, err := net.Listen("tcp", ":0") + require.NoError(t, err) + defer backendListener.Close() + + tlsListener := tls.NewListener(backendListener, &tls.Config{ + // For TLS + Certificates: []tls.Certificate{cert}, + + // For mTLS + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: clientPool, + }) + defer tlsListener.Close() + + go fakeRedis(t, tlsListener) + + _, port, err := net.SplitHostPort(tlsListener.Addr().String()) + require.NoError(t, err) + + dialerManager := NewDialerManager(nil) + + dynamicConf := map[string]*dynamic.TCPServersTransport{ + "test": { + TLS: &dynamic.TLSClientConfig{ + ServerName: "example.com", + // For TLS + RootCAs: []traefiktls.FileOrContent{traefiktls.FileOrContent(LocalhostCert)}, + + // For mTLS + Certificates: traefiktls.Certificates{ + traefiktls.Certificate{ + CertFile: traefiktls.FileOrContent(mTLSCert), + KeyFile: traefiktls.FileOrContent(mTLSKey), + }, + }, + }, + }, + } + + dialerManager.Update(dynamicConf) + + dialer, err := dialerManager.Get("test", true) + require.NoError(t, err) + + conn, err := dialer.Dial("tcp", ":"+port) + require.NoError(t, err) + + _, err = conn.Write([]byte("ping\n")) + require.NoError(t, err) + + err = conn.(*tls.Conn).CloseWrite() + require.NoError(t, err) + + var buf []byte + buffer := bytes.NewBuffer(buf) + n, err := io.Copy(buffer, conn) + require.NoError(t, err) + + assert.Equal(t, int64(4), n) + assert.Equal(t, "PONG", buffer.String()) +} + +func TestSpiffeMTLS(t *testing.T) { + backendListener, err := net.Listen("tcp", ":0") + require.NoError(t, err) + defer backendListener.Close() + + trustDomain := spiffeid.RequireTrustDomainFromString("spiffe://traefik.test") + + pki := newFakeSpiffePKI(t, trustDomain) + + serverSVID := pki.genSVID(t, spiffeid.RequireFromPath(trustDomain, "/server")) + require.NoError(t, err) + + serverSource := fakeSpiffeSource{ + svid: serverSVID, + bundle: pki.bundle, + } + + // go-spiffe's `tlsconfig.MTLSServerConfig` (that should be used here) does not set a certificate on + // the returned `tls.Config` and relies instead on `GetCertificate` being always called. + // But it turns out that `StartTLS` from `httptest.Server`, enforces a default certificate + // if no certificate is previously set on the configured TLS config. + // It makes the test server always serve the httptest default certificate, and not the SPIFFE certificate, + // as GetCertificate is in that case never called (there's a default cert, and SNI is not used). + // To bypass this issue, we're manually extracting the server ceritificate from the server SVID + // and use another initialization method that forces serving the server SPIFFE certificate. + serverCert, err := tlsconfig.GetCertificate(&serverSource)(nil) + require.NoError(t, err) + + tlsListener := tls.NewListener(backendListener, tlsconfig.MTLSWebServerConfig( + serverCert, + &serverSource, + tlsconfig.AuthorizeAny(), + )) + defer tlsListener.Close() + + _, port, err := net.SplitHostPort(tlsListener.Addr().String()) + require.NoError(t, err) + + clientSVID := pki.genSVID(t, spiffeid.RequireFromPath(trustDomain, "/client")) + + clientSource := fakeSpiffeSource{ + svid: clientSVID, + bundle: pki.bundle, + } + + testCases := []struct { + desc string + config dynamic.Spiffe + clientSource SpiffeX509Source + wantError bool + }{ + { + desc: "supports SPIFFE mTLS", + config: dynamic.Spiffe{}, + clientSource: &clientSource, + }, + { + desc: "allows expected server SPIFFE ID", + config: dynamic.Spiffe{ + IDs: []string{"spiffe://traefik.test/server"}, + }, + clientSource: &clientSource, + }, + { + desc: "blocks unexpected server SPIFFE ID", + config: dynamic.Spiffe{ + IDs: []string{"spiffe://traefik.test/not-server"}, + }, + clientSource: &clientSource, + wantError: true, + }, + { + desc: "allows expected server trust domain", + config: dynamic.Spiffe{ + TrustDomain: "spiffe://traefik.test", + }, + clientSource: &clientSource, + }, + { + desc: "denies unexpected server trust domain", + config: dynamic.Spiffe{ + TrustDomain: "spiffe://not-traefik.test", + }, + clientSource: &clientSource, + wantError: true, + }, + { + desc: "spiffe IDs allowlist takes precedence", + config: dynamic.Spiffe{ + IDs: []string{"spiffe://traefik.test/not-server"}, + TrustDomain: "spiffe://not-traefik.test", + }, + clientSource: &clientSource, + wantError: true, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + go fakeRedis(t, tlsListener) + + dialerManager := NewDialerManager(test.clientSource) + + dynamicConf := map[string]*dynamic.TCPServersTransport{ + "test": { + TLS: &dynamic.TLSClientConfig{ + Spiffe: &test.config, + }, + }, + } + + dialerManager.Update(dynamicConf) + + dialer, err := dialerManager.Get("test", true) + require.NoError(t, err) + + conn, err := dialer.Dial("tcp", ":"+port) + + if test.wantError { + require.Error(t, err) + return + } + + require.NoError(t, err) + + _, err = conn.Write([]byte("ping\n")) + require.NoError(t, err) + + err = conn.(*tls.Conn).CloseWrite() + require.NoError(t, err) + + var buf []byte + buffer := bytes.NewBuffer(buf) + n, err := io.Copy(buffer, conn) + require.NoError(t, err) + + assert.Equal(t, int64(4), n) + assert.Equal(t, "PONG", buffer.String()) + }) + } +} + +// fakeSpiffePKI simulates a SPIFFE aware PKI and allows generating multiple valid SVIDs. +type fakeSpiffePKI struct { + caPrivateKey *rsa.PrivateKey + + bundle *x509bundle.Bundle +} + +func newFakeSpiffePKI(t *testing.T, trustDomain spiffeid.TrustDomain) fakeSpiffePKI { + t.Helper() + + caPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048) + require.NoError(t, err) + + caTemplate := x509.Certificate{ + SerialNumber: big.NewInt(2000), + Subject: pkix.Name{ + Organization: []string{"spiffe"}, + }, + URIs: []*url.URL{spiffeid.RequireFromPath(trustDomain, "/ca").URL()}, + NotBefore: time.Now(), + NotAfter: time.Now().Add(time.Hour), + SubjectKeyId: []byte("ca"), + KeyUsage: x509.KeyUsageCertSign | + x509.KeyUsageCRLSign, + BasicConstraintsValid: true, + IsCA: true, + PublicKey: caPrivateKey.Public(), + } + + caCertDER, err := x509.CreateCertificate( + rand.Reader, + &caTemplate, + &caTemplate, + caPrivateKey.Public(), + caPrivateKey, + ) + require.NoError(t, err) + + bundle, err := x509bundle.ParseRaw( + trustDomain, + caCertDER, + ) + require.NoError(t, err) + + return fakeSpiffePKI{ + bundle: bundle, + caPrivateKey: caPrivateKey, + } +} + +func (f *fakeSpiffePKI) genSVID(t *testing.T, id spiffeid.ID) *x509svid.SVID { + t.Helper() + + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + require.NoError(t, err) + + template := x509.Certificate{ + SerialNumber: big.NewInt(200001), + URIs: []*url.URL{id.URL()}, + NotBefore: time.Now(), + NotAfter: time.Now().Add(time.Hour), + SubjectKeyId: []byte("svid"), + KeyUsage: x509.KeyUsageKeyEncipherment | + x509.KeyUsageKeyAgreement | + x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{ + x509.ExtKeyUsageServerAuth, + x509.ExtKeyUsageClientAuth, + }, + BasicConstraintsValid: true, + PublicKey: privateKey.PublicKey, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, + } + + certDER, err := x509.CreateCertificate( + rand.Reader, + &template, + f.bundle.X509Authorities()[0], + privateKey.Public(), + f.caPrivateKey, + ) + require.NoError(t, err) + + keyPKCS8, err := x509.MarshalPKCS8PrivateKey(privateKey) + require.NoError(t, err) + + svid, err := x509svid.ParseRaw(certDER, keyPKCS8) + require.NoError(t, err) + + return svid +} + +// fakeSpiffeSource allows retrieving staticly an SVID and its associated bundle. +type fakeSpiffeSource struct { + bundle *x509bundle.Bundle + svid *x509svid.SVID +} + +func (s *fakeSpiffeSource) GetX509BundleForTrustDomain(trustDomain spiffeid.TrustDomain) (*x509bundle.Bundle, error) { + return s.bundle, nil +} + +func (s *fakeSpiffeSource) GetX509SVID() (*x509svid.SVID, error) { + return s.svid, nil +} diff --git a/pkg/tcp/proxy.go b/pkg/tcp/proxy.go index 525c43c4b..7a32b713d 100644 --- a/pkg/tcp/proxy.go +++ b/pkg/tcp/proxy.go @@ -15,40 +15,30 @@ import ( // Proxy forwards a TCP request to a TCP service. type Proxy struct { - address string - tcpAddr *net.TCPAddr - terminationDelay time.Duration - proxyProtocol *dynamic.ProxyProtocol + address string + proxyProtocol *dynamic.ProxyProtocol + dialer Dialer } // NewProxy creates a new Proxy. -func NewProxy(address string, terminationDelay time.Duration, proxyProtocol *dynamic.ProxyProtocol) (*Proxy, error) { +func NewProxy(address string, proxyProtocol *dynamic.ProxyProtocol, dialer Dialer) (*Proxy, error) { if proxyProtocol != nil && (proxyProtocol.Version < 1 || proxyProtocol.Version > 2) { return nil, fmt.Errorf("unknown proxyProtocol version: %d", proxyProtocol.Version) } - // Creates the tcpAddr only for IP based addresses, - // because there is no need to resolve the name on every new connection, - // and building it should happen once. - var tcpAddr *net.TCPAddr - if host, _, err := net.SplitHostPort(address); err == nil && net.ParseIP(host) != nil { - tcpAddr, err = net.ResolveTCPAddr("tcp", address) - if err != nil { - return nil, err - } - } - return &Proxy{ - address: address, - tcpAddr: tcpAddr, - terminationDelay: terminationDelay, - proxyProtocol: proxyProtocol, + address: address, + proxyProtocol: proxyProtocol, + dialer: dialer, }, nil } // ServeTCP forwards the connection to a service. func (p *Proxy) ServeTCP(conn WriteCloser) { - log.Debug().Msgf("Handling connection from %s to %s", conn.RemoteAddr(), p.address) + log.Debug(). + Str("address", p.address). + Str("remoteAddr", conn.RemoteAddr().String()). + Msg("Handling connection") // needed because of e.g. server.trackedConnection defer conn.Close() @@ -89,21 +79,13 @@ func (p *Proxy) ServeTCP(conn WriteCloser) { <-errChan } -func (p Proxy) dialBackend() (*net.TCPConn, error) { - // Dial using directly the TCPAddr for IP based addresses. - if p.tcpAddr != nil { - return net.DialTCP("tcp", nil, p.tcpAddr) - } - - log.Debug().Msgf("Dial with lookup to address %s", p.address) - - // Dial with DNS lookup for host based addresses. - conn, err := net.Dial("tcp", p.address) +func (p Proxy) dialBackend() (WriteCloser, error) { + conn, err := p.dialer.Dial("tcp", p.address) if err != nil { return nil, err } - return conn.(*net.TCPConn), nil + return conn.(WriteCloser), nil } func (p Proxy) connCopy(dst, src WriteCloser, errCh chan error) { @@ -125,8 +107,8 @@ func (p Proxy) connCopy(dst, src WriteCloser, errCh chan error) { return } - if p.terminationDelay >= 0 { - err := dst.SetReadDeadline(time.Now().Add(p.terminationDelay)) + if p.dialer.TerminationDelay() >= 0 { + err := dst.SetReadDeadline(time.Now().Add(p.dialer.TerminationDelay())) if err != nil { log.Debug().Err(err).Msg("Error while setting deadline") } diff --git a/pkg/tcp/proxy_test.go b/pkg/tcp/proxy_test.go index fb8cad1dd..ec51df83d 100644 --- a/pkg/tcp/proxy_test.go +++ b/pkg/tcp/proxy_test.go @@ -3,7 +3,6 @@ package tcp import ( "bytes" "errors" - "fmt" "io" "net" "testing" @@ -20,7 +19,6 @@ func fakeRedis(t *testing.T, listener net.Listener) { for { conn, err := listener.Accept() - fmt.Println("Accept on server") require.NoError(t, err) for { @@ -54,7 +52,9 @@ func TestCloseWrite(t *testing.T) { _, port, err := net.SplitHostPort(backendListener.Addr().String()) require.NoError(t, err) - proxy, err := NewProxy(":"+port, 10*time.Millisecond, nil) + dialer := tcpDialer{&net.Dialer{}, 10 * time.Millisecond} + + proxy, err := NewProxy(":"+port, nil, dialer) require.NoError(t, err) proxyListener, err := net.Listen("tcp", ":0") @@ -133,7 +133,9 @@ func TestProxyProtocol(t *testing.T) { _, port, err := net.SplitHostPort(proxyBackendListener.Addr().String()) require.NoError(t, err) - proxy, err := NewProxy(":"+port, 10*time.Millisecond, &dynamic.ProxyProtocol{Version: test.version}) + dialer := tcpDialer{&net.Dialer{}, 10 * time.Millisecond} + + proxy, err := NewProxy(":"+port, &dynamic.ProxyProtocol{Version: test.version}, dialer) require.NoError(t, err) proxyListener, err := net.Listen("tcp", ":0") @@ -171,42 +173,3 @@ func TestProxyProtocol(t *testing.T) { }) } } - -func TestLookupAddress(t *testing.T) { - testCases := []struct { - desc string - address string - expectAddr assert.ComparisonAssertionFunc - expectRefresh assert.ValueAssertionFunc - }{ - { - desc: "IP doesn't need refresh", - address: "8.8.4.4:53", - expectAddr: assert.Equal, - expectRefresh: assert.NotNil, - }, - { - desc: "Hostname needs refresh", - address: "dns.google:53", - expectAddr: assert.NotEqual, - expectRefresh: assert.Nil, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - proxy, err := NewProxy(test.address, 10*time.Millisecond, nil) - require.NoError(t, err) - - test.expectRefresh(t, proxy.tcpAddr) - - conn, err := proxy.dialBackend() - require.NoError(t, err) - - test.expectAddr(t, test.address, conn.RemoteAddr().String()) - }) - } -} diff --git a/webui/src/components/_commons/PanelServiceDetails.vue b/webui/src/components/_commons/PanelServiceDetails.vue index b73436172..38c7cc1a6 100644 --- a/webui/src/components/_commons/PanelServiceDetails.vue +++ b/webui/src/components/_commons/PanelServiceDetails.vue @@ -55,19 +55,6 @@ - -
-
-
Termination Delay
- - {{ data.loadBalancer.terminationDelay }} ms - -
-
-
-
From a08a428787f2fafa5de1f5cabc8e5a2e84033e9b Mon Sep 17 00:00:00 2001 From: Douglas De Toni Machado Date: Mon, 12 Dec 2022 12:30:05 -0300 Subject: [PATCH 04/74] Support HostSNIRegexp in GatewayAPI TLS routes --- .../tlsroute/with_invalid_SNI_matching.yml | 2 +- pkg/provider/kubernetes/gateway/kubernetes.go | 43 ++++++++++++------- .../kubernetes/gateway/kubernetes_test.go | 24 ++++++++--- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml index 004e1a4b9..512e39770 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml @@ -39,7 +39,7 @@ spec: kind: Gateway group: gateway.networking.k8s.io hostnames: - - "*.foo.bar" + - "*.foo.*.bar" rules: - backendRefs: - name: whoamitcp diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index fc620ae69..847d1c09b 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -839,7 +839,7 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2. } router := dynamic.TCPRouter{ - Rule: "HostSNI(`*`)", // Gateway listener hostname not available in TCP + Rule: "HostSNI(`*`)", EntryPoints: []string{ep}, } @@ -970,8 +970,16 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2. hostnames := matchingHostnames(listener, route.Spec.Hostnames) if len(hostnames) == 0 && listener.Hostname != nil && *listener.Hostname != "" && len(route.Spec.Hostnames) > 0 { - // TODO update the corresponding route parent status - // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.TLSRoute + for _, parent := range route.Status.Parents { + parent.Conditions = append(parent.Conditions, metav1.Condition{ + Type: string(v1alpha2.GatewayClassConditionStatusAccepted), + Status: metav1.ConditionFalse, + Reason: string(v1alpha2.ListenerReasonRouteConflict), + Message: fmt.Sprintf("No hostname match between listener: %v and route: %v", listener.Hostname, route.Spec.Hostnames), + LastTransitionTime: metav1.Now(), + }) + } + continue } @@ -1207,7 +1215,7 @@ func hostRule(hostnames []v1alpha2.Hostname) (string, error) { } func hostSNIRule(hostnames []v1alpha2.Hostname) (string, error) { - var matchers []string + rules := make([]string, 0, len(hostnames)) uniqHostnames := map[v1alpha2.Hostname]struct{}{} for _, hostname := range hostnames { @@ -1219,25 +1227,28 @@ func hostSNIRule(hostnames []v1alpha2.Hostname) (string, error) { continue } - h := string(hostname) + host := string(hostname) + uniqHostnames[hostname] = struct{}{} - // TODO support wildcard hostnames with an HostSNI regexp matcher - if strings.Contains(h, "*") { - return "", fmt.Errorf("wildcard hostname is not supported: %q", h) + wildcard := strings.Count(host, "*") + if wildcard == 0 { + rules = append(rules, fmt.Sprintf("HostSNI(`%s`)", host)) + continue } - matchers = append(matchers, fmt.Sprintf("HostSNI(`%s`)", h)) - uniqHostnames[hostname] = struct{}{} + if !strings.HasPrefix(host, "*.") || wildcard > 1 { + return "", fmt.Errorf("invalid rule: %q", host) + } + + host = strings.Replace(regexp.QuoteMeta(host), `\*\.`, `[a-zA-Z0-9-]+\.`, 1) + rules = append(rules, fmt.Sprintf("HostSNIRegexp(`^%s$`)", host)) } - switch len(matchers) { - case 0: + if len(hostnames) == 0 || len(rules) == 0 { return "HostSNI(`*`)", nil - case 1: - return matchers[0], nil - default: - return fmt.Sprintf("(%s)", strings.Join(matchers, " || ")), nil } + + return strings.Join(rules, " || "), nil } func extractRule(routeRule v1alpha2.HTTPRouteRule, hostRule string) (string, error) { diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index f7b6b9cd9..28946ba7b 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -3076,10 +3076,10 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-tls-dfc5c7506ac1b172c8b7": { + "default-tls-app-1-my-gateway-tls-d5342d75658583f03593": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-1-my-gateway-tls-dfc5c7506ac1b172c8b7-wrr-0", - Rule: "(HostSNI(`foo.example.com`) || HostSNI(`bar.example.com`))", + Service: "default-tls-app-1-my-gateway-tls-d5342d75658583f03593-wrr-0", + Rule: "HostSNI(`foo.example.com`) || HostSNI(`bar.example.com`)", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, @@ -3087,7 +3087,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-tls-dfc5c7506ac1b172c8b7-wrr-0": { + "default-tls-app-1-my-gateway-tls-d5342d75658583f03593-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4780,6 +4780,11 @@ func Test_hostSNIRule(t *testing.T) { hostnames: []v1alpha2.Hostname{"*"}, expectError: true, }, + { + desc: "Supported wildcard", + hostnames: []v1alpha2.Hostname{"*.foo"}, + expectedRule: "HostSNIRegexp(`^[a-zA-Z0-9-]+\\.foo$`)", + }, { desc: "Multiple malformed wildcard", hostnames: []v1alpha2.Hostname{"*.foo.*"}, @@ -4788,7 +4793,7 @@ func Test_hostSNIRule(t *testing.T) { { desc: "Some empty hostnames", hostnames: []v1alpha2.Hostname{"foo", "", "bar"}, - expectedRule: "(HostSNI(`foo`) || HostSNI(`bar`))", + expectedRule: "HostSNI(`foo`) || HostSNI(`bar`)", }, { desc: "Valid hostname", @@ -4798,12 +4803,17 @@ func Test_hostSNIRule(t *testing.T) { { desc: "Multiple valid hostnames", hostnames: []v1alpha2.Hostname{"foo", "bar"}, - expectedRule: "(HostSNI(`foo`) || HostSNI(`bar`))", + expectedRule: "HostSNI(`foo`) || HostSNI(`bar`)", + }, + { + desc: "Multiple valid hostnames with wildcard", + hostnames: []v1alpha2.Hostname{"bar.foo", "foo.foo", "*.foo"}, + expectedRule: "HostSNI(`bar.foo`) || HostSNI(`foo.foo`) || HostSNIRegexp(`^[a-zA-Z0-9-]+\\.foo$`)", }, { desc: "Multiple overlapping hostnames", hostnames: []v1alpha2.Hostname{"foo", "bar", "foo", "baz"}, - expectedRule: "(HostSNI(`foo`) || HostSNI(`bar`) || HostSNI(`baz`))", + expectedRule: "HostSNI(`foo`) || HostSNI(`bar`) || HostSNI(`baz`)", }, } From 748254b6c50d672448b1f8eeba453476d92c4af4 Mon Sep 17 00:00:00 2001 From: mloiseleur <97035654+mloiseleur@users.noreply.github.com> Date: Tue, 13 Dec 2022 16:16:06 +0100 Subject: [PATCH 05/74] doc: Update Grafana Official Dashboards --- contrib/grafana/traefik-kubernetes.json | 1311 ++++++++++++----------- contrib/grafana/traefik.json | 173 ++- 2 files changed, 839 insertions(+), 645 deletions(-) diff --git a/contrib/grafana/traefik-kubernetes.json b/contrib/grafana/traefik-kubernetes.json index 75cf074fb..6774af097 100644 --- a/contrib/grafana/traefik-kubernetes.json +++ b/contrib/grafana/traefik-kubernetes.json @@ -15,7 +15,7 @@ "type": "grafana", "id": "grafana", "name": "Grafana", - "version": "9.2.2" + "version": "9.3.1" }, { "type": "panel", @@ -64,8 +64,10 @@ } ] }, - "editable": true, + "description": "Official dashboard for Traefik on Kubernetes", + "editable": false, "fiscalYearStartMonth": 0, + "gnetId": 17347, "graphTooltip": 0, "id": null, "links": [], @@ -133,7 +135,7 @@ }, "textMode": "auto" }, - "pluginVersion": "9.2.2", + "pluginVersion": "9.3.1", "targets": [ { "datasource": { @@ -818,7 +820,7 @@ "type": "row" }, { - "collapsed": true, + "collapsed": false, "gridPos": { "h": 1, "w": 24, @@ -826,607 +828,706 @@ "y": 18 }, "id": 16, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "reqps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 27 - }, - "id": 17, - "options": { - "legend": { - "calcs": [ - "mean", - "max" - ], - "displayMode": "table", - "placement": "right", - "showLegend": true, - "sortBy": "Mean", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "desc" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"2..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", - "legendFormat": "{{method}}[{{code}}] on {{service}}", - "range": true, - "refId": "A" - } - ], - "title": "2xx over 5 min", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisGridShow": true, - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "reqps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 27 - }, - "id": 18, - "options": { - "legend": { - "calcs": [ - "mean", - "max" - ], - "displayMode": "table", - "placement": "right", - "showLegend": true, - "sortBy": "Mean", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "desc" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"5..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", - "legendFormat": "{{method}}[{{code}}] on {{service}}", - "range": true, - "refId": "A" - } - ], - "title": "5xx over 5 min", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisGridShow": true, - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "reqps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 35 - }, - "id": 19, - "options": { - "legend": { - "calcs": [ - "mean", - "max" - ], - "displayMode": "table", - "placement": "right", - "showLegend": true, - "sortBy": "Mean", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "desc" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code!~\"2..|5..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", - "legendFormat": "{{method}}[{{code}}] on {{service}}", - "range": true, - "refId": "A" - } - ], - "title": "Other codes over 5 min", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisGridShow": true, - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "binBps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 35 - }, - "id": 20, - "options": { - "legend": { - "calcs": [ - "mean", - "max" - ], - "displayMode": "table", - "placement": "right", - "showLegend": true, - "sortBy": "Mean", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "desc" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_requests_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", - "legendFormat": "{{method}} on {{service}}", - "range": true, - "refId": "A" - } - ], - "title": "Requests Size", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 43 - }, - "id": 2, - "options": { - "legend": { - "calcs": [ - "mean", - "max" - ], - "displayMode": "table", - "placement": "right", - "showLegend": true, - "sortBy": "Max", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "desc" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "label_replace(\n sum(traefik_service_open_connections{service=~\"$service.*\"}) by (service),\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")", - "legendFormat": "{{service}}", - "range": true, - "refId": "A" - } - ], - "title": "Connections per Service", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 43 - }, - "id": 21, - "options": { - "legend": { - "calcs": [ - "mean", - "max" - ], - "displayMode": "table", - "placement": "right", - "showLegend": true, - "sortBy": "Max", - "sortDesc": true - }, - "tooltip": { - "mode": "multi", - "sort": "desc" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "sum(traefik_entrypoint_open_connections{entrypoint=~\"$entrypoint\"}) by (entrypoint)\n", - "legendFormat": "{{entrypoint}}", - "range": true, - "refId": "A" - } - ], - "title": "Connections per Entrypoint", - "type": "timeseries" - } - ], + "panels": [], "title": "HTTP Details", "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 8, + "x": 0, + "y": 19 + }, + "id": 17, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"2..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", + "legendFormat": "{{method}}[{{code}}] on {{service}}", + "range": true, + "refId": "A" + } + ], + "title": "2xx over 5 min", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisGridShow": true, + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 8, + "x": 8, + "y": 19 + }, + "id": 18, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"5..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", + "legendFormat": "{{method}}[{{code}}] on {{service}}", + "range": true, + "refId": "A" + } + ], + "title": "5xx over 5 min", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisGridShow": true, + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 8, + "x": 16, + "y": 19 + }, + "id": 19, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code!~\"2..|5..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", + "legendFormat": "{{method}}[{{code}}] on {{service}}", + "range": true, + "refId": "A" + } + ], + "title": "Other codes over 5 min", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisGridShow": true, + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "binBps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 20, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_requests_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", + "legendFormat": "{{method}} on {{service}}", + "range": true, + "refId": "A" + } + ], + "title": "Requests Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisGridShow": true, + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "binBps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 24, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_responses_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", + "legendFormat": "{{method}} on {{service}}", + "range": true, + "refId": "A" + } + ], + "title": "Responses Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 39 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "label_replace(\n sum(traefik_service_open_connections{service=~\"$service.*\"}) by (service),\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")", + "legendFormat": "{{service}}", + "range": true, + "refId": "A" + } + ], + "title": "Connections per Service", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 39 + }, + "id": 21, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Max", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(traefik_entrypoint_open_connections{entrypoint=~\"$entrypoint\"}) by (entrypoint)\n", + "legendFormat": "{{entrypoint}}", + "range": true, + "refId": "A" + } + ], + "title": "Connections per Entrypoint", + "type": "timeseries" } ], "refresh": false, @@ -1504,8 +1605,8 @@ }, "timepicker": {}, "timezone": "", - "title": "Traefik Official Standalone Dashboard", + "title": "Traefik Official Kubernetes Dashboard", "uid": "n5bu_kv4k", - "version": 3, + "version": 5, "weekStart": "" } diff --git a/contrib/grafana/traefik.json b/contrib/grafana/traefik.json index 75cf074fb..34a1e8127 100644 --- a/contrib/grafana/traefik.json +++ b/contrib/grafana/traefik.json @@ -15,7 +15,7 @@ "type": "grafana", "id": "grafana", "name": "Grafana", - "version": "9.2.2" + "version": "9.3.1" }, { "type": "panel", @@ -64,8 +64,10 @@ } ] }, - "editable": true, + "description": "Official dashboard for Standalone Traefik", + "editable": false, "fiscalYearStartMonth": 0, + "gnetId": 17346, "graphTooltip": 0, "id": null, "links": [], @@ -133,7 +135,7 @@ }, "textMode": "auto" }, - "pluginVersion": "9.2.2", + "pluginVersion": "9.3.1", "targets": [ { "datasource": { @@ -669,8 +671,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" } ] }, @@ -764,8 +765,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" } ] }, @@ -873,8 +873,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -887,10 +886,10 @@ "overrides": [] }, "gridPos": { - "h": 8, - "w": 12, + "h": 12, + "w": 8, "x": 0, - "y": 27 + "y": 19 }, "id": 17, "options": { @@ -900,7 +899,7 @@ "max" ], "displayMode": "table", - "placement": "right", + "placement": "bottom", "showLegend": true, "sortBy": "Mean", "sortDesc": true @@ -973,8 +972,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -987,10 +985,10 @@ "overrides": [] }, "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 27 + "h": 12, + "w": 8, + "x": 8, + "y": 19 }, "id": 18, "options": { @@ -1000,7 +998,7 @@ "max" ], "displayMode": "table", - "placement": "right", + "placement": "bottom", "showLegend": true, "sortBy": "Mean", "sortDesc": true @@ -1073,8 +1071,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1087,10 +1084,10 @@ "overrides": [] }, "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 35 + "h": 12, + "w": 8, + "x": 16, + "y": 19 }, "id": 19, "options": { @@ -1100,7 +1097,7 @@ "max" ], "displayMode": "table", - "placement": "right", + "placement": "bottom", "showLegend": true, "sortBy": "Mean", "sortDesc": true @@ -1173,8 +1170,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1189,8 +1185,8 @@ "gridPos": { "h": 8, "w": 12, - "x": 12, - "y": 35 + "x": 0, + "y": 31 }, "id": 20, "options": { @@ -1240,6 +1236,7 @@ "custom": { "axisCenteredZero": false, "axisColorMode": "text", + "axisGridShow": true, "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, @@ -1272,8 +1269,105 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "binBps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 24, + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_responses_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", + "legendFormat": "{{method}} on {{service}}", + "range": true, + "refId": "A" + } + ], + "title": "Responses Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" }, { "color": "red", @@ -1289,7 +1383,7 @@ "h": 8, "w": 12, "x": 0, - "y": 43 + "y": 39 }, "id": 2, "options": { @@ -1371,8 +1465,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1388,7 +1481,7 @@ "h": 8, "w": 12, "x": 12, - "y": 43 + "y": 39 }, "id": 21, "options": { @@ -1491,7 +1584,7 @@ "refId": "StandardVariableQuery" }, "refresh": 2, - "regex": "/([^-]+-[^-]+).*/", + "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" @@ -1505,7 +1598,7 @@ "timepicker": {}, "timezone": "", "title": "Traefik Official Standalone Dashboard", - "uid": "n5bu_kv4k", - "version": 3, + "uid": "n5bu_kv45", + "version": 5, "weekStart": "" } From 74ef79ea236884167adeaa06515f595a0b610327 Mon Sep 17 00:00:00 2001 From: mpl Date: Thu, 15 Dec 2022 11:18:05 +0100 Subject: [PATCH 06/74] mitigate race against server readiness in test Co-authored-by: Romain --- pkg/server/server_entrypoint_tcp_http3_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/server/server_entrypoint_tcp_http3_test.go b/pkg/server/server_entrypoint_tcp_http3_test.go index 6544dd2e0..257ac3d72 100644 --- a/pkg/server/server_entrypoint_tcp_http3_test.go +++ b/pkg/server/server_entrypoint_tcp_http3_test.go @@ -6,6 +6,7 @@ import ( "crypto/tls" "net/http" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -113,6 +114,9 @@ func TestHTTP3AdvertisedPort(t *testing.T) { }) require.NoError(t, err) + // We are racing with the http3Server readiness happening in the goroutine starting the entrypoint + time.Sleep(time.Second) + request, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:8090", nil) require.NoError(t, err) From e7baf44a2e9b8bb3de8553b3be793b4295f4f5dd Mon Sep 17 00:00:00 2001 From: mloiseleur <97035654+mloiseleur@users.noreply.github.com> Date: Thu, 15 Dec 2022 14:32:06 +0100 Subject: [PATCH 07/74] doc: Improve TLSStore CRD documentation --- .../content/routing/providers/kubernetes-crd.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/docs/content/routing/providers/kubernetes-crd.md b/docs/content/routing/providers/kubernetes-crd.md index 2fb474dda..e2ba50fa5 100644 --- a/docs/content/routing/providers/kubernetes-crd.md +++ b/docs/content/routing/providers/kubernetes-crd.md @@ -1609,14 +1609,14 @@ or referencing TLS options in the [`IngressRoute`](#kind-ingressroute) / [`Ingre `TLSStore` is the CRD implementation of a [Traefik "TLS Store"](../../https/tls.md#certificates-stores). -Register the `TLSStore` kind in the Kubernetes cluster before creating `TLSStore` objects -or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`IngressRouteTCP`](#kind-ingressroutetcp) objects. +Register the `TLSStore` kind in the Kubernetes cluster before creating `TLSStore` objects. !!! important "Default TLS Store" Traefik currently only uses the [TLS Store named "default"](../../https/tls.md#certificates-stores). + This _default_ `TLSStore` should be in a namespace discoverable by Traefik. Since it is used by default on [`IngressRoute`](#kind-ingressroute) and [`IngressRouteTCP`](#kind-ingressroutetcp) objects, there never is a need to actually reference it. This means that you cannot have two stores that are named default in different Kubernetes namespaces. - For the time being, please only configure one TLSStore named default. + As a consequence, with respect to TLS stores, the only change that makes sense (and only if needed) is to configure the default TLSStore. !!! info "TLSStore Attributes" ```yaml tab="TLSStore" @@ -1624,7 +1624,7 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres kind: TLSStore metadata: name: default - namespace: default + spec: certificates: # [1] - secretName: foo @@ -1645,8 +1645,7 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres kind: TLSStore metadata: name: default - namespace: default - + spec: defaultCertificate: secretName: supersecret @@ -1660,16 +1659,14 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres spec: entryPoints: - - web + - websecure routes: - match: Host(`example.com`) && PathPrefix(`/stripit`) kind: Rule services: - name: whoami port: 80 - tls: - store: - name: default + tls: {} ``` ```yaml tab="Secret" From 29b8b6911eff9c3b3cfc6c9bf5d8d30305a6c98b Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 16 Dec 2022 10:34:04 +0100 Subject: [PATCH 08/74] fix: sanitize X-Forwarded-Proto header in RedirectScheme middleware Co-authored-by: Julien Salleyron --- pkg/middlewares/redirect/redirect_scheme.go | 25 +++++++++++++++---- .../redirect/redirect_scheme_test.go | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/pkg/middlewares/redirect/redirect_scheme.go b/pkg/middlewares/redirect/redirect_scheme.go index 063d6c4bc..2828aa48a 100644 --- a/pkg/middlewares/redirect/redirect_scheme.go +++ b/pkg/middlewares/redirect/redirect_scheme.go @@ -18,6 +18,12 @@ const ( xForwardedProto = "X-Forwarded-Proto" ) +type redirectScheme struct { + http.Handler + + name string +} + // NewRedirectScheme creates a new RedirectScheme middleware. func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.RedirectScheme, name string) (http.Handler, error) { logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeSchemeName)) @@ -33,10 +39,19 @@ func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.Redi port = ":" + conf.Port } - return newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, clientRequestURL, name) + rs := &redirectScheme{name: name} + + handler, err := newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, rs.clientRequestURL, name) + if err != nil { + return nil, err + } + + rs.Handler = handler + + return rs, nil } -func clientRequestURL(req *http.Request) string { +func (r *redirectScheme) clientRequestURL(req *http.Request) string { scheme := schemeHTTP host, port, err := net.SplitHostPort(req.Host) if err != nil { @@ -71,12 +86,12 @@ func clientRequestURL(req *http.Request) string { // Given that we're in a middleware that is only used in the context of HTTP(s) requests, // the only possible valid schemes are one of "http" or "https", so we convert back to them. switch { - case strings.EqualFold(xProto, "ws"): + case strings.EqualFold(xProto, schemeHTTP), strings.EqualFold(xProto, "ws"): scheme = schemeHTTP - case strings.EqualFold(xProto, "wss"): + case strings.EqualFold(xProto, schemeHTTPS), strings.EqualFold(xProto, "wss"): scheme = schemeHTTPS default: - scheme = xProto + log.FromContext(middlewares.GetLoggerCtx(req.Context(), r.name, typeSchemeName)).Debugf("invalid X-Forwarded-Proto: %s", xProto) } } diff --git a/pkg/middlewares/redirect/redirect_scheme_test.go b/pkg/middlewares/redirect/redirect_scheme_test.go index dea1d6265..07ae54246 100644 --- a/pkg/middlewares/redirect/redirect_scheme_test.go +++ b/pkg/middlewares/redirect/redirect_scheme_test.go @@ -72,7 +72,7 @@ func TestRedirectSchemeHandler(t *testing.T) { headers: map[string]string{ "X-Forwarded-Proto": "bar", }, - expectedURL: "https://bar://foo", + expectedURL: "https://foo", expectedStatus: http.StatusFound, }, { From 7129f03dc94db348621ec1c82c6cf071675140f2 Mon Sep 17 00:00:00 2001 From: Charlie Haley Date: Mon, 19 Dec 2022 08:54:04 +0000 Subject: [PATCH 09/74] fix: update opentelemetry dependency versions --- go.mod | 49 ++++++------ go.sum | 143 +++++++++++++---------------------- pkg/metrics/opentelemetry.go | 26 +++---- 3 files changed, 86 insertions(+), 132 deletions(-) diff --git a/go.mod b/go.mod index 47c37943d..520be5f38 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000 github.com/andybalholm/brotli v1.0.4 github.com/aws/aws-sdk-go v1.44.47 - github.com/cenkalti/backoff/v4 v4.1.3 + github.com/cenkalti/backoff/v4 v4.2.0 github.com/compose-spec/compose-go v1.0.3 github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf @@ -78,24 +78,24 @@ require ( go.elastic.co/apm v1.13.1 go.elastic.co/apm/module/apmot v1.13.1 go.opentelemetry.io/collector/pdata v0.64.1 - go.opentelemetry.io/otel v1.11.1 - go.opentelemetry.io/otel/bridge/opentracing v1.11.1 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.33.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.33.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 - go.opentelemetry.io/otel/metric v0.33.0 - go.opentelemetry.io/otel/sdk v1.11.1 - go.opentelemetry.io/otel/sdk/metric v0.33.0 - go.opentelemetry.io/otel/trace v1.11.1 + go.opentelemetry.io/otel v1.11.2 + go.opentelemetry.io/otel/bridge/opentracing v1.11.2 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.2 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.2 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.2 + go.opentelemetry.io/otel/metric v0.34.0 + go.opentelemetry.io/otel/sdk v1.11.2 + go.opentelemetry.io/otel/sdk/metric v0.34.0 + go.opentelemetry.io/otel/trace v1.11.2 golang.org/x/exp v0.0.0-20221114191408-850992195362 golang.org/x/mod v0.6.0 - golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 + golang.org/x/net v0.4.0 golang.org/x/text v0.5.0 golang.org/x/time v0.0.0-20220609170525-579cf78fd858 golang.org/x/tools v0.2.0 - google.golang.org/grpc v1.50.1 + google.golang.org/grpc v1.51.0 gopkg.in/DataDog/dd-trace-go.v1 v1.43.1 gopkg.in/fsnotify.v1 v1.4.7 gopkg.in/yaml.v3 v3.0.1 @@ -109,7 +109,7 @@ require ( ) require ( - cloud.google.com/go v0.97.0 // indirect + cloud.google.com/go/compute/metadata v0.2.0 // indirect github.com/AlecAivazis/survey/v2 v2.2.3 // indirect github.com/Azure/azure-sdk-for-go v40.3.0+incompatible // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect @@ -211,12 +211,13 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/gax-go/v2 v2.1.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.6.0 // indirect github.com/gophercloud/gophercloud v1.0.0 // indirect github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0 // indirect github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect github.com/hashicorp/consul/sdk v0.10.0 // indirect github.com/hashicorp/cronexpr v1.1.1 // indirect @@ -347,8 +348,8 @@ require ( go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect go.etcd.io/etcd/client/v3 v3.5.4 // indirect go.opencensus.io v0.23.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.33.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect @@ -358,14 +359,14 @@ require ( go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect golang.org/x/crypto v0.1.0 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect + golang.org/x/oauth2 v0.2.0 // indirect + golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 // indirect golang.org/x/sys v0.3.0 // indirect golang.org/x/term v0.3.0 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/api v0.57.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/api v0.100.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect + google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.6 // indirect diff --git a/go.sum b/go.sum index 629581f80..915832e96 100644 --- a/go.sum +++ b/go.sum @@ -25,23 +25,19 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute/metadata v0.2.0 h1:nBbNSZyDpkNlo3DepaaLKVuO7ClyifSAmNloSCZrHnQ= +cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -294,8 +290,8 @@ github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= -github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= +github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20180118203423-deb3ae2ef261/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -851,7 +847,6 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= @@ -897,7 +892,6 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -911,8 +905,6 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -923,12 +915,14 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0 h1:6DWmvNpomjL1+3liNSZbVns3zsYzzCjm6pRBO1tLeso= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= @@ -968,8 +962,9 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpg github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0 h1:t7uX3JBHdVwAi3G7sSSdbsk8NfgA+LnUS88V/2EKaA0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0/go.mod h1:4OGVnY4qf2+gw+ssiHbW+pq4mo2yko94YxxMmXZ7jCA= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= @@ -1998,32 +1993,32 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/collector/pdata v0.64.1 h1:8E06uHr0nnenGftFwhwdenA88QhVnF4dJam+qVXgdVg= go.opentelemetry.io/collector/pdata v0.64.1/go.mod h1:IzvXUGQml2mrnvdb8zIlEW3qQs9oFLdD2hLwJdZ+pek= -go.opentelemetry.io/otel v1.11.1 h1:4WLLAmcfkmDk2ukNXJyq3/kiz/3UzCaYq6PskJsaou4= -go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE= -go.opentelemetry.io/otel/bridge/opentracing v1.11.1 h1:/ZBsgjXWUpiZ5M9zm+Ft3kuDUGErIGcEJbKRIsFN6jA= -go.opentelemetry.io/otel/bridge/opentracing v1.11.1/go.mod h1:vw9hN4H+G0ek+XQtxP+Mm1McLcmdx2FXHNrWn2bBqxU= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 h1:X2GndnMCsUPh6CiY2a+frAbNsXaPLbB0soHRYhAZ5Ig= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1/go.mod h1:i8vjiSzbiUC7wOQplijSXMYUpNM93DtlS5CbUT+C6oQ= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.33.0 h1:OT/UjHcjog4A1s1UMCtyehIKS+vpjM5Du0r7KGsH6TE= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.33.0/go.mod h1:0XctNDHEWmiSDIU8NPbJElrK05gBJFcYlGP4FMGo4g4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.33.0 h1:1SVtGtRsNyGgv1fRfNXfh+sJowIwzF0gkf+61lvTgdg= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.33.0/go.mod h1:ryB27ubOBXsiqfh6MwtSdx5knzbSZtjvPnMMmt3AykQ= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.33.0 h1:NoG4v01cdLZfOeNGBQmSe4f4SeP+fx8I/0qzRgTKsGI= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.33.0/go.mod h1:6anbDXBcTp3Qit87pfFmT0paxTJ8sWRccTNYVywN/H8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 h1:MEQNafcNCB0uQIti/oHgU7CZpUMYQ7qigBwMVKycHvc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1/go.mod h1:19O5I2U5iys38SsmT2uDJja/300woyzE1KPIQxEUBUc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 h1:LYyG/f1W/jzAix16jbksJfMQFpOH/Ma6T639pVPMgfI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1/go.mod h1:QrRRQiY3kzAoYPNLP0W/Ikg0gR6V3LMc+ODSxr7yyvg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 h1:tFl63cpAAcD9TOU6U8kZU7KyXuSRYAZlbx1C61aaB74= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1/go.mod h1:X620Jww3RajCJXw/unA+8IRTgxkdS7pi+ZwK9b7KUJk= -go.opentelemetry.io/otel/metric v0.33.0 h1:xQAyl7uGEYvrLAiV/09iTJlp1pZnQ9Wl793qbVvED1E= -go.opentelemetry.io/otel/metric v0.33.0/go.mod h1:QlTYc+EnYNq/M2mNk1qDDMRLpqCOj2f/r5c7Fd5FYaI= -go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs= -go.opentelemetry.io/otel/sdk v1.11.1/go.mod h1:/l3FE4SupHJ12TduVjUkZtlfFqDCQJlOlithYrdktys= -go.opentelemetry.io/otel/sdk/metric v0.33.0 h1:oTqyWfksgKoJmbrs2q7O7ahkJzt+Ipekihf8vhpa9qo= -go.opentelemetry.io/otel/sdk/metric v0.33.0/go.mod h1:xdypMeA21JBOvjjzDUtD0kzIcHO/SPez+a8HOzJPGp0= -go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ= -go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk= +go.opentelemetry.io/otel v1.11.2 h1:YBZcQlsVekzFsFbjygXMOXSs6pialIZxcjfO/mBDmR0= +go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI= +go.opentelemetry.io/otel/bridge/opentracing v1.11.2 h1:Wx51zQDSZDNo5wxMPhkPwzgpUZLQYYDtT41LCcl7opg= +go.opentelemetry.io/otel/bridge/opentracing v1.11.2/go.mod h1:kBrIQ2vqDIqtuS7Np7ALjmm8Tml7yxgsAGQwBhNvuU0= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 h1:htgM8vZIF8oPSCxa341e3IZ4yr/sKxgu8KZYllByiVY= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2/go.mod h1:rqbht/LlhVBgn5+k3M5QK96K5Xb0DvXpMJ5SFQpY6uw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 h1:kpskzLZ60cJ48SJ4uxWa6waBL+4kSV6nVK8rP+QM8Wg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0/go.mod h1:4+x3i62TEegDHuzNva0bMcAN8oUi5w4liGb1d/VgPYo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 h1:e7kFb4pJLbhJgAwUdoVTHzB9pGujs5O8/7gFyZL88fg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0/go.mod h1:3x00m9exjIbhK+zTO4MsCSlfbVmgvLP0wjDgDKa/8bw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 h1:t4Ajxj8JGjxkqoBtbkCOY2cDUl9RwiNE9LPQavooi9U= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0/go.mod h1:WO7omosl4P7JoanH9NgInxDxEn2F2M5YinIh8EyeT8w= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.2 h1:fqR1kli93643au1RKo0Uma3d2aPQKT+WBKfTSBaKbOc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.2/go.mod h1:5Qn6qvgkMsLDX+sYK64rHb1FPhpn0UtxF+ouX1uhyJE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.2 h1:ERwKPn9Aer7Gxsc0+ZlutlH1bEEAUXAUhqm3Y45ABbk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.2/go.mod h1:jWZUM2MWhWCJ9J9xVbRx7tzK1mXKpAlze4CeulycwVY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.2 h1:Us8tbCmuN16zAnK5TC69AtODLycKbwnskQzaB6DfFhc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.2/go.mod h1:GZWSQQky8AgdJj50r1KJm8oiQiIPaAX7uZCFQX9GzC8= +go.opentelemetry.io/otel/metric v0.34.0 h1:MCPoQxcg/26EuuJwpYN1mZTeCYAUGx8ABxfW07YkjP8= +go.opentelemetry.io/otel/metric v0.34.0/go.mod h1:ZFuI4yQGNCupurTXCwkeD/zHBt+C2bR7bw5JqUm/AP8= +go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU= +go.opentelemetry.io/otel/sdk v1.11.2/go.mod h1:wZ1WxImwpq+lVRo4vsmSOxdd+xwoUJ6rqyLc3SyX9aU= +go.opentelemetry.io/otel/sdk/metric v0.34.0 h1:7ElxfQpXCFZlRTvVRTkcUvK8Gt5DC8QzmzsLsO2gdzo= +go.opentelemetry.io/otel/sdk/metric v0.34.0/go.mod h1:l4r16BIqiqPy5rd14kkxllPy/fOI4tWo1jkpD9Z3ffQ= +go.opentelemetry.io/otel/trace v1.11.2 h1:Xf7hWSF2Glv0DE3MH7fBHvtpSBsjcBUe5MYAmZM/+y0= +go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= @@ -2213,7 +2208,6 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -2224,8 +2218,8 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 h1:Frnccbp+ok2GkUS2tC84yAq/U9Vg+0sIO7aRL3T4Xnc= -golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -2242,13 +2236,10 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.2.0 h1:GtQkldQ9m7yvzCL1V+LrYow3Khe0eJH0w7RbX/VbaIU= +golang.org/x/oauth2 v0.2.0/go.mod h1:Cwn6afJ8jrQwYMxQDTpISoXmXW9I6qF6vDeuuoX3Ibs= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2261,8 +2252,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 h1:cu5kTvlzcw1Q5S9f5ip1/cpiB4nXvw1XYzFPGgzLUOY= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2376,16 +2367,12 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2499,8 +2486,6 @@ golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= @@ -2508,8 +2493,9 @@ golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM= @@ -2544,14 +2530,8 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0 h1:4t9zuDlHLcIx0ZEhmXEeFVCRsiOgpgn2QOH9N0MNjPI= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.100.0 h1:LGUYIrbW9pzYQQ8NWXlaIVkgnfubVBZbMFb9P8TK374= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2618,25 +2598,11 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 h1:jmIfw8+gSvXcZSgaFAGyInDXeWzUhvYH57G/5GKMn70= +google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -2667,18 +2633,13 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/pkg/metrics/opentelemetry.go b/pkg/metrics/opentelemetry.go index 328f6fc54..94f170132 100644 --- a/pkg/metrics/opentelemetry.go +++ b/pkg/metrics/opentelemetry.go @@ -23,7 +23,6 @@ import ( "go.opentelemetry.io/otel/metric/unit" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/metric/aggregation" - "go.opentelemetry.io/otel/sdk/metric/view" "google.golang.org/grpc/credentials" "google.golang.org/grpc/encoding/gzip" ) @@ -144,23 +143,16 @@ func newOpenTelemetryMeterProvider(ctx context.Context, config *types.OpenTeleme sdkmetric.WithInterval(time.Duration(config.PushInterval)), } - // View to customize histogram buckets and rename a single histogram instrument. - customBucketsView, err := view.New( - // Match* to match instruments - view.MatchInstrumentName("traefik_*_request_duration_seconds"), - - view.WithSetAggregation(aggregation.ExplicitBucketHistogram{ - Boundaries: config.ExplicitBoundaries, - }), + meterProvider := sdkmetric.NewMeterProvider( + sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter, opts...)), + // View to customize histogram buckets and rename a single histogram instrument. + sdkmetric.WithView(sdkmetric.NewView( + sdkmetric.Instrument{Name: "traefik_*_request_duration_seconds"}, + sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{ + Boundaries: config.ExplicitBoundaries, + }}, + )), ) - if err != nil { - return nil, fmt.Errorf("creating histogram view: %w", err) - } - - meterProvider := sdkmetric.NewMeterProvider(sdkmetric.WithReader( - sdkmetric.NewPeriodicReader(exporter, opts...), - customBucketsView, - )) global.SetMeterProvider(meterProvider) From 2ad1fd725aaafcb97762082f6970ca9af21de16c Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Mon, 19 Dec 2022 10:42:05 +0100 Subject: [PATCH 10/74] Remove Rancher v1 provider --- README.md | 3 +- docs/content/contributing/maintainers.md | 1 - .../include-acme-multiple-domains-example.md | 10 - ...acme-multiple-domains-from-rule-example.md | 8 - .../include-acme-single-domain-example.md | 8 - docs/content/https/tailscale.md | 15 - docs/content/middlewares/http/addprefix.md | 6 - docs/content/middlewares/http/basicauth.md | 27 - docs/content/middlewares/http/buffering.md | 31 - docs/content/middlewares/http/chain.md | 12 - .../middlewares/http/circuitbreaker.md | 6 - docs/content/middlewares/http/compress.md | 16 - docs/content/middlewares/http/contenttype.md | 8 +- docs/content/middlewares/http/digestauth.md | 31 - docs/content/middlewares/http/errorpages.md | 8 - docs/content/middlewares/http/forwardauth.md | 53 - docs/content/middlewares/http/grpcweb.md | 5 - docs/content/middlewares/http/headers.md | 26 - docs/content/middlewares/http/inflightreq.md | 32 - docs/content/middlewares/http/ipallowlist.md | 19 - docs/content/middlewares/http/overview.md | 9 - .../middlewares/http/passtlsclientcert.md | 29 - docs/content/middlewares/http/ratelimit.md | 45 - .../content/middlewares/http/redirectregex.md | 8 - .../middlewares/http/redirectscheme.md | 27 - docs/content/middlewares/http/replacepath.md | 6 - .../middlewares/http/replacepathregex.md | 7 - docs/content/middlewares/http/retry.md | 7 - docs/content/middlewares/http/stripprefix.md | 6 - .../middlewares/http/stripprefixregex.md | 5 - docs/content/middlewares/overview.md | 9 - docs/content/middlewares/tcp/inflightconn.md | 6 - docs/content/middlewares/tcp/ipallowlist.md | 6 - docs/content/middlewares/tcp/overview.md | 9 - docs/content/migration/v2-to-v3.md | 7 + .../operations/include-api-examples.md | 9 - .../operations/include-dashboard-examples.md | 9 - docs/content/providers/overview.md | 3 - docs/content/providers/rancher.md | 286 ---- docs/content/providers/rancher.toml | 20 - docs/content/providers/rancher.txt | 20 - docs/content/providers/rancher.yml | 21 - .../dynamic-configuration/rancher.md | 17 - .../dynamic-configuration/rancher.yml | 1 - .../reference/static-configuration/cli-ref.md | 27 - .../reference/static-configuration/env-ref.md | 27 - .../reference/static-configuration/file.toml | 9 - .../reference/static-configuration/file.yaml | 9 - docs/content/routing/providers/rancher.md | 545 -------- docs/content/routing/routers/index.md | 2 +- docs/mkdocs.yml | 3 - go.mod | 1 - go.sum | 2 - pkg/api/handler_overview_test.go | 2 - pkg/api/testdata/overview-providers.json | 1 - pkg/config/dynamic/fixtures/sample.toml | 9 - pkg/config/static/static_config.go | 8 - pkg/provider/aggregator/aggregator.go | 4 - pkg/provider/rancher/config.go | 299 ---- pkg/provider/rancher/config_test.go | 1203 ----------------- pkg/provider/rancher/label.go | 22 - pkg/provider/rancher/rancher.go | 232 ---- pkg/redactor/redactor_config_test.go | 12 - .../testdata/anonymized-static-config.json | 10 - pkg/redactor/testdata/example.json | 1 - pkg/redactor/testdata/expected.json | 1 - 66 files changed, 10 insertions(+), 3316 deletions(-) delete mode 100644 docs/content/providers/rancher.md delete mode 100644 docs/content/providers/rancher.toml delete mode 100644 docs/content/providers/rancher.txt delete mode 100644 docs/content/providers/rancher.yml delete mode 100644 docs/content/reference/dynamic-configuration/rancher.md delete mode 100644 docs/content/reference/dynamic-configuration/rancher.yml delete mode 100644 docs/content/routing/providers/rancher.md delete mode 100644 pkg/provider/rancher/config.go delete mode 100644 pkg/provider/rancher/config_test.go delete mode 100644 pkg/provider/rancher/label.go delete mode 100644 pkg/provider/rancher/rancher.go diff --git a/README.md b/README.md index 544eddb92..cc23c04a0 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![Twitter](https://img.shields.io/twitter/follow/traefik.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefik) Traefik (pronounced _traffic_) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. -Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. +Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher v2](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. Pointing Traefik at your orchestrator should be the _only_ configuration step you need. --- @@ -69,7 +69,6 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t - [Docker](https://doc.traefik.io/traefik/providers/docker/) / [Swarm mode](https://doc.traefik.io/traefik/providers/docker/) - [Kubernetes](https://doc.traefik.io/traefik/providers/kubernetes-crd/) - [Marathon](https://doc.traefik.io/traefik/providers/marathon/) -- [Rancher](https://doc.traefik.io/traefik/providers/rancher/) (Metadata) - [File](https://doc.traefik.io/traefik/providers/file/) ## Quickstart diff --git a/docs/content/contributing/maintainers.md b/docs/content/contributing/maintainers.md index eee5ec69a..cfad7eb7a 100644 --- a/docs/content/contributing/maintainers.md +++ b/docs/content/contributing/maintainers.md @@ -107,7 +107,6 @@ The `status/*` labels represent the desired state in the workflow. * `area/provider/kv`: KV related. * `area/provider/marathon`: Marathon related. * `area/provider/mesos`: Mesos related. -* `area/provider/rancher`: Rancher related. * `area/provider/servicefabric`: Azure service fabric related. * `area/provider/zk`: Zoo Keeper related. * `area/rules`: Rules related. diff --git a/docs/content/https/include-acme-multiple-domains-example.md b/docs/content/https/include-acme-multiple-domains-example.md index 8107eb24f..63cb382ba 100644 --- a/docs/content/https/include-acme-multiple-domains-example.md +++ b/docs/content/https/include-acme-multiple-domains-example.md @@ -54,16 +54,6 @@ labels: { } ``` -```yaml tab="Rancher" -## Dynamic configuration -labels: - - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) - - traefik.http.routers.blog.tls=true - - traefik.http.routers.blog.tls.certresolver=myresolver - - traefik.http.routers.blog.tls.domains[0].main=example.org - - traefik.http.routers.blog.tls.domains[0].sans=*.example.org -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/include-acme-multiple-domains-from-rule-example.md b/docs/content/https/include-acme-multiple-domains-from-rule-example.md index 01252360b..9bd522c10 100644 --- a/docs/content/https/include-acme-multiple-domains-from-rule-example.md +++ b/docs/content/https/include-acme-multiple-domains-from-rule-example.md @@ -44,14 +44,6 @@ labels: { } ``` -```yaml tab="Rancher" -## Dynamic configuration -labels: - - traefik.http.routers.blog.rule=(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`) - - traefik.http.routers.blog.tls=true - - traefik.http.routers.blog.tls.certresolver=myresolver -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/include-acme-single-domain-example.md b/docs/content/https/include-acme-single-domain-example.md index 30bfa9229..1b87873e1 100644 --- a/docs/content/https/include-acme-single-domain-example.md +++ b/docs/content/https/include-acme-single-domain-example.md @@ -44,14 +44,6 @@ labels: { } ``` -```yaml tab="Rancher" -## Dynamic configuration -labels: - - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) - - traefik.http.routers.blog.tls=true - - traefik.http.routers.blog.tls.certresolver=myresolver -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/tailscale.md b/docs/content/https/tailscale.md index abc742b83..d6b783b2c 100644 --- a/docs/content/https/tailscale.md +++ b/docs/content/https/tailscale.md @@ -127,13 +127,6 @@ A certificate resolver requests certificates for a set of domain names inferred } ``` - ```yaml tab="Rancher" - ## Dynamic configuration - labels: - - traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`) - - traefik.http.routers.blog.tls.certresolver=myresolver - ``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: @@ -200,14 +193,6 @@ A certificate resolver requests certificates for a set of domain names inferred } ``` - ```yaml tab="Rancher" - ## Dynamic configuration - labels: - - traefik.http.routers.blog.rule=Path(`/metrics`) - - traefik.http.routers.blog.tls.certresolver=myresolver - - traefik.http.routers.blog.tls.domains[0].main=monitoring.yak-bebop.ts.net - ``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/middlewares/http/addprefix.md b/docs/content/middlewares/http/addprefix.md index 9f909aa8f..05cba3ad5 100644 --- a/docs/content/middlewares/http/addprefix.md +++ b/docs/content/middlewares/http/addprefix.md @@ -42,12 +42,6 @@ spec: } ``` -```yaml tab="Rancher" -# Prefixing with /foo -labels: - - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" -``` - ```yaml tab="File (YAML)" # Prefixing with /foo http: diff --git a/docs/content/middlewares/http/basicauth.md b/docs/content/middlewares/http/basicauth.md index c9ef0e212..98e1c1560 100644 --- a/docs/content/middlewares/http/basicauth.md +++ b/docs/content/middlewares/http/basicauth.md @@ -47,12 +47,6 @@ spec: } ``` -```yaml tab="Rancher" -# Declaring the user list -labels: - - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" -``` - ```yaml tab="File (YAML)" # Declaring the user list http: @@ -163,12 +157,6 @@ data: } ``` -```yaml tab="Rancher" -# Declaring the user list -labels: - - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" -``` - ```yaml tab="File (YAML)" # Declaring the user list http: @@ -238,11 +226,6 @@ data: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -293,11 +276,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -386,11 +364,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.basicauth.removeheader=true" -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/buffering.md b/docs/content/middlewares/http/buffering.md index f172faffa..e76d5b40e 100644 --- a/docs/content/middlewares/http/buffering.md +++ b/docs/content/middlewares/http/buffering.md @@ -46,12 +46,6 @@ spec: } ``` -```yaml tab="Rancher" -# Sets the maximum request body to 2MB -labels: - - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" -``` - ```yaml tab="File (YAML)" # Sets the maximum request body to 2MB http: @@ -103,11 +97,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -153,11 +142,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -205,11 +189,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -255,11 +234,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -307,11 +281,6 @@ You can have the Buffering middleware replay the request using `retryExpression` } ``` - ```yaml tab="Rancher" - labels: - - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" - ``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/chain.md b/docs/content/middlewares/http/chain.md index f9768adfb..e7cbdc456 100644 --- a/docs/content/middlewares/http/chain.md +++ b/docs/content/middlewares/http/chain.md @@ -110,18 +110,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.routers.router1.service=service1" - - "traefik.http.routers.router1.middlewares=secured" - - "traefik.http.routers.router1.rule=Host(`mydomain`)" - - "traefik.http.middlewares.secured.chain.middlewares=https-only,known-ips,auth-users" - - "traefik.http.middlewares.auth-users.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" - - "traefik.http.middlewares.https-only.redirectscheme.scheme=https" - - "traefik.http.middlewares.known-ips.ipallowlist.sourceRange=192.168.1.7,127.0.0.1/32" - - "traefik.http.services.service1.loadbalancer.server.port=80" -``` - ```yaml tab="File (YAML)" # ... http: diff --git a/docs/content/middlewares/http/circuitbreaker.md b/docs/content/middlewares/http/circuitbreaker.md index 4399be1e1..21cd45fea 100644 --- a/docs/content/middlewares/http/circuitbreaker.md +++ b/docs/content/middlewares/http/circuitbreaker.md @@ -58,12 +58,6 @@ spec: } ``` -```yaml tab="Rancher" -# Latency Check -labels: - - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" -``` - ```yaml tab="File (YAML)" # Latency Check http: diff --git a/docs/content/middlewares/http/compress.md b/docs/content/middlewares/http/compress.md index 7e4b79613..90cb5c0be 100644 --- a/docs/content/middlewares/http/compress.md +++ b/docs/content/middlewares/http/compress.md @@ -42,12 +42,6 @@ spec: } ``` -```yaml tab="Rancher" -# Enable compression -labels: - - "traefik.http.middlewares.test-compress.compress=true" -``` - ```yaml tab="File (YAML)" # Enable compression http: @@ -120,11 +114,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -173,11 +162,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200" -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/contenttype.md b/docs/content/middlewares/http/contenttype.md index 38072958a..4770defa2 100644 --- a/docs/content/middlewares/http/contenttype.md +++ b/docs/content/middlewares/http/contenttype.md @@ -45,12 +45,6 @@ spec: } ``` -```yaml tab="Rancher" -# Enable auto-detection -labels: - - "traefik.http.middlewares.autodetect.contenttype=true" -``` - ```yaml tab="File (YAML)" # Enable auto-detection http: @@ -63,4 +57,4 @@ http: # Enable auto-detection [http.middlewares] [http.middlewares.autodetect.contentType] -``` \ No newline at end of file +``` diff --git a/docs/content/middlewares/http/digestauth.md b/docs/content/middlewares/http/digestauth.md index 14e3982b5..8a24f0580 100644 --- a/docs/content/middlewares/http/digestauth.md +++ b/docs/content/middlewares/http/digestauth.md @@ -42,12 +42,6 @@ spec: } ``` -```yaml tab="Rancher" -# Declaring the user list -labels: - - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" -``` - ```yaml tab="File (YAML)" # Declaring the user list http: @@ -120,11 +114,6 @@ data: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -192,11 +181,6 @@ data: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -247,11 +231,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -296,11 +275,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -345,11 +319,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.digestauth.removeheader=true" -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/errorpages.md b/docs/content/middlewares/http/errorpages.md index 81986d667..1fd537191 100644 --- a/docs/content/middlewares/http/errorpages.md +++ b/docs/content/middlewares/http/errorpages.md @@ -56,14 +56,6 @@ spec: } ``` -```yaml tab="Rancher" -# Dynamic Custom Error Page for 5XX Status Code -labels: - - "traefik.http.middlewares.test-errors.errors.status=500-599" - - "traefik.http.middlewares.test-errors.errors.service=serviceError" - - "traefik.http.middlewares.test-errors.errors.query=/{status}.html" -``` - ```yaml tab="File (YAML)" # Custom Error Page for 5XX http: diff --git a/docs/content/middlewares/http/forwardauth.md b/docs/content/middlewares/http/forwardauth.md index fdcff0321..64e64d60e 100644 --- a/docs/content/middlewares/http/forwardauth.md +++ b/docs/content/middlewares/http/forwardauth.md @@ -44,12 +44,6 @@ spec: } ``` -```yaml tab="Rancher" -# Forward authentication to example.com -labels: - - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" -``` - ```yaml tab="File (YAML)" # Forward authentication to example.com http: @@ -109,11 +103,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -158,11 +147,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -212,11 +196,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -268,11 +247,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -329,11 +303,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -403,11 +372,6 @@ data: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -474,12 +438,6 @@ data: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" - - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -552,12 +510,6 @@ data: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" - - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -615,11 +567,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true" -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/grpcweb.md b/docs/content/middlewares/http/grpcweb.md index d6d2c9a6b..ca5b50850 100644 --- a/docs/content/middlewares/http/grpcweb.md +++ b/docs/content/middlewares/http/grpcweb.md @@ -43,11 +43,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-grpcweb.grpcweb.alloworigins=*" -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/headers.md b/docs/content/middlewares/http/headers.md index a8532e6be..ab9474f57 100644 --- a/docs/content/middlewares/http/headers.md +++ b/docs/content/middlewares/http/headers.md @@ -51,12 +51,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" - - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -117,13 +111,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" - - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header=" - - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -180,11 +167,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.testheader.headers.framedeny=true" - - "traefik.http.middlewares.testheader.headers.browserxssfilter=true" -``` ```yaml tab="File (YAML)" http: @@ -251,14 +233,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" - - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org" - - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100" - - "traefik.http.middlewares.testheader.headers.addvaryheader=true" -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/inflightreq.md b/docs/content/middlewares/http/inflightreq.md index b3712b148..985a2ea11 100644 --- a/docs/content/middlewares/http/inflightreq.md +++ b/docs/content/middlewares/http/inflightreq.md @@ -40,12 +40,6 @@ spec: } ``` -```yaml tab="Rancher" -# Limiting to 10 simultaneous connections -labels: - - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" -``` - ```yaml tab="File (YAML)" # Limiting to 10 simultaneous connections http: @@ -95,12 +89,6 @@ spec: } ``` -```yaml tab="Rancher" -# Limiting to 10 simultaneous connections -labels: - - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" -``` - ```yaml tab="File (YAML)" # Limiting to 10 simultaneous connections http: @@ -171,11 +159,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -238,11 +221,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -292,11 +270,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -343,11 +316,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/ipallowlist.md b/docs/content/middlewares/http/ipallowlist.md index 56450d736..63701f773 100644 --- a/docs/content/middlewares/http/ipallowlist.md +++ b/docs/content/middlewares/http/ipallowlist.md @@ -41,12 +41,6 @@ spec: } ``` -```yaml tab="Rancher" -# Accepts request from defined IP -labels: - - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" -``` - ```yaml tab="File (YAML)" # Accepts request from defined IP http: @@ -127,13 +121,6 @@ spec: } ``` -```yaml tab="Rancher" -# Allowlisting Based on `X-Forwarded-For` with `depth=2` -labels: - - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" - - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" -``` - ```yaml tab="File (YAML)" # Allowlisting Based on `X-Forwarded-For` with `depth=2` http: @@ -203,12 +190,6 @@ spec: } ``` -```yaml tab="Rancher" -# Exclude from `X-Forwarded-For` -labels: - - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" -``` - ```yaml tab="File (YAML)" # Exclude from `X-Forwarded-For` http: diff --git a/docs/content/middlewares/http/overview.md b/docs/content/middlewares/http/overview.md index c4a9f9791..27277677c 100644 --- a/docs/content/middlewares/http/overview.md +++ b/docs/content/middlewares/http/overview.md @@ -76,15 +76,6 @@ spec: } ``` -```yaml tab="Rancher" -# As a Rancher Label -labels: - # Create a middleware named `foo-add-prefix` - - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo" - # Apply the middleware named `foo-add-prefix` to the router named `router1` - - "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher" -``` - ```toml tab="File (TOML)" # As TOML Configuration File [http.routers] diff --git a/docs/content/middlewares/http/passtlsclientcert.md b/docs/content/middlewares/http/passtlsclientcert.md index 28c5f7fff..f55982a90 100644 --- a/docs/content/middlewares/http/passtlsclientcert.md +++ b/docs/content/middlewares/http/passtlsclientcert.md @@ -45,12 +45,6 @@ spec: } ``` -```yaml tab="Rancher" -# Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. -labels: - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" -``` - ```yaml tab="File (YAML)" # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. http: @@ -169,29 +163,6 @@ http: } ``` - ```yaml tab="Rancher" - # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header - labels: - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province=true" - - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true" - ``` - ```yaml tab="File (YAML)" # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header http: diff --git a/docs/content/middlewares/http/ratelimit.md b/docs/content/middlewares/http/ratelimit.md index 8d62afd9c..2fb11f6ee 100644 --- a/docs/content/middlewares/http/ratelimit.md +++ b/docs/content/middlewares/http/ratelimit.md @@ -47,14 +47,6 @@ spec: } ``` -```yaml tab="Rancher" -# Here, an average of 100 requests per second is allowed. -# In addition, a burst of 50 requests is allowed. -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" - - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50" -``` - ```yaml tab="File (YAML)" # Here, an average of 100 requests per second is allowed. # In addition, a burst of 50 requests is allowed. @@ -114,11 +106,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" -``` - ```yaml tab="File (YAML)" # 100 reqs/s http: @@ -177,13 +164,6 @@ spec: } ``` -```yaml tab="Rancher" -# 6 reqs/minute -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.average=6" - - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m" -``` - ```yaml tab="File (YAML)" # 6 reqs/minute http: @@ -233,11 +213,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -306,11 +281,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -400,11 +370,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -454,11 +419,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -505,11 +465,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/redirectregex.md b/docs/content/middlewares/http/redirectregex.md index 97d2d83e6..74f0e3c23 100644 --- a/docs/content/middlewares/http/redirectregex.md +++ b/docs/content/middlewares/http/redirectregex.md @@ -50,14 +50,6 @@ spec: } ``` -```yaml tab="Rancher" -# Redirect with domain replacement -# Note: all dollar signs need to be doubled for escaping. -labels: - - "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^http://localhost/(.*)" - - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}" -``` - ```yaml tab="File (YAML)" # Redirect with domain replacement http: diff --git a/docs/content/middlewares/http/redirectscheme.md b/docs/content/middlewares/http/redirectscheme.md index 9c7a67ec1..841ec018b 100644 --- a/docs/content/middlewares/http/redirectscheme.md +++ b/docs/content/middlewares/http/redirectscheme.md @@ -58,13 +58,6 @@ labels: } ``` -```yaml tab="Rancher" -# Redirect to https -labels: - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -122,13 +115,6 @@ labels: } ``` -```yaml tab="Rancher" -# Redirect to https -labels: - # ... - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -180,12 +166,6 @@ labels: } ``` -```yaml tab="Rancher" -# Redirect to https -labels: - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -239,13 +219,6 @@ labels: } ``` -```yaml tab="Rancher" -# Redirect to https -labels: - # ... - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443" -``` - ```yaml tab="File (YAML)" # Redirect to https http: diff --git a/docs/content/middlewares/http/replacepath.md b/docs/content/middlewares/http/replacepath.md index 0617508e9..e4d138c2c 100644 --- a/docs/content/middlewares/http/replacepath.md +++ b/docs/content/middlewares/http/replacepath.md @@ -44,12 +44,6 @@ spec: } ``` -```yaml tab="Rancher" -# Replace the path with /foo -labels: - - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" -``` - ```yaml tab="File (YAML)" # Replace the path with /foo http: diff --git a/docs/content/middlewares/http/replacepathregex.md b/docs/content/middlewares/http/replacepathregex.md index b729a30ab..a2fd561bd 100644 --- a/docs/content/middlewares/http/replacepathregex.md +++ b/docs/content/middlewares/http/replacepathregex.md @@ -48,13 +48,6 @@ spec: } ``` -```yaml tab="Rancher" -# Replace path with regex -labels: - - "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex=^/foo/(.*)" - - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1" -``` - ```yaml tab="File (YAML)" # Replace path with regex http: diff --git a/docs/content/middlewares/http/retry.md b/docs/content/middlewares/http/retry.md index 956bdc498..2a3288eac 100644 --- a/docs/content/middlewares/http/retry.md +++ b/docs/content/middlewares/http/retry.md @@ -50,13 +50,6 @@ spec: } ``` -```yaml tab="Rancher" -# Retry 4 times with exponential backoff -labels: - - "traefik.http.middlewares.test-retry.retry.attempts=4" - - "traefik.http.middlewares.test-retry.retry.initialinterval=100ms" -``` - ```yaml tab="File (YAML)" # Retry 4 times with exponential backoff http: diff --git a/docs/content/middlewares/http/stripprefix.md b/docs/content/middlewares/http/stripprefix.md index afc20f2ac..f84735cb5 100644 --- a/docs/content/middlewares/http/stripprefix.md +++ b/docs/content/middlewares/http/stripprefix.md @@ -46,12 +46,6 @@ spec: } ``` -```yaml tab="Rancher" -# Strip prefix /foobar and /fiibar -labels: - - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" -``` - ```yaml tab="File (YAML)" # Strip prefix /foobar and /fiibar http: diff --git a/docs/content/middlewares/http/stripprefixregex.md b/docs/content/middlewares/http/stripprefixregex.md index d560a5d12..1a3ec09e6 100644 --- a/docs/content/middlewares/http/stripprefixregex.md +++ b/docs/content/middlewares/http/stripprefixregex.md @@ -38,11 +38,6 @@ spec: } ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/overview.md b/docs/content/middlewares/overview.md index 90748ef6c..09e17278e 100644 --- a/docs/content/middlewares/overview.md +++ b/docs/content/middlewares/overview.md @@ -73,15 +73,6 @@ spec: } ``` -```yaml tab="Rancher" -# As a Rancher Label -labels: - # Create a middleware named `foo-add-prefix` - - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo" - # Apply the middleware named `foo-add-prefix` to the router named `router1` - - "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher" -``` - ```yaml tab="File (YAML)" # As YAML Configuration File http: diff --git a/docs/content/middlewares/tcp/inflightconn.md b/docs/content/middlewares/tcp/inflightconn.md index 036ca74e1..2550181df 100644 --- a/docs/content/middlewares/tcp/inflightconn.md +++ b/docs/content/middlewares/tcp/inflightconn.md @@ -33,12 +33,6 @@ spec: } ``` -```yaml tab="Rancher" -# Limiting to 10 simultaneous connections. -labels: - - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" -``` - ```yaml tab="File (YAML)" # Limiting to 10 simultaneous connections. tcp: diff --git a/docs/content/middlewares/tcp/ipallowlist.md b/docs/content/middlewares/tcp/ipallowlist.md index 2cc51fd57..25730eb1e 100644 --- a/docs/content/middlewares/tcp/ipallowlist.md +++ b/docs/content/middlewares/tcp/ipallowlist.md @@ -41,12 +41,6 @@ spec: } ``` -```yaml tab="Rancher" -# Accepts request from defined IP -labels: - - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" -``` - ```toml tab="File (TOML)" # Accepts request from defined IP [tcp.middlewares] diff --git a/docs/content/middlewares/tcp/overview.md b/docs/content/middlewares/tcp/overview.md index cc1302530..8fde185e9 100644 --- a/docs/content/middlewares/tcp/overview.md +++ b/docs/content/middlewares/tcp/overview.md @@ -77,15 +77,6 @@ spec: } ``` -```yaml tab="Rancher" -# As a Rancher Label -labels: - # Create a middleware named `foo-ip-allowlist` - - "traefik.tcp.middlewares.foo-ip-allowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" - # Apply the middleware named `foo-ip-allowlist` to the router named `router1` - - "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@rancher" -``` - ```toml tab="File (TOML)" # As TOML Configuration File [tcp.routers] diff --git a/docs/content/migration/v2-to-v3.md b/docs/content/migration/v2-to-v3.md index b8f600d54..e729d69b3 100644 --- a/docs/content/migration/v2-to-v3.md +++ b/docs/content/migration/v2-to-v3.md @@ -65,3 +65,10 @@ When using the KubernetesCRD provider, it is therefore necessary to update [RBAC The TCP LoadBalancer `terminationDelay` option has been removed. This option can now be configured directly on the `TCPServersTransport` level, please take a look at this [documentation](../routing/services/index.md#terminationdelay) + +## Rancher v1 + +In v3, the rancher v1 provider has been removed because Rancher v1 is [no longer actively maintaned](https://rancher.com/docs/os/v1.x/en/support/) and v2 is supported as a standard Kubernetes provider. + +Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. +As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](../providers/kubernetes-crd.md) directly. diff --git a/docs/content/operations/include-api-examples.md b/docs/content/operations/include-api-examples.md index 33fc71a09..12ef27edb 100644 --- a/docs/content/operations/include-api-examples.md +++ b/docs/content/operations/include-api-examples.md @@ -60,15 +60,6 @@ spec: } ``` -```yaml tab="Rancher" -# Dynamic Configuration -labels: - - "traefik.http.routers.api.rule=Host(`traefik.example.com`)" - - "traefik.http.routers.api.service=api@internal" - - "traefik.http.routers.api.middlewares=auth" - - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" -``` - ```yaml tab="File (YAML)" # Dynamic Configuration http: diff --git a/docs/content/operations/include-dashboard-examples.md b/docs/content/operations/include-dashboard-examples.md index eb72d3a0a..da8d0d8ae 100644 --- a/docs/content/operations/include-dashboard-examples.md +++ b/docs/content/operations/include-dashboard-examples.md @@ -60,15 +60,6 @@ spec: } ``` -```yaml tab="Rancher" -# Dynamic Configuration -labels: - - "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" - - "traefik.http.routers.dashboard.service=api@internal" - - "traefik.http.routers.dashboard.middlewares=auth" - - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" -``` - ```yaml tab="File (YAML)" # Dynamic Configuration http: diff --git a/docs/content/providers/overview.md b/docs/content/providers/overview.md index de0af45fe..9589ce21d 100644 --- a/docs/content/providers/overview.md +++ b/docs/content/providers/overview.md @@ -142,7 +142,6 @@ Below is the list of the currently supported providers in Traefik. | [Nomad](./nomad.md) | Orchestrator | Label | `nomad` | | [ECS](./ecs.md) | Orchestrator | Label | `ecs` | | [Marathon](./marathon.md) | Orchestrator | Label | `marathon` | -| [Rancher](./rancher.md) | Orchestrator | Label | `rancher` | | [File](./file.md) | Manual | YAML/TOML format | `file` | | [Consul](./consul.md) | KV | KV | `consul` | | [Etcd](./etcd.md) | KV | KV | `etcd` | @@ -216,7 +215,6 @@ List of providers that support these features: - [ECS](./ecs.md#exposedbydefault) - [Consul Catalog](./consul-catalog.md#exposedbydefault) - [Nomad](./nomad.md#exposedbydefault) -- [Rancher](./rancher.md#exposedbydefault) - [Marathon](./marathon.md#exposedbydefault) ### Constraints @@ -227,7 +225,6 @@ List of providers that support constraints: - [ECS](./ecs.md#constraints) - [Consul Catalog](./consul-catalog.md#constraints) - [Nomad](./nomad.md#constraints) -- [Rancher](./rancher.md#constraints) - [Marathon](./marathon.md#constraints) - [Kubernetes CRD](./kubernetes-crd.md#labelselector) - [Kubernetes Ingress](./kubernetes-ingress.md#labelselector) diff --git a/docs/content/providers/rancher.md b/docs/content/providers/rancher.md deleted file mode 100644 index b709a5329..000000000 --- a/docs/content/providers/rancher.md +++ /dev/null @@ -1,286 +0,0 @@ ---- -title: ""Traefik Configuration Discovery: Rancher"" -description: "Read the official Traefik documentation to learn how to expose Rancher services by default in Traefik Proxy." ---- - -# Traefik & Rancher - -A Story of Labels, Services & Containers -{: .subtitle } - -![Rancher](../assets/img/providers/rancher.png) - -Attach labels to your services and let Traefik do the rest! - -!!! important "This provider is specific to Rancher 1.x." - - Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. - As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](./kubernetes-crd.md) directly. - -## Configuration Examples - -??? example "Configuring Rancher & Deploying / Exposing Services" - - Enabling the Rancher provider - - ```yaml tab="File (YAML)" - providers: - rancher: {} - ``` - - ```toml tab="File (TOML)" - [providers.rancher] - ``` - - ```bash tab="CLI" - --providers.rancher=true - ``` - - Attaching labels to services - - ```yaml - labels: - - traefik.http.services.my-service.rule=Host(`example.com`) - ``` - -## Routing Configuration - -See the dedicated section in [routing](../routing/providers/rancher.md). - -## Provider Configuration - -??? tip "Browse the Reference" - - For an overview of all the options that can be set with the Rancher provider, see the following snippets: - - ```yaml tab="File (YAML)" - --8<-- "content/providers/rancher.yml" - ``` - - ```toml tab="File (TOML)" - --8<-- "content/providers/rancher.toml" - ``` - - ```bash tab="CLI" - --8<-- "content/providers/rancher.txt" - ``` - -### `exposedByDefault` - -_Optional, Default=true_ - -Expose Rancher services by default in Traefik. -If set to `false`, services that do not have a `traefik.enable=true` label are ignored from the resulting routing configuration. - -For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). - -```yaml tab="File (YAML)" -providers: - rancher: - exposedByDefault: false - # ... -``` - -```toml tab="File (TOML)" -[providers.rancher] - exposedByDefault = false - # ... -``` - -```bash tab="CLI" ---providers.rancher.exposedByDefault=false -# ... -``` - -### `defaultRule` - -_Optional, Default=```Host(`{{ normalize .Name }}`)```_ - -The default host rule for all services. - -The `defaultRule` option defines what routing rule to apply to a container if no rule is defined by a label. - -It must be a valid [Go template](https://pkg.go.dev/text/template/), and can use -[sprig template functions](https://masterminds.github.io/sprig/). -The service name can be accessed with the `Name` identifier, -and the template has access to all the labels defined on this container. - -This option can be overridden on a container basis with the `traefik.http.routers.Router1.rule` label. - -```yaml tab="File (YAML)" -providers: - rancher: - defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" - # ... -``` - -```toml tab="File (TOML)" -[providers.rancher] - defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" - # ... -``` - -```bash tab="CLI" ---providers.rancher.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`) -# ... -``` - -### `enableServiceHealthFilter` - -_Optional, Default=true_ - -Filter out services with unhealthy states and inactive states. - -```yaml tab="File (YAML)" -providers: - rancher: - enableServiceHealthFilter: false - # ... -``` - -```toml tab="File (TOML)" -[providers.rancher] - enableServiceHealthFilter = false - # ... -``` - -```bash tab="CLI" ---providers.rancher.enableServiceHealthFilter=false -# ... -``` - -### `refreshSeconds` - -_Optional, Default=15_ - -Defines the polling interval (in seconds). - -```yaml tab="File (YAML)" -providers: - rancher: - refreshSeconds: 30 - # ... -``` - -```toml tab="File (TOML)" -[providers.rancher] - refreshSeconds = 30 - # ... -``` - -```bash tab="CLI" ---providers.rancher.refreshSeconds=30 -# ... -``` - -### `intervalPoll` - -_Optional, Default=false_ - -Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, -which is less accurate than the default long polling technique which provides near instantaneous updates to Traefik. - -```yaml tab="File (YAML)" -providers: - rancher: - intervalPoll: true - # ... -``` - -```toml tab="File (TOML)" -[providers.rancher] - intervalPoll = true - # ... -``` - -```bash tab="CLI" ---providers.rancher.intervalPoll=true -# ... -``` - -### `prefix` - -_Optional, Default="/latest"_ - -Prefix used for accessing the Rancher metadata service. - -```yaml tab="File (YAML)" -providers: - rancher: - prefix: "/test" - # ... -``` - -```toml tab="File (TOML)" -[providers.rancher] - prefix = "/test" - # ... -``` - -```bash tab="CLI" ---providers.rancher.prefix=/test -# ... -``` - -### `constraints` - -_Optional, Default=""_ - -The `constraints` option can be set to an expression that Traefik matches against the container labels to determine whether -to create any route for that container. If none of the container tags match the expression, no route for that container is -created. If the expression is empty, all detected containers are included. - -The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as -the usual boolean logic, as shown in examples below. - -??? example "Constraints Expression Examples" - - ```toml - # Includes only containers having a label with key `a.label.name` and value `foo` - constraints = "Label(`a.label.name`, `foo`)" - ``` - - ```toml - # Excludes containers having any label with key `a.label.name` and value `foo` - constraints = "!Label(`a.label.name`, `value`)" - ``` - - ```toml - # With logical AND. - constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)" - ``` - - ```toml - # With logical OR. - constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)" - ``` - - ```toml - # With logical AND and OR, with precedence set by parentheses. - constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))" - ``` - - ```toml - # Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression. - constraints = "LabelRegex(`a.label.name`, `a.+`)" - ``` - -For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). - -```yaml tab="File (YAML)" -providers: - rancher: - constraints: "Label(`a.label.name`,`foo`)" - # ... -``` - -```toml tab="File (TOML)" -[providers.rancher] - constraints = "Label(`a.label.name`,`foo`)" - # ... -``` - -```bash tab="CLI" ---providers.rancher.constraints=Label(`a.label.name`,`foo`) -# ... -``` diff --git a/docs/content/providers/rancher.toml b/docs/content/providers/rancher.toml deleted file mode 100644 index e809d737d..000000000 --- a/docs/content/providers/rancher.toml +++ /dev/null @@ -1,20 +0,0 @@ -# Enable Rancher Provider. -[providers.rancher] - - # Expose Rancher services by default in Traefik. - exposedByDefault = true - - # Enable watch Rancher changes. - watch = true - - # Filter services with unhealthy states and inactive states. - enableServiceHealthFilter = true - - # Defines the polling interval (in seconds). - refreshSeconds = 15 - - # Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, which is less accurate - intervalPoll = false - - # Prefix used for accessing the Rancher metadata service - prefix = "/latest" diff --git a/docs/content/providers/rancher.txt b/docs/content/providers/rancher.txt deleted file mode 100644 index 158826cda..000000000 --- a/docs/content/providers/rancher.txt +++ /dev/null @@ -1,20 +0,0 @@ -# Enable Rancher Provider. ---providers.rancher=true - -# Expose Rancher services by default in Traefik. ---providers.rancher.exposedByDefault=true - -# Enable watch Rancher changes. ---providers.rancher.watch=true - -# Filter services with unhealthy states and inactive states. ---providers.rancher.enableServiceHealthFilter=true - -# Defines the polling interval (in seconds). ---providers.rancher.refreshSeconds=15 - -# Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, which is less accurate ---providers.rancher.intervalPoll=false - -# Prefix used for accessing the Rancher metadata service ---providers.rancher.prefix=/latest diff --git a/docs/content/providers/rancher.yml b/docs/content/providers/rancher.yml deleted file mode 100644 index 227b352c3..000000000 --- a/docs/content/providers/rancher.yml +++ /dev/null @@ -1,21 +0,0 @@ -# Enable Rancher Provider. -providers: - rancher: - - # Expose Rancher services by default in Traefik. - exposedByDefault: true - - # Enable watch Rancher changes. - watch: true - - # Filter services with unhealthy states and inactive states. - enableServiceHealthFilter: true - - # Defines the polling interval (in seconds). - refreshSeconds: 15 - - # Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, which is less accurate - intervalPoll: false - - # Prefix used for accessing the Rancher metadata service - prefix: /latest diff --git a/docs/content/reference/dynamic-configuration/rancher.md b/docs/content/reference/dynamic-configuration/rancher.md deleted file mode 100644 index c2762999d..000000000 --- a/docs/content/reference/dynamic-configuration/rancher.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "Traefik Dynamic Configuration with Rancher" -description: "Read the official Traefik documentation to learn more on dynamic configuration in Traefik Proxy with Rancher Labels." ---- - -# Rancher Configuration Reference - -Dynamic configuration with Rancher Labels -{: .subtitle } - -The labels are case insensitive. - -```yaml -labels: - --8<-- "content/reference/dynamic-configuration/rancher.yml" - --8<-- "content/reference/dynamic-configuration/docker-labels.yml" -``` diff --git a/docs/content/reference/dynamic-configuration/rancher.yml b/docs/content/reference/dynamic-configuration/rancher.yml deleted file mode 100644 index 23efc00c6..000000000 --- a/docs/content/reference/dynamic-configuration/rancher.yml +++ /dev/null @@ -1 +0,0 @@ -- "traefik.enable=true" diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 3a200ac6b..773f07829 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -912,33 +912,6 @@ Plugins configuration. `--providers.providersthrottleduration`: Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time. (Default: ```2```) -`--providers.rancher`: -Enable Rancher backend with default settings. (Default: ```false```) - -`--providers.rancher.constraints`: -Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container. - -`--providers.rancher.defaultrule`: -Default rule. (Default: ```Host(`{{ normalize .Name }}`)```) - -`--providers.rancher.enableservicehealthfilter`: -Filter services with unhealthy states and inactive states. (Default: ```true```) - -`--providers.rancher.exposedbydefault`: -Expose containers by default. (Default: ```true```) - -`--providers.rancher.intervalpoll`: -Poll the Rancher metadata service every 'rancher.refreshseconds' (less accurate). (Default: ```false```) - -`--providers.rancher.prefix`: -Prefix used for accessing the Rancher metadata service. (Default: ```latest```) - -`--providers.rancher.refreshseconds`: -Defines the polling interval in seconds. (Default: ```15```) - -`--providers.rancher.watch`: -Watch provider. (Default: ```true```) - `--providers.redis`: Enable Redis backend with default settings. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 0e28c8313..38f8bcba9 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -912,33 +912,6 @@ Plugins configuration. `TRAEFIK_PROVIDERS_PROVIDERSTHROTTLEDURATION`: Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time. (Default: ```2```) -`TRAEFIK_PROVIDERS_RANCHER`: -Enable Rancher backend with default settings. (Default: ```false```) - -`TRAEFIK_PROVIDERS_RANCHER_CONSTRAINTS`: -Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container. - -`TRAEFIK_PROVIDERS_RANCHER_DEFAULTRULE`: -Default rule. (Default: ```Host(`{{ normalize .Name }}`)```) - -`TRAEFIK_PROVIDERS_RANCHER_ENABLESERVICEHEALTHFILTER`: -Filter services with unhealthy states and inactive states. (Default: ```true```) - -`TRAEFIK_PROVIDERS_RANCHER_EXPOSEDBYDEFAULT`: -Expose containers by default. (Default: ```true```) - -`TRAEFIK_PROVIDERS_RANCHER_INTERVALPOLL`: -Poll the Rancher metadata service every 'rancher.refreshseconds' (less accurate). (Default: ```false```) - -`TRAEFIK_PROVIDERS_RANCHER_PREFIX`: -Prefix used for accessing the Rancher metadata service. (Default: ```latest```) - -`TRAEFIK_PROVIDERS_RANCHER_REFRESHSECONDS`: -Defines the polling interval in seconds. (Default: ```15```) - -`TRAEFIK_PROVIDERS_RANCHER_WATCH`: -Watch provider. (Default: ```true```) - `TRAEFIK_PROVIDERS_REDIS`: Enable Redis backend with default settings. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index cce2f600f..8e634d9cf 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -154,15 +154,6 @@ throttleDuration = "42s" [providers.rest] insecure = true - [providers.rancher] - constraints = "foobar" - watch = true - defaultRule = "foobar" - exposedByDefault = true - enableServiceHealthFilter = true - refreshSeconds = 42 - intervalPoll = true - prefix = "foobar" [providers.consulCatalog] constraints = "foobar" prefix = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index ee7eb4ff3..32116d797 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -167,15 +167,6 @@ providers: throttleDuration: 42s rest: insecure: true - rancher: - constraints: foobar - watch: true - defaultRule: foobar - exposedByDefault: true - enableServiceHealthFilter: true - refreshSeconds: 42 - intervalPoll: true - prefix: foobar consulCatalog: constraints: foobar prefix: foobar diff --git a/docs/content/routing/providers/rancher.md b/docs/content/routing/providers/rancher.md deleted file mode 100644 index 5e711ed5e..000000000 --- a/docs/content/routing/providers/rancher.md +++ /dev/null @@ -1,545 +0,0 @@ ---- -title: "Routing & Load Balancing Providers: Rancher" -description: "Traefik Proxy creates a corresponding service and router for each Rancher Service. Read the full documentation to learn more." ---- - -# Traefik & Rancher - -A Story of Labels, Services & Containers -{: .subtitle } - -![Rancher](../../assets/img/providers/rancher.png) - -Attach labels to your services and let Traefik do the rest! - -!!! important "This provider is specific to Rancher 1.x." - - Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. - As such, Rancher 2.x users should utilize the [Kubernetes provider](./kubernetes-crd.md) directly. - -## Routing Configuration - -!!! info "Labels" - - - Labels are case insensitive. - - The complete list of labels can be found in [the reference page](../../reference/dynamic-configuration/rancher.md). - -### General - -Traefik creates, for each rancher service, a corresponding [service](../services/index.md) and [router](../routers/index.md). - -The Service automatically gets a server per container in this rancher service, and the router gets a default rule attached to it, based on the service name. - -#### Service definition - ---8<-- "content/routing/providers/service-by-label.md" - -??? example "Automatic service assignment with labels" - - With labels in a compose file - - ```yaml - labels: - - "traefik.http.routers.myproxy.rule=Host(`example.net`)" - # service myservice gets automatically assigned to router myproxy - - "traefik.http.services.myservice.loadbalancer.server.port=80" - ``` - -??? example "Automatic service creation and assignment with labels" - - With labels in a compose file - - ```yaml - labels: - # no service specified or defined and yet one gets automatically created - # and assigned to router myproxy. - - "traefik.http.routers.myproxy.rule=Host(`example.net`)" - ``` - -### Routers - -To update the configuration of the Router automatically attached to the container, add labels starting with `traefik.routers.{name-of-your-choice}.` and followed by the option you want to change. - -For example, to change the rule, you could add the label ```traefik.http.routers.my-container.rule=Host(`example.com`)```. - -!!! warning "The character `@` is not authorized in the router name ``." - -??? info "`traefik.http.routers..rule`" - - See [rule](../routers/index.md#rule) for more information. - - ```yaml - - "traefik.http.routers.myrouter.rule=Host(`example.com`)" - ``` - -??? info "`traefik.http.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints) for more information. - - ```yaml - - "traefik.http.routers.myrouter.entrypoints=ep1,ep2" - ``` - -??? info "`traefik.http.routers..middlewares`" - - See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information. - - ```yaml - - "traefik.http.routers.myrouter.middlewares=auth,prefix,cb" - ``` - -??? info "`traefik.http.routers..service`" - - See [rule](../routers/index.md#service) for more information. - - ```yaml - - "traefik.http.routers.myrouter.service=myservice" - ``` - -??? info "`traefik.http.routers..tls`" - - See [tls](../routers/index.md#tls) for more information. - - ```yaml - - "traefik.http.routers.myrouter>.tls=true" - ``` - -??? info "`traefik.http.routers..tls.certresolver`" - - See [certResolver](../routers/index.md#certresolver) for more information. - - ```yaml - - "traefik.http.routers.myrouter.tls.certresolver=myresolver" - ``` - -??? info "`traefik.http.routers..tls.domains[n].main`" - - See [domains](../routers/index.md#domains) for more information. - - ```yaml - - "traefik.http.routers.myrouter.tls.domains[0].main=example.org" - ``` - -??? info "`traefik.http.routers..tls.domains[n].sans`" - - See [domains](../routers/index.md#domains) for more information. - - ```yaml - - "traefik.http.routers.myrouter.tls.domains[0].sans=test.example.org,dev.example.org" - ``` - -??? info "`traefik.http.routers..tls.options`" - - See [options](../routers/index.md#options) for more information. - - ```yaml - - "traefik.http.routers.myrouter.tls.options=foobar" - ``` - -??? info "`traefik.http.routers..priority`" - - See [priority](../routers/index.md#priority) for more information. - - ```yaml - - "traefik.http.routers.myrouter.priority=42" - ``` - -### Services - -To update the configuration of the Service automatically attached to the container, -add labels starting with `traefik.http.services.{name-of-your-choice}.`, followed by the option you want to change. - -For example, to change the `passHostHeader` behavior, -you'd add the label `traefik.http.services.{name-of-your-choice}.loadbalancer.passhostheader=false`. - -!!! warning "The character `@` is not authorized in the service name ``." - -??? info "`traefik.http.services..loadbalancer.server.port`" - - Registers a port. - Useful when the container exposes multiples ports. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.server.port=8080" - ``` - -??? info "`traefik.http.services..loadbalancer.server.scheme`" - - Overrides the default scheme. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.server.scheme=http" - ``` - -??? info "`traefik.http.services..loadbalancer.serverstransport`" - - Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. - See [serverstransport](../services/index.md#serverstransport) for more information. - - ```yaml - - "traefik.http.services..loadbalancer.serverstransport=foobar@file" - ``` - -??? info "`traefik.http.services..loadbalancer.passhostheader`" - - See [pass Host header](../services/index.md#pass-host-header) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.passhostheader=true" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.headers.`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.headers.X-Foo=foobar" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.hostname`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.hostname=example.org" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.interval`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.interval=10s" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.path`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.path=/foo" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.method`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.method=foobar" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.status`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.status=42" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.port`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.port=42" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.scheme`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.scheme=http" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.timeout`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.timeout=10" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.followredirects`" - - See [health check](../services/index.md#health-check) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.healthcheck.followredirects=true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.sticky.cookie=true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.httponly`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.sticky.cookie.httponly=true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.name`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.secure`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.sticky.cookie.secure=true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.samesite`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none" - ``` - -??? info "`traefik.http.services..loadbalancer.responseforwarding.flushinterval`" - - See [response forwarding](../services/index.md#response-forwarding) for more information. - - ```yaml - - "traefik.http.services.myservice.loadbalancer.responseforwarding.flushinterval=10" - ``` - -### Middleware - -You can declare pieces of middleware using labels starting with `traefik.http.middlewares.{name-of-your-choice}.`, followed by the middleware type/options. - -For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme: https`. - -More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). - -!!! warning "The character `@` is not authorized in the middleware name." - -??? example "Declaring and Referencing a Middleware" - - ```yaml - # ... - labels: - # Declaring a middleware - - traefik.http.middlewares.my-redirect.redirectscheme.scheme=https - # Referencing a middleware - - traefik.http.routers.my-container.middlewares=my-redirect - ``` - -!!! warning "Conflicts in Declaration" - - If you declare multiple middleware with the same name but with different parameters, the middleware fails to be declared. - -### TCP - -You can declare TCP Routers and/or Services using labels. - -??? example "Declaring TCP Routers and Services" - - ```yaml - services: - my-container: - # ... - labels: - - "traefik.tcp.routers.my-router.rule=HostSNI(`example.com`)" - - "traefik.tcp.routers.my-router.tls=true" - - "traefik.tcp.services.my-service.loadbalancer.server.port=4123" - ``` - -!!! warning "TCP and HTTP" - - If you declare a TCP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no TCP Router/Service is defined). - You can declare both a TCP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually). - -#### TCP Routers - -??? info "`traefik.tcp.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints_1) for more information. - - ```yaml - - "traefik.tcp.routers.mytcprouter.entrypoints=ep1,ep2" - ``` - -??? info "`traefik.tcp.routers..rule`" - - See [rule](../routers/index.md#rule_1) for more information. - - ```yaml - - "traefik.tcp.routers.mytcprouter.rule=HostSNI(`example.com`)" - ``` - -??? info "`traefik.tcp.routers..service`" - - See [service](../routers/index.md#services) for more information. - - ```yaml - - "traefik.tcp.routers.mytcprouter.service=myservice" - ``` - -??? info "`traefik.tcp.routers..tls`" - - See [TLS](../routers/index.md#tls_1) for more information. - - ```yaml - - "traefik.tcp.routers.mytcprouter.tls=true" - ``` - -??? info "`traefik.tcp.routers..tls.certresolver`" - - See [certResolver](../routers/index.md#certresolver_1) for more information. - - ```yaml - - "traefik.tcp.routers.mytcprouter.tls.certresolver=myresolver" - ``` - -??? info "`traefik.tcp.routers..tls.domains[n].main`" - - See [domains](../routers/index.md#domains_1) for more information. - - ```yaml - - "traefik.tcp.routers.mytcprouter.tls.domains[0].main=example.org" - ``` - -??? info "`traefik.tcp.routers..tls.domains[n].sans`" - - See [domains](../routers/index.md#domains_1) for more information. - - ```yaml - - "traefik.tcp.routers.mytcprouter.tls.domains[0].sans=test.example.org,dev.example.org" - ``` - -??? info "`traefik.tcp.routers..tls.options`" - - See [options](../routers/index.md#options_1) for more information. - - ```yaml - - "traefik.tcp.routers.mytcprouter.tls.options=mysoptions" - ``` - -??? info "`traefik.tcp.routers..tls.passthrough`" - - See [TLS](../routers/index.md#tls_1) for more information. - - ```yaml - - "traefik.tcp.routers.mytcprouter.tls.passthrough=true" - ``` - -??? info "`traefik.tcp.routers..priority`" - - See [priority](../routers/index.md#priority_1) for more information. - - ```yaml - - "traefik.tcp.routers.myrouter.priority=42" - ``` - -#### TCP Services - -??? info "`traefik.tcp.services..loadbalancer.server.port`" - - Registers a port of the application. - - ```yaml - - "traefik.tcp.services.mytcpservice.loadbalancer.server.port=423" - ``` - -??? info "`traefik.tcp.services..loadbalancer.server.tls`" - - Determines whether to use TLS when dialing with the backend. - - ```yaml - - "traefik.tcp.services.mytcpservice.loadbalancer.server.tls=true" - ``` - -??? info "`traefik.tcp.services..loadbalancer.proxyprotocol.version`" - - See [PROXY protocol](../services/index.md#proxy-protocol) for more information. - - ```yaml - - "traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version=1" - ``` - -??? info "`traefik.tcp.services..loadbalancer.serverstransport`" - - Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. - See [serverstransport](../services/index.md#serverstransport_2) for more information. - - ```yaml - - "traefik.tcp.services..loadbalancer.serverstransport=foobar@file" - ``` - -### UDP - -You can declare UDP Routers and/or Services using labels. - -??? example "Declaring UDP Routers and Services" - - ```yaml - services: - my-container: - # ... - labels: - - "traefik.udp.routers.my-router.entrypoints=udp" - - "traefik.udp.services.my-service.loadbalancer.server.port=4123" - ``` - -!!! warning "UDP and HTTP" - - If you declare a UDP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no UDP Router/Service is defined). - You can declare both a UDP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually). - -#### UDP Routers - -??? info "`traefik.udp.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints_2) for more information. - - ```yaml - - "traefik.udp.routers.myudprouter.entrypoints=ep1,ep2" - ``` - -??? info "`traefik.udp.routers..service`" - - See [service](../routers/index.md#services_1) for more information. - - ```yaml - - "traefik.udp.routers.myudprouter.service=myservice" - ``` - -#### UDP Services - -??? info "`traefik.udp.services..loadbalancer.server.port`" - - Registers a port of the application. - - ```yaml - - "traefik.udp.services.myudpservice.loadbalancer.server.port=423" - ``` - -### Specific Provider Options - -#### `traefik.enable` - -```yaml -- "traefik.enable=true" -``` - -You can tell Traefik to consider (or not) the container by setting `traefik.enable` to true or false. - -This option overrides the value of `exposedByDefault`. - -#### Port Lookup - -Traefik is capable of detecting the port to use, by following the default rancher flow. -That means, if you just expose lets say port `:1337` on the rancher ui, traefik will pick up this port and use it. diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index 51328317b..7253eb24f 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -557,7 +557,7 @@ which is basically where the request will be passed along to. In general, a service assigned to a router should have been defined, but there are exceptions for label-based providers. -See the specific [docker](../providers/docker.md#service-definition), [rancher](../providers/rancher.md#service-definition), +See the specific [docker](../providers/docker.md#service-definition), or [marathon](../providers/marathon.md#service-definition) documentation. !!! warning "The character `@` is not authorized in the service name." diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 91b163347..d45f42498 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -82,7 +82,6 @@ nav: - 'Nomad': 'providers/nomad.md' - 'ECS': 'providers/ecs.md' - 'Marathon': 'providers/marathon.md' - - 'Rancher': 'providers/rancher.md' - 'File': 'providers/file.md' - 'Consul': 'providers/consul.md' - 'Etcd': 'providers/etcd.md' @@ -103,7 +102,6 @@ nav: - 'Nomad': 'routing/providers/nomad.md' - 'ECS': 'routing/providers/ecs.md' - 'Marathon': 'routing/providers/marathon.md' - - 'Rancher': 'routing/providers/rancher.md' - 'KV': 'routing/providers/kv.md' - 'HTTPS & TLS': - 'Overview': 'https/overview.md' @@ -209,7 +207,6 @@ nav: - 'ECS': 'reference/dynamic-configuration/ecs.md' - 'KV': 'reference/dynamic-configuration/kv.md' - 'Marathon': 'reference/dynamic-configuration/marathon.md' - - 'Rancher': 'reference/dynamic-configuration/rancher.md' - 'Deprecation Notices': - 'Releases': 'deprecation/releases.md' - 'Features': 'deprecation/features.md' diff --git a/go.mod b/go.mod index 520be5f38..1ddd41337 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.12.2-0.20220704083116-e8f91604d835 github.com/prometheus/client_model v0.2.0 - github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac github.com/rs/zerolog v1.28.0 github.com/sirupsen/logrus v1.9.0 github.com/spiffe/go-spiffe/v2 v2.1.1 diff --git a/go.sum b/go.sum index 915832e96..11aa3b6de 100644 --- a/go.sum +++ b/go.sum @@ -1663,8 +1663,6 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/qri-io/jsonpointer v0.1.0/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64= github.com/qri-io/jsonschema v0.1.1/go.mod h1:QpzJ6gBQ0GYgGmh7mDQ1YsvvhSgE4rYj0k8t5MBOmUY= -github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac h1:wBGhHdXKICZmvAPWS8gQoMyOWDH7QAi9bU4Z1nDWnFU= -github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac/go.mod h1:67sLWL17mVlO1HFROaTBmU71NB4R8UNCesFHhg0f6LQ= github.com/rboyer/safeio v0.2.1/go.mod h1:Cq/cEPK+YXFn622lsQ0K4KsPZSPtaptHHEldsy7Fmig= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= diff --git a/pkg/api/handler_overview_test.go b/pkg/api/handler_overview_test.go index b7f96c6b9..92584b9f8 100644 --- a/pkg/api/handler_overview_test.go +++ b/pkg/api/handler_overview_test.go @@ -19,7 +19,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/ingress" "github.com/traefik/traefik/v2/pkg/provider/marathon" - "github.com/traefik/traefik/v2/pkg/provider/rancher" "github.com/traefik/traefik/v2/pkg/provider/rest" "github.com/traefik/traefik/v2/pkg/tracing/jaeger" "github.com/traefik/traefik/v2/pkg/types" @@ -242,7 +241,6 @@ func TestHandler_Overview(t *testing.T) { KubernetesIngress: &ingress.Provider{}, KubernetesCRD: &crd.Provider{}, Rest: &rest.Provider{}, - Rancher: &rancher.Provider{}, Plugin: map[string]static.PluginConf{ "test": map[string]interface{}{}, }, diff --git a/pkg/api/testdata/overview-providers.json b/pkg/api/testdata/overview-providers.json index 95d4d10d2..29d9ce9a7 100644 --- a/pkg/api/testdata/overview-providers.json +++ b/pkg/api/testdata/overview-providers.json @@ -29,7 +29,6 @@ "KubernetesIngress", "KubernetesCRD", "Rest", - "Rancher", "plugin-test" ], "tcp": { diff --git a/pkg/config/dynamic/fixtures/sample.toml b/pkg/config/dynamic/fixtures/sample.toml index 6f5137f4c..b823c67ca 100644 --- a/pkg/config/dynamic/fixtures/sample.toml +++ b/pkg/config/dynamic/fixtures/sample.toml @@ -96,15 +96,6 @@ ingressClass = "foobar" [providers.rest] entryPoint = "foobar" - [providers.rancher] - constraints = "foobar" - watch = true - defaultRule = "foobar" - exposedByDefault = true - enableServiceHealthFilter = true - refreshSeconds = 42 - intervalPoll = true - prefix = "foobar" [api] entryPoint = "foobar" diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index eba224bd1..4085bfe31 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -27,7 +27,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/kv/zk" "github.com/traefik/traefik/v2/pkg/provider/marathon" "github.com/traefik/traefik/v2/pkg/provider/nomad" - "github.com/traefik/traefik/v2/pkg/provider/rancher" "github.com/traefik/traefik/v2/pkg/provider/rest" "github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/tracing/datadog" @@ -219,7 +218,6 @@ type Providers struct { KubernetesCRD *crd.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesCRD,omitempty" toml:"kubernetesCRD,omitempty" yaml:"kubernetesCRD,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesGateway *gateway.Provider `description:"Enable Kubernetes gateway api provider with default settings." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Rest *rest.Provider `description:"Enable Rest backend with default settings." json:"rest,omitempty" toml:"rest,omitempty" yaml:"rest,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` - Rancher *rancher.Provider `description:"Enable Rancher backend with default settings." json:"rancher,omitempty" toml:"rancher,omitempty" yaml:"rancher,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` ConsulCatalog *consulcatalog.ProviderBuilder `description:"Enable ConsulCatalog backend with default settings." json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` Nomad *nomad.ProviderBuilder `description:"Enable Nomad backend with default settings." json:"nomad,omitempty" toml:"nomad,omitempty" yaml:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` Ecs *ecs.Provider `description:"Enable AWS ECS backend with default settings." json:"ecs,omitempty" toml:"ecs,omitempty" yaml:"ecs,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` @@ -278,12 +276,6 @@ func (c *Configuration) SetEffectiveConfiguration() { } } - if c.Providers.Rancher != nil { - if c.Providers.Rancher.RefreshSeconds <= 0 { - c.Providers.Rancher.RefreshSeconds = 15 - } - } - // Disable Gateway API provider if not enabled in experimental. if c.Experimental == nil || !c.Experimental.KubernetesGateway { c.Providers.KubernetesGateway = nil diff --git a/pkg/provider/aggregator/aggregator.go b/pkg/provider/aggregator/aggregator.go index 8001711fc..c1164c28e 100644 --- a/pkg/provider/aggregator/aggregator.go +++ b/pkg/provider/aggregator/aggregator.go @@ -100,10 +100,6 @@ func NewProviderAggregator(conf static.Providers) ProviderAggregator { p.quietAddProvider(conf.KubernetesGateway) } - if conf.Rancher != nil { - p.quietAddProvider(conf.Rancher) - } - if conf.Ecs != nil { p.quietAddProvider(conf.Ecs) } diff --git a/pkg/provider/rancher/config.go b/pkg/provider/rancher/config.go deleted file mode 100644 index e61c2784d..000000000 --- a/pkg/provider/rancher/config.go +++ /dev/null @@ -1,299 +0,0 @@ -package rancher - -import ( - "context" - "errors" - "fmt" - "net" - "strings" - - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/label" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/constraints" -) - -func (p *Provider) buildConfiguration(ctx context.Context, services []rancherData) *dynamic.Configuration { - configurations := make(map[string]*dynamic.Configuration) - - for _, service := range services { - logger := log.Ctx(ctx).With().Str("service", service.Name).Logger() - ctxService := logger.WithContext(ctx) - - if !p.keepService(ctx, service) { - continue - } - - confFromLabel, err := label.DecodeConfiguration(service.Labels) - if err != nil { - logger.Error().Err(err).Send() - continue - } - - var tcpOrUDP bool - if len(confFromLabel.TCP.Routers) > 0 || len(confFromLabel.TCP.Services) > 0 { - tcpOrUDP = true - - err := p.buildTCPServiceConfiguration(ctxService, service, confFromLabel.TCP) - if err != nil { - logger.Error().Err(err).Send() - continue - } - provider.BuildTCPRouterConfiguration(ctxService, confFromLabel.TCP) - } - - if len(confFromLabel.UDP.Routers) > 0 || len(confFromLabel.UDP.Services) > 0 { - tcpOrUDP = true - - err := p.buildUDPServiceConfiguration(ctxService, service, confFromLabel.UDP) - if err != nil { - logger.Error().Err(err).Send() - continue - } - provider.BuildUDPRouterConfiguration(ctxService, confFromLabel.UDP) - } - - if tcpOrUDP && len(confFromLabel.HTTP.Routers) == 0 && - len(confFromLabel.HTTP.Middlewares) == 0 && - len(confFromLabel.HTTP.Services) == 0 { - configurations[service.Name] = confFromLabel - continue - } - - err = p.buildServiceConfiguration(ctx, service, confFromLabel.HTTP) - if err != nil { - logger.Error().Err(err).Send() - continue - } - - model := struct { - Name string - Labels map[string]string - }{ - Name: service.Name, - Labels: service.Labels, - } - - provider.BuildRouterConfiguration(ctx, confFromLabel.HTTP, service.Name, p.defaultRuleTpl, model) - - configurations[service.Name] = confFromLabel - } - - return provider.Merge(ctx, configurations) -} - -func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, service rancherData, configuration *dynamic.TCPConfiguration) error { - serviceName := service.Name - - if len(configuration.Services) == 0 { - configuration.Services = map[string]*dynamic.TCPService{ - serviceName: { - LoadBalancer: new(dynamic.TCPServersLoadBalancer), - }, - } - } - - for _, confService := range configuration.Services { - err := p.addServerTCP(ctx, service, confService.LoadBalancer) - if err != nil { - return err - } - } - - return nil -} - -func (p *Provider) buildUDPServiceConfiguration(ctx context.Context, service rancherData, configuration *dynamic.UDPConfiguration) error { - serviceName := service.Name - - if len(configuration.Services) == 0 { - configuration.Services = make(map[string]*dynamic.UDPService) - lb := &dynamic.UDPServersLoadBalancer{} - - configuration.Services[serviceName] = &dynamic.UDPService{ - LoadBalancer: lb, - } - } - - for _, confService := range configuration.Services { - err := p.addServerUDP(ctx, service, confService.LoadBalancer) - if err != nil { - return err - } - } - - return nil -} - -func (p *Provider) buildServiceConfiguration(ctx context.Context, service rancherData, configuration *dynamic.HTTPConfiguration) error { - serviceName := service.Name - - if len(configuration.Services) == 0 { - configuration.Services = make(map[string]*dynamic.Service) - lb := &dynamic.ServersLoadBalancer{} - lb.SetDefaults() - configuration.Services[serviceName] = &dynamic.Service{ - LoadBalancer: lb, - } - } - - for _, confService := range configuration.Services { - err := p.addServers(ctx, service, confService.LoadBalancer) - if err != nil { - return err - } - } - - return nil -} - -func (p *Provider) keepService(ctx context.Context, service rancherData) bool { - logger := log.Ctx(ctx) - - if !service.ExtraConf.Enable { - logger.Debug().Msg("Filtering disabled service") - return false - } - - matches, err := constraints.MatchLabels(service.Labels, p.Constraints) - if err != nil { - logger.Error().Err(err).Msg("Error matching constraint expression") - return false - } - if !matches { - logger.Debug().Msgf("Service pruned by constraint expression: %q", p.Constraints) - return false - } - - if p.EnableServiceHealthFilter { - if service.Health != "" && service.Health != healthy && service.Health != updatingHealthy { - logger.Debug().Msgf("Filtering service %s with healthState of %s", service.Name, service.Health) - return false - } - if service.State != "" && service.State != active && service.State != updatingActive && service.State != upgraded && service.State != upgrading { - logger.Debug().Msgf("Filtering service %s with state of %s", service.Name, service.State) - return false - } - } - - return true -} - -func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBalancer *dynamic.TCPServersLoadBalancer) error { - log.Ctx(ctx).Debug().Msgf("Trying to add servers for service %s", service.Name) - - if loadBalancer == nil { - return errors.New("load-balancer is not defined") - } - - if len(loadBalancer.Servers) == 0 { - loadBalancer.Servers = []dynamic.TCPServer{{}} - } - - port := loadBalancer.Servers[0].Port - loadBalancer.Servers[0].Port = "" - - if port == "" { - port = getServicePort(service) - } - - if port == "" { - return errors.New("port is missing") - } - - var servers []dynamic.TCPServer - for _, containerIP := range service.Containers { - servers = append(servers, dynamic.TCPServer{ - Address: net.JoinHostPort(containerIP, port), - }) - } - - loadBalancer.Servers = servers - - return nil -} - -func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBalancer *dynamic.UDPServersLoadBalancer) error { - log.Ctx(ctx).Debug().Msgf("Trying to add servers for service %s", service.Name) - - if loadBalancer == nil { - return errors.New("load-balancer is not defined") - } - - if len(loadBalancer.Servers) == 0 { - loadBalancer.Servers = []dynamic.UDPServer{{}} - } - - port := loadBalancer.Servers[0].Port - loadBalancer.Servers[0].Port = "" - - if port == "" { - port = getServicePort(service) - } - - if port == "" { - return errors.New("port is missing") - } - - var servers []dynamic.UDPServer - for _, containerIP := range service.Containers { - servers = append(servers, dynamic.UDPServer{ - Address: net.JoinHostPort(containerIP, port), - }) - } - - loadBalancer.Servers = servers - - return nil -} - -func (p *Provider) addServers(ctx context.Context, service rancherData, loadBalancer *dynamic.ServersLoadBalancer) error { - log.Ctx(ctx).Debug().Msgf("Trying to add servers for service %s", service.Name) - - if loadBalancer == nil { - return errors.New("load-balancer is not defined") - } - - if len(loadBalancer.Servers) == 0 { - server := dynamic.Server{} - server.SetDefaults() - - loadBalancer.Servers = []dynamic.Server{server} - } - - port := loadBalancer.Servers[0].Port - loadBalancer.Servers[0].Port = "" - - if port == "" { - port = getServicePort(service) - } - - if port == "" { - return errors.New("port is missing") - } - - var servers []dynamic.Server - for _, containerIP := range service.Containers { - servers = append(servers, dynamic.Server{ - URL: fmt.Sprintf("%s://%s", loadBalancer.Servers[0].Scheme, net.JoinHostPort(containerIP, port)), - }) - } - - loadBalancer.Servers = servers - - return nil -} - -func getServicePort(data rancherData) string { - rawPort := strings.Split(data.Port, "/")[0] - hostPort := strings.Split(rawPort, ":") - - if len(hostPort) >= 2 { - return hostPort[1] - } - if len(hostPort) > 0 && hostPort[0] != "" { - return hostPort[0] - } - return rawPort -} diff --git a/pkg/provider/rancher/config_test.go b/pkg/provider/rancher/config_test.go deleted file mode 100644 index 20b8940b4..000000000 --- a/pkg/provider/rancher/config_test.go +++ /dev/null @@ -1,1203 +0,0 @@ -package rancher - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" -) - -func Int(v int) *int { return &v } -func Bool(v bool) *bool { return &v } - -func Test_buildConfiguration(t *testing.T) { - testCases := []struct { - desc string - containers []rancherData - constraints string - expected *dynamic.Configuration - }{ - { - desc: "one service no label", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{}, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Test": { - Service: "Test", - Rule: "Host(`Test.traefik.wtf`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Test": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two services no label", - containers: []rancherData{ - { - Name: "Test1", - Labels: map[string]string{}, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - { - Name: "Test2", - Labels: map[string]string{}, - Port: "80/tcp", - Containers: []string{"127.0.0.2"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Test1": { - Service: "Test1", - Rule: "Host(`Test1.traefik.wtf`)", - }, - "Test2": { - Service: "Test2", - Rule: "Host(`Test2.traefik.wtf`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Test1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "Test2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.2:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two services no label multiple containers", - containers: []rancherData{ - { - Name: "Test1", - Labels: map[string]string{}, - Port: "80/tcp", - Containers: []string{"127.0.0.1", "127.0.0.2"}, - Health: "", - State: "", - }, - { - Name: "Test2", - Labels: map[string]string{}, - Port: "80/tcp", - Containers: []string{"128.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Test1": { - Service: "Test1", - Rule: "Host(`Test1.traefik.wtf`)", - }, - "Test2": { - Service: "Test2", - Rule: "Host(`Test2.traefik.wtf`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Test1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - { - URL: "http://127.0.0.2:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "Test2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://128.0.0.1:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one service some labels", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.http.services.Service1.loadbalancer.passhostheader": "true", - "traefik.http.routers.Router1.rule": "Host(`foo.com`)", - "traefik.http.routers.Router1.service": "Service1", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`foo.com`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one service which is unhealthy", - containers: []rancherData{ - { - Name: "Test", - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "broken", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one service which is upgrading", - containers: []rancherData{ - { - Name: "Test", - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "upgradefailed", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one service with rule label and has a host exposed port", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.http.routers.Router1.rule": "Host(`foo.com`)", - }, - Port: "12345:80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Test", - Rule: "Host(`foo.com`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Test": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one service with non matching constraints", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.http.routers.Router1.rule": "Host(`foo.com`)", - }, - Port: "12345:80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - constraints: `Label("traefik.tags", "bar")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one service with matching constraints", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.tags": "foo", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - constraints: `Label("traefik.tags", "foo")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Test": { - Service: "Test", - Rule: "Host(`Test.traefik.wtf`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Test": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "Middlewares used in router", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.http.middlewares.Middleware1.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - "traefik.http.routers.Test.middlewares": "Middleware1", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Test": { - Service: "Test", - Rule: "Host(`Test.traefik.wtf`)", - Middlewares: []string{"Middleware1"}, - }, - }, - Middlewares: map[string]*dynamic.Middleware{ - "Middleware1": { - BasicAuth: &dynamic.BasicAuth{ - Users: []string{ - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - }, - }, - }, - }, - Services: map[string]*dynamic.Service{ - "Test": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "Middlewares used in TCP router", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.tcp.routers.Test.rule": "HostSNI(`foo.bar`)", - "traefik.tcp.middlewares.Middleware1.ipallowlist.sourcerange": "foobar, fiibar", - "traefik.tcp.routers.Test.middlewares": "Middleware1", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "Test": { - Service: "Test", - Rule: "HostSNI(`foo.bar`)", - Middlewares: []string{"Middleware1"}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{ - "Middleware1": { - IPAllowList: &dynamic.TCPIPAllowList{ - SourceRange: []string{"foobar", "fiibar"}, - }, - }, - }, - Services: map[string]*dynamic.TCPService{ - "Test": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "127.0.0.1:80", - }, - }, - }, - }, - }, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "Port in labels", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.http.services.Test.loadbalancer.server.port": "80", - }, - Port: "", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Test": { - Service: "Test", - Rule: "Host(`Test.traefik.wtf`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Test": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "tcp with label", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.tcp.routers.foo.rule": "HostSNI(`foo.bar`)", - "traefik.tcp.routers.foo.tls": "true", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "Test", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "Test": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "127.0.0.1:80", - }, - }, - }, - }, - }, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "udp with label", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.udp.routers.foo.entrypoints": "mydns", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{ - "foo": { - Service: "Test", - EntryPoints: []string{"mydns"}, - }, - }, - Services: map[string]*dynamic.UDPService{ - "Test": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "127.0.0.1:80", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "tcp with label without rule", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.tcp.routers.foo.tls": "true", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "Test": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "127.0.0.1:80", - }, - }, - }, - }, - }, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "tcp with label and port", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.tcp.routers.foo.rule": "HostSNI(`foo.bar`)", - "traefik.tcp.services.foo.loadbalancer.server.port": "8080", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "foo", - Rule: "HostSNI(`foo.bar`)", - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "127.0.0.1:8080", - }, - }, - }, - }, - }, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "udp with label and port", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.udp.routers.foo.entrypoints": "mydns", - "traefik.udp.services.foo.loadbalancer.server.port": "8080", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{ - "foo": { - Service: "foo", - EntryPoints: []string{"mydns"}, - }, - }, - Services: map[string]*dynamic.UDPService{ - "foo": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "127.0.0.1:8080", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "tcp with label and port and http service", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.tcp.routers.foo.rule": "HostSNI(`foo.bar`)", - "traefik.tcp.routers.foo.tls": "true", - "traefik.tcp.services.foo.loadbalancer.server.port": "8080", - "traefik.http.services.Service1.loadbalancer.passhostheader": "true", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1", "127.0.0.2"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "foo", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "127.0.0.1:8080", - }, - { - Address: "127.0.0.2:8080", - }, - }, - }, - }, - }, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Test": { - Service: "Service1", - Rule: "Host(`Test.traefik.wtf`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - { - URL: "http://127.0.0.2:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "udp with label and port and http service", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.udp.routers.foo.entrypoints": "mydns", - "traefik.udp.services.foo.loadbalancer.server.port": "8080", - "traefik.http.services.Service1.loadbalancer.passhostheader": "true", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1", "127.0.0.2"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{ - "foo": { - Service: "foo", - EntryPoints: []string{"mydns"}, - }, - }, - Services: map[string]*dynamic.UDPService{ - "foo": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "127.0.0.1:8080", - }, - { - Address: "127.0.0.2:8080", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Test": { - Service: "Service1", - Rule: "Host(`Test.traefik.wtf`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1:80", - }, - { - URL: "http://127.0.0.2:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "tcp with label for tcp service", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.tcp.services.foo.loadbalancer.server.port": "8080", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "127.0.0.1:8080", - }, - }, - }, - }, - }, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "udp with label for tcp service", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.udp.services.foo.loadbalancer.server.port": "8080", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{ - "foo": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "127.0.0.1:8080", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - // TODO: replace or delete? - desc: "tcp with label for tcp service, with termination delay", - containers: []rancherData{ - { - Name: "Test", - Labels: map[string]string{ - "traefik.tcp.services.foo.loadbalancer.server.port": "8080", - }, - Port: "80/tcp", - Containers: []string{"127.0.0.1"}, - Health: "", - State: "", - }, - }, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "127.0.0.1:8080", - }, - }, - }, - }, - }, - ServersTransports: make(map[string]*dynamic.TCPServersTransport), - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - } - - for _, test := range testCases { - test := test - - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - p := Provider{ - ExposedByDefault: true, - DefaultRule: "Host(`{{ normalize .Name }}.traefik.wtf`)", - EnableServiceHealthFilter: true, - } - - p.Constraints = test.constraints - - err := p.Init() - require.NoError(t, err) - - for i := 0; i < len(test.containers); i++ { - var err error - test.containers[i].ExtraConf, err = p.getConfiguration(test.containers[i]) - require.NoError(t, err) - } - - configuration := p.buildConfiguration(context.Background(), test.containers) - - assert.Equal(t, test.expected, configuration) - }) - } -} diff --git a/pkg/provider/rancher/label.go b/pkg/provider/rancher/label.go deleted file mode 100644 index 6e90a6098..000000000 --- a/pkg/provider/rancher/label.go +++ /dev/null @@ -1,22 +0,0 @@ -package rancher - -import ( - "github.com/traefik/traefik/v2/pkg/config/label" -) - -type configuration struct { - Enable bool -} - -func (p *Provider) getConfiguration(service rancherData) (configuration, error) { - conf := configuration{ - Enable: p.ExposedByDefault, - } - - err := label.Decode(service.Labels, &conf, "traefik.rancher.", "traefik.enable") - if err != nil { - return configuration{}, err - } - - return conf, nil -} diff --git a/pkg/provider/rancher/rancher.go b/pkg/provider/rancher/rancher.go deleted file mode 100644 index 212c6607c..000000000 --- a/pkg/provider/rancher/rancher.go +++ /dev/null @@ -1,232 +0,0 @@ -package rancher - -import ( - "context" - "fmt" - "text/template" - "time" - - "github.com/cenkalti/backoff/v4" - rancher "github.com/rancher/go-rancher-metadata/metadata" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/safe" -) - -const ( - // DefaultTemplateRule The default template for the default rule. - DefaultTemplateRule = "Host(`{{ normalize .Name }}`)" -) - -// Health. -const ( - healthy = "healthy" - updatingHealthy = "updating-healthy" -) - -// States. -const ( - active = "active" - running = "running" - upgraded = "upgraded" - upgrading = "upgrading" - updatingActive = "updating-active" - updatingRunning = "updating-running" -) - -var _ provider.Provider = (*Provider)(nil) - -// Provider holds configurations of the provider. -type Provider struct { - Constraints string `description:"Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container." json:"constraints,omitempty" toml:"constraints,omitempty" yaml:"constraints,omitempty" export:"true"` - Watch bool `description:"Watch provider." json:"watch,omitempty" toml:"watch,omitempty" yaml:"watch,omitempty" export:"true"` - DefaultRule string `description:"Default rule." json:"defaultRule,omitempty" toml:"defaultRule,omitempty" yaml:"defaultRule,omitempty"` - ExposedByDefault bool `description:"Expose containers by default." json:"exposedByDefault,omitempty" toml:"exposedByDefault,omitempty" yaml:"exposedByDefault,omitempty" export:"true"` - EnableServiceHealthFilter bool `description:"Filter services with unhealthy states and inactive states." json:"enableServiceHealthFilter,omitempty" toml:"enableServiceHealthFilter,omitempty" yaml:"enableServiceHealthFilter,omitempty" export:"true"` - RefreshSeconds int `description:"Defines the polling interval in seconds." json:"refreshSeconds,omitempty" toml:"refreshSeconds,omitempty" yaml:"refreshSeconds,omitempty" export:"true"` - IntervalPoll bool `description:"Poll the Rancher metadata service every 'rancher.refreshseconds' (less accurate)." json:"intervalPoll,omitempty" toml:"intervalPoll,omitempty" yaml:"intervalPoll,omitempty" export:"true"` - Prefix string `description:"Prefix used for accessing the Rancher metadata service." json:"prefix,omitempty" toml:"prefix,omitempty" yaml:"prefix,omitempty"` - defaultRuleTpl *template.Template -} - -// SetDefaults sets the default values. -func (p *Provider) SetDefaults() { - p.Watch = true - p.ExposedByDefault = true - p.EnableServiceHealthFilter = true - p.RefreshSeconds = 15 - p.DefaultRule = DefaultTemplateRule - p.Prefix = "latest" -} - -type rancherData struct { - Name string - Labels map[string]string - Containers []string - Health string - State string - Port string - ExtraConf configuration -} - -// Init the provider. -func (p *Provider) Init() error { - defaultRuleTpl, err := provider.MakeDefaultRuleTemplate(p.DefaultRule, nil) - if err != nil { - return fmt.Errorf("error while parsing default rule: %w", err) - } - - p.defaultRuleTpl = defaultRuleTpl - return nil -} - -func (p *Provider) createClient(ctx context.Context) (rancher.Client, error) { - metadataServiceURL := fmt.Sprintf("http://rancher-metadata.rancher.internal/%s", p.Prefix) - client, err := rancher.NewClientAndWait(metadataServiceURL) - if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("Failed to create Rancher metadata service client") - return nil, err - } - - return client, nil -} - -// Provide allows the rancher provider to provide configurations to traefik using the given configuration channel. -func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - pool.GoCtx(func(routineCtx context.Context) { - logger := log.Ctx(routineCtx).With().Str(logs.ProviderName, "rancher").Logger() - ctxLog := logger.WithContext(routineCtx) - - operation := func() error { - client, err := p.createClient(ctxLog) - if err != nil { - logger.Error().Err(err).Msg("Failed to create the metadata client metadata service") - return err - } - - updateConfiguration := func(_ string) { - stacks, err := client.GetStacks() - if err != nil { - logger.Error().Err(err).Msg("Failed to query Rancher metadata service") - return - } - - rancherData := p.parseMetadataSourcedRancherData(ctxLog, stacks) - - logger.Printf("Received Rancher data %+v", rancherData) - - configuration := p.buildConfiguration(ctxLog, rancherData) - configurationChan <- dynamic.Message{ - ProviderName: "rancher", - Configuration: configuration, - } - } - updateConfiguration("init") - - if p.Watch { - if p.IntervalPoll { - p.intervalPoll(ctxLog, client, updateConfiguration) - } else { - // Long polling should be favored for the most accurate configuration updates. - // Holds the connection until there is either a change in the metadata repository or `p.RefreshSeconds` has elapsed. - client.OnChangeCtx(ctxLog, p.RefreshSeconds, updateConfiguration) - } - } - - return nil - } - - notify := func(err error, time time.Duration) { - logger.Error().Err(err).Msgf("Provider error, retrying in %s", time) - } - err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxLog), notify) - if err != nil { - logger.Error().Err(err).Msg("Cannot retrieve data") - } - }) - - return nil -} - -func (p *Provider) intervalPoll(ctx context.Context, client rancher.Client, updateConfiguration func(string)) { - ticker := time.NewTicker(time.Duration(p.RefreshSeconds) * time.Second) - defer ticker.Stop() - - var version string - for { - select { - case <-ticker.C: - newVersion, err := client.GetVersion() - if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("Failed to create Rancher metadata service client") - } else if version != newVersion { - version = newVersion - updateConfiguration(version) - } - case <-ctx.Done(): - return - } - } -} - -func (p *Provider) parseMetadataSourcedRancherData(ctx context.Context, stacks []rancher.Stack) (rancherDataList []rancherData) { - for _, stack := range stacks { - for _, service := range stack.Services { - logger := log.Ctx(ctx).With().Str("stack", stack.Name).Str("service", service.Name).Logger() - ctxSvc := logger.WithContext(ctx) - - servicePort := "" - if len(service.Ports) > 0 { - servicePort = service.Ports[0] - } - for _, port := range service.Ports { - logger.Debug().Msgf("Set Port %s", port) - } - - var containerIPAddresses []string - for _, container := range service.Containers { - if containerFilter(ctxSvc, container.Name, container.HealthState, container.State) { - containerIPAddresses = append(containerIPAddresses, container.PrimaryIp) - } - } - - service := rancherData{ - Name: service.Name + "_" + stack.Name, - State: service.State, - Labels: service.Labels, - Port: servicePort, - Containers: containerIPAddresses, - } - - extraConf, err := p.getConfiguration(service) - if err != nil { - logger.Error().Err(err).Msgf("Skip container %s", service.Name) - continue - } - - service.ExtraConf = extraConf - - rancherDataList = append(rancherDataList, service) - } - } - return rancherDataList -} - -func containerFilter(ctx context.Context, name, healthState, state string) bool { - logger := log.Ctx(ctx) - - if healthState != "" && healthState != healthy && healthState != updatingHealthy { - logger.Debug().Msgf("Filtering container %s with healthState of %s", name, healthState) - return false - } - - if state != "" && state != running && state != updatingRunning && state != upgraded { - logger.Debug().Msgf("Filtering container %s with state of %s", name, state) - return false - } - - return true -} diff --git a/pkg/redactor/redactor_config_test.go b/pkg/redactor/redactor_config_test.go index 300b43035..3c564c7a3 100644 --- a/pkg/redactor/redactor_config_test.go +++ b/pkg/redactor/redactor_config_test.go @@ -29,7 +29,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/kv/redis" "github.com/traefik/traefik/v2/pkg/provider/kv/zk" "github.com/traefik/traefik/v2/pkg/provider/marathon" - "github.com/traefik/traefik/v2/pkg/provider/rancher" "github.com/traefik/traefik/v2/pkg/provider/rest" traefiktls "github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/tracing/datadog" @@ -675,17 +674,6 @@ func TestDo_staticConfiguration(t *testing.T) { Insecure: true, } - config.Providers.Rancher = &rancher.Provider{ - Constraints: `Label("foo", "bar")`, - Watch: true, - DefaultRule: "PathPrefix(`/`)", - ExposedByDefault: true, - EnableServiceHealthFilter: true, - RefreshSeconds: 42, - IntervalPoll: true, - Prefix: "MyPrefix", - } - config.Providers.ConsulCatalog = &consulcatalog.ProviderBuilder{ Configuration: consulcatalog.Configuration{ Constraints: `Label("foo", "bar")`, diff --git a/pkg/redactor/testdata/anonymized-static-config.json b/pkg/redactor/testdata/anonymized-static-config.json index 01883306f..1b116aaaf 100644 --- a/pkg/redactor/testdata/anonymized-static-config.json +++ b/pkg/redactor/testdata/anonymized-static-config.json @@ -180,16 +180,6 @@ "rest": { "insecure": true }, - "rancher": { - "constraints": "Label(\"foo\", \"bar\")", - "watch": true, - "defaultRule": "xxxx", - "exposedByDefault": true, - "enableServiceHealthFilter": true, - "refreshSeconds": 42, - "intervalPoll": true, - "prefix": "xxxx" - }, "consulCatalog": { "constraints": "Label(\"foo\", \"bar\")", "endpoint": { diff --git a/pkg/redactor/testdata/example.json b/pkg/redactor/testdata/example.json index 0d12d63d9..5e5aa7f0a 100644 --- a/pkg/redactor/testdata/example.json +++ b/pkg/redactor/testdata/example.json @@ -76,7 +76,6 @@ "Mesos": null, "Eureka": null, "ECS": null, - "Rancher": null, "DynamoDB": null, "ConfigFile": "/etc/traefik/traefik.toml" } diff --git a/pkg/redactor/testdata/expected.json b/pkg/redactor/testdata/expected.json index 7319a7f1a..22305449a 100644 --- a/pkg/redactor/testdata/expected.json +++ b/pkg/redactor/testdata/expected.json @@ -76,7 +76,6 @@ "Mesos": null, "Eureka": null, "ECS": null, - "Rancher": null, "DynamoDB": null, "ConfigFile": "/etc/traefik/traefik.toml" } From 943811fad65b91c23b0eef737c57b0db7f08837e Mon Sep 17 00:00:00 2001 From: tfny <95721958+tfny@users.noreply.github.com> Date: Mon, 19 Dec 2022 04:42:04 -0600 Subject: [PATCH 11/74] Update submitting pull requests to include language about drafts --- docs/content/contributing/submitting-pull-requests.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/content/contributing/submitting-pull-requests.md b/docs/content/contributing/submitting-pull-requests.md index ec26125f9..855c04cf4 100644 --- a/docs/content/contributing/submitting-pull-requests.md +++ b/docs/content/contributing/submitting-pull-requests.md @@ -56,6 +56,7 @@ Merging a PR requires the following steps to be completed before it is merged au * Do not open the PR from an organization repository. * Keep "allows edit from maintainer" checked. * Use semantic line breaks for documentation. + * Ensure your PR is not a draft. We do not review drafts, but do answer questions and confer with developers on them as needed. * Pass the validation check. * Pass all tests. * Receive 3 approving reviews maintainers. From 2b67f1f66f611ecc8d1a6d6a778dfbfc2b9ef4b2 Mon Sep 17 00:00:00 2001 From: Romain Date: Mon, 19 Dec 2022 11:52:05 +0100 Subject: [PATCH 12/74] Remove Marathon provider --- README.md | 3 +- .../include-acme-multiple-domains-example.md | 11 - ...acme-multiple-domains-from-rule-example.md | 9 - .../include-acme-single-domain-example.md | 9 - docs/content/https/tailscale.md | 15 - docs/content/https/tls.md | 8 - docs/content/index.md | 2 +- docs/content/middlewares/http/addprefix.md | 6 - docs/content/middlewares/http/basicauth.md | 36 - docs/content/middlewares/http/buffering.md | 36 - docs/content/middlewares/http/chain.md | 13 - .../middlewares/http/circuitbreaker.md | 6 - docs/content/middlewares/http/compress.md | 18 - docs/content/middlewares/http/contenttype.md | 6 - docs/content/middlewares/http/digestauth.md | 36 - docs/content/middlewares/http/errorpages.md | 8 - docs/content/middlewares/http/forwardauth.md | 62 - docs/content/middlewares/http/grpcweb.md | 6 - docs/content/middlewares/http/headers.md | 32 - docs/content/middlewares/http/inflightreq.md | 36 - docs/content/middlewares/http/ipallowlist.md | 19 - docs/content/middlewares/http/overview.md | 7 - .../middlewares/http/passtlsclientcert.md | 29 - docs/content/middlewares/http/ratelimit.md | 50 - .../content/middlewares/http/redirectregex.md | 7 - .../middlewares/http/redirectscheme.md | 27 - docs/content/middlewares/http/replacepath.md | 6 - .../middlewares/http/replacepathregex.md | 7 - docs/content/middlewares/http/retry.md | 7 - docs/content/middlewares/http/stripprefix.md | 6 - .../middlewares/http/stripprefixregex.md | 6 - docs/content/middlewares/overview.md | 7 - docs/content/middlewares/tcp/inflightconn.md | 6 - docs/content/middlewares/tcp/ipallowlist.md | 6 - docs/content/middlewares/tcp/overview.md | 7 - docs/content/migration/v2-to-v3.md | 6 +- .../operations/include-api-examples.md | 9 - .../operations/include-dashboard-examples.md | 9 - docs/content/providers/marathon.md | 583 ---- docs/content/providers/overview.md | 3 - .../marathon-labels.json | 210 -- .../dynamic-configuration/marathon.json | 2 - .../dynamic-configuration/marathon.md | 16 - .../reference/static-configuration/cli-ref.md | 60 - .../reference/static-configuration/env-ref.md | 60 - .../reference/static-configuration/file.toml | 22 - .../reference/static-configuration/file.yaml | 22 - docs/content/routing/providers/marathon.md | 545 ---- docs/content/routing/routers/index.md | 3 +- docs/content/user-guides/marathon.md | 133 - docs/mkdocs.yml | 4 - go.mod | 2 - go.sum | 4 - integration/fixtures/marathon/simple.toml | 22 - integration/integration_test.go | 2 - integration/marathon15_test.go | 94 - integration/marathon_test.go | 98 - integration/resources/compose/marathon.yml | 60 - integration/resources/compose/marathon15.yml | 59 - pkg/api/handler_overview_test.go | 2 - pkg/api/testdata/overview-providers.json | 1 - pkg/config/dynamic/fixtures/sample.toml | 22 - pkg/config/static/static_config.go | 2 - pkg/provider/aggregator/aggregator.go | 4 - .../constraints/constraints_labels.go | 26 +- .../constraints/constraints_labels_test.go | 27 - pkg/provider/marathon/builder_test.go | 205 -- pkg/provider/marathon/config.go | 473 ---- pkg/provider/marathon/config_test.go | 2447 ----------------- pkg/provider/marathon/fake_client_test.go | 24 - pkg/provider/marathon/label.go | 42 - pkg/provider/marathon/label_test.go | 136 - pkg/provider/marathon/marathon.go | 221 -- pkg/provider/marathon/mocks/Marathon.go | 1286 --------- pkg/provider/marathon/readiness.go | 122 - pkg/provider/marathon/readiness_test.go | 134 - pkg/redactor/redactor_config_test.go | 27 - .../testdata/anonymized-static-config.json | 25 - pkg/redactor/testdata/example.json | 2 - pkg/redactor/testdata/expected.json | 2 - 80 files changed, 11 insertions(+), 7802 deletions(-) delete mode 100644 docs/content/providers/marathon.md delete mode 100644 docs/content/reference/dynamic-configuration/marathon-labels.json delete mode 100644 docs/content/reference/dynamic-configuration/marathon.json delete mode 100644 docs/content/reference/dynamic-configuration/marathon.md delete mode 100644 docs/content/routing/providers/marathon.md delete mode 100644 docs/content/user-guides/marathon.md delete mode 100644 integration/fixtures/marathon/simple.toml delete mode 100644 integration/marathon15_test.go delete mode 100644 integration/marathon_test.go delete mode 100644 integration/resources/compose/marathon.yml delete mode 100644 integration/resources/compose/marathon15.yml delete mode 100644 pkg/provider/marathon/builder_test.go delete mode 100644 pkg/provider/marathon/config.go delete mode 100644 pkg/provider/marathon/config_test.go delete mode 100644 pkg/provider/marathon/fake_client_test.go delete mode 100644 pkg/provider/marathon/label.go delete mode 100644 pkg/provider/marathon/label_test.go delete mode 100644 pkg/provider/marathon/marathon.go delete mode 100644 pkg/provider/marathon/mocks/Marathon.go delete mode 100644 pkg/provider/marathon/readiness.go delete mode 100644 pkg/provider/marathon/readiness_test.go diff --git a/README.md b/README.md index cc23c04a0..6e967ab06 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![Twitter](https://img.shields.io/twitter/follow/traefik.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefik) Traefik (pronounced _traffic_) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. -Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher v2](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. +Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher v2](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. Pointing Traefik at your orchestrator should be the _only_ configuration step you need. --- @@ -68,7 +68,6 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t - [Docker](https://doc.traefik.io/traefik/providers/docker/) / [Swarm mode](https://doc.traefik.io/traefik/providers/docker/) - [Kubernetes](https://doc.traefik.io/traefik/providers/kubernetes-crd/) -- [Marathon](https://doc.traefik.io/traefik/providers/marathon/) - [File](https://doc.traefik.io/traefik/providers/file/) ## Quickstart diff --git a/docs/content/https/include-acme-multiple-domains-example.md b/docs/content/https/include-acme-multiple-domains-example.md index 63cb382ba..8395887eb 100644 --- a/docs/content/https/include-acme-multiple-domains-example.md +++ b/docs/content/https/include-acme-multiple-domains-example.md @@ -43,17 +43,6 @@ spec: - '*.example.org' ``` -```json tab="Marathon" -labels: { - "traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)", - "traefik.http.routers.blog.tls": "true", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - "traefik.http.routers.blog.tls.domains[0].main": "example.com", - "traefik.http.routers.blog.tls.domains[0].sans": "*.example.com", - "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" -} -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/include-acme-multiple-domains-from-rule-example.md b/docs/content/https/include-acme-multiple-domains-from-rule-example.md index 9bd522c10..9a758ab20 100644 --- a/docs/content/https/include-acme-multiple-domains-from-rule-example.md +++ b/docs/content/https/include-acme-multiple-domains-from-rule-example.md @@ -35,15 +35,6 @@ spec: certResolver: myresolver ``` -```json tab="Marathon" -labels: { - "traefik.http.routers.blog.rule": "(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`)", - "traefik.http.routers.blog.tls": "true", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" -} -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/include-acme-single-domain-example.md b/docs/content/https/include-acme-single-domain-example.md index 1b87873e1..b7f5c84f0 100644 --- a/docs/content/https/include-acme-single-domain-example.md +++ b/docs/content/https/include-acme-single-domain-example.md @@ -35,15 +35,6 @@ spec: certResolver: myresolver ``` -```json tab="Marathon" -labels: { - "traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)", - "traefik.http.routers.blog.tls": "true", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" -} -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/tailscale.md b/docs/content/https/tailscale.md index d6b783b2c..a4ab0a79c 100644 --- a/docs/content/https/tailscale.md +++ b/docs/content/https/tailscale.md @@ -120,13 +120,6 @@ A certificate resolver requests certificates for a set of domain names inferred certResolver: myresolver ``` - ```json tab="Marathon" - labels: { - "traefik.http.routers.blog.rule": "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - } - ``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: @@ -185,14 +178,6 @@ A certificate resolver requests certificates for a set of domain names inferred - main: monitoring.yak-bebop.ts.net ``` - ```json tab="Marathon" - labels: { - "traefik.http.routers.blog.rule": "Path(`/metrics`)", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - "traefik.http.routers.blog.tls.domains[0].main": "monitoring.yak-bebop.ts.net", - } - ``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/tls.md b/docs/content/https/tls.md index dd756dd44..f6d84f5ce 100644 --- a/docs/content/https/tls.md +++ b/docs/content/https/tls.md @@ -219,14 +219,6 @@ labels: - "traefik.tls.stores.default.defaultgeneratedcert.domain.sans=foo.example.org, bar.example.org" ``` -```json tab="Marathon" -labels: { - "traefik.tls.stores.default.defaultgeneratedcert.resolver": "myresolver", - "traefik.tls.stores.default.defaultgeneratedcert.domain.main": "example.org", - "traefik.tls.stores.default.defaultgeneratedcert.domain.sans": "foo.example.org, bar.example.org", -} -``` - ## TLS Options The TLS options allow one to configure some parameters of the TLS connection. diff --git a/docs/content/index.md b/docs/content/index.md index b882fb148..3ee028a79 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -13,7 +13,7 @@ It receives requests on behalf of your system and finds out which components are What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services. The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request. -Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, Mesos, Marathon, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) +Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions). With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state. diff --git a/docs/content/middlewares/http/addprefix.md b/docs/content/middlewares/http/addprefix.md index 05cba3ad5..995524ff2 100644 --- a/docs/content/middlewares/http/addprefix.md +++ b/docs/content/middlewares/http/addprefix.md @@ -36,12 +36,6 @@ spec: - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.add-foo.addprefix.prefix": "/foo" -} -``` - ```yaml tab="File (YAML)" # Prefixing with /foo http: diff --git a/docs/content/middlewares/http/basicauth.md b/docs/content/middlewares/http/basicauth.md index 98e1c1560..7707f270b 100644 --- a/docs/content/middlewares/http/basicauth.md +++ b/docs/content/middlewares/http/basicauth.md @@ -41,12 +41,6 @@ spec: - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" -} -``` - ```yaml tab="File (YAML)" # Declaring the user list http: @@ -151,12 +145,6 @@ data: - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" -} -``` - ```yaml tab="File (YAML)" # Declaring the user list http: @@ -220,12 +208,6 @@ data: - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.usersfile": "/path/to/my/usersfile" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -270,12 +252,6 @@ spec: - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.realm": "MyRealm" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -314,12 +290,6 @@ spec: - "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.my-auth.basicauth.headerField": "X-WebAuth-User" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -358,12 +328,6 @@ spec: - "traefik.http.middlewares.test-auth.basicauth.removeheader=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.removeheader": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/buffering.md b/docs/content/middlewares/http/buffering.md index e76d5b40e..6e9d7b9ab 100644 --- a/docs/content/middlewares/http/buffering.md +++ b/docs/content/middlewares/http/buffering.md @@ -40,12 +40,6 @@ spec: - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" # Sets the maximum request body to 2MB http: @@ -91,12 +85,6 @@ spec: - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -136,12 +124,6 @@ spec: - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -183,12 +165,6 @@ spec: - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -228,12 +204,6 @@ spec: - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -275,12 +245,6 @@ You can have the Buffering middleware replay the request using `retryExpression` - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" ``` - ```json tab="Marathon" - "labels": { - "traefik.http.middlewares.limit.buffering.retryExpression": "IsNetworkError() && Attempts() < 2" - } - ``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/chain.md b/docs/content/middlewares/http/chain.md index e7cbdc456..ce3806a5d 100644 --- a/docs/content/middlewares/http/chain.md +++ b/docs/content/middlewares/http/chain.md @@ -97,19 +97,6 @@ spec: - "traefik.http.services.service1.loadbalancer.server.port=80" ``` -```json tab="Marathon" -"labels": { - "traefik.http.routers.router1.service": "service1", - "traefik.http.routers.router1.middlewares": "secured", - "traefik.http.routers.router1.rule": "Host(`mydomain`)", - "traefik.http.middlewares.secured.chain.middlewares": "https-only,known-ips,auth-users", - "traefik.http.middlewares.auth-users.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", - "traefik.http.middlewares.https-only.redirectscheme.scheme": "https", - "traefik.http.middlewares.known-ips.ipallowlist.sourceRange": "192.168.1.7,127.0.0.1/32", - "traefik.http.services.service1.loadbalancer.server.port": "80" -} -``` - ```yaml tab="File (YAML)" # ... http: diff --git a/docs/content/middlewares/http/circuitbreaker.md b/docs/content/middlewares/http/circuitbreaker.md index 21cd45fea..7ff406c17 100644 --- a/docs/content/middlewares/http/circuitbreaker.md +++ b/docs/content/middlewares/http/circuitbreaker.md @@ -52,12 +52,6 @@ spec: - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.latency-check.circuitbreaker.expression": "LatencyAtQuantileMS(50.0) > 100" -} -``` - ```yaml tab="File (YAML)" # Latency Check http: diff --git a/docs/content/middlewares/http/compress.md b/docs/content/middlewares/http/compress.md index 90cb5c0be..4a17c9430 100644 --- a/docs/content/middlewares/http/compress.md +++ b/docs/content/middlewares/http/compress.md @@ -36,12 +36,6 @@ spec: - "traefik.http.middlewares.test-compress.compress=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-compress.compress": "true" -} -``` - ```yaml tab="File (YAML)" # Enable compression http: @@ -108,12 +102,6 @@ spec: - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes": "text/event-stream" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -156,12 +144,6 @@ spec: - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes": 1200 -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/contenttype.md b/docs/content/middlewares/http/contenttype.md index 4770defa2..b74bfa6c2 100644 --- a/docs/content/middlewares/http/contenttype.md +++ b/docs/content/middlewares/http/contenttype.md @@ -39,12 +39,6 @@ spec: - "traefik.http.middlewares.autodetect.contenttype=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.autodetect.contenttype": "true" -} -``` - ```yaml tab="File (YAML)" # Enable auto-detection http: diff --git a/docs/content/middlewares/http/digestauth.md b/docs/content/middlewares/http/digestauth.md index 8a24f0580..d49d8f581 100644 --- a/docs/content/middlewares/http/digestauth.md +++ b/docs/content/middlewares/http/digestauth.md @@ -36,12 +36,6 @@ spec: - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" -} -``` - ```yaml tab="File (YAML)" # Declaring the user list http: @@ -108,12 +102,6 @@ data: - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -175,12 +163,6 @@ data: - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.usersfile": "/path/to/my/usersfile" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -225,12 +207,6 @@ spec: - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.realm": "MyRealm" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -269,12 +245,6 @@ spec: - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.my-auth.digestauth.headerField": "X-WebAuth-User" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -313,12 +283,6 @@ spec: - "traefik.http.middlewares.test-auth.digestauth.removeheader=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.removeheader": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/errorpages.md b/docs/content/middlewares/http/errorpages.md index 1fd537191..3ec1c1e20 100644 --- a/docs/content/middlewares/http/errorpages.md +++ b/docs/content/middlewares/http/errorpages.md @@ -48,14 +48,6 @@ spec: - "traefik.http.middlewares.test-errors.errors.query=/{status}.html" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-errors.errors.status": "500-599", - "traefik.http.middlewares.test-errors.errors.service": "serviceError", - "traefik.http.middlewares.test-errors.errors.query": "/{status}.html" -} -``` - ```yaml tab="File (YAML)" # Custom Error Page for 5XX http: diff --git a/docs/content/middlewares/http/forwardauth.md b/docs/content/middlewares/http/forwardauth.md index 64e64d60e..f7a038020 100644 --- a/docs/content/middlewares/http/forwardauth.md +++ b/docs/content/middlewares/http/forwardauth.md @@ -38,12 +38,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth" -} -``` - ```yaml tab="File (YAML)" # Forward authentication to example.com http: @@ -97,12 +91,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -141,12 +129,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -190,12 +172,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders": "X-Auth-User,X-Secret" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -241,12 +217,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex": "^X-" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -297,12 +267,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders": "Accept,X-CustomHeader" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -366,12 +330,6 @@ data: - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.tls.ca": "path/to/local.crt" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -431,13 +389,6 @@ data: - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert", - "traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -503,13 +454,6 @@ data: - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert", - "traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -561,12 +505,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/grpcweb.md b/docs/content/middlewares/http/grpcweb.md index ca5b50850..c76153a26 100644 --- a/docs/content/middlewares/http/grpcweb.md +++ b/docs/content/middlewares/http/grpcweb.md @@ -37,12 +37,6 @@ spec: - "traefik.http.middlewares.test-grpcweb.grpcWeb.allowOrigins=*" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-grpcweb.grpcweb.alloworigins": "*" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/headers.md b/docs/content/middlewares/http/headers.md index ab9474f57..739380b42 100644 --- a/docs/content/middlewares/http/headers.md +++ b/docs/content/middlewares/http/headers.md @@ -44,13 +44,6 @@ spec: - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test", - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "value" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -103,14 +96,6 @@ spec: - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test", - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header": "", - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "", -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -160,14 +145,6 @@ spec: - "traefik.http.middlewares.testheader.headers.browserxssfilter=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.testheader.headers.framedeny": "true", - "traefik.http.middlewares.testheader.headers.browserxssfilter": "true" -} -``` - - ```yaml tab="File (YAML)" http: middlewares: @@ -224,15 +201,6 @@ spec: - "traefik.http.middlewares.testheader.headers.addvaryheader=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods": "GET,OPTIONS,PUT", - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist": "https://foo.bar.org,https://example.org", - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage": "100", - "traefik.http.middlewares.testheader.headers.addvaryheader": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/inflightreq.md b/docs/content/middlewares/http/inflightreq.md index 985a2ea11..71190631e 100644 --- a/docs/content/middlewares/http/inflightreq.md +++ b/docs/content/middlewares/http/inflightreq.md @@ -34,12 +34,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10" -} -``` - ```yaml tab="File (YAML)" # Limiting to 10 simultaneous connections http: @@ -83,12 +77,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10" -} -``` - ```yaml tab="File (YAML)" # Limiting to 10 simultaneous connections http: @@ -153,12 +141,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth": "2" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -215,12 +197,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -264,12 +240,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername": "username" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -310,12 +280,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/ipallowlist.md b/docs/content/middlewares/http/ipallowlist.md index 63701f773..703293d32 100644 --- a/docs/content/middlewares/http/ipallowlist.md +++ b/docs/content/middlewares/http/ipallowlist.md @@ -35,12 +35,6 @@ spec: - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32,192.168.1.7" -} -``` - ```yaml tab="File (YAML)" # Accepts request from defined IP http: @@ -114,13 +108,6 @@ spec: - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32, 192.168.1.7", - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth": "2" -} -``` - ```yaml tab="File (YAML)" # Allowlisting Based on `X-Forwarded-For` with `depth=2` http: @@ -184,12 +171,6 @@ spec: - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" -} -``` - ```yaml tab="File (YAML)" # Exclude from `X-Forwarded-For` http: diff --git a/docs/content/middlewares/http/overview.md b/docs/content/middlewares/http/overview.md index 27277677c..5757b3335 100644 --- a/docs/content/middlewares/http/overview.md +++ b/docs/content/middlewares/http/overview.md @@ -69,13 +69,6 @@ spec: - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", - "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" -} -``` - ```toml tab="File (TOML)" # As TOML Configuration File [http.routers] diff --git a/docs/content/middlewares/http/passtlsclientcert.md b/docs/content/middlewares/http/passtlsclientcert.md index f55982a90..4264dd711 100644 --- a/docs/content/middlewares/http/passtlsclientcert.md +++ b/docs/content/middlewares/http/passtlsclientcert.md @@ -39,12 +39,6 @@ spec: - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem": "true" -} -``` - ```yaml tab="File (YAML)" # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. http: @@ -140,29 +134,6 @@ http: - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true" ``` - ```json tab="Marathon" - "labels": { - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber": "true" - } - ``` - ```yaml tab="File (YAML)" # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header http: diff --git a/docs/content/middlewares/http/ratelimit.md b/docs/content/middlewares/http/ratelimit.md index 2fb11f6ee..48057fe85 100644 --- a/docs/content/middlewares/http/ratelimit.md +++ b/docs/content/middlewares/http/ratelimit.md @@ -40,13 +40,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.average": "100", - "traefik.http.middlewares.test-ratelimit.ratelimit.burst": "50" -} -``` - ```yaml tab="File (YAML)" # Here, an average of 100 requests per second is allowed. # In addition, a burst of 50 requests is allowed. @@ -100,12 +93,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.average": "100", -} -``` - ```yaml tab="File (YAML)" # 100 reqs/s http: @@ -157,13 +144,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.average": "6", - "traefik.http.middlewares.test-ratelimit.ratelimit.period": "1m", -} -``` - ```yaml tab="File (YAML)" # 6 reqs/minute http: @@ -207,12 +187,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.burst": "100", -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -275,12 +249,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth": "2" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -364,12 +332,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -413,12 +375,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername": "username" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -459,12 +415,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/redirectregex.md b/docs/content/middlewares/http/redirectregex.md index 74f0e3c23..fe4da4b30 100644 --- a/docs/content/middlewares/http/redirectregex.md +++ b/docs/content/middlewares/http/redirectregex.md @@ -43,13 +43,6 @@ spec: - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-redirectregex.redirectregex.regex": "^http://localhost/(.*)", - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement": "http://mydomain/${1}" -} -``` - ```yaml tab="File (YAML)" # Redirect with domain replacement http: diff --git a/docs/content/middlewares/http/redirectscheme.md b/docs/content/middlewares/http/redirectscheme.md index 841ec018b..14e715add 100644 --- a/docs/content/middlewares/http/redirectscheme.md +++ b/docs/content/middlewares/http/redirectscheme.md @@ -51,13 +51,6 @@ labels: - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https" - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true" -} -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -108,13 +101,6 @@ labels: - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" ``` -```json tab="Marathon" -"labels": { - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true" -} -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -160,12 +146,6 @@ labels: - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https" -} -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -212,13 +192,6 @@ labels: - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443" ``` -```json tab="Marathon" -"labels": { - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port": "443" -} -``` - ```yaml tab="File (YAML)" # Redirect to https http: diff --git a/docs/content/middlewares/http/replacepath.md b/docs/content/middlewares/http/replacepath.md index e4d138c2c..f2ddf0758 100644 --- a/docs/content/middlewares/http/replacepath.md +++ b/docs/content/middlewares/http/replacepath.md @@ -38,12 +38,6 @@ spec: - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-replacepath.replacepath.path": "/foo" -} -``` - ```yaml tab="File (YAML)" # Replace the path with /foo http: diff --git a/docs/content/middlewares/http/replacepathregex.md b/docs/content/middlewares/http/replacepathregex.md index a2fd561bd..1acd76591 100644 --- a/docs/content/middlewares/http/replacepathregex.md +++ b/docs/content/middlewares/http/replacepathregex.md @@ -41,13 +41,6 @@ spec: - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex": "^/foo/(.*)", - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement": "/bar/$1" -} -``` - ```yaml tab="File (YAML)" # Replace path with regex http: diff --git a/docs/content/middlewares/http/retry.md b/docs/content/middlewares/http/retry.md index 2a3288eac..187d107a6 100644 --- a/docs/content/middlewares/http/retry.md +++ b/docs/content/middlewares/http/retry.md @@ -43,13 +43,6 @@ spec: - "traefik.http.middlewares.test-retry.retry.initialinterval=100ms" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-retry.retry.attempts": "4", - "traefik.http.middlewares.test-retry.retry.initialinterval": "100ms", -} -``` - ```yaml tab="File (YAML)" # Retry 4 times with exponential backoff http: diff --git a/docs/content/middlewares/http/stripprefix.md b/docs/content/middlewares/http/stripprefix.md index f84735cb5..135f7e08a 100644 --- a/docs/content/middlewares/http/stripprefix.md +++ b/docs/content/middlewares/http/stripprefix.md @@ -40,12 +40,6 @@ spec: - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes": "/foobar,/fiibar" -} -``` - ```yaml tab="File (YAML)" # Strip prefix /foobar and /fiibar http: diff --git a/docs/content/middlewares/http/stripprefixregex.md b/docs/content/middlewares/http/stripprefixregex.md index 1a3ec09e6..f6e58d871 100644 --- a/docs/content/middlewares/http/stripprefixregex.md +++ b/docs/content/middlewares/http/stripprefixregex.md @@ -32,12 +32,6 @@ spec: - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex": "/foo/[a-z0-9]+/[0-9]+/" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/overview.md b/docs/content/middlewares/overview.md index 09e17278e..eeb70ea4f 100644 --- a/docs/content/middlewares/overview.md +++ b/docs/content/middlewares/overview.md @@ -66,13 +66,6 @@ spec: - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", - "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" -} -``` - ```yaml tab="File (YAML)" # As YAML Configuration File http: diff --git a/docs/content/middlewares/tcp/inflightconn.md b/docs/content/middlewares/tcp/inflightconn.md index 2550181df..9619cd63e 100644 --- a/docs/content/middlewares/tcp/inflightconn.md +++ b/docs/content/middlewares/tcp/inflightconn.md @@ -27,12 +27,6 @@ spec: - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" ``` -```json tab="Marathon" -"labels": { - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount": "10" -} -``` - ```yaml tab="File (YAML)" # Limiting to 10 simultaneous connections. tcp: diff --git a/docs/content/middlewares/tcp/ipallowlist.md b/docs/content/middlewares/tcp/ipallowlist.md index 25730eb1e..fad1f9cbf 100644 --- a/docs/content/middlewares/tcp/ipallowlist.md +++ b/docs/content/middlewares/tcp/ipallowlist.md @@ -35,12 +35,6 @@ spec: - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32,192.168.1.7" -} -``` - ```toml tab="File (TOML)" # Accepts request from defined IP [tcp.middlewares] diff --git a/docs/content/middlewares/tcp/overview.md b/docs/content/middlewares/tcp/overview.md index 8fde185e9..dfbdd3f9b 100644 --- a/docs/content/middlewares/tcp/overview.md +++ b/docs/content/middlewares/tcp/overview.md @@ -70,13 +70,6 @@ spec: - "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@consulcatalog" ``` -```json tab="Marathon" -"labels": { - "traefik.tcp.middlewares.foo-ip-allowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7", - "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@marathon" -} -``` - ```toml tab="File (TOML)" # As TOML Configuration File [tcp.routers] diff --git a/docs/content/migration/v2-to-v3.md b/docs/content/migration/v2-to-v3.md index e729d69b3..6c8d36e5e 100644 --- a/docs/content/migration/v2-to-v3.md +++ b/docs/content/migration/v2-to-v3.md @@ -26,7 +26,7 @@ In v3, the reported status code for gRPC requests is now the value of the `Grpc- - The `pilot` option has been removed from the static configuration. - The `tracing.datadog.globaltag` option has been removed. - The `namespace` option of Consul, Consul Catalog and Nomad providers has been removed. -- The `tls.caOptional` option has been removed from the ForwardAuth middleware, as well as from the HTTP, Consul, Etcd, Redis, ZooKeeper, Marathon, Consul Catalog, and Docker providers. +- The `tls.caOptional` option has been removed from the ForwardAuth middleware, as well as from the HTTP, Consul, Etcd, Redis, ZooKeeper, Consul Catalog, and Docker providers. - `sslRedirect`, `sslTemporaryRedirect`, `sslHost`, `sslForceHost` and `featurePolicy` options of the Headers middleware have been removed. - The `forceSlash` option of the StripPrefix middleware has been removed. - the `preferServerCipherSuites` option has been removed. @@ -72,3 +72,7 @@ In v3, the rancher v1 provider has been removed because Rancher v1 is [no longer Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](../providers/kubernetes-crd.md) directly. + +## Marathon provider + +In v3, the Marathon provider has been removed. diff --git a/docs/content/operations/include-api-examples.md b/docs/content/operations/include-api-examples.md index 12ef27edb..aa49dae33 100644 --- a/docs/content/operations/include-api-examples.md +++ b/docs/content/operations/include-api-examples.md @@ -51,15 +51,6 @@ spec: - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" ``` -```json tab="Marathon" -"labels": { - "traefik.http.routers.api.rule": "Host(`traefik.example.com`)", - "traefik.http.routers.api.service": "api@internal", - "traefik.http.routers.api.middlewares": "auth", - "traefik.http.middlewares.auth.basicauth.users": "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" -} -``` - ```yaml tab="File (YAML)" # Dynamic Configuration http: diff --git a/docs/content/operations/include-dashboard-examples.md b/docs/content/operations/include-dashboard-examples.md index da8d0d8ae..9d90c42c4 100644 --- a/docs/content/operations/include-dashboard-examples.md +++ b/docs/content/operations/include-dashboard-examples.md @@ -51,15 +51,6 @@ spec: - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" ``` -```json tab="Marathon" -"labels": { - "traefik.http.routers.dashboard.rule": "Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))", - "traefik.http.routers.dashboard.service": "api@internal", - "traefik.http.routers.dashboard.middlewares": "auth", - "traefik.http.middlewares.auth.basicauth.users": "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" -} -``` - ```yaml tab="File (YAML)" # Dynamic Configuration http: diff --git a/docs/content/providers/marathon.md b/docs/content/providers/marathon.md deleted file mode 100644 index a0ab85ccb..000000000 --- a/docs/content/providers/marathon.md +++ /dev/null @@ -1,583 +0,0 @@ ---- -title: "Traefik Configuration for Marathon" -description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation to learn how." ---- - -# Traefik & Marathon - -Traefik can be configured to use Marathon as a provider. -{: .subtitle } - -For additional information, refer to [Marathon user guide](../user-guides/marathon.md). - -## Configuration Examples - -??? example "Configuring Marathon & Deploying / Exposing Applications" - - Enabling the Marathon provider - - ```yaml tab="File (YAML)" - providers: - marathon: {} - ``` - - ```toml tab="File (TOML)" - [providers.marathon] - ``` - - ```bash tab="CLI" - --providers.marathon=true - ``` - - Attaching labels to Marathon applications - - ```json - { - "id": "/whoami", - "container": { - "type": "DOCKER", - "docker": { - "image": "traefik/whoami", - "network": "BRIDGE", - "portMappings": [ - { - "containerPort": 80, - "hostPort": 0, - "protocol": "tcp" - } - ] - } - }, - "labels": { - "traefik.http.Routers.app.Rule": "PathPrefix(`/app`)" - } - } - ``` - -## Routing Configuration - -See the dedicated section in [routing](../routing/providers/marathon.md). - -## Provider Configuration - -### `basic` - -_Optional_ - -Enables Marathon basic authentication. - -```yaml tab="File (YAML)" -providers: - marathon: - basic: - httpBasicAuthUser: foo - httpBasicPassword: bar -``` - -```toml tab="File (TOML)" -[providers.marathon.basic] - httpBasicAuthUser = "foo" - httpBasicPassword = "bar" -``` - -```bash tab="CLI" ---providers.marathon.basic.httpbasicauthuser=foo ---providers.marathon.basic.httpbasicpassword=bar -``` - -### `dcosToken` - -_Optional_ - -Datacenter Operating System (DCOS) Token for DCOS environment. - -If set, it overrides the Authorization header. - -```toml tab="File (YAML)" -providers: - marathon: - dcosToken: "xxxxxx" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - dcosToken = "xxxxxx" - # ... -``` - -```bash tab="CLI" ---providers.marathon.dcosToken=xxxxxx -``` - -### `defaultRule` - -_Optional, Default=```Host(`{{ normalize .Name }}`)```_ - -The default host rule for all services. - -For a given application, if no routing rule was defined by a label, it is defined by this `defaultRule` instead. - -It must be a valid [Go template](https://pkg.go.dev/text/template/), -and can include [sprig template functions](https://masterminds.github.io/sprig/). - -The app ID can be accessed with the `Name` identifier, -and the template has access to all the labels defined on this Marathon application. - -```yaml tab="File (YAML)" -providers: - marathon: - defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" - # ... -``` - -```bash tab="CLI" ---providers.marathon.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`) -# ... -``` - -### `dialerTimeout` - -_Optional, Default=5s_ - -Amount of time the Marathon provider should wait before timing out, -when trying to open a TCP connection to a Marathon master. - -The value of `dialerTimeout` should be provided in seconds or as a valid duration format, -see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). - -```yaml tab="File (YAML)" -providers: - marathon: - dialerTimeout: "10s" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - dialerTimeout = "10s" - # ... -``` - -```bash tab="CLI" ---providers.marathon.dialerTimeout=10s -``` - -### `endpoint` - -_Optional, Default=http://127.0.0.1:8080_ - -Marathon server endpoint. - -You can optionally specify multiple endpoints. - -```yaml tab="File (YAML)" -providers: - marathon: - endpoint: "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - endpoint = "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080" - # ... -``` - -```bash tab="CLI" ---providers.marathon.endpoint=http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080 -``` - -### `exposedByDefault` - -_Optional, Default=true_ - -Exposes Marathon applications by default through Traefik. - -If set to `false`, applications that do not have a `traefik.enable=true` label are ignored from the resulting routing configuration. - -For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). - -```yaml tab="File (YAML)" -providers: - marathon: - exposedByDefault: false - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - exposedByDefault = false - # ... -``` - -```bash tab="CLI" ---providers.marathon.exposedByDefault=false -# ... -``` - -### `constraints` - -_Optional, Default=""_ - -The `constraints` option can be set to an expression that Traefik matches against the application labels to determine whether -to create any route for that application. If none of the application labels match the expression, no route for that application is -created. In addition, the expression is also matched against the application constraints, such as described -in [Marathon constraints](https://mesosphere.github.io/marathon/docs/constraints.html). -If the expression is empty, all detected applications are included. - -The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as the usual boolean logic. -In addition, to match against Marathon constraints, the function `MarathonConstraint("field:operator:value")` can be used, where the field, operator, and value parts are concatenated in a single string using the `:` separator. - -??? example "Constraints Expression Examples" - - ```toml - # Includes only applications having a label with key `a.label.name` and value `foo` - constraints = "Label(`a.label.name`, `foo`)" - ``` - - ```toml - # Excludes applications having any label with key `a.label.name` and value `foo` - constraints = "!Label(`a.label.name`, `value`)" - ``` - - ```toml - # With logical AND. - constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)" - ``` - - ```toml - # With logical OR. - constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)" - ``` - - ```toml - # With logical AND and OR, with precedence set by parentheses. - constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))" - ``` - - ```toml - # Includes only applications having a label with key `a.label.name` and a value matching the `a.+` regular expression. - constraints = "LabelRegex(`a.label.name`, `a.+`)" - ``` - - ```toml - # Includes only applications having a Marathon constraint with field `A`, operator `B`, and value `C`. - constraints = "MarathonConstraint(`A:B:C`)" - ``` - - ```toml - # Uses both Marathon constraint and application label with logical operator. - constraints = "MarathonConstraint(`A:B:C`) && Label(`a.label.name`, `value`)" - ``` - -For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). - -```yaml tab="File (YAML)" -providers: - marathon: - constraints: "Label(`a.label.name`,`foo`)" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - constraints = "Label(`a.label.name`,`foo`)" - # ... -``` - -```bash tab="CLI" ---providers.marathon.constraints=Label(`a.label.name`,`foo`) -# ... -``` - -### `forceTaskHostname` - -_Optional, Default=false_ - -By default, the task IP address (as returned by the Marathon API) is used as backend server if an IP-per-task configuration can be found; -otherwise, the name of the host running the task is used. -The latter behavior can be enforced by setting this option to `true`. - -```yaml tab="File (YAML)" -providers: - marathon: - forceTaskHostname: true - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - forceTaskHostname = true - # ... -``` - -```bash tab="CLI" ---providers.marathon.forceTaskHostname=true -# ... -``` - -### `keepAlive` - -_Optional, Default=10s_ - -Set the TCP Keep Alive duration for the Marathon HTTP Client. -The value of `keepAlive` should be provided in seconds or as a valid duration format, -see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). - -```yaml tab="File (YAML)" -providers: - marathon: - keepAlive: "30s" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - keepAlive = "30s" - # ... -``` - -```bash tab="CLI" ---providers.marathon.keepAlive=30s -# ... -``` - -### `respectReadinessChecks` - -_Optional, Default=false_ - -Applications may define readiness checks which are probed by Marathon during deployments periodically, and these check results are exposed via the API. -Enabling `respectReadinessChecks` causes Traefik to filter out tasks whose readiness checks have not succeeded. -Note that the checks are only valid during deployments. - -See the Marathon guide for details. - -```yaml tab="File (YAML)" -providers: - marathon: - respectReadinessChecks: true - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - respectReadinessChecks = true - # ... -``` - -```bash tab="CLI" ---providers.marathon.respectReadinessChecks=true -# ... -``` - -### `responseHeaderTimeout` - -_Optional, Default=60s_ - -Amount of time the Marathon provider should wait before timing out when waiting for the first response header -from a Marathon master. - -The value of `responseHeaderTimeout` should be provided in seconds or as a valid duration format, -see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). - -```yaml tab="File (YAML)" -providers: - marathon: - responseHeaderTimeout: "66s" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - responseHeaderTimeout = "66s" - # ... -``` - -```bash tab="CLI" ---providers.marathon.responseHeaderTimeout=66s -# ... -``` - -### `tls` - -_Optional_ - -Defines the TLS configuration used for the secure connection to Marathon. - -#### `ca` - -`ca` is the path to the certificate authority used for the secure connection to Marathon, -it defaults to the system bundle. - -```yaml tab="File (YAML)" -providers: - marathon: - tls: - ca: path/to/ca.crt -``` - -```toml tab="File (TOML)" -[providers.marathon.tls] - ca = "path/to/ca.crt" -``` - -```bash tab="CLI" ---providers.marathon.tls.ca=path/to/ca.crt -``` - -#### `cert` - -_Optional_ - -`cert` is the path to the public certificate used for the secure connection to Marathon. -When using this option, setting the `key` option is required. - -```yaml tab="File (YAML)" -providers: - marathon: - tls: - cert: path/to/foo.cert - key: path/to/foo.key -``` - -```toml tab="File (TOML)" -[providers.marathon.tls] - cert = "path/to/foo.cert" - key = "path/to/foo.key" -``` - -```bash tab="CLI" ---providers.marathon.tls.cert=path/to/foo.cert ---providers.marathon.tls.key=path/to/foo.key -``` - -#### `key` - -_Optional_ - -`key` is the path to the private key used for the secure connection to Marathon. -When using this option, setting the `cert` option is required. - -```yaml tab="File (YAML)" -providers: - marathon: - tls: - cert: path/to/foo.cert - key: path/to/foo.key -``` - -```toml tab="File (TOML)" -[providers.marathon.tls] - cert = "path/to/foo.cert" - key = "path/to/foo.key" -``` - -```bash tab="CLI" ---providers.marathon.tls.cert=path/to/foo.cert ---providers.marathon.tls.key=path/to/foo.key -``` - -#### `insecureSkipVerify` - -_Optional, Default=false_ - -If `insecureSkipVerify` is `true`, the TLS connection to Marathon accepts any certificate presented by the server regardless of the hostnames it covers. - -```yaml tab="File (YAML)" -providers: - marathon: - tls: - insecureSkipVerify: true -``` - -```toml tab="File (TOML)" -[providers.marathon.tls] - insecureSkipVerify = true -``` - -```bash tab="CLI" ---providers.marathon.tls.insecureSkipVerify=true -``` - -### `tlsHandshakeTimeout` - -_Optional, Default=5s_ - -Amount of time the Marathon provider should wait before timing out, -when waiting for the TLS handshake to complete. - -The value of `tlsHandshakeTimeout` should be provided in seconds or as a valid duration format, -see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). - -```yaml tab="File (YAML)" -providers: - marathon: - tlsHandshakeTimeout: "10s" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - tlsHandshakeTimeout = "10s" - # ... -``` - -```bash tab="CLI" ---providers.marathon.tlsHandshakeTimeout=10s -# ... -``` - -### `trace` - -_Optional, Default=false_ - -Displays additional provider logs when available. - -```yaml tab="File (YAML)" -providers: - marathon: - trace: true - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - trace = true - # ... -``` - -```bash tab="CLI" ---providers.marathon.trace=true -# ... -``` - -### `watch` - -_Optional, Default=true_ - -When set to `true`, watches for Marathon changes. - -```yaml tab="File (YAML)" -providers: - marathon: - watch: false - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - watch = false - # ... -``` - -```bash tab="CLI" ---providers.marathon.watch=false -# ... -``` diff --git a/docs/content/providers/overview.md b/docs/content/providers/overview.md index 9589ce21d..47d6178e8 100644 --- a/docs/content/providers/overview.md +++ b/docs/content/providers/overview.md @@ -141,7 +141,6 @@ Below is the list of the currently supported providers in Traefik. | [Consul Catalog](./consul-catalog.md) | Orchestrator | Label | `consulcatalog` | | [Nomad](./nomad.md) | Orchestrator | Label | `nomad` | | [ECS](./ecs.md) | Orchestrator | Label | `ecs` | -| [Marathon](./marathon.md) | Orchestrator | Label | `marathon` | | [File](./file.md) | Manual | YAML/TOML format | `file` | | [Consul](./consul.md) | KV | KV | `consul` | | [Etcd](./etcd.md) | KV | KV | `etcd` | @@ -215,7 +214,6 @@ List of providers that support these features: - [ECS](./ecs.md#exposedbydefault) - [Consul Catalog](./consul-catalog.md#exposedbydefault) - [Nomad](./nomad.md#exposedbydefault) -- [Marathon](./marathon.md#exposedbydefault) ### Constraints @@ -225,7 +223,6 @@ List of providers that support constraints: - [ECS](./ecs.md#constraints) - [Consul Catalog](./consul-catalog.md#constraints) - [Nomad](./nomad.md#constraints) -- [Marathon](./marathon.md#constraints) - [Kubernetes CRD](./kubernetes-crd.md#labelselector) - [Kubernetes Ingress](./kubernetes-ingress.md#labelselector) - [Kubernetes Gateway](./kubernetes-gateway.md#labelselector) diff --git a/docs/content/reference/dynamic-configuration/marathon-labels.json b/docs/content/reference/dynamic-configuration/marathon-labels.json deleted file mode 100644 index afac8bb13..000000000 --- a/docs/content/reference/dynamic-configuration/marathon-labels.json +++ /dev/null @@ -1,210 +0,0 @@ -"traefik.http.middlewares.middleware00.addprefix.prefix": "foobar", -"traefik.http.middlewares.middleware01.basicauth.headerfield": "foobar", -"traefik.http.middlewares.middleware01.basicauth.realm": "foobar", -"traefik.http.middlewares.middleware01.basicauth.removeheader": "true", -"traefik.http.middlewares.middleware01.basicauth.users": "foobar, foobar", -"traefik.http.middlewares.middleware01.basicauth.usersfile": "foobar", -"traefik.http.middlewares.middleware02.buffering.maxrequestbodybytes": "42", -"traefik.http.middlewares.middleware02.buffering.maxresponsebodybytes": "42", -"traefik.http.middlewares.middleware02.buffering.memrequestbodybytes": "42", -"traefik.http.middlewares.middleware02.buffering.memresponsebodybytes": "42", -"traefik.http.middlewares.middleware02.buffering.retryexpression": "foobar", -"traefik.http.middlewares.middleware03.chain.middlewares": "foobar, foobar", -"traefik.http.middlewares.middleware04.circuitbreaker.expression": "foobar", -"traefik.http.middlewares.middleware04.circuitbreaker.checkperiod": "42s", -"traefik.http.middlewares.middleware04.circuitbreaker.fallbackduration": "42s", -"traefik.http.middlewares.middleware04.circuitbreaker.recoveryduration": "42s", -"traefik.http.middlewares.middleware05.compress": "true", -"traefik.http.middlewares.middleware05.compress.excludedcontenttypes": "foobar, foobar", -"traefik.http.middlewares.middleware05.compress.minresponsebodybytes": "42", -"traefik.http.middlewares.middleware06.contenttype": "true", -"traefik.http.middlewares.middleware07.digestauth.headerfield": "foobar", -"traefik.http.middlewares.middleware07.digestauth.realm": "foobar", -"traefik.http.middlewares.middleware07.digestauth.removeheader": "true", -"traefik.http.middlewares.middleware07.digestauth.users": "foobar, foobar", -"traefik.http.middlewares.middleware07.digestauth.usersfile": "foobar", -"traefik.http.middlewares.middleware08.errors.query": "foobar", -"traefik.http.middlewares.middleware08.errors.service": "foobar", -"traefik.http.middlewares.middleware08.errors.status": "foobar, foobar", -"traefik.http.middlewares.middleware09.forwardauth.address": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.authrequestheaders": "foobar, foobar", -"traefik.http.middlewares.middleware09.forwardauth.authresponseheaders": "foobar, foobar", -"traefik.http.middlewares.middleware09.forwardauth.authresponseheadersregex": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.tls.ca": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.tls.cert": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.tls.insecureskipverify": "true", -"traefik.http.middlewares.middleware09.forwardauth.tls.key": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.trustforwardheader": "true", -"traefik.http.middlewares.middleware10.headers.accesscontrolallowcredentials": "true", -"traefik.http.middlewares.middleware10.headers.accesscontrolallowheaders": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolallowmethods": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlist": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlistregex": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolexposeheaders": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolmaxage": "42", -"traefik.http.middlewares.middleware10.headers.addvaryheader": "true", -"traefik.http.middlewares.middleware10.headers.allowedhosts": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.browserxssfilter": "true", -"traefik.http.middlewares.middleware10.headers.contentsecuritypolicy": "foobar", -"traefik.http.middlewares.middleware10.headers.contenttypenosniff": "true", -"traefik.http.middlewares.middleware10.headers.custombrowserxssvalue": "foobar", -"traefik.http.middlewares.middleware10.headers.customframeoptionsvalue": "foobar", -"traefik.http.middlewares.middleware10.headers.customrequestheaders.name0": "foobar", -"traefik.http.middlewares.middleware10.headers.customrequestheaders.name1": "foobar", -"traefik.http.middlewares.middleware10.headers.customresponseheaders.name0": "foobar", -"traefik.http.middlewares.middleware10.headers.customresponseheaders.name1": "foobar", -"traefik.http.middlewares.middleware10.headers.forcestsheader": "true", -"traefik.http.middlewares.middleware10.headers.framedeny": "true", -"traefik.http.middlewares.middleware10.headers.hostsproxyheaders": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.isdevelopment": "true", -"traefik.http.middlewares.middleware10.headers.permissionspolicy": "foobar", -"traefik.http.middlewares.middleware10.headers.publickey": "foobar", -"traefik.http.middlewares.middleware10.headers.referrerpolicy": "foobar", -"traefik.http.middlewares.middleware10.headers.sslproxyheaders.name0": "foobar", -"traefik.http.middlewares.middleware10.headers.sslproxyheaders.name1": "foobar", -"traefik.http.middlewares.middleware10.headers.stsincludesubdomains": "true", -"traefik.http.middlewares.middleware10.headers.stspreload": "true", -"traefik.http.middlewares.middleware10.headers.stsseconds": "42", -"traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.depth": "42", -"traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.excludedips": "foobar, foobar", -"traefik.http.middlewares.middleware11.ipallowlist.sourcerange": "foobar, foobar", -"traefik.http.middlewares.middleware12.inflightreq.amount": "42", -"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.depth": "42", -"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.excludedips": "foobar, foobar", -"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.requestheadername": "foobar", -"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.requesthost": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.commonname": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.country": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.domaincomponent": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.locality": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.organization": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.province": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.serialnumber": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.notafter": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.notbefore": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.sans": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.serialnumber": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.commonname": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.country": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.domaincomponent": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.locality": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organization": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organizationalunit": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.province": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.serialnumber": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.pem": "true", -"traefik.http.middlewares.middleware14.plugin.foobar.foo": "bar", -"traefik.http.middlewares.middleware15.ratelimit.average": "42", -"traefik.http.middlewares.middleware15.ratelimit.burst": "42", -"traefik.http.middlewares.middleware15.ratelimit.period": "42", -"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.ipstrategy.depth": "42", -"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.ipstrategy.excludedips": "foobar, foobar", -"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.requestheadername": "foobar", -"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.requesthost": "true", -"traefik.http.middlewares.middleware16.redirectregex.permanent": "true", -"traefik.http.middlewares.middleware16.redirectregex.regex": "foobar", -"traefik.http.middlewares.middleware16.redirectregex.replacement": "foobar", -"traefik.http.middlewares.middleware17.redirectscheme.permanent": "true", -"traefik.http.middlewares.middleware17.redirectscheme.port": "foobar", -"traefik.http.middlewares.middleware17.redirectscheme.scheme": "foobar", -"traefik.http.middlewares.middleware18.replacepath.path": "foobar", -"traefik.http.middlewares.middleware19.replacepathregex.regex": "foobar", -"traefik.http.middlewares.middleware19.replacepathregex.replacement": "foobar", -"traefik.http.middlewares.middleware20.retry.attempts": "42", -"traefik.http.middlewares.middleware20.retry.initialinterval": "42", -"traefik.http.middlewares.middleware21.stripprefix.prefixes": "foobar, foobar", -"traefik.http.middlewares.middleware22.stripprefixregex.regex": "foobar, foobar", -"traefik.http.middlewares.middleware23.grpcweb.alloworigins": "foobar, foobar", -"traefik.http.routers.router0.entrypoints": "foobar, foobar", -"traefik.http.routers.router0.middlewares": "foobar, foobar", -"traefik.http.routers.router0.priority": "42", -"traefik.http.routers.router0.rule": "foobar", -"traefik.http.routers.router0.service": "foobar", -"traefik.http.routers.router0.tls": "true", -"traefik.http.routers.router0.tls.certresolver": "foobar", -"traefik.http.routers.router0.tls.domains[0].main": "foobar", -"traefik.http.routers.router0.tls.domains[0].sans": "foobar, foobar", -"traefik.http.routers.router0.tls.domains[1].main": "foobar", -"traefik.http.routers.router0.tls.domains[1].sans": "foobar, foobar", -"traefik.http.routers.router0.tls.options": "foobar", -"traefik.http.routers.router1.entrypoints": "foobar, foobar", -"traefik.http.routers.router1.middlewares": "foobar, foobar", -"traefik.http.routers.router1.priority": "42", -"traefik.http.routers.router1.rule": "foobar", -"traefik.http.routers.router1.service": "foobar", -"traefik.http.routers.router1.tls": "true", -"traefik.http.routers.router1.tls.certresolver": "foobar", -"traefik.http.routers.router1.tls.domains[0].main": "foobar", -"traefik.http.routers.router1.tls.domains[0].sans": "foobar, foobar", -"traefik.http.routers.router1.tls.domains[1].main": "foobar", -"traefik.http.routers.router1.tls.domains[1].sans": "foobar, foobar", -"traefik.http.routers.router1.tls.options": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.followredirects": "true", -"traefik.http.services.service01.loadbalancer.healthcheck.headers.name0": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.headers.name1": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.hostname": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.interval": "42s", -"traefik.http.services.service01.loadbalancer.healthcheck.path": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.method": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.status": "42", -"traefik.http.services.service01.loadbalancer.healthcheck.port": "42", -"traefik.http.services.service01.loadbalancer.healthcheck.scheme": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.mode": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.timeout": "42s", -"traefik.http.services.service01.loadbalancer.passhostheader": "true", -"traefik.http.services.service01.loadbalancer.responseforwarding.flushinterval": "42s", -"traefik.http.services.service01.loadbalancer.serverstransport": "foobar", -"traefik.http.services.service01.loadbalancer.sticky.cookie": "true", -"traefik.http.services.service01.loadbalancer.sticky.cookie.httponly": "true", -"traefik.http.services.service01.loadbalancer.sticky.cookie.name": "foobar", -"traefik.http.services.service01.loadbalancer.sticky.cookie.samesite": "foobar", -"traefik.http.services.service01.loadbalancer.sticky.cookie.secure": "true", -"traefik.http.services.service01.loadbalancer.server.port": "foobar", -"traefik.http.services.service01.loadbalancer.server.scheme": "foobar", -"traefik.tcp.middlewares.tcpmiddleware00.ipallowlist.sourcerange": "foobar, foobar", -"traefik.tcp.middlewares.tcpmiddleware01.inflightconn.amount": "42", -"traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar", -"traefik.tcp.routers.tcprouter0.middlewares": "foobar, foobar", -"traefik.tcp.routers.tcprouter0.rule": "foobar", -"traefik.tcp.routers.tcprouter0.priority": "42", -"traefik.tcp.routers.tcprouter0.service": "foobar", -"traefik.tcp.routers.tcprouter0.tls": "true", -"traefik.tcp.routers.tcprouter0.tls.certresolver": "foobar", -"traefik.tcp.routers.tcprouter0.tls.domains[0].main": "foobar", -"traefik.tcp.routers.tcprouter0.tls.domains[0].sans": "foobar, foobar", -"traefik.tcp.routers.tcprouter0.tls.domains[1].main": "foobar", -"traefik.tcp.routers.tcprouter0.tls.domains[1].sans": "foobar, foobar", -"traefik.tcp.routers.tcprouter0.tls.options": "foobar", -"traefik.tcp.routers.tcprouter0.tls.passthrough": "true", -"traefik.tcp.routers.tcprouter1.entrypoints": "foobar, foobar", -"traefik.tcp.routers.tcprouter1.middlewares": "foobar, foobar", -"traefik.tcp.routers.tcprouter1.rule": "foobar", -"traefik.tcp.routers.tcprouter1.priority": "42", -"traefik.tcp.routers.tcprouter1.service": "foobar", -"traefik.tcp.routers.tcprouter1.tls": "true", -"traefik.tcp.routers.tcprouter1.tls.certresolver": "foobar", -"traefik.tcp.routers.tcprouter1.tls.domains[0].main": "foobar", -"traefik.tcp.routers.tcprouter1.tls.domains[0].sans": "foobar, foobar", -"traefik.tcp.routers.tcprouter1.tls.domains[1].main": "foobar", -"traefik.tcp.routers.tcprouter1.tls.domains[1].sans": "foobar, foobar", -"traefik.tcp.routers.tcprouter1.tls.options": "foobar", -"traefik.tcp.routers.tcprouter1.tls.passthrough": "true", -"traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version": "42", -"traefik.tcp.services.tcpservice01.loadbalancer.server.port": "foobar", -"traefik.tcp.services.tcpservice01.loadbalancer.server.tls": "true", -"traefik.tcp.services.tcpservice01.loadbalancer.serverstransport": "foobar", -"traefik.udp.routers.udprouter0.entrypoints": "foobar, foobar", -"traefik.udp.routers.udprouter0.service": "foobar", -"traefik.udp.routers.udprouter1.entrypoints": "foobar, foobar", -"traefik.udp.routers.udprouter1.service": "foobar", -"traefik.udp.services.udpservice01.loadbalancer.server.port": "foobar", -"traefik.tls.stores.Store0.defaultcertificate.certfile": "foobar", -"traefik.tls.stores.Store0.defaultcertificate.keyfile": "foobar", -"traefik.tls.stores.Store0.defaultgeneratedcert.domain.main": "foobar", -"traefik.tls.stores.Store0.defaultgeneratedcert.domain.sans": "foobar, foobar", -"traefik.tls.stores.Store0.defaultgeneratedcert.resolver": "foobar", -"traefik.tls.stores.Store1.defaultcertificate.certfile": "foobar", -"traefik.tls.stores.Store1.defaultcertificate.keyfile": "foobar", -"traefik.tls.stores.Store1.defaultgeneratedcert.domain.main": "foobar", -"traefik.tls.stores.Store1.defaultgeneratedcert.domain.sans": "foobar, foobar", -"traefik.tls.stores.Store1.defaultgeneratedcert.resolver": "foobar", diff --git a/docs/content/reference/dynamic-configuration/marathon.json b/docs/content/reference/dynamic-configuration/marathon.json deleted file mode 100644 index 131344a7e..000000000 --- a/docs/content/reference/dynamic-configuration/marathon.json +++ /dev/null @@ -1,2 +0,0 @@ -"traefik.enable": "true", -"traefik.marathon.ipaddressidx": "42", diff --git a/docs/content/reference/dynamic-configuration/marathon.md b/docs/content/reference/dynamic-configuration/marathon.md deleted file mode 100644 index 0e20679f8..000000000 --- a/docs/content/reference/dynamic-configuration/marathon.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Dynamic Configuration with Marathon Labels" -description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation on the Traefik dynamic configuration with Marathon Labels." ---- - -# Marathon Configuration Reference - -Dynamic configuration with Marathon Labels -{: .subtitle } - -```json -"labels": { - --8<-- "content/reference/dynamic-configuration/marathon.json" - --8<-- "content/reference/dynamic-configuration/marathon-labels.json" -} -``` diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 773f07829..1a95f346b 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -798,66 +798,6 @@ Ingress refresh throttle duration (Default: ```0```) `--providers.kubernetesingress.token`: Kubernetes bearer token (not needed for in-cluster client). -`--providers.marathon`: -Enable Marathon backend with default settings. (Default: ```false```) - -`--providers.marathon.basic.httpbasicauthuser`: -Basic authentication User. - -`--providers.marathon.basic.httpbasicpassword`: -Basic authentication Password. - -`--providers.marathon.constraints`: -Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application. - -`--providers.marathon.dcostoken`: -DCOSToken for DCOS environment, This will override the Authorization header. - -`--providers.marathon.defaultrule`: -Default rule. (Default: ```Host(`{{ normalize .Name }}`)```) - -`--providers.marathon.dialertimeout`: -Set a dialer timeout for Marathon. (Default: ```5```) - -`--providers.marathon.endpoint`: -Marathon server endpoint. You can also specify multiple endpoint for Marathon. (Default: ```http://127.0.0.1:8080```) - -`--providers.marathon.exposedbydefault`: -Expose Marathon apps by default. (Default: ```true```) - -`--providers.marathon.forcetaskhostname`: -Force to use the task's hostname. (Default: ```false```) - -`--providers.marathon.keepalive`: -Set a TCP Keep Alive time. (Default: ```10```) - -`--providers.marathon.respectreadinesschecks`: -Filter out tasks with non-successful readiness checks during deployments. (Default: ```false```) - -`--providers.marathon.responseheadertimeout`: -Set a response header timeout for Marathon. (Default: ```60```) - -`--providers.marathon.tls.ca`: -TLS CA - -`--providers.marathon.tls.cert`: -TLS cert - -`--providers.marathon.tls.insecureskipverify`: -TLS insecure skip verify (Default: ```false```) - -`--providers.marathon.tls.key`: -TLS key - -`--providers.marathon.tlshandshaketimeout`: -Set a TLS handshake timeout for Marathon. (Default: ```5```) - -`--providers.marathon.trace`: -Display additional provider logs. (Default: ```false```) - -`--providers.marathon.watch`: -Watch provider. (Default: ```true```) - `--providers.nomad`: Enable Nomad backend with default settings. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 38f8bcba9..065ae8bff 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -798,66 +798,6 @@ Ingress refresh throttle duration (Default: ```0```) `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_TOKEN`: Kubernetes bearer token (not needed for in-cluster client). -`TRAEFIK_PROVIDERS_MARATHON`: -Enable Marathon backend with default settings. (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_BASIC_HTTPBASICAUTHUSER`: -Basic authentication User. - -`TRAEFIK_PROVIDERS_MARATHON_BASIC_HTTPBASICPASSWORD`: -Basic authentication Password. - -`TRAEFIK_PROVIDERS_MARATHON_CONSTRAINTS`: -Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application. - -`TRAEFIK_PROVIDERS_MARATHON_DCOSTOKEN`: -DCOSToken for DCOS environment, This will override the Authorization header. - -`TRAEFIK_PROVIDERS_MARATHON_DEFAULTRULE`: -Default rule. (Default: ```Host(`{{ normalize .Name }}`)```) - -`TRAEFIK_PROVIDERS_MARATHON_DIALERTIMEOUT`: -Set a dialer timeout for Marathon. (Default: ```5```) - -`TRAEFIK_PROVIDERS_MARATHON_ENDPOINT`: -Marathon server endpoint. You can also specify multiple endpoint for Marathon. (Default: ```http://127.0.0.1:8080```) - -`TRAEFIK_PROVIDERS_MARATHON_EXPOSEDBYDEFAULT`: -Expose Marathon apps by default. (Default: ```true```) - -`TRAEFIK_PROVIDERS_MARATHON_FORCETASKHOSTNAME`: -Force to use the task's hostname. (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_KEEPALIVE`: -Set a TCP Keep Alive time. (Default: ```10```) - -`TRAEFIK_PROVIDERS_MARATHON_RESPECTREADINESSCHECKS`: -Filter out tasks with non-successful readiness checks during deployments. (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_RESPONSEHEADERTIMEOUT`: -Set a response header timeout for Marathon. (Default: ```60```) - -`TRAEFIK_PROVIDERS_MARATHON_TLSHANDSHAKETIMEOUT`: -Set a TLS handshake timeout for Marathon. (Default: ```5```) - -`TRAEFIK_PROVIDERS_MARATHON_TLS_CA`: -TLS CA - -`TRAEFIK_PROVIDERS_MARATHON_TLS_CERT`: -TLS cert - -`TRAEFIK_PROVIDERS_MARATHON_TLS_INSECURESKIPVERIFY`: -TLS insecure skip verify (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_TLS_KEY`: -TLS key - -`TRAEFIK_PROVIDERS_MARATHON_TRACE`: -Display additional provider logs. (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_WATCH`: -Watch provider. (Default: ```true```) - `TRAEFIK_PROVIDERS_NOMAD`: Enable Nomad backend with default settings. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 8e634d9cf..5b68317a9 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -98,28 +98,6 @@ watch = true filename = "foobar" debugLogGeneratedTemplate = true - [providers.marathon] - constraints = "foobar" - trace = true - watch = true - endpoint = "foobar" - defaultRule = "foobar" - exposedByDefault = true - dcosToken = "foobar" - dialerTimeout = "42s" - responseHeaderTimeout = "42s" - tlsHandshakeTimeout = "42s" - keepAlive = "42s" - forceTaskHostname = true - respectReadinessChecks = true - [providers.marathon.tls] - ca = "foobar" - cert = "foobar" - key = "foobar" - insecureSkipVerify = true - [providers.marathon.basic] - httpBasicAuthUser = "foobar" - httpBasicPassword = "foobar" [providers.kubernetesIngress] endpoint = "foobar" token = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 32116d797..1ce4ec6c1 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -105,28 +105,6 @@ providers: watch: true filename: foobar debugLogGeneratedTemplate: true - marathon: - constraints: foobar - trace: true - watch: true - endpoint: foobar - defaultRule: foobar - exposedByDefault: true - dcosToken: foobar - tls: - ca: foobar - cert: foobar - key: foobar - insecureSkipVerify: true - dialerTimeout: 42s - responseHeaderTimeout: 42s - tlsHandshakeTimeout: 42s - keepAlive: 42s - forceTaskHostname: true - basic: - httpBasicAuthUser: foobar - httpBasicPassword: foobar - respectReadinessChecks: true kubernetesIngress: endpoint: foobar token: foobar diff --git a/docs/content/routing/providers/marathon.md b/docs/content/routing/providers/marathon.md deleted file mode 100644 index ea13368ad..000000000 --- a/docs/content/routing/providers/marathon.md +++ /dev/null @@ -1,545 +0,0 @@ ---- -title: "Traefik Routing Configuration for Marathon" -description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation to understand the Traefik routing configuration for Marathon." ---- - -# Traefik & Marathon - -Traefik can be configured to use Marathon as a provider. -{: .subtitle } - -See also [Marathon user guide](../../user-guides/marathon.md). - -## Routing Configuration - -!!! info "Labels" - - - Labels are case insensitive. - - The complete list of labels can be found in [the reference page](../../reference/dynamic-configuration/marathon.md). - -### General - -Traefik creates, for each Marathon application, a corresponding [service](../services/index.md) and [router](../routers/index.md). - -The Service automatically gets a server per instance of the application, -and the router automatically gets a rule defined by defaultRule (if no rule for it was defined in labels). - -#### Service definition - ---8<-- "content/routing/providers/service-by-label.md" - -??? example "Automatic service assignment with labels" - - Service myservice gets automatically assigned to router myproxy. - - ```json - labels: { - "traefik.http.routers.myproxy.rule": "Host(`example.net`)", - "traefik.http.services.myservice.loadbalancer.server.port": "80" - } - ``` - -??? example "Automatic service creation and assignment with labels" - - No service specified or defined, and yet one gets automatically created. - and assigned to router myproxy. - - ```json - labels: { - "traefik.http.routers.myproxy.rule": "Host(`example.net`)" - } - ``` - -### Routers - -To update the configuration of the Router automatically attached to the application, -add labels starting with `traefik.http.routers.{router-name-of-your-choice}.` and followed by the option you want to change. - -For example, to change the routing rule, you could add the label ```"traefik.http.routers.routername.rule": "Host(`example.com`)"```. - -!!! warning "The character `@` is not authorized in the router name ``." - -??? info "`traefik.http.routers..rule`" - - See [rule](../routers/index.md#rule) for more information. - - ```json - "traefik.http.routers.myrouter.rule": "Host(`example.com`)" - ``` - -??? info "`traefik.http.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints) for more information. - - ```json - "traefik.http.routers.myrouter.entrypoints": "ep1,ep2" - ``` - -??? info "`traefik.http.routers..middlewares`" - - See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information. - - ```json - "traefik.http.routers.myrouter.middlewares": "auth,prefix,cb" - ``` - -??? info "`traefik.http.routers..service`" - - See [rule](../routers/index.md#service) for more information. - - ```json - "traefik.http.routers.myrouter.service": "myservice" - ``` - -??? info "`traefik.http.routers..tls`" - - See [tls](../routers/index.md#tls) for more information. - - ```json - "traefik.http.routers.myrouter.tls": "true" - ``` - -??? info "`traefik.http.routers..tls.certresolver`" - - See [certResolver](../routers/index.md#certresolver) for more information. - - ```json - "traefik.http.routers.myrouter.tls.certresolver": "myresolver" - ``` - -??? info "`traefik.http.routers..tls.domains[n].main`" - - See [domains](../routers/index.md#domains) for more information. - - ```json - "traefik.http.routers.myrouter.tls.domains[0].main": "example.org" - ``` - -??? info "`traefik.http.routers..tls.domains[n].sans`" - - See [domains](../routers/index.md#domains) for more information. - - ```json - "traefik.http.routers.myrouter.tls.domains[0].sans": "test.example.org,dev.example.org" - ``` - -??? info "`traefik.http.routers..tls.options`" - - See [options](../routers/index.md#options) for more information. - - ```json - "traefik.http.routers.myrouter.tls.options": "foobar" - ``` - -??? info "`traefik.http.routers..priority`" - - See [priority](../routers/index.md#priority) for more information. - - ```json - "traefik.http.routers.myrouter.priority": "42" - ``` - -### Services - -To update the configuration of the Service automatically attached to the container, -add labels starting with `traefik.http.services.{service-name-of-your-choice}.`, followed by the option you want to change. - -For example, to change the passHostHeader behavior, you'd add the label `"traefik.http.services.servicename.loadbalancer.passhostheader": "false"`. - -!!! warning "The character `@` is not authorized in the service name ``." - -??? info "`traefik.http.services..loadbalancer.server.port`" - - Registers a port. - Useful when the container exposes multiples ports. - - ```json - "traefik.http.services.myservice.loadbalancer.server.port": "8080" - ``` - -??? info "`traefik.http.services..loadbalancer.server.scheme`" - - Overrides the default scheme. - - ```json - "traefik.http.services.myservice.loadbalancer.server.scheme": "http" - ``` - -??? info "`traefik.http.services..loadbalancer.serverstransport`" - - Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. - See [serverstransport](../services/index.md#serverstransport) for more information. - - ```json - "traefik.http.services..loadbalancer.serverstransport": "foobar@file" - ``` - -??? info "`traefik.http.services..loadbalancer.passhostheader`" - - See [pass Host header](../services/index.md#pass-host-header) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.passhostheader": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.headers.`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.headers.X-Foo": "foobar" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.hostname`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.hostname": "example.org" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.interval`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.interval": "10" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.path`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.path": "/foo" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.method`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.method": "foobar" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.status`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.status": "42" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.port`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.port": "42" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.scheme`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.scheme": "http" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.timeout`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.timeout": "10" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.followredirects`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.followredirects": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.httponly`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie.httponly": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.name`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie.name": "foobar" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.secure`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie.secure": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.samesite`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite": "none" - ``` - -??? info "`traefik.http.services..loadbalancer.responseforwarding.flushinterval`" - - See [response forwarding](../services/index.md#response-forwarding) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.responseforwarding.flushinterval": "10" - ``` - -### Middleware - -You can declare pieces of middleware using labels starting with `traefik.http.middlewares.{middleware-name-of-your-choice}.`, followed by the middleware type/options. - -For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `"traefik.http.middlewares.my-redirect.redirectscheme.scheme": "https"`. - -More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). - -!!! warning "The character `@` is not authorized in the middleware name." - -??? example "Declaring and Referencing a Middleware" - - ```json - { - ... - "labels": { - "traefik.http.middlewares.my-redirect.redirectscheme.scheme": "https", - "traefik.http.routers.my-container.middlewares": "my-redirect" - } - } - ``` - -!!! warning "Conflicts in Declaration" - - If you declare multiple middleware with the same name but with different parameters, the middleware fails to be declared. - -### TCP - -You can declare TCP Routers and/or Services using labels. - -??? example "Declaring TCP Routers and Services" - - ```json - { - ... - "labels": { - "traefik.tcp.routers.my-router.rule": "HostSNI(`example.com`)", - "traefik.tcp.routers.my-router.tls": "true", - "traefik.tcp.services.my-service.loadbalancer.server.port": "4123" - } - } - ``` - -!!! warning "TCP and HTTP" - - If you declare a TCP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no TCP Router/Service is defined). - You can declare both a TCP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually). - -#### TCP Routers - -??? info "`traefik.tcp.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.entrypoints": "ep1,ep2" - ``` - - -??? info "`traefik.tcp.routers..rule`" - - See [rule](../routers/index.md#rule_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.rule": "HostSNI(`example.com`)" - ``` - -??? info "`traefik.tcp.routers..service`" - - See [service](../routers/index.md#services) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.service": "myservice" - ``` - -??? info "`traefik.tcp.routers..tls`" - - See [TLS](../routers/index.md#tls_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls": "true - ``` - -??? info "`traefik.tcp.routers..tls.certresolver`" - - See [certResolver](../routers/index.md#certresolver_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.certresolver": "myresolver" - ``` - -??? info "`traefik.tcp.routers..tls.domains[n].main`" - - See [domains](../routers/index.md#domains_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.domains[0].main": "example.org" - ``` - -??? info "`traefik.tcp.routers..tls.domains[n].sans`" - - See [domains](../routers/index.md#domains_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.domains[0].sans": "test.example.org,dev.example.org" - ``` - -??? info "`traefik.tcp.routers..tls.options`" - - See [options](../routers/index.md#options_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.options": "mysoptions" - ``` - -??? info "`traefik.tcp.routers..tls.passthrough`" - - See [TLS](../routers/index.md#tls_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.passthrough": "true" - ``` - -??? info "`traefik.tcp.routers..priority`" - - See [priority](../routers/index.md#priority_1) for more information. - - ```json - "traefik.tcp.routers.myrouter.priority": "42" - ``` - -#### TCP Services - -??? info "`traefik.tcp.services..loadbalancer.server.port`" - - Registers a port of the application. - - ```json - "traefik.tcp.services.mytcpservice.loadbalancer.server.port": "423" - ``` - -??? info "`traefik.tcp.services..loadbalancer.server.tls`" - - Determines whether to use TLS when dialing with the backend. - - ```json - "traefik.tcp.services.mytcpservice.loadbalancer.server.tls": "true" - ``` - -??? info "`traefik.tcp.services..loadbalancer.proxyprotocol.version`" - - See [PROXY protocol](../services/index.md#proxy-protocol) for more information. - - ```json - "traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version": "1" - ``` - -??? info "`traefik.tcp.services..loadbalancer.serverstransport`" - - Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. - See [serverstransport](../services/index.md#serverstransport_2) for more information. - - ```json - "traefik.tcp.services..loadbalancer.serverstransport": "foobar@file" - ``` - -### UDP - -You can declare UDP Routers and/or Services using labels. - -??? example "Declaring UDP Routers and Services" - - ```json - { - ... - "labels": { - "traefik.udp.routers.my-router.entrypoints": "udp", - "traefik.udp.services.my-service.loadbalancer.server.port": "4123" - } - } - ``` - -!!! warning "UDP and HTTP" - - If you declare a UDP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no UDP Router/Service is defined). - You can declare both a UDP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually). - -#### UDP Routers - -??? info "`traefik.udp.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints_2) for more information. - - ```json - "traefik.udp.routers.myudprouter.entrypoints": "ep1,ep2" - ``` - -??? info "`traefik.udp.routers..service`" - - See [service](../routers/index.md#services_1) for more information. - - ```json - "traefik.udp.routers.myudprouter.service": "myservice" - ``` - -#### UDP Services - -??? info "`traefik.udp.services..loadbalancer.server.port`" - - Registers a port of the application. - - ```json - "traefik.udp.services.myudpservice.loadbalancer.server.port": "423" - ``` - -### Specific Provider Options - -#### `traefik.enable` - -```json -"traefik.enable": "true" -``` - -Setting this option controls whether Traefik exposes the application. -It overrides the value of `exposedByDefault`. - -#### `traefik.marathon.ipadressidx` - -```json -"traefik.marathon.ipadressidx": "1" -``` - -If a task has several IP addresses, this option specifies which one, in the list of available addresses, to select. diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index 7253eb24f..12bc83f60 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -557,8 +557,7 @@ which is basically where the request will be passed along to. In general, a service assigned to a router should have been defined, but there are exceptions for label-based providers. -See the specific [docker](../providers/docker.md#service-definition), -or [marathon](../providers/marathon.md#service-definition) documentation. +See the specific [docker](../providers/docker.md#service-definition) documentation. !!! warning "The character `@` is not authorized in the service name." diff --git a/docs/content/user-guides/marathon.md b/docs/content/user-guides/marathon.md deleted file mode 100644 index 2b374ca24..000000000 --- a/docs/content/user-guides/marathon.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: "Traefik Proxy and Marathon Integration Guide |Traefik Docs" -description: "This guide explains how to integrate Marathon and operate the cluster in a reliable way from the Traefik Proxy standpoint." ---- - -# Marathon - -This guide explains how to integrate Marathon and operate the cluster in a reliable way from Traefik's standpoint. - -## Host detection - -Marathon offers multiple ways to run (Docker-containerized) applications, the most popular ones being - -- BRIDGE-networked containers with dynamic high ports exposed -- HOST-networked containers with host machine ports -- containers with dedicated IP addresses ([IP-per-task](https://mesosphere.github.io/marathon/docs/ip-per-task.html)). - -Traefik tries to detect the configured mode and route traffic to the right IP addresses. It is possible to force using task hosts with the `forceTaskHostname` option. - -## Port detection - -Traefik also attempts to determine the right port (which is a [non-trivial matter in Marathon](https://mesosphere.github.io/marathon/docs/ports.html)) from the following sources: - -1. An arbitrary port specified through label `traefik.http.services.serviceName.loadbalancer.server.port=8080` -1. The task port. -1. The port from the application's `portDefinitions` field. -1. The port from the application's `ipAddressPerTask` field. - -### Port label syntax - -To select a port, you can either - -- specify the port directly: `traefik.http.services.serviceName.loadbalancer.server.port=8080` -- specify a port index: `traefik.http.services.serviceName.loadbalancer.server.port=index:0` -- specify a port name: `traefik.http.services.serviceName.loadbalancer.server.port=name:http` -- otherwise the first one is selected. - -## Achieving high availability - -### Scenarios - -There are three scenarios where the availability of a Marathon application could be impaired along with the risk of losing or failing requests: - -- During the startup phase when Traefik already routes requests to the backend even though it has not completed its bootstrapping process yet. -- During the shutdown phase when Traefik still routes requests to the backend while the backend is already terminating. -- During a failure of the application when Traefik has not yet identified the backend as being erroneous. - -The first two scenarios are common with every rolling upgrade of an application (i.e. a new version release or configuration update). - -The following sub-sections describe how to resolve or mitigate each scenario. - -#### Startup - -It is possible to define [readiness checks](https://mesosphere.github.io/marathon/docs/readiness-checks.html) (available since Marathon version 1.1) per application and have Marathon take these into account during the startup phase. - -The idea is that each application provides an HTTP endpoint that Marathon queries periodically during an ongoing deployment in order to mark the associated readiness check result as successful if and only if the endpoint returns a response within the configured HTTP code range. -As long as the check keeps failing, Marathon will not proceed with the deployment (within the configured upgrade strategy bounds). - -Beginning with version 1.4, Traefik respects readiness check results if the Traefik option is set and checks are configured on the applications accordingly. - -!!! note - Due to the way readiness check results are currently exposed by the Marathon API, ready tasks may be taken into rotation with a small delay. - It is on the order of one readiness check timeout interval (as configured on the application specification) and guarantees that non-ready tasks do not receive traffic prematurely. - -If readiness checks are not possible, a current mitigation strategy is to enable [retries](../middlewares/http/retry.md) and make sure that a sufficient number of healthy application tasks exist so that one retry will likely hit one of those. -Apart from its probabilistic nature, the workaround comes at the price of increased latency. - -#### Shutdown - -It is possible to install a [termination handler](https://mesosphere.github.io/marathon/docs/health-checks.html) (available since Marathon version 1.3) with each application whose responsibility it is to delay the shutdown process long enough until the backend has been taken out of load-balancing rotation with reasonable confidence (i.e., Traefik has received an update from the Marathon event bus, recomputes the available Marathon backends, and applies the new configuration). -Specifically, each termination handler should install a signal handler listening for a SIGTERM signal and implement the following steps on signal reception: - -1. Disable Keep-Alive HTTP connections. -1. Keep accepting HTTP requests for a certain period of time. -1. Stop accepting new connections. -1. Finish serving any in-flight requests. -1. Shut down. - -Traefik already ignores Marathon tasks whose state does not match `TASK_RUNNING`; since terminating tasks transition into the `TASK_KILLING` and eventually `TASK_KILLED` state, there is nothing further that needs to be done on Traefik's end. - -How long HTTP requests should continue to be accepted in step 2 depends on how long Traefik needs to receive and process the Marathon configuration update. -Under regular operational conditions, it should be on the order of seconds, with 10 seconds possibly being a good default value. - -Again, configuring Traefik to do retries (as discussed in the previous section) can serve as a decent workaround strategy. -Paired with termination handlers, they would cover for those cases where either the termination sequence or Traefik cannot complete their part of the orchestration process in time. - -#### Failure - -A failing application always happens unexpectedly, and hence, it is very difficult or even impossible to rule out the adversal effects categorically. - -Failure reasons vary broadly and could stretch from unacceptable slowness, a task crash, or a network split. - -There are two mitigation efforts: - -1. Configure [Marathon health checks](https://mesosphere.github.io/marathon/docs/health-checks.html) on each application. -2. Configure Traefik health checks (possibly via the `traefik.http.services.yourServiceName.loadbalancer.healthcheck.*` labels) and make sure they probe with proper frequency. - -The Marathon health check makes sure that applications once deemed dysfunctional are being rescheduled to different slaves. -However, they might take a while to get triggered and the follow-up processes to complete. - -For that reason, the Traefik health check provides an additional check that responds more rapidly and does not require a configuration reload to happen. -Additionally, it protects from cases that the Marathon health check may not be able to cover, such as a network split. - -### (Non-)Alternatives - -There are a few alternatives of varying quality that are frequently asked for. - -The remaining section is going to explore them along with a benefit/cost trade-off. - -#### Reusing Marathon health checks - -It may seem obvious to reuse the Marathon health checks as a signal to Traefik whether an application should be taken into load-balancing rotation or not. - -Apart from the increased latency a failing health check may have, a major problem with this is that Marathon does not persist the health check results. -Consequently, if a master re-election occurs in the Marathon clusters, all health check results will revert to the _unknown_ state, effectively causing all applications inside the cluster to become unavailable and leading to a complete cluster failure. -Re-elections do not only happen during regular maintenance work (often requiring rolling upgrades of the Marathon nodes) but also when the Marathon leader fails spontaneously. -As such, there is no way to handle this situation deterministically. - -Finally, Marathon health checks are not mandatory (the default is to use the task state as reported by Mesos), so requiring them for Traefik would raise the entry barrier for Marathon users. - -Traefik used to use the health check results as a strict requirement but moved away from it as [users reported the dramatic consequences](https://github.com/traefik/traefik/issues/653). - -#### Draining - -Another common approach is to let a proxy drain backends that are supposed to shut down. -That is, once a backend is supposed to shut down, Traefik would stop forwarding requests. - -On the plus side, this would not require any modifications to the application in question. -However, implementing this fully within Traefik seems like a non-trivial undertaking. - -Additionally, the approach is less flexible compared to a custom termination handler since only the latter allows for the implementation of custom termination sequences that go beyond simple request draining (e.g., persisting a snapshot state to disk prior to terminating). - -The feature is currently not implemented; a request for draining in general is at [issue 41](https://github.com/traefik/traefik/issues/41). diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index d45f42498..4819e16c8 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -81,7 +81,6 @@ nav: - 'Consul Catalog': 'providers/consul-catalog.md' - 'Nomad': 'providers/nomad.md' - 'ECS': 'providers/ecs.md' - - 'Marathon': 'providers/marathon.md' - 'File': 'providers/file.md' - 'Consul': 'providers/consul.md' - 'Etcd': 'providers/etcd.md' @@ -101,7 +100,6 @@ nav: - 'Consul Catalog': 'routing/providers/consul-catalog.md' - 'Nomad': 'routing/providers/nomad.md' - 'ECS': 'routing/providers/ecs.md' - - 'Marathon': 'routing/providers/marathon.md' - 'KV': 'routing/providers/kv.md' - 'HTTPS & TLS': - 'Overview': 'https/overview.md' @@ -170,7 +168,6 @@ nav: - 'User Guides': - 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md' - 'gRPC Examples': 'user-guides/grpc.md' - - 'Marathon': 'user-guides/marathon.md' - 'Docker': - 'Basic Example': 'user-guides/docker-compose/basic-example/index.md' - 'HTTPS with Let''s Encrypt': @@ -206,7 +203,6 @@ nav: - 'Nomad': "reference/dynamic-configuration/nomad.md" - 'ECS': 'reference/dynamic-configuration/ecs.md' - 'KV': 'reference/dynamic-configuration/kv.md' - - 'Marathon': 'reference/dynamic-configuration/marathon.md' - 'Deprecation Notices': - 'Releases': 'deprecation/releases.md' - 'Features': 'deprecation/features.md' diff --git a/go.mod b/go.mod index 1ddd41337..bca864e5b 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,6 @@ require ( github.com/docker/docker v20.10.7+incompatible github.com/docker/go-connections v0.4.0 github.com/fatih/structs v1.1.0 - github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2 github.com/go-acme/lego/v4 v4.9.1 github.com/go-check/check v0.0.0-00010101000000-000000000000 github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea @@ -173,7 +172,6 @@ require ( github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/go-licenser v0.3.1 // indirect github.com/elastic/go-sysinfo v1.1.1 // indirect diff --git a/go.sum b/go.sum index 11aa3b6de..8d94db2f0 100644 --- a/go.sum +++ b/go.sum @@ -589,8 +589,6 @@ github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNE github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e h1:rMOGp6HPeMHbdLrZkX2nD+94uqDunc27tXVuS+ey4mQ= -github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -665,8 +663,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2 h1:df6OFl8WNXk82xxP3R9ZPZ5seOA8XZkwLdbEzZF1/xI= -github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2/go.mod h1:GLyXJD41gBO/NPKVPGQbhyyC06eugGy15QEZyUkE2/s= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.87.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= diff --git a/integration/fixtures/marathon/simple.toml b/integration/fixtures/marathon/simple.toml deleted file mode 100644 index d43cdbc2e..000000000 --- a/integration/fixtures/marathon/simple.toml +++ /dev/null @@ -1,22 +0,0 @@ -[global] - checkNewVersion = false - sendAnonymousUsage = false - -[log] - level = "DEBUG" - noColor = true - -[entryPoints] - [entryPoints.web] - address = ":8000" - [entryPoints.traefik] - address = ":9090" - -[api] - insecure = true - -[providers] - [providers.marathon] - endpoint = "{{.MarathonURL}}" - watch = true - exposedByDefault = true diff --git a/integration/integration_test.go b/integration/integration_test.go index d71409d38..8e7f19e25 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -91,8 +91,6 @@ func Test(t *testing.T) { } check.Suite(&KeepAliveSuite{}) check.Suite(&LogRotationSuite{}) - check.Suite(&MarathonSuite{}) - check.Suite(&MarathonSuite15{}) if !useVPN { check.Suite(&ProxyProtocolSuite{}) } diff --git a/integration/marathon15_test.go b/integration/marathon15_test.go deleted file mode 100644 index 493db256a..000000000 --- a/integration/marathon15_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package integration - -import ( - "net/http" - "os" - "time" - - "github.com/gambol99/go-marathon" - "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - checker "github.com/vdemeester/shakers" -) - -// Marathon test suites. -type MarathonSuite15 struct { - BaseSuite - marathonURL string -} - -func (s *MarathonSuite15) SetUpSuite(c *check.C) { - s.createComposeProject(c, "marathon15") - s.composeUp(c) - - s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080" - - // Wait for Marathon readiness prior to creating the client so that we - // don't run into the "all cluster members down" state right from the - // start. - err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) -} - -func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) { - // Start Traefik. - file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct { - MarathonURL string - }{s.marathonURL}) - defer os.Remove(file) - cmd, display := s.traefikCmd(withConfigFile(file)) - defer display(c) - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - // Wait for Traefik to turn ready. - err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound)) - c.Assert(err, checker.IsNil) - - // Prepare Marathon client. - config := marathon.NewDefaultConfig() - config.URL = s.marathonURL - client, err := marathon.NewClient(config) - c.Assert(err, checker.IsNil) - - // Create test application to be deployed. - app := marathon.NewDockerApplication(). - Name("/whoami"). - CPU(0.1). - Memory(32). - EmptyNetworks(). - AddLabel("traefik.http.Routers.rt.Rule", "PathPrefix(`/service`)") - app.Container. - Expose(80). - Docker. - Container("traefik/whoami") - *app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork()) - - // Deploy the test application. - deployApplication(c, client, app) - - // Query application via Traefik. - err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - - // Create test application with services to be deployed. - app = marathon.NewDockerApplication(). - Name("/whoami"). - CPU(0.1). - Memory(32). - EmptyNetworks(). - AddLabel("traefik.http.Routers.app.Rule", "PathPrefix(`/app`)") - app.Container. - Expose(80). - Docker. - Container("traefik/whoami") - *app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork()) - - // Deploy the test application. - deployApplication(c, client, app) - - // Query application via Traefik. - err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) -} diff --git a/integration/marathon_test.go b/integration/marathon_test.go deleted file mode 100644 index 5552e0d0b..000000000 --- a/integration/marathon_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package integration - -import ( - "net/http" - "os" - "time" - - "github.com/gambol99/go-marathon" - "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - checker "github.com/vdemeester/shakers" -) - -const containerNameMarathon = "marathon" - -// Marathon test suites. -type MarathonSuite struct { - BaseSuite - marathonURL string -} - -func (s *MarathonSuite) SetUpSuite(c *check.C) { - s.createComposeProject(c, "marathon") - s.composeUp(c) - - s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080" - - // Wait for Marathon readiness prior to creating the client so that we - // don't run into the "all cluster members down" state right from the - // start. - err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) -} - -func deployApplication(c *check.C, client marathon.Marathon, application *marathon.Application) { - deploy, err := client.UpdateApplication(application, false) - c.Assert(err, checker.IsNil) - // Wait for deployment to complete. - c.Assert(client.WaitOnDeployment(deploy.DeploymentID, 1*time.Minute), checker.IsNil) -} - -func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) { - // Start Traefik. - file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct { - MarathonURL string - }{s.marathonURL}) - defer os.Remove(file) - - cmd, display := s.traefikCmd(withConfigFile(file)) - defer display(c) - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - // Wait for Traefik to turn ready. - err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound)) - c.Assert(err, checker.IsNil) - - // Prepare Marathon client. - config := marathon.NewDefaultConfig() - config.URL = s.marathonURL - client, err := marathon.NewClient(config) - c.Assert(err, checker.IsNil) - - // Create test application to be deployed. - app := marathon.NewDockerApplication(). - Name("/whoami"). - CPU(0.1). - Memory(32). - AddLabel("traefik.http.Routers.rt.Rule", "PathPrefix(`/service`)") - app.Container.Docker.Bridged(). - Expose(80). - Container("traefik/whoami") - - // Deploy the test application. - deployApplication(c, client, app) - - // Query application via Traefik. - err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - - // Create test application with services to be deployed. - app = marathon.NewDockerApplication(). - Name("/whoami"). - CPU(0.1). - Memory(32). - AddLabel("traefik.http.Routers.app.Rule", "PathPrefix(`/app`)") - app.Container.Docker.Bridged(). - Expose(80). - Container("traefik/whoami") - - // Deploy the test application. - deployApplication(c, client, app) - - // Query application via Traefik. - err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) -} diff --git a/integration/resources/compose/marathon.yml b/integration/resources/compose/marathon.yml deleted file mode 100644 index 5a2be1e67..000000000 --- a/integration/resources/compose/marathon.yml +++ /dev/null @@ -1,60 +0,0 @@ -version: "3.8" -services: - zookeeper: - image: zookeeper:3.4.10 - - mesos-master: - image: mesosphere/mesos-master:1.0.1-2.0.93.ubuntu1404 - # Uncomment published ports for interactive debugging. - # ports: - # - "5050:5050" - environment: - MESOS_HOSTNAME: mesos-master - MESOS_CLUSTER: local - MESOS_REGISTRY: in_memory - MESOS_LOG_DIR: /var/log - MESOS_WORK_DIR: /var/lib/mesos - MESOS_ZK: zk://zookeeper:2181/mesos - - mesos-slave: - image: docker:dind - privileged: true - # Uncomment published ports for interactive debugging. - # ports: - # - "5051:5051" - # docker version in mesosphere/mesos-slave-dind:0.3.0_mesos-1.0.1_docker-1.10.3_ubuntu-14.04.5 is too old and can't - # pull images on new kernels. - command: - - "/bin/sh" - - "-c" - - "(/usr/local/bin/dockerd-entrypoint.sh &); sleep 10; set -x; \ - docker -H unix:///var/run/docker.sock run -d --net=host --privileged \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v /cgroup:/cgroup -v /sys:/sys \ - -v /usr/local/bin/docker:/usr/local/bin/docker \ - -e MESOS_HOSTNAME=$$(hostname -i) \ - -e MESOS_CONTAINERIZERS=docker,mesos \ - -e MESOS_ISOLATOR=cgroups/cpu,cgroups/mem \ - -e MESOS_LOG_DIR=/var/log \ - -e MESOS_MASTER=zk://zookeeper:2181/mesos \ - -e MESOS_PORT=5051 \ - -e MESOS_WORK_DIR=/var/lib/mesos \ - -e MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins \ - -e MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs \ - -e MESOS_DOCKER_STOP_TIMEOUT=60secs \ - -e MESOS_RESOURCES='cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]' \ - mesosphere/mesos-slave:1.0.3; sleep 600" - - marathon: - image: mesosphere/marathon:v1.3.12 - # Uncomment published ports for interactive debugging. - # ports: - # - "8080:8080" - environment: - MARATHON_ZK: zk://zookeeper:2181/marathon - MARATHON_MASTER: zk://zookeeper:2181/mesos - -networks: - default: - name: traefik-test-network - external: true diff --git a/integration/resources/compose/marathon15.yml b/integration/resources/compose/marathon15.yml deleted file mode 100644 index 6a5774fc7..000000000 --- a/integration/resources/compose/marathon15.yml +++ /dev/null @@ -1,59 +0,0 @@ -version: "3.8" -services: - zookeeper: - image: zookeeper:3.4.10 - - mesos-master: - image: mesosphere/mesos-master:1.4.1 - # Uncomment published ports for interactive debugging. - # ports: - # - "5050:5050" - environment: - MESOS_HOSTNAME: mesos-master - MESOS_CLUSTER: local - MESOS_REGISTRY: in_memory - MESOS_LOG_DIR: /var/log - MESOS_WORK_DIR: /var/lib/mesos - MESOS_ZK: zk://zookeeper:2181/mesos - - mesos-slave: - image: docker:dind - privileged: true - # Uncomment published ports for interactive debugging. - # ports: - # - "5051:5051" - command: - - "/bin/sh" - - "-c" - - "(/usr/local/bin/dockerd-entrypoint.sh &); sleep 10; set -x; \ - docker -H unix:///var/run/docker.sock run -d --net=host --privileged \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v /cgroup:/cgroup -v /sys:/sys \ - -v /usr/local/bin/docker:/usr/local/bin/docker \ - -e MESOS_HOSTNAME=$$(hostname -i) \ - -e MESOS_CONTAINERIZERS=docker,mesos \ - -e MESOS_ISOLATOR=cgroups/cpu,cgroups/mem \ - -e MESOS_LOG_DIR=/var/log \ - -e MESOS_MASTER=zk://zookeeper:2181/mesos \ - -e MESOS_PORT=5051 \ - -e MESOS_WORK_DIR=/var/lib/mesos \ - -e MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins \ - -e MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs \ - -e MESOS_DOCKER_STOP_TIMEOUT=60secs \ - -e MESOS_RESOURCES='cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]' \ - -e MESOS_SYSTEMD_ENABLE_SUPPORT=false \ - mesosphere/mesos-slave:1.4.1; sleep 600" - - marathon: - image: mesosphere/marathon:v1.5.9 - # Uncomment published ports for interactive debugging. - # ports: - # - "8080:8080" - environment: - MARATHON_ZK: zk://zookeeper:2181/marathon - MARATHON_MASTER: zk://zookeeper:2181/mesos - -networks: - default: - name: traefik-test-network - external: true diff --git a/pkg/api/handler_overview_test.go b/pkg/api/handler_overview_test.go index 92584b9f8..2985d93ae 100644 --- a/pkg/api/handler_overview_test.go +++ b/pkg/api/handler_overview_test.go @@ -18,7 +18,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/hub" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/ingress" - "github.com/traefik/traefik/v2/pkg/provider/marathon" "github.com/traefik/traefik/v2/pkg/provider/rest" "github.com/traefik/traefik/v2/pkg/tracing/jaeger" "github.com/traefik/traefik/v2/pkg/types" @@ -237,7 +236,6 @@ func TestHandler_Overview(t *testing.T) { Providers: &static.Providers{ Docker: &docker.Provider{}, File: &file.Provider{}, - Marathon: &marathon.Provider{}, KubernetesIngress: &ingress.Provider{}, KubernetesCRD: &crd.Provider{}, Rest: &rest.Provider{}, diff --git a/pkg/api/testdata/overview-providers.json b/pkg/api/testdata/overview-providers.json index 29d9ce9a7..20f134354 100644 --- a/pkg/api/testdata/overview-providers.json +++ b/pkg/api/testdata/overview-providers.json @@ -25,7 +25,6 @@ "providers": [ "Docker", "File", - "Marathon", "KubernetesIngress", "KubernetesCRD", "Rest", diff --git a/pkg/config/dynamic/fixtures/sample.toml b/pkg/config/dynamic/fixtures/sample.toml index b823c67ca..58534c553 100644 --- a/pkg/config/dynamic/fixtures/sample.toml +++ b/pkg/config/dynamic/fixtures/sample.toml @@ -54,28 +54,6 @@ watch = true filename = "foobar" debugLogGeneratedTemplate = true - [providers.marathon] - constraints = "foobar" - trace = true - watch = true - endpoint = "foobar" - defaultRule = "foobar" - exposedByDefault = true - dcosToken = "foobar" - dialerTimeout = 42 - responseHeaderTimeout = 42 - tlsHandshakeTimeout = 42 - keepAlive = 42 - forceTaskHostname = true - respectReadinessChecks = true - [providers.marathon.tls] - ca = "foobar" - cert = "foobar" - key = "foobar" - insecureSkipVerify = true - [providers.marathon.basic] - httpBasicAuthUser = "foobar" - httpBasicPassword = "foobar" [providers.kubernetesIngress] endpoint = "foobar" token = "foobar" diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index 4085bfe31..943e2cdec 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -25,7 +25,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/kv/etcd" "github.com/traefik/traefik/v2/pkg/provider/kv/redis" "github.com/traefik/traefik/v2/pkg/provider/kv/zk" - "github.com/traefik/traefik/v2/pkg/provider/marathon" "github.com/traefik/traefik/v2/pkg/provider/nomad" "github.com/traefik/traefik/v2/pkg/provider/rest" "github.com/traefik/traefik/v2/pkg/tls" @@ -213,7 +212,6 @@ type Providers struct { Docker *docker.Provider `description:"Enable Docker backend with default settings." json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` File *file.Provider `description:"Enable File backend with default settings." json:"file,omitempty" toml:"file,omitempty" yaml:"file,omitempty" export:"true"` - Marathon *marathon.Provider `description:"Enable Marathon backend with default settings." json:"marathon,omitempty" toml:"marathon,omitempty" yaml:"marathon,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesIngress *ingress.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesCRD *crd.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesCRD,omitempty" toml:"kubernetesCRD,omitempty" yaml:"kubernetesCRD,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesGateway *gateway.Provider `description:"Enable Kubernetes gateway api provider with default settings." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` diff --git a/pkg/provider/aggregator/aggregator.go b/pkg/provider/aggregator/aggregator.go index c1164c28e..ccdaa3d5f 100644 --- a/pkg/provider/aggregator/aggregator.go +++ b/pkg/provider/aggregator/aggregator.go @@ -80,10 +80,6 @@ func NewProviderAggregator(conf static.Providers) ProviderAggregator { p.quietAddProvider(conf.Docker) } - if conf.Marathon != nil { - p.quietAddProvider(conf.Marathon) - } - if conf.Rest != nil { p.quietAddProvider(conf.Rest) } diff --git a/pkg/provider/constraints/constraints_labels.go b/pkg/provider/constraints/constraints_labels.go index 6f194ba33..6d74bfbab 100644 --- a/pkg/provider/constraints/constraints_labels.go +++ b/pkg/provider/constraints/constraints_labels.go @@ -3,22 +3,16 @@ package constraints import ( "errors" "regexp" - "strings" "github.com/vulcand/predicate" ) -// MarathonConstraintPrefix is the prefix for each label's key created from a Marathon application constraint. -// It is used in order to create a specific and unique pattern for these labels. -const MarathonConstraintPrefix = "Traefik-Marathon-505F9E15-BDC7-45E7-828D-C06C7BAB8091" - type constraintLabelFunc func(map[string]string) bool // MatchLabels reports whether the expression matches with the given labels. // The expression must match any logical boolean combination of: // - `Label(labelName, labelValue)` -// - `LabelRegex(labelName, regexValue)` -// - `MarathonConstraint(field:operator:value)`. +// - `LabelRegex(labelName, regexValue)`. func MatchLabels(labels map[string]string, expr string) (bool, error) { if expr == "" { return true, nil @@ -31,9 +25,8 @@ func MatchLabels(labels map[string]string, expr string) (bool, error) { OR: orLabelFunc, }, Functions: map[string]interface{}{ - "Label": labelFn, - "LabelRegex": labelRegexFn, - "MarathonConstraint": marathonFn, + "Label": labelFn, + "LabelRegex": labelRegexFn, }, }) if err != nil { @@ -68,19 +61,6 @@ func labelRegexFn(name, expr string) constraintLabelFunc { } } -func marathonFn(value string) constraintLabelFunc { - return func(labels map[string]string) bool { - for k, v := range labels { - if strings.HasPrefix(k, MarathonConstraintPrefix) { - if v == value { - return true - } - } - } - return false - } -} - func andLabelFunc(a, b constraintLabelFunc) constraintLabelFunc { return func(labels map[string]string) bool { return a(labels) && b(labels) diff --git a/pkg/provider/constraints/constraints_labels_test.go b/pkg/provider/constraints/constraints_labels_test.go index 43fb9e0c6..8068735eb 100644 --- a/pkg/provider/constraints/constraints_labels_test.go +++ b/pkg/provider/constraints/constraints_labels_test.go @@ -118,33 +118,6 @@ func TestMatchLabels(t *testing.T) { expr: ``, expected: true, }, - { - expr: `MarathonConstraint("bar")`, - labels: map[string]string{ - "hello": "world", - MarathonConstraintPrefix + "-1": "bar", - MarathonConstraintPrefix + "-2": "foo", - }, - expected: true, - }, - { - expr: `MarathonConstraint("bur")`, - labels: map[string]string{ - "hello": "world", - MarathonConstraintPrefix + "-1": "bar", - MarathonConstraintPrefix + "-2": "foo", - }, - expected: false, - }, - { - expr: `Label("hello", "world") && MarathonConstraint("bar")`, - labels: map[string]string{ - "hello": "world", - MarathonConstraintPrefix + "-1": "bar", - MarathonConstraintPrefix + "-2": "foo", - }, - expected: true, - }, { expr: `LabelRegex("hello", "w\\w+")`, labels: map[string]string{ diff --git a/pkg/provider/marathon/builder_test.go b/pkg/provider/marathon/builder_test.go deleted file mode 100644 index e18110787..000000000 --- a/pkg/provider/marathon/builder_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package marathon - -import ( - "strings" - "time" - - "github.com/gambol99/go-marathon" -) - -const testTaskName = "taskID" - -// Functions related to building applications. - -func withApplications(apps ...marathon.Application) *marathon.Applications { - return &marathon.Applications{Apps: apps} -} - -func application(ops ...func(*marathon.Application)) marathon.Application { - app := marathon.Application{} - app.EmptyLabels() - app.Deployments = []map[string]string{} - app.ReadinessChecks = &[]marathon.ReadinessCheck{} - app.ReadinessCheckResults = &[]marathon.ReadinessCheckResult{} - - for _, op := range ops { - op(&app) - } - - return app -} - -func appID(name string) func(*marathon.Application) { - return func(app *marathon.Application) { - app.Name(name) - } -} - -func appPorts(ports ...int) func(*marathon.Application) { - return func(app *marathon.Application) { - app.Ports = append(app.Ports, ports...) - } -} - -func withLabel(key, value string) func(*marathon.Application) { - return func(app *marathon.Application) { - app.AddLabel(key, value) - } -} - -func constraint(value string) func(*marathon.Application) { - return func(app *marathon.Application) { - app.AddConstraint(strings.Split(value, ":")...) - } -} - -func portDefinition(port int, name string) func(*marathon.Application) { - return func(app *marathon.Application) { - app.AddPortDefinition(marathon.PortDefinition{ - Port: &port, - Name: name, - }) - } -} - -func bridgeNetwork() func(*marathon.Application) { - return func(app *marathon.Application) { - app.SetNetwork("bridge", marathon.BridgeNetworkMode) - } -} - -func containerNetwork() func(*marathon.Application) { - return func(app *marathon.Application) { - app.SetNetwork("cni", marathon.ContainerNetworkMode) - } -} - -func ipAddrPerTask(port int) func(*marathon.Application) { - return func(app *marathon.Application) { - p := marathon.Port{ - Number: port, - Name: "port", - } - disc := marathon.Discovery{} - disc.AddPort(p) - ipAddr := marathon.IPAddressPerTask{} - ipAddr.SetDiscovery(disc) - app.SetIPAddressPerTask(ipAddr) - } -} - -func deployments(ids ...string) func(*marathon.Application) { - return func(app *marathon.Application) { - for _, id := range ids { - app.Deployments = append(app.Deployments, map[string]string{ - "ID": id, - }) - } - } -} - -func readinessCheck(timeout time.Duration) func(*marathon.Application) { - return func(app *marathon.Application) { - app.ReadinessChecks = &[]marathon.ReadinessCheck{ - { - Path: "/ready", - TimeoutSeconds: int(timeout.Seconds()), - }, - } - } -} - -func readinessCheckResult(taskID string, ready bool) func(*marathon.Application) { - return func(app *marathon.Application) { - *app.ReadinessCheckResults = append(*app.ReadinessCheckResults, marathon.ReadinessCheckResult{ - TaskID: taskID, - Ready: ready, - }) - } -} - -func withTasks(tasks ...marathon.Task) func(*marathon.Application) { - return func(application *marathon.Application) { - for _, task := range tasks { - tu := task - application.Tasks = append(application.Tasks, &tu) - } - } -} - -// Functions related to building tasks. - -func task(ops ...func(*marathon.Task)) marathon.Task { - t := &marathon.Task{ - ID: testTaskName, - // The vast majority of tests expect the task state to be TASK_RUNNING. - State: string(taskStateRunning), - } - - for _, op := range ops { - op(t) - } - - return *t -} - -func withTaskID(id string) func(*marathon.Task) { - return func(task *marathon.Task) { - task.ID = id - } -} - -func localhostTask(ops ...func(*marathon.Task)) marathon.Task { - t := task( - host("localhost"), - ipAddresses("127.0.0.1"), - taskState(taskStateRunning), - ) - - for _, op := range ops { - op(&t) - } - - return t -} - -func taskPorts(ports ...int) func(*marathon.Task) { - return func(t *marathon.Task) { - t.Ports = append(t.Ports, ports...) - } -} - -func taskState(state TaskState) func(*marathon.Task) { - return func(t *marathon.Task) { - t.State = string(state) - } -} - -func host(h string) func(*marathon.Task) { - return func(t *marathon.Task) { - t.Host = h - } -} - -func ipAddresses(addresses ...string) func(*marathon.Task) { - return func(t *marathon.Task) { - for _, addr := range addresses { - t.IPAddresses = append(t.IPAddresses, &marathon.IPAddress{ - IPAddress: addr, - Protocol: "tcp", - }) - } - } -} - -func startedAt(timestamp string) func(*marathon.Task) { - return func(t *marathon.Task) { - t.StartedAt = timestamp - } -} - -func startedAtFromNow(offset time.Duration) func(*marathon.Task) { - return func(t *marathon.Task) { - t.StartedAt = time.Now().Add(-offset).Format(time.RFC3339) - } -} diff --git a/pkg/provider/marathon/config.go b/pkg/provider/marathon/config.go deleted file mode 100644 index 5c7e0b059..000000000 --- a/pkg/provider/marathon/config.go +++ /dev/null @@ -1,473 +0,0 @@ -package marathon - -import ( - "context" - "errors" - "fmt" - "math" - "net" - "strconv" - "strings" - - "github.com/gambol99/go-marathon" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/label" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/constraints" -) - -func (p *Provider) buildConfiguration(ctx context.Context, applications *marathon.Applications) *dynamic.Configuration { - configurations := make(map[string]*dynamic.Configuration) - - for _, app := range applications.Apps { - logger := log.Ctx(ctx).With().Str("applicationID", app.ID).Logger() - ctxApp := logger.WithContext(ctx) - - extraConf, err := p.getConfiguration(app) - if err != nil { - logger.Error().Err(err).Msg("Skip application") - continue - } - - labels := stringValueMap(app.Labels) - - if app.Constraints != nil { - for i, constraintParts := range *app.Constraints { - key := constraints.MarathonConstraintPrefix + "-" + strconv.Itoa(i) - labels[key] = strings.Join(constraintParts, ":") - } - } - - if !p.keepApplication(ctxApp, extraConf, labels) { - continue - } - - confFromLabel, err := label.DecodeConfiguration(labels) - if err != nil { - logger.Error().Err(err).Send() - continue - } - - var tcpOrUDP bool - if len(confFromLabel.TCP.Routers) > 0 || len(confFromLabel.TCP.Services) > 0 { - tcpOrUDP = true - - err := p.buildTCPServiceConfiguration(ctxApp, app, extraConf, confFromLabel.TCP) - if err != nil { - logger.Error().Err(err).Send() - continue - } - provider.BuildTCPRouterConfiguration(ctxApp, confFromLabel.TCP) - } - - if len(confFromLabel.UDP.Routers) > 0 || len(confFromLabel.UDP.Services) > 0 { - tcpOrUDP = true - - err := p.buildUDPServiceConfiguration(ctxApp, app, extraConf, confFromLabel.UDP) - if err != nil { - logger.Error().Err(err).Send() - } else { - provider.BuildUDPRouterConfiguration(ctxApp, confFromLabel.UDP) - } - } - - if tcpOrUDP && len(confFromLabel.HTTP.Routers) == 0 && - len(confFromLabel.HTTP.Middlewares) == 0 && - len(confFromLabel.HTTP.Services) == 0 { - configurations[app.ID] = confFromLabel - continue - } - - err = p.buildServiceConfiguration(ctxApp, app, extraConf, confFromLabel.HTTP) - if err != nil { - logger.Error().Err(err).Send() - continue - } - - model := struct { - Name string - Labels map[string]string - }{ - Name: app.ID, - Labels: labels, - } - - serviceName := getServiceName(app) - - provider.BuildRouterConfiguration(ctxApp, confFromLabel.HTTP, serviceName, p.defaultRuleTpl, model) - - configurations[app.ID] = confFromLabel - } - - return provider.Merge(ctx, configurations) -} - -func getServiceName(app marathon.Application) string { - return strings.ReplaceAll(strings.TrimPrefix(app.ID, "/"), "/", "_") -} - -func (p *Provider) buildServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.HTTPConfiguration) error { - appName := getServiceName(app) - - logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() - - if len(conf.Services) == 0 { - conf.Services = make(map[string]*dynamic.Service) - lb := &dynamic.ServersLoadBalancer{} - lb.SetDefaults() - conf.Services[appName] = &dynamic.Service{ - LoadBalancer: lb, - } - } - - for serviceName, service := range conf.Services { - var servers []dynamic.Server - - defaultServer := dynamic.Server{} - defaultServer.SetDefaults() - - if len(service.LoadBalancer.Servers) > 0 { - defaultServer = service.LoadBalancer.Servers[0] - } - - for _, task := range app.Tasks { - if !p.taskFilter(ctx, *task, app) { - continue - } - server, err := p.getServer(app, *task, extraConf, defaultServer) - if err != nil { - logger.Error().Err(err).Msg("Skip task") - continue - } - servers = append(servers, server) - } - if len(servers) == 0 { - return fmt.Errorf("no server for the service %s", serviceName) - } - service.LoadBalancer.Servers = servers - } - - return nil -} - -func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.TCPConfiguration) error { - appName := getServiceName(app) - - logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() - - if len(conf.Services) == 0 { - conf.Services = map[string]*dynamic.TCPService{ - appName: { - LoadBalancer: new(dynamic.TCPServersLoadBalancer), - }, - } - } - - for serviceName, service := range conf.Services { - var servers []dynamic.TCPServer - - defaultServer := dynamic.TCPServer{} - - if len(service.LoadBalancer.Servers) > 0 { - defaultServer = service.LoadBalancer.Servers[0] - } - - for _, task := range app.Tasks { - if p.taskFilter(ctx, *task, app) { - server, err := p.getTCPServer(app, *task, extraConf, defaultServer) - if err != nil { - logger.Error().Err(err).Msg("Skip task") - continue - } - servers = append(servers, server) - } - } - if len(servers) == 0 { - return fmt.Errorf("no server for the service %s", serviceName) - } - service.LoadBalancer.Servers = servers - } - - return nil -} - -func (p *Provider) buildUDPServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.UDPConfiguration) error { - appName := getServiceName(app) - logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() - - if len(conf.Services) == 0 { - conf.Services = make(map[string]*dynamic.UDPService) - lb := &dynamic.UDPServersLoadBalancer{} - - conf.Services[appName] = &dynamic.UDPService{ - LoadBalancer: lb, - } - } - - for serviceName, service := range conf.Services { - var servers []dynamic.UDPServer - - defaultServer := dynamic.UDPServer{} - - if len(service.LoadBalancer.Servers) > 0 { - defaultServer = service.LoadBalancer.Servers[0] - } - - for _, task := range app.Tasks { - if p.taskFilter(ctx, *task, app) { - server, err := p.getUDPServer(app, *task, extraConf, defaultServer) - if err != nil { - logger.Error().Err(err).Msg("Skip task") - continue - } - servers = append(servers, server) - } - } - if len(servers) == 0 { - return fmt.Errorf("no server for the service %s", serviceName) - } - service.LoadBalancer.Servers = servers - } - - return nil -} - -func (p *Provider) keepApplication(ctx context.Context, extraConf configuration, labels map[string]string) bool { - logger := log.Ctx(ctx) - - // Filter disabled application. - if !extraConf.Enable { - logger.Debug().Msg("Filtering disabled Marathon application") - return false - } - - // Filter by constraints. - matches, err := constraints.MatchLabels(labels, p.Constraints) - if err != nil { - logger.Error().Err(err).Msg("Error matching constraints expression") - return false - } - if !matches { - logger.Debug().Msgf("Marathon application filtered by constraint expression: %q", p.Constraints) - return false - } - - return true -} - -func (p *Provider) taskFilter(ctx context.Context, task marathon.Task, application marathon.Application) bool { - if task.State != string(taskStateRunning) { - return false - } - - if ready := p.readyChecker.Do(task, application); !ready { - log.Ctx(ctx).Info().Msgf("Filtering unready task %s from application %s", task.ID, application.ID) - return false - } - - return true -} - -func (p *Provider) getTCPServer(app marathon.Application, task marathon.Task, extraConf configuration, defaultServer dynamic.TCPServer) (dynamic.TCPServer, error) { - host, err := p.getServerHost(task, app, extraConf) - if len(host) == 0 { - return dynamic.TCPServer{}, err - } - - port, err := getPort(task, app, defaultServer.Port) - if err != nil { - return dynamic.TCPServer{}, err - } - - server := dynamic.TCPServer{ - Address: net.JoinHostPort(host, port), - } - - return server, nil -} - -func (p *Provider) getUDPServer(app marathon.Application, task marathon.Task, extraConf configuration, defaultServer dynamic.UDPServer) (dynamic.UDPServer, error) { - host, err := p.getServerHost(task, app, extraConf) - if len(host) == 0 { - return dynamic.UDPServer{}, err - } - - port, err := getPort(task, app, defaultServer.Port) - if err != nil { - return dynamic.UDPServer{}, err - } - - server := dynamic.UDPServer{ - Address: net.JoinHostPort(host, port), - } - - return server, nil -} - -func (p *Provider) getServer(app marathon.Application, task marathon.Task, extraConf configuration, defaultServer dynamic.Server) (dynamic.Server, error) { - host, err := p.getServerHost(task, app, extraConf) - if len(host) == 0 { - return dynamic.Server{}, err - } - - port, err := getPort(task, app, defaultServer.Port) - if err != nil { - return dynamic.Server{}, err - } - - server := dynamic.Server{ - URL: fmt.Sprintf("%s://%s", defaultServer.Scheme, net.JoinHostPort(host, port)), - } - - return server, nil -} - -func (p *Provider) getServerHost(task marathon.Task, app marathon.Application, extraConf configuration) (string, error) { - networks := app.Networks - var hostFlag bool - - if networks == nil { - hostFlag = app.IPAddressPerTask == nil - } else { - hostFlag = (*networks)[0].Mode != marathon.ContainerNetworkMode - } - - if hostFlag || p.ForceTaskHostname { - if len(task.Host) == 0 { - return "", fmt.Errorf("host is undefined for task %q app %q", task.ID, app.ID) - } - return task.Host, nil - } - - numTaskIPAddresses := len(task.IPAddresses) - switch numTaskIPAddresses { - case 0: - return "", fmt.Errorf("missing IP address for Marathon application %s on task %s", app.ID, task.ID) - case 1: - return task.IPAddresses[0].IPAddress, nil - default: - if extraConf.Marathon.IPAddressIdx == math.MinInt32 { - return "", fmt.Errorf("found %d task IP addresses but missing IP address index for Marathon application %s on task %s", - numTaskIPAddresses, app.ID, task.ID) - } - if extraConf.Marathon.IPAddressIdx < 0 || extraConf.Marathon.IPAddressIdx > numTaskIPAddresses { - return "", fmt.Errorf("cannot use IP address index to select from %d task IP addresses for Marathon application %s on task %s", - numTaskIPAddresses, app.ID, task.ID) - } - - return task.IPAddresses[extraConf.Marathon.IPAddressIdx].IPAddress, nil - } -} - -func getPort(task marathon.Task, app marathon.Application, serverPort string) (string, error) { - port, err := processPorts(app, task, serverPort) - if err != nil { - return "", fmt.Errorf("unable to process ports for %s %s: %w", app.ID, task.ID, err) - } - - return strconv.Itoa(port), nil -} - -// processPorts returns the configured port. -// An explicitly specified port is preferred. If none is specified, it selects -// one of the available port. The first such found port is returned unless an -// optional index is provided. -func processPorts(app marathon.Application, task marathon.Task, serverPort string) (int, error) { - if len(serverPort) > 0 && !(strings.HasPrefix(serverPort, "index:") || strings.HasPrefix(serverPort, "name:")) { - port, err := strconv.Atoi(serverPort) - if err != nil { - return 0, err - } - - if port <= 0 { - return 0, fmt.Errorf("explicitly specified port %d must be greater than zero", port) - } else if port > 0 { - return port, nil - } - } - - if strings.HasPrefix(serverPort, "name:") { - name := strings.TrimPrefix(serverPort, "name:") - port := retrieveNamedPort(app, name) - - if port == 0 { - return 0, fmt.Errorf("no port with name %s", name) - } - - return port, nil - } - - ports := retrieveAvailablePorts(app, task) - if len(ports) == 0 { - return 0, errors.New("no port found") - } - - portIndex := 0 - if strings.HasPrefix(serverPort, "index:") { - indexString := strings.TrimPrefix(serverPort, "index:") - index, err := strconv.Atoi(indexString) - if err != nil { - return 0, err - } - - if index < 0 || index > len(ports)-1 { - return 0, fmt.Errorf("index %d must be within range (0, %d)", index, len(ports)-1) - } - - portIndex = index - } - - return ports[portIndex], nil -} - -func retrieveNamedPort(app marathon.Application, name string) int { - // Using port definition if available - if app.PortDefinitions != nil && len(*app.PortDefinitions) > 0 { - for _, def := range *app.PortDefinitions { - if def.Port != nil && *def.Port > 0 && def.Name == name { - return *def.Port - } - } - } - - // If using IP-per-task using this port definition - if app.IPAddressPerTask != nil && app.IPAddressPerTask.Discovery != nil && len(*(app.IPAddressPerTask.Discovery.Ports)) > 0 { - for _, def := range *(app.IPAddressPerTask.Discovery.Ports) { - if def.Number > 0 && def.Name == name { - return def.Number - } - } - } - - return 0 -} - -func retrieveAvailablePorts(app marathon.Application, task marathon.Task) []int { - // Using default port configuration - if len(task.Ports) > 0 { - return task.Ports - } - - // Using port definition if available - if app.PortDefinitions != nil && len(*app.PortDefinitions) > 0 { - var ports []int - for _, def := range *app.PortDefinitions { - if def.Port != nil { - ports = append(ports, *def.Port) - } - } - return ports - } - - // If using IP-per-task using this port definition - if app.IPAddressPerTask != nil && app.IPAddressPerTask.Discovery != nil && len(*(app.IPAddressPerTask.Discovery.Ports)) > 0 { - var ports []int - for _, def := range *(app.IPAddressPerTask.Discovery.Ports) { - ports = append(ports, def.Number) - } - return ports - } - - return []int{} -} diff --git a/pkg/provider/marathon/config_test.go b/pkg/provider/marathon/config_test.go deleted file mode 100644 index 8648c7e84..000000000 --- a/pkg/provider/marathon/config_test.go +++ /dev/null @@ -1,2447 +0,0 @@ -package marathon - -import ( - "context" - "math" - "testing" - "time" - - "github.com/gambol99/go-marathon" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" -) - -func Int(v int) *int { return &v } -func Bool(v bool) *bool { return &v } - -func TestGetConfigurationAPIErrors(t *testing.T) { - fakeClient := newFakeClient(true, marathon.Applications{}) - - p := &Provider{ - marathonClient: fakeClient, - } - - actualConfig := p.getConfigurations(context.Background()) - fakeClient.AssertExpectations(t) - - if actualConfig != nil { - t.Errorf("configuration should have been nil, got %v", actualConfig) - } -} - -func TestBuildConfiguration(t *testing.T) { - testCases := []struct { - desc string - applications *marathon.Applications - constraints string - defaultRule string - expected *dynamic.Configuration - }{ - { - desc: "simple application", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "filtered task", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80), taskState(taskStateStaging))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "multiple ports", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "with basic auth", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withLabel("traefik.http.middlewares.Middleware1.basicauth.users", "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), - withLabel("traefik.http.routers.app.middlewares", "Middleware1"), - withTasks(localhostTask(taskPorts(80))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - Middlewares: []string{"Middleware1"}, - }, - }, - Middlewares: map[string]*dynamic.Middleware{ - "Middleware1": { - BasicAuth: &dynamic.BasicAuth{ - Users: []string{ - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - }, - }, - }, - }, - Services: map[string]*dynamic.Service{ - "app": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "TCP with IP allowlist", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - - withLabel("traefik.tcp.routers.Test.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.middlewares.Middleware1.ipallowlist.sourcerange", "foobar, fiibar"), - withLabel("traefik.tcp.routers.Test.middlewares", "Middleware1"), - withTasks(localhostTask(taskPorts(80))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "Test": { - Service: "app", - Rule: "HostSNI(`foo.bar`)", - Middlewares: []string{"Middleware1"}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{ - "Middleware1": { - IPAllowList: &dynamic.TCPIPAllowList{ - SourceRange: []string{"foobar", "fiibar"}, - }, - }, - }, - Services: map[string]*dynamic.TCPService{ - "app": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:80", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "2 applications in the same service", - applications: withApplications( - application( - appID("/foo-v000"), - withTasks(localhostTask(taskPorts(8080))), - - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"), - withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"), - ), - application( - appID("/foo-v001"), - withTasks(localhostTask(taskPorts(8081))), - - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"), - withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"), - ), - ), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8080", - }, - { - URL: "http://localhost:8081", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "2 applications with 2 tasks in the same service", - applications: withApplications( - application( - appID("/foo-v000"), - withTasks(localhostTask(taskPorts(8080))), - withTasks(localhostTask(taskPorts(8081))), - - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"), - withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"), - ), - application( - appID("/foo-v001"), - withTasks(localhostTask(taskPorts(8082))), - withTasks(localhostTask(taskPorts(8083))), - - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"), - withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"), - ), - ), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8080", - }, - { - URL: "http://localhost:8081", - }, - { - URL: "http://localhost:8082", - }, - { - URL: "http://localhost:8083", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "2 applications", - applications: withApplications( - application( - appID("/foo"), - withTasks(localhostTask(taskPorts(8080))), - ), - application( - appID("/bar"), - withTasks(localhostTask(taskPorts(8081))), - ), - ), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "foo": { - Service: "foo", - Rule: "Host(`foo.marathon.localhost`)", - }, - "bar": { - Service: "bar", - Rule: "Host(`bar.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "foo": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8080", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - "bar": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8081", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two tasks no labels", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80)), localhostTask(taskPorts(81))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - { - URL: "http://localhost:81", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "simple application with label on service", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with labels", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.routers.Router1.service", "Service1"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`foo.com`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with rule label", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "app", - Rule: "Host(`foo.com`)", - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with rule label and one service", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`foo.com`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with rule label and two services", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - withLabel("traefik.http.services.Service2.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "Service2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with same service name and different passhostheader", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "false"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - "app2": { - Service: "Service1", - Rule: "Host(`app2.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two identical middleware", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "42"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "42"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - "app2": { - Service: "app2", - Rule: "Host(`app2.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{ - "Middleware1": { - InFlightReq: &dynamic.InFlightReq{ - Amount: 42, - }, - }, - }, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "app2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two different middlewares", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "42"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "41"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - "app2": { - Service: "app2", - Rule: "Host(`app2.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "app2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two different routers with same name", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`bar.com`)"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "app2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two identical routers with same name", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.services.Service1.LoadBalancer.passhostheader", "true"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.services.Service1.LoadBalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`foo.com`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two identical routers with same name", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "app2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with wrong label", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.wrong.label", "tchouk"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with label port", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.LoadBalancer.server.scheme", "h2c"), - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "90"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "h2c://localhost:90", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with label port on two services", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", ""), - withLabel("traefik.http.services.Service2.LoadBalancer.server.port", "8080"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "Service2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8080", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app without port", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask()), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app without port with middleware", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask()), - withLabel("traefik.http.middlewares.Middleware1.basicauth.users", "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with traefik.enable=false", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask()), - withLabel("traefik.enable", "false"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with traefik.enable=false", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask()), - withLabel("traefik.enable", "false"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with non matching constraint", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tags", "foo"), - )), - constraints: `Label("traefik.tags", "bar")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with non matching marathon constraint", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - constraint("rack_id:CLUSTER:rack-1"), - )), - constraints: `MarathonConstraint("rack_id:CLUSTER:rack-2")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with matching marathon constraint", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - constraint("rack_id:CLUSTER:rack-1"), - )), - constraints: `MarathonConstraint("rack_id:CLUSTER:rack-1")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with matching constraint", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tags", "bar"), - )), - constraints: `Label("traefik.tags", "bar")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with group as subdomain rule", - defaultRule: `Host("{{ .Name | trimPrefix "/" | splitList "/" | strsToItfs | reverse | join "." }}.marathon.localhost")`, - applications: withApplications( - application( - appID("/a/b/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "a_b_app": { - Service: "a_b_app", - Rule: `Host("app.b.a.marathon.localhost")`, - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "a_b_app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with tcp labels", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.routers.foo.tls", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "app", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "app": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:80", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with udp labels", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.udp.routers.foo.entrypoints", "mydns"), - )), - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{ - "foo": { - Service: "app", - EntryPoints: []string{"mydns"}, - }, - }, - Services: map[string]*dynamic.UDPService{ - "app": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "localhost:80", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with tcp labels without rule", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.tls", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "app": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:80", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with tcp labels with port", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.routers.foo.tls", "true"), - withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "foo", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with udp labels with port", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.udp.routers.foo.entrypoints", "mydns"), - withLabel("traefik.udp.services.foo.loadbalancer.server.port", "8080"), - )), - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{ - "foo": { - Service: "foo", - EntryPoints: []string{"mydns"}, - }, - }, - Services: map[string]*dynamic.UDPService{ - "foo": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - // TODO: replace or delete? - desc: "one app with tcp labels with port, with termination delay", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.routers.foo.tls", "true"), - withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "foo", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - 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{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with tcp labels with port and http service", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.routers.foo.tls", "true"), - withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"), - withLabel("traefik.http.services.bar.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "foo", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "bar", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "bar": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with udp labels with port and http service", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.udp.routers.foo.entrypoints", "mydns"), - withLabel("traefik.udp.services.foo.loadbalancer.server.port", "8080"), - withLabel("traefik.http.services.bar.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{ - "foo": { - Service: "foo", - EntryPoints: []string{"mydns"}, - }, - }, - Services: map[string]*dynamic.UDPService{ - "foo": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "bar", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "bar": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - defaultRule := "Host(`{{ normalize .Name }}.marathon.localhost`)" - if len(test.defaultRule) > 0 { - defaultRule = test.defaultRule - } - - p := &Provider{ - DefaultRule: defaultRule, - ExposedByDefault: true, - } - p.Constraints = test.constraints - - err := p.Init() - require.NoError(t, err) - - actualConfig := p.buildConfiguration(context.Background(), test.applications) - - assert.NotNil(t, actualConfig) - assert.Equal(t, test.expected, actualConfig) - }) - } -} - -func TestApplicationFilterEnabled(t *testing.T) { - testCases := []struct { - desc string - exposedByDefault bool - enabledLabel string - expected bool - }{ - { - desc: "exposed and tolerated by valid label value", - exposedByDefault: true, - enabledLabel: "true", - expected: true, - }, - { - desc: "exposed but overridden by label", - exposedByDefault: true, - enabledLabel: "false", - expected: false, - }, - { - desc: "non-exposed but overridden by label", - exposedByDefault: false, - enabledLabel: "true", - expected: true, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - provider := &Provider{ExposedByDefault: true} - - app := application(withLabel("traefik.enable", test.enabledLabel)) - - extraConf, err := provider.getConfiguration(app) - require.NoError(t, err) - - if provider.keepApplication(context.Background(), extraConf, stringValueMap(app.Labels)) != test.expected { - t.Errorf("got unexpected filtering = %t", !test.expected) - } - }) - } -} - -func TestGetServer(t *testing.T) { - type expected struct { - server dynamic.Server - error string - } - - testCases := []struct { - desc string - provider Provider - app marathon.Application - extraConf configuration - defaultServer dynamic.Server - expected expected - }{ - { - desc: "undefined host", - provider: Provider{}, - app: application(), - extraConf: configuration{}, - defaultServer: dynamic.Server{}, - expected: expected{ - error: `host is undefined for task "taskID" app ""`, - }, - }, - { - desc: "with task port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:80", - }, - }, - }, - { - desc: "without task port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - error: "unable to process ports for /app taskID: no port found", - }, - }, - { - desc: "with default server port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "88", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:88", - }, - }, - }, - { - desc: "with invalid default server port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "aaaa", - }, - expected: expected{ - error: `unable to process ports for /app taskID: strconv.Atoi: parsing "aaaa": invalid syntax`, - }, - }, - { - desc: "with negative default server port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "-6", - }, - expected: expected{ - error: `unable to process ports for /app taskID: explicitly specified port -6 must be greater than zero`, - }, - }, - { - desc: "with port index", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "index:1", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:81", - }, - }, - }, - { - desc: "with out of range port index", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "index:2", - }, - expected: expected{ - error: "unable to process ports for /app taskID: index 2 must be within range (0, 1)", - }, - }, - { - desc: "with invalid port index", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "index:aaa", - }, - expected: expected{ - error: `unable to process ports for /app taskID: strconv.Atoi: parsing "aaa": invalid syntax`, - }, - }, - { - desc: "with port name", - provider: Provider{}, - app: application( - appID("/app"), - portDefinition(80, "fist-port"), - portDefinition(81, "second-port"), - portDefinition(82, "third-port"), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "name:third-port", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:82", - }, - }, - }, - { - desc: "with port name not found", - provider: Provider{}, - app: application( - appID("/app"), - portDefinition(80, "fist-port"), - portDefinition(81, "second-port"), - portDefinition(82, "third-port"), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "name:other-name", - }, - expected: expected{ - error: `unable to process ports for /app taskID: no port with name other-name`, - }, - }, - { - desc: "with application port and no task port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - portDefinition(80, "http"), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:80", - }, - }, - }, - { - desc: "with IP per task", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - ipAddrPerTask(88), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://127.0.0.1:88", - }, - }, - }, - { - desc: "with container network", - provider: Provider{}, - app: application( - containerNetwork(), - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://127.0.0.1:80", - }, - }, - }, - { - desc: "with bridge network", - provider: Provider{}, - app: application( - bridgeNetwork(), - appID("/app"), - appPorts(83), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:80", - }, - }, - }, - { - desc: "with several IP addresses on task", - provider: Provider{}, - app: application( - ipAddrPerTask(88), - appID("/app"), - appPorts(83), - withTasks( - task( - withTaskID("myTask"), - host("localhost"), - ipAddresses("127.0.0.1", "127.0.0.2"), - taskState(taskStateRunning), - )), - ), - extraConf: configuration{ - Marathon: specificConfiguration{ - IPAddressIdx: 0, - }, - }, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://127.0.0.1:88", - }, - }, - }, - { - desc: "with several IP addresses on task, undefined [MinInt32] IPAddressIdx", - provider: Provider{}, - app: application( - ipAddrPerTask(88), - appID("/app"), - appPorts(83), - withTasks( - task( - host("localhost"), - ipAddresses("127.0.0.1", "127.0.0.2"), - taskState(taskStateRunning), - )), - ), - extraConf: configuration{ - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - error: "found 2 task IP addresses but missing IP address index for Marathon application /app on task taskID", - }, - }, - { - desc: "with several IP addresses on task, IPAddressIdx out of range", - provider: Provider{}, - app: application( - ipAddrPerTask(88), - appID("/app"), - appPorts(83), - withTasks( - task( - host("localhost"), - ipAddresses("127.0.0.1", "127.0.0.2"), - taskState(taskStateRunning), - )), - ), - extraConf: configuration{ - Marathon: specificConfiguration{ - IPAddressIdx: 3, - }, - }, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - error: "cannot use IP address index to select from 2 task IP addresses for Marathon application /app on task taskID", - }, - }, - { - desc: "with task without IP address", - provider: Provider{}, - app: application( - ipAddrPerTask(88), - appID("/app"), - appPorts(83), - withTasks( - task( - host("localhost"), - taskState(taskStateRunning), - )), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - error: "missing IP address for Marathon application /app on task taskID", - }, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - task := task() - if len(test.app.Tasks) > 0 { - task = *test.app.Tasks[0] - } - - server, err := test.provider.getServer(test.app, task, test.extraConf, test.defaultServer) - if len(test.expected.error) > 0 { - require.EqualError(t, err, test.expected.error) - } else { - require.NoError(t, err) - - assert.Equal(t, test.expected.server, server) - } - }) - } -} diff --git a/pkg/provider/marathon/fake_client_test.go b/pkg/provider/marathon/fake_client_test.go deleted file mode 100644 index c30941482..000000000 --- a/pkg/provider/marathon/fake_client_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package marathon - -import ( - "errors" - - "github.com/gambol99/go-marathon" - "github.com/stretchr/testify/mock" - "github.com/traefik/traefik/v2/pkg/provider/marathon/mocks" -) - -type fakeClient struct { - mocks.Marathon -} - -func newFakeClient(applicationsError bool, applications marathon.Applications) *fakeClient { - // create an instance of our test object - fakeClient := new(fakeClient) - if applicationsError { - fakeClient.On("Applications", mock.Anything).Return(nil, errors.New("fake Marathon server error")) - } else { - fakeClient.On("Applications", mock.Anything).Return(&applications, nil) - } - return fakeClient -} diff --git a/pkg/provider/marathon/label.go b/pkg/provider/marathon/label.go deleted file mode 100644 index f6da87870..000000000 --- a/pkg/provider/marathon/label.go +++ /dev/null @@ -1,42 +0,0 @@ -package marathon - -import ( - "math" - - "github.com/gambol99/go-marathon" - "github.com/traefik/traefik/v2/pkg/config/label" -) - -type configuration struct { - Enable bool - Marathon specificConfiguration -} - -type specificConfiguration struct { - IPAddressIdx int -} - -func (p *Provider) getConfiguration(app marathon.Application) (configuration, error) { - labels := stringValueMap(app.Labels) - - conf := configuration{ - Enable: p.ExposedByDefault, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - } - - err := label.Decode(labels, &conf, "traefik.marathon.", "traefik.enable") - if err != nil { - return configuration{}, err - } - - return conf, nil -} - -func stringValueMap(mp *map[string]string) map[string]string { - if mp != nil { - return *mp - } - return make(map[string]string) -} diff --git a/pkg/provider/marathon/label_test.go b/pkg/provider/marathon/label_test.go deleted file mode 100644 index 472b91d23..000000000 --- a/pkg/provider/marathon/label_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package marathon - -import ( - "math" - "testing" - - "github.com/gambol99/go-marathon" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetConfiguration(t *testing.T) { - testCases := []struct { - desc string - app marathon.Application - p Provider - expected configuration - }{ - { - desc: "Empty labels", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{}, - }, - p: Provider{ - ExposedByDefault: false, - }, - expected: configuration{ - Enable: false, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - { - desc: "label enable", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{ - "traefik.enable": "true", - }, - }, - p: Provider{ - ExposedByDefault: false, - }, - expected: configuration{ - Enable: true, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - { - desc: "Use ip address index", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{ - "traefik.marathon.IPAddressIdx": "4", - }, - }, - p: Provider{ - ExposedByDefault: false, - }, - expected: configuration{ - Enable: false, - Marathon: specificConfiguration{ - IPAddressIdx: 4, - }, - }, - }, - { - desc: "Use marathon constraints", - app: marathon.Application{ - Constraints: &[][]string{ - {"key", "value"}, - }, - Labels: &map[string]string{}, - }, - p: Provider{ - ExposedByDefault: false, - }, - expected: configuration{ - Enable: false, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - { - desc: "ExposedByDefault and no enable label", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{}, - }, - p: Provider{ - ExposedByDefault: true, - }, - expected: configuration{ - Enable: true, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - { - desc: "ExposedByDefault and enable label false", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{ - "traefik.enable": "false", - }, - }, - p: Provider{ - ExposedByDefault: true, - }, - expected: configuration{ - Enable: false, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - extraConf, err := test.p.getConfiguration(test.app) - require.NoError(t, err) - - assert.Equal(t, test.expected, extraConf) - }) - } -} diff --git a/pkg/provider/marathon/marathon.go b/pkg/provider/marathon/marathon.go deleted file mode 100644 index d4e8cccd8..000000000 --- a/pkg/provider/marathon/marathon.go +++ /dev/null @@ -1,221 +0,0 @@ -package marathon - -import ( - "context" - "fmt" - "net" - "net/http" - "net/url" - "text/template" - "time" - - "github.com/cenkalti/backoff/v4" - "github.com/gambol99/go-marathon" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/types" -) - -const ( - // DefaultTemplateRule The default template for the default rule. - DefaultTemplateRule = "Host(`{{ normalize .Name }}`)" - marathonEventIDs = marathon.EventIDApplications | - marathon.EventIDAddHealthCheck | - marathon.EventIDDeploymentSuccess | - marathon.EventIDDeploymentFailed | - marathon.EventIDDeploymentInfo | - marathon.EventIDDeploymentStepSuccess | - marathon.EventIDDeploymentStepFailed -) - -// TaskState denotes the Mesos state a task can have. -type TaskState string - -const ( - taskStateRunning TaskState = "TASK_RUNNING" - taskStateStaging TaskState = "TASK_STAGING" -) - -var _ provider.Provider = (*Provider)(nil) - -// Provider holds configuration of the provider. -type Provider struct { - Constraints string `description:"Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application." json:"constraints,omitempty" toml:"constraints,omitempty" yaml:"constraints,omitempty" export:"true"` - Trace bool `description:"Display additional provider logs." json:"trace,omitempty" toml:"trace,omitempty" yaml:"trace,omitempty" export:"true"` - Watch bool `description:"Watch provider." json:"watch,omitempty" toml:"watch,omitempty" yaml:"watch,omitempty" export:"true"` - Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"` - DefaultRule string `description:"Default rule." json:"defaultRule,omitempty" toml:"defaultRule,omitempty" yaml:"defaultRule,omitempty"` - ExposedByDefault bool `description:"Expose Marathon apps by default." json:"exposedByDefault,omitempty" toml:"exposedByDefault,omitempty" yaml:"exposedByDefault,omitempty" export:"true"` - DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header." json:"dcosToken,omitempty" toml:"dcosToken,omitempty" yaml:"dcosToken,omitempty" loggable:"false"` - TLS *types.ClientTLS `description:"Enable TLS support." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` - DialerTimeout ptypes.Duration `description:"Set a dialer timeout for Marathon." json:"dialerTimeout,omitempty" toml:"dialerTimeout,omitempty" yaml:"dialerTimeout,omitempty" export:"true"` - ResponseHeaderTimeout ptypes.Duration `description:"Set a response header timeout for Marathon." json:"responseHeaderTimeout,omitempty" toml:"responseHeaderTimeout,omitempty" yaml:"responseHeaderTimeout,omitempty" export:"true"` - TLSHandshakeTimeout ptypes.Duration `description:"Set a TLS handshake timeout for Marathon." json:"tlsHandshakeTimeout,omitempty" toml:"tlsHandshakeTimeout,omitempty" yaml:"tlsHandshakeTimeout,omitempty" export:"true"` - KeepAlive ptypes.Duration `description:"Set a TCP Keep Alive time." json:"keepAlive,omitempty" toml:"keepAlive,omitempty" yaml:"keepAlive,omitempty" export:"true"` - ForceTaskHostname bool `description:"Force to use the task's hostname." json:"forceTaskHostname,omitempty" toml:"forceTaskHostname,omitempty" yaml:"forceTaskHostname,omitempty" export:"true"` - Basic *Basic `description:"Enable basic authentication." json:"basic,omitempty" toml:"basic,omitempty" yaml:"basic,omitempty" export:"true"` - RespectReadinessChecks bool `description:"Filter out tasks with non-successful readiness checks during deployments." json:"respectReadinessChecks,omitempty" toml:"respectReadinessChecks,omitempty" yaml:"respectReadinessChecks,omitempty" export:"true"` - readyChecker *readinessChecker - marathonClient marathon.Marathon - defaultRuleTpl *template.Template -} - -// SetDefaults sets the default values. -func (p *Provider) SetDefaults() { - p.Watch = true - p.Endpoint = "http://127.0.0.1:8080" - p.ExposedByDefault = true - p.DialerTimeout = ptypes.Duration(5 * time.Second) - p.ResponseHeaderTimeout = ptypes.Duration(60 * time.Second) - p.TLSHandshakeTimeout = ptypes.Duration(5 * time.Second) - p.KeepAlive = ptypes.Duration(10 * time.Second) - p.DefaultRule = DefaultTemplateRule -} - -// Basic holds basic authentication specific configurations. -type Basic struct { - HTTPBasicAuthUser string `description:"Basic authentication User." json:"httpBasicAuthUser,omitempty" toml:"httpBasicAuthUser,omitempty" yaml:"httpBasicAuthUser,omitempty" loggable:"false"` - HTTPBasicPassword string `description:"Basic authentication Password." json:"httpBasicPassword,omitempty" toml:"httpBasicPassword,omitempty" yaml:"httpBasicPassword,omitempty" loggable:"false"` -} - -// Init the provider. -func (p *Provider) Init() error { - fm := template.FuncMap{ - "strsToItfs": func(values []string) []interface{} { - var r []interface{} - for _, v := range values { - r = append(r, v) - } - return r - }, - } - - defaultRuleTpl, err := provider.MakeDefaultRuleTemplate(p.DefaultRule, fm) - if err != nil { - return fmt.Errorf("error while parsing default rule: %w", err) - } - - p.defaultRuleTpl = defaultRuleTpl - return nil -} - -// Provide allows the marathon provider to provide configurations to traefik -// using the given configuration channel. -func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - logger := log.With().Str(logs.ProviderName, "marathon").Logger() - ctx := logger.WithContext(context.Background()) - - operation := func() error { - confg := marathon.NewDefaultConfig() - confg.URL = p.Endpoint - confg.EventsTransport = marathon.EventsTransportSSE - - if p.Trace { - confg.LogOutput = logs.NoLevel(logger, zerolog.DebugLevel) - } - - if p.Basic != nil { - confg.HTTPBasicAuthUser = p.Basic.HTTPBasicAuthUser - confg.HTTPBasicPassword = p.Basic.HTTPBasicPassword - } - var rc *readinessChecker - if p.RespectReadinessChecks { - logger.Debug().Msg("Enabling Marathon readiness checker") - rc = defaultReadinessChecker(p.Trace) - } - p.readyChecker = rc - - if len(p.DCOSToken) > 0 { - confg.DCOSToken = p.DCOSToken - } - TLSConfig, err := p.TLS.CreateTLSConfig(ctx) - if err != nil { - return fmt.Errorf("unable to create client TLS configuration: %w", err) - } - confg.HTTPClient = &http.Client{ - Transport: &http.Transport{ - DialContext: (&net.Dialer{ - KeepAlive: time.Duration(p.KeepAlive), - Timeout: time.Duration(p.DialerTimeout), - }).DialContext, - ResponseHeaderTimeout: time.Duration(p.ResponseHeaderTimeout), - TLSHandshakeTimeout: time.Duration(p.TLSHandshakeTimeout), - TLSClientConfig: TLSConfig, - }, - } - client, err := marathon.NewClient(confg) - if err != nil { - logger.Error().Err(err).Msg("Failed to create a client for marathon") - return err - } - p.marathonClient = client - - if p.Watch { - update, err := client.AddEventsListener(marathonEventIDs) - if err != nil { - logger.Error().Err(err).Msg("Failed to register for events") - return err - } - pool.GoCtx(func(ctxPool context.Context) { - defer close(update) - for { - select { - case <-ctxPool.Done(): - return - case event := <-update: - logger.Debug().Msgf("Received provider event %s", event) - - conf := p.getConfigurations(ctx) - if conf != nil { - configurationChan <- dynamic.Message{ - ProviderName: "marathon", - Configuration: conf, - } - } - } - } - }) - } - - configuration := p.getConfigurations(ctx) - configurationChan <- dynamic.Message{ - ProviderName: "marathon", - Configuration: configuration, - } - return nil - } - - notify := func(err error, time time.Duration) { - logger.Error().Err(err).Msgf("Provider error, retrying in %s", time) - } - err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctx), notify) - if err != nil { - logger.Error().Err(err).Msg("Cannot retrieve data") - } - return nil -} - -func (p *Provider) getConfigurations(ctx context.Context) *dynamic.Configuration { - applications, err := p.getApplications() - if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("Failed to retrieve Marathon applications") - return nil - } - - return p.buildConfiguration(ctx, applications) -} - -func (p *Provider) getApplications() (*marathon.Applications, error) { - v := url.Values{} - v.Add("embed", "apps.tasks") - v.Add("embed", "apps.deployments") - v.Add("embed", "apps.readiness") - - return p.marathonClient.Applications(v) -} diff --git a/pkg/provider/marathon/mocks/Marathon.go b/pkg/provider/marathon/mocks/Marathon.go deleted file mode 100644 index d2506bc79..000000000 --- a/pkg/provider/marathon/mocks/Marathon.go +++ /dev/null @@ -1,1286 +0,0 @@ -// Package mocks Code generated by mockery v1.0.0. DO NOT EDIT. -// mockery -recursive -dir=vendor/github.com/gambol99/ -name=Marathon -output=provider/marathon/mocks -package mocks - -import ( - "net/url" - "time" - - "github.com/gambol99/go-marathon" - "github.com/stretchr/testify/mock" -) - -// Marathon is an autogenerated mock type for the Marathon type -type Marathon struct { - mock.Mock -} - -// AbdicateLeader provides a mock function with given fields: -func (_m *Marathon) AbdicateLeader() (string, error) { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// AddEventsListener provides a mock function with given fields: filter -func (_m *Marathon) AddEventsListener(filter int) (marathon.EventsChannel, error) { - ret := _m.Called(filter) - - var r0 marathon.EventsChannel - if rf, ok := ret.Get(0).(func(int) marathon.EventsChannel); ok { - r0 = rf(filter) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(marathon.EventsChannel) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(int) error); ok { - r1 = rf(filter) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// AllTasks provides a mock function with given fields: opts -func (_m *Marathon) AllTasks(opts *marathon.AllTasksOpts) (*marathon.Tasks, error) { - ret := _m.Called(opts) - - var r0 *marathon.Tasks - if rf, ok := ret.Get(0).(func(*marathon.AllTasksOpts) *marathon.Tasks); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Tasks) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.AllTasksOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Application provides a mock function with given fields: name -func (_m *Marathon) Application(name string) (*marathon.Application, error) { - ret := _m.Called(name) - - var r0 *marathon.Application - if rf, ok := ret.Get(0).(func(string) *marathon.Application); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Application) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationBy provides a mock function with given fields: name, opts -func (_m *Marathon) ApplicationBy(name string, opts *marathon.GetAppOpts) (*marathon.Application, error) { - ret := _m.Called(name, opts) - - var r0 *marathon.Application - if rf, ok := ret.Get(0).(func(string, *marathon.GetAppOpts) *marathon.Application); ok { - r0 = rf(name, opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Application) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.GetAppOpts) error); ok { - r1 = rf(name, opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationByVersion provides a mock function with given fields: name, version -func (_m *Marathon) ApplicationByVersion(name, version string) (*marathon.Application, error) { - ret := _m.Called(name, version) - - var r0 *marathon.Application - if rf, ok := ret.Get(0).(func(string, string) *marathon.Application); ok { - r0 = rf(name, version) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Application) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(name, version) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationDeployments provides a mock function with given fields: name -func (_m *Marathon) ApplicationDeployments(name string) ([]*marathon.DeploymentID, error) { - ret := _m.Called(name) - - var r0 []*marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string) []*marathon.DeploymentID); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationOK provides a mock function with given fields: name -func (_m *Marathon) ApplicationOK(name string) (bool, error) { - ret := _m.Called(name) - - var r0 bool - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(name) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationVersions provides a mock function with given fields: name -func (_m *Marathon) ApplicationVersions(name string) (*marathon.ApplicationVersions, error) { - ret := _m.Called(name) - - var r0 *marathon.ApplicationVersions - if rf, ok := ret.Get(0).(func(string) *marathon.ApplicationVersions); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.ApplicationVersions) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Applications provides a mock function with given fields: _a0 -func (_m *Marathon) Applications(_a0 url.Values) (*marathon.Applications, error) { - ret := _m.Called(_a0) - - var r0 *marathon.Applications - if rf, ok := ret.Get(0).(func(url.Values) *marathon.Applications); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Applications) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(url.Values) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// CreateApplication provides a mock function with given fields: application -func (_m *Marathon) CreateApplication(application *marathon.Application) (*marathon.Application, error) { - ret := _m.Called(application) - - var r0 *marathon.Application - if rf, ok := ret.Get(0).(func(*marathon.Application) *marathon.Application); ok { - r0 = rf(application) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Application) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.Application) error); ok { - r1 = rf(application) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// CreateGroup provides a mock function with given fields: group -func (_m *Marathon) CreateGroup(group *marathon.Group) error { - ret := _m.Called(group) - - var r0 error - if rf, ok := ret.Get(0).(func(*marathon.Group) error); ok { - r0 = rf(group) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// CreatePod provides a mock function with given fields: pod -func (_m *Marathon) CreatePod(pod *marathon.Pod) (*marathon.Pod, error) { - ret := _m.Called(pod) - - var r0 *marathon.Pod - if rf, ok := ret.Get(0).(func(*marathon.Pod) *marathon.Pod); ok { - r0 = rf(pod) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.Pod) error); ok { - r1 = rf(pod) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteApplication provides a mock function with given fields: name, force -func (_m *Marathon) DeleteApplication(name string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(name, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(name, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteDeployment provides a mock function with given fields: id, force -func (_m *Marathon) DeleteDeployment(id string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(id, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(id, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(id, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteGroup provides a mock function with given fields: name, force -func (_m *Marathon) DeleteGroup(name string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(name, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(name, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeletePod provides a mock function with given fields: name, force -func (_m *Marathon) DeletePod(name string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(name, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(name, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeletePodInstance provides a mock function with given fields: name, instance -func (_m *Marathon) DeletePodInstance(name, instance string) (*marathon.PodInstance, error) { - ret := _m.Called(name, instance) - - var r0 *marathon.PodInstance - if rf, ok := ret.Get(0).(func(string, string) *marathon.PodInstance); ok { - r0 = rf(name, instance) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.PodInstance) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(name, instance) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeletePodInstances provides a mock function with given fields: name, instances -func (_m *Marathon) DeletePodInstances(name string, instances []string) ([]*marathon.PodInstance, error) { - ret := _m.Called(name, instances) - - var r0 []*marathon.PodInstance - if rf, ok := ret.Get(0).(func(string, []string) []*marathon.PodInstance); ok { - r0 = rf(name, instances) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*marathon.PodInstance) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, []string) error); ok { - r1 = rf(name, instances) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteQueueDelay provides a mock function with given fields: appID -func (_m *Marathon) DeleteQueueDelay(appID string) error { - ret := _m.Called(appID) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(appID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Deployments provides a mock function with given fields: -func (_m *Marathon) Deployments() ([]*marathon.Deployment, error) { - ret := _m.Called() - - var r0 []*marathon.Deployment - if rf, ok := ret.Get(0).(func() []*marathon.Deployment); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*marathon.Deployment) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetMarathonURL provides a mock function with given fields: -func (_m *Marathon) GetMarathonURL() string { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// Group provides a mock function with given fields: name -func (_m *Marathon) Group(name string) (*marathon.Group, error) { - ret := _m.Called(name) - - var r0 *marathon.Group - if rf, ok := ret.Get(0).(func(string) *marathon.Group); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Group) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GroupBy provides a mock function with given fields: name, opts -func (_m *Marathon) GroupBy(name string, opts *marathon.GetGroupOpts) (*marathon.Group, error) { - ret := _m.Called(name, opts) - - var r0 *marathon.Group - if rf, ok := ret.Get(0).(func(string, *marathon.GetGroupOpts) *marathon.Group); ok { - r0 = rf(name, opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Group) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.GetGroupOpts) error); ok { - r1 = rf(name, opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Groups provides a mock function with given fields: -func (_m *Marathon) Groups() (*marathon.Groups, error) { - ret := _m.Called() - - var r0 *marathon.Groups - if rf, ok := ret.Get(0).(func() *marathon.Groups); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Groups) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GroupsBy provides a mock function with given fields: opts -func (_m *Marathon) GroupsBy(opts *marathon.GetGroupOpts) (*marathon.Groups, error) { - ret := _m.Called(opts) - - var r0 *marathon.Groups - if rf, ok := ret.Get(0).(func(*marathon.GetGroupOpts) *marathon.Groups); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Groups) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.GetGroupOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// HasApplicationVersion provides a mock function with given fields: name, version -func (_m *Marathon) HasApplicationVersion(name, version string) (bool, error) { - ret := _m.Called(name, version) - - var r0 bool - if rf, ok := ret.Get(0).(func(string, string) bool); ok { - r0 = rf(name, version) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(name, version) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// HasDeployment provides a mock function with given fields: id -func (_m *Marathon) HasDeployment(id string) (bool, error) { - ret := _m.Called(id) - - var r0 bool - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(id) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// HasGroup provides a mock function with given fields: name -func (_m *Marathon) HasGroup(name string) (bool, error) { - ret := _m.Called(name) - - var r0 bool - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(name) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Info provides a mock function with given fields: -func (_m *Marathon) Info() (*marathon.Info, error) { - ret := _m.Called() - - var r0 *marathon.Info - if rf, ok := ret.Get(0).(func() *marathon.Info); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Info) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// KillApplicationTasks provides a mock function with given fields: applicationID, opts -func (_m *Marathon) KillApplicationTasks(applicationID string, opts *marathon.KillApplicationTasksOpts) (*marathon.Tasks, error) { - ret := _m.Called(applicationID, opts) - - var r0 *marathon.Tasks - if rf, ok := ret.Get(0).(func(string, *marathon.KillApplicationTasksOpts) *marathon.Tasks); ok { - r0 = rf(applicationID, opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Tasks) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.KillApplicationTasksOpts) error); ok { - r1 = rf(applicationID, opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// KillTask provides a mock function with given fields: taskID, opts -func (_m *Marathon) KillTask(taskID string, opts *marathon.KillTaskOpts) (*marathon.Task, error) { - ret := _m.Called(taskID, opts) - - var r0 *marathon.Task - if rf, ok := ret.Get(0).(func(string, *marathon.KillTaskOpts) *marathon.Task); ok { - r0 = rf(taskID, opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Task) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.KillTaskOpts) error); ok { - r1 = rf(taskID, opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// KillTasks provides a mock function with given fields: taskIDs, opts -func (_m *Marathon) KillTasks(taskIDs []string, opts *marathon.KillTaskOpts) error { - ret := _m.Called(taskIDs, opts) - - var r0 error - if rf, ok := ret.Get(0).(func([]string, *marathon.KillTaskOpts) error); ok { - r0 = rf(taskIDs, opts) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Leader provides a mock function with given fields: -func (_m *Marathon) Leader() (string, error) { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ListApplications provides a mock function with given fields: _a0 -func (_m *Marathon) ListApplications(_a0 url.Values) ([]string, error) { - ret := _m.Called(_a0) - - var r0 []string - if rf, ok := ret.Get(0).(func(url.Values) []string); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(url.Values) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Ping provides a mock function with given fields: -func (_m *Marathon) Ping() (bool, error) { - ret := _m.Called() - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Pod provides a mock function with given fields: name -func (_m *Marathon) Pod(name string) (*marathon.Pod, error) { - ret := _m.Called(name) - - var r0 *marathon.Pod - if rf, ok := ret.Get(0).(func(string) *marathon.Pod); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PodByVersion provides a mock function with given fields: name, version -func (_m *Marathon) PodByVersion(name, version string) (*marathon.Pod, error) { - ret := _m.Called(name, version) - - var r0 *marathon.Pod - if rf, ok := ret.Get(0).(func(string, string) *marathon.Pod); ok { - r0 = rf(name, version) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(name, version) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PodIsRunning provides a mock function with given fields: name -func (_m *Marathon) PodIsRunning(name string) bool { - ret := _m.Called(name) - - var r0 bool - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(name) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// PodStatus provides a mock function with given fields: name -func (_m *Marathon) PodStatus(name string) (*marathon.PodStatus, error) { - ret := _m.Called(name) - - var r0 *marathon.PodStatus - if rf, ok := ret.Get(0).(func(string) *marathon.PodStatus); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.PodStatus) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PodStatuses provides a mock function with given fields: -func (_m *Marathon) PodStatuses() ([]*marathon.PodStatus, error) { - ret := _m.Called() - - var r0 []*marathon.PodStatus - if rf, ok := ret.Get(0).(func() []*marathon.PodStatus); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*marathon.PodStatus) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PodVersions provides a mock function with given fields: name -func (_m *Marathon) PodVersions(name string) ([]string, error) { - ret := _m.Called(name) - - var r0 []string - if rf, ok := ret.Get(0).(func(string) []string); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Pods provides a mock function with given fields: -func (_m *Marathon) Pods() ([]marathon.Pod, error) { - ret := _m.Called() - - var r0 []marathon.Pod - if rf, ok := ret.Get(0).(func() []marathon.Pod); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Queue provides a mock function with given fields: -func (_m *Marathon) Queue() (*marathon.Queue, error) { - ret := _m.Called() - - var r0 *marathon.Queue - if rf, ok := ret.Get(0).(func() *marathon.Queue); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Queue) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RemoveEventsListener provides a mock function with given fields: channel -func (_m *Marathon) RemoveEventsListener(channel marathon.EventsChannel) { - _m.Called(channel) -} - -// RestartApplication provides a mock function with given fields: name, force -func (_m *Marathon) RestartApplication(name string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(name, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(name, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ScaleApplicationInstances provides a mock function with given fields: name, instances, force -func (_m *Marathon) ScaleApplicationInstances(name string, instances int, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, instances, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, int, bool) *marathon.DeploymentID); ok { - r0 = rf(name, instances, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, int, bool) error); ok { - r1 = rf(name, instances, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// SetApplicationVersion provides a mock function with given fields: name, version -func (_m *Marathon) SetApplicationVersion(name string, version *marathon.ApplicationVersion) (*marathon.DeploymentID, error) { - ret := _m.Called(name, version) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, *marathon.ApplicationVersion) *marathon.DeploymentID); ok { - r0 = rf(name, version) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.ApplicationVersion) error); ok { - r1 = rf(name, version) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Subscribe provides a mock function with given fields: _a0 -func (_m *Marathon) Subscribe(_a0 string) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Subscriptions provides a mock function with given fields: -func (_m *Marathon) Subscriptions() (*marathon.Subscriptions, error) { - ret := _m.Called() - - var r0 *marathon.Subscriptions - if rf, ok := ret.Get(0).(func() *marathon.Subscriptions); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Subscriptions) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// SupportsPods provides a mock function with given fields: -func (_m *Marathon) SupportsPods() (bool, error) { - ret := _m.Called() - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// TaskEndpoints provides a mock function with given fields: name, port, healthCheck -func (_m *Marathon) TaskEndpoints(name string, port int, healthCheck bool) ([]string, error) { - ret := _m.Called(name, port, healthCheck) - - var r0 []string - if rf, ok := ret.Get(0).(func(string, int, bool) []string); ok { - r0 = rf(name, port, healthCheck) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, int, bool) error); ok { - r1 = rf(name, port, healthCheck) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Tasks provides a mock function with given fields: application -func (_m *Marathon) Tasks(application string) (*marathon.Tasks, error) { - ret := _m.Called(application) - - var r0 *marathon.Tasks - if rf, ok := ret.Get(0).(func(string) *marathon.Tasks); ok { - r0 = rf(application) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Tasks) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(application) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Unsubscribe provides a mock function with given fields: _a0 -func (_m *Marathon) Unsubscribe(_a0 string) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// UpdateApplication provides a mock function with given fields: application, force -func (_m *Marathon) UpdateApplication(application *marathon.Application, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(application, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(*marathon.Application, bool) *marathon.DeploymentID); ok { - r0 = rf(application, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.Application, bool) error); ok { - r1 = rf(application, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// UpdateGroup provides a mock function with given fields: id, group, force -func (_m *Marathon) UpdateGroup(id string, group *marathon.Group, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(id, group, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, *marathon.Group, bool) *marathon.DeploymentID); ok { - r0 = rf(id, group, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.Group, bool) error); ok { - r1 = rf(id, group, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// UpdatePod provides a mock function with given fields: pod, force -func (_m *Marathon) UpdatePod(pod *marathon.Pod, force bool) (*marathon.Pod, error) { - ret := _m.Called(pod, force) - - var r0 *marathon.Pod - if rf, ok := ret.Get(0).(func(*marathon.Pod, bool) *marathon.Pod); ok { - r0 = rf(pod, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.Pod, bool) error); ok { - r1 = rf(pod, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// WaitOnApplication provides a mock function with given fields: name, timeout -func (_m *Marathon) WaitOnApplication(name string, timeout time.Duration) error { - ret := _m.Called(name, timeout) - - var r0 error - if rf, ok := ret.Get(0).(func(string, time.Duration) error); ok { - r0 = rf(name, timeout) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// WaitOnDeployment provides a mock function with given fields: id, timeout -func (_m *Marathon) WaitOnDeployment(id string, timeout time.Duration) error { - ret := _m.Called(id, timeout) - - var r0 error - if rf, ok := ret.Get(0).(func(string, time.Duration) error); ok { - r0 = rf(id, timeout) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// WaitOnGroup provides a mock function with given fields: name, timeout -func (_m *Marathon) WaitOnGroup(name string, timeout time.Duration) error { - ret := _m.Called(name, timeout) - - var r0 error - if rf, ok := ret.Get(0).(func(string, time.Duration) error); ok { - r0 = rf(name, timeout) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// WaitOnPod provides a mock function with given fields: name, timeout -func (_m *Marathon) WaitOnPod(name string, timeout time.Duration) error { - ret := _m.Called(name, timeout) - - var r0 error - if rf, ok := ret.Get(0).(func(string, time.Duration) error); ok { - r0 = rf(name, timeout) - } else { - r0 = ret.Error(0) - } - - return r0 -} diff --git a/pkg/provider/marathon/readiness.go b/pkg/provider/marathon/readiness.go deleted file mode 100644 index 76785df13..000000000 --- a/pkg/provider/marathon/readiness.go +++ /dev/null @@ -1,122 +0,0 @@ -package marathon - -import ( - "time" - - "github.com/gambol99/go-marathon" - "github.com/rs/zerolog/log" -) - -const ( - // readinessCheckDefaultTimeout is the default timeout for a readiness - // check if no check timeout is specified on the application spec. This - // should really never be the case, but better be safe than sorry. - readinessCheckDefaultTimeout = 10 * time.Second - // readinessCheckSafetyMargin is some buffer duration to account for - // small offsets in readiness check execution. - readinessCheckSafetyMargin = 5 * time.Second - readinessLogHeader = "Marathon readiness check: " -) - -type readinessChecker struct { - checkDefaultTimeout time.Duration - checkSafetyMargin time.Duration - traceLogging bool -} - -func defaultReadinessChecker(isTraceLogging bool) *readinessChecker { - return &readinessChecker{ - checkDefaultTimeout: readinessCheckDefaultTimeout, - checkSafetyMargin: readinessCheckSafetyMargin, - traceLogging: isTraceLogging, - } -} - -func (rc *readinessChecker) Do(task marathon.Task, app marathon.Application) bool { - if rc == nil { - // Readiness checker disabled. - return true - } - - switch { - case len(app.Deployments) == 0: - // We only care about readiness during deployments; post-deployment readiness - // can be covered by a periodic post-deployment probe (i.e., Traefik health checks). - rc.tracef("task %s app %s: ready = true [no deployment ongoing]", task.ID, app.ID) - return true - - case app.ReadinessChecks == nil || len(*app.ReadinessChecks) == 0: - // Applications without configured readiness checks are always considered - // ready. - rc.tracef("task %s app %s: ready = true [no readiness checks on app]", task.ID, app.ID) - return true - } - - // Loop through all readiness check results and return the results for - // matching task IDs. - if app.ReadinessCheckResults != nil { - for _, readinessCheckResult := range *app.ReadinessCheckResults { - if readinessCheckResult.TaskID == task.ID { - rc.tracef("task %s app %s: ready = %t [evaluating readiness check ready state]", task.ID, app.ID, readinessCheckResult.Ready) - return readinessCheckResult.Ready - } - } - } - - // There's a corner case sometimes hit where the first new task of a - // deployment goes from TASK_STAGING to TASK_RUNNING without a corresponding - // readiness check result being included in the API response. This only happens - // in a very short (yet unlucky) time frame and does not repeat for subsequent - // tasks of the same deployment. - // Complicating matters, the situation may occur for both initially deploying - // applications as well as rolling-upgraded ones where one or more tasks from - // a previous deployment exist already and are joined by new tasks from a - // subsequent deployment. We must always make sure that pre-existing tasks - // maintain their ready state while newly launched tasks must be considered - // unready until a check result appears. - // We distinguish the two cases by comparing the current time with the start - // time of the task: It should take Marathon at most one readiness check timeout - // interval (plus some safety margin to account for the delayed nature of - // distributed systems) for readiness check results to be returned along the API - // response. Once the task turns old enough, we assume it to be part of a - // pre-existing deployment and mark it as ready. Note that it is okay to err - // on the side of caution and consider a task unready until the safety time - // window has elapsed because a newly created task should be readiness-checked - // and be given a result fairly shortly after its creation (i.e., on the scale - // of seconds). - readinessCheckTimeoutSecs := (*app.ReadinessChecks)[0].TimeoutSeconds - readinessCheckTimeout := time.Duration(readinessCheckTimeoutSecs) * time.Second - if readinessCheckTimeout == 0 { - rc.tracef("task %s app %s: readiness check timeout not set, using default value %s", task.ID, app.ID, rc.checkDefaultTimeout) - readinessCheckTimeout = rc.checkDefaultTimeout - } else { - readinessCheckTimeout += rc.checkSafetyMargin - } - - startTime, err := time.Parse(time.RFC3339, task.StartedAt) - if err != nil { - // An unparseable start time should never occur; if it does, we assume the - // problem should be surfaced as quickly as possible, which is easiest if - // we shun the task from rotation. - log.Warn().Err(err).Msgf("Failed to parse start-time %s of task %s from application %s (assuming unready)", task.StartedAt, task.ID, app.ID) - return false - } - - since := time.Since(startTime) - if since < readinessCheckTimeout { - rc.tracef("task %s app %s: ready = false [task with start-time %s not within assumed check timeout window of %s (elapsed time since task start: %s)]", task.ID, app.ID, startTime.Format(time.RFC3339), readinessCheckTimeout, since) - return false - } - - // Finally, we can be certain this task is not part of the deployment (i.e., - // it's an old task that's going to transition into the TASK_KILLING and/or - // TASK_KILLED state as new tasks' readiness checks gradually turn green.) - rc.tracef("task %s app %s: ready = true [task with start-time %s not involved in deployment (elapsed time since task start: %s)]", task.ID, app.ID, startTime.Format(time.RFC3339), since) - return true -} - -func (rc *readinessChecker) tracef(format string, args ...interface{}) { - if rc.traceLogging { - log.Debug().Msgf(readinessLogHeader+format, args...) - } -} diff --git a/pkg/provider/marathon/readiness_test.go b/pkg/provider/marathon/readiness_test.go deleted file mode 100644 index 8d61c01c4..000000000 --- a/pkg/provider/marathon/readiness_test.go +++ /dev/null @@ -1,134 +0,0 @@ -package marathon - -import ( - "testing" - "time" - - "github.com/gambol99/go-marathon" -) - -func testReadinessChecker() *readinessChecker { - return defaultReadinessChecker(false) -} - -func TestDisabledReadinessChecker(t *testing.T) { - var rc *readinessChecker - tsk := task() - app := application( - deployments("deploymentId"), - readinessCheck(0), - readinessCheckResult(testTaskName, false), - ) - - if ready := rc.Do(tsk, app); !ready { - t.Error("expected ready = true") - } -} - -func TestEnabledReadinessChecker(t *testing.T) { - tests := []struct { - desc string - task marathon.Task - app marathon.Application - rc readinessChecker - expectedReady bool - }{ - { - desc: "no deployment running", - task: task(), - app: application(), - expectedReady: true, - }, - { - desc: "no readiness checks defined", - task: task(), - app: application(deployments("deploymentId")), - expectedReady: true, - }, - { - desc: "readiness check result negative", - task: task(), - app: application( - deployments("deploymentId"), - readinessCheck(0), - readinessCheckResult("otherTaskID", true), - readinessCheckResult(testTaskName, false), - ), - expectedReady: false, - }, - { - desc: "readiness check result positive", - task: task(), - app: application( - deployments("deploymentId"), - readinessCheck(0), - readinessCheckResult("otherTaskID", false), - readinessCheckResult(testTaskName, true), - ), - expectedReady: true, - }, - { - desc: "no readiness check result with default timeout", - task: task(startedAtFromNow(3 * time.Minute)), - app: application( - deployments("deploymentId"), - readinessCheck(0), - ), - rc: readinessChecker{ - checkDefaultTimeout: 5 * time.Minute, - }, - expectedReady: false, - }, - { - desc: "no readiness check result with readiness check timeout", - task: task(startedAtFromNow(4 * time.Minute)), - app: application( - deployments("deploymentId"), - readinessCheck(3*time.Minute), - ), - rc: readinessChecker{ - checkSafetyMargin: 3 * time.Minute, - }, - expectedReady: false, - }, - { - desc: "invalid task start time", - task: task(startedAt("invalid")), - app: application( - deployments("deploymentId"), - readinessCheck(0), - ), - expectedReady: false, - }, - { - desc: "task not involved in deployment", - task: task(startedAtFromNow(1 * time.Hour)), - app: application( - deployments("deploymentId"), - readinessCheck(0), - ), - rc: readinessChecker{ - checkDefaultTimeout: 10 * time.Second, - }, - expectedReady: true, - }, - } - - for _, test := range tests { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - rc := testReadinessChecker() - if test.rc.checkDefaultTimeout > 0 { - rc.checkDefaultTimeout = test.rc.checkDefaultTimeout - } - if test.rc.checkSafetyMargin > 0 { - rc.checkSafetyMargin = test.rc.checkSafetyMargin - } - actualReady := test.rc.Do(test.task, test.app) - if actualReady != test.expectedReady { - t.Errorf("actual ready = %t, expected ready = %t", actualReady, test.expectedReady) - } - }) - } -} diff --git a/pkg/redactor/redactor_config_test.go b/pkg/redactor/redactor_config_test.go index 3c564c7a3..468b34251 100644 --- a/pkg/redactor/redactor_config_test.go +++ b/pkg/redactor/redactor_config_test.go @@ -28,7 +28,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/kv/etcd" "github.com/traefik/traefik/v2/pkg/provider/kv/redis" "github.com/traefik/traefik/v2/pkg/provider/kv/zk" - "github.com/traefik/traefik/v2/pkg/provider/marathon" "github.com/traefik/traefik/v2/pkg/provider/rest" traefiktls "github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/tracing/datadog" @@ -610,32 +609,6 @@ func TestDo_staticConfiguration(t *testing.T) { HTTPClientTimeout: 42, } - config.Providers.Marathon = &marathon.Provider{ - Constraints: `Label("foo", "bar")`, - Trace: true, - Watch: true, - Endpoint: "foobar", - DefaultRule: "PathPrefix(`/`)", - ExposedByDefault: true, - DCOSToken: "foobar", - TLS: &types.ClientTLS{ - CA: "myCa", - Cert: "mycert.pem", - Key: "mycert.key", - InsecureSkipVerify: true, - }, - DialerTimeout: 42, - ResponseHeaderTimeout: 42, - TLSHandshakeTimeout: 42, - KeepAlive: 42, - ForceTaskHostname: true, - Basic: &marathon.Basic{ - HTTPBasicAuthUser: "user", - HTTPBasicPassword: "password", - }, - RespectReadinessChecks: true, - } - config.Providers.KubernetesIngress = &ingress.Provider{ Endpoint: "MyEndpoint", Token: "MyToken", diff --git a/pkg/redactor/testdata/anonymized-static-config.json b/pkg/redactor/testdata/anonymized-static-config.json index 1b116aaaf..35a447ef4 100644 --- a/pkg/redactor/testdata/anonymized-static-config.json +++ b/pkg/redactor/testdata/anonymized-static-config.json @@ -112,31 +112,6 @@ "filename": "file Filename", "debugLogGeneratedTemplate": true }, - "marathon": { - "constraints": "Label(\"foo\", \"bar\")", - "trace": true, - "watch": true, - "endpoint": "xxxx", - "defaultRule": "xxxx", - "exposedByDefault": true, - "dcosToken": "xxxx", - "tls": { - "ca": "xxxx", - "cert": "xxxx", - "key": "xxxx", - "insecureSkipVerify": true - }, - "dialerTimeout": "42ns", - "responseHeaderTimeout": "42ns", - "tlsHandshakeTimeout": "42ns", - "keepAlive": "42ns", - "forceTaskHostname": true, - "basic": { - "httpBasicAuthUser": "xxxx", - "httpBasicPassword": "xxxx" - }, - "respectReadinessChecks": true - }, "kubernetesIngress": { "endpoint": "xxxx", "token": "xxxx", diff --git a/pkg/redactor/testdata/example.json b/pkg/redactor/testdata/example.json index 5e5aa7f0a..3dd94d238 100644 --- a/pkg/redactor/testdata/example.json +++ b/pkg/redactor/testdata/example.json @@ -65,7 +65,6 @@ "Docker": null, "File": null, "Web": null, - "Marathon": null, "Consul": null, "ConsulCatalog": null, "Etcd": null, @@ -73,7 +72,6 @@ "Boltdb": null, "KubernetesIngress": null, "KubernetesCRD": null, - "Mesos": null, "Eureka": null, "ECS": null, "DynamoDB": null, diff --git a/pkg/redactor/testdata/expected.json b/pkg/redactor/testdata/expected.json index 22305449a..5849375f8 100644 --- a/pkg/redactor/testdata/expected.json +++ b/pkg/redactor/testdata/expected.json @@ -65,7 +65,6 @@ "Docker": null, "File": null, "Web": null, - "Marathon": null, "Consul": null, "ConsulCatalog": null, "Etcd": null, @@ -73,7 +72,6 @@ "Boltdb": null, "KubernetesIngress": null, "KubernetesCRD": null, - "Mesos": null, "Eureka": null, "ECS": null, "DynamoDB": null, From 943238faba7d99a693416e4e569081cfbc4a4823 Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Mon, 19 Dec 2022 14:32:04 +0100 Subject: [PATCH 13/74] Remove InfluxDB v1 metrics middleware --- README.md | 2 +- cmd/traefik/traefik.go | 10 - docs/content/migration/v2-to-v3.md | 6 +- .../content/observability/metrics/influxdb.md | 268 ------------------ .../content/observability/metrics/overview.md | 11 +- .../reference/static-configuration/cli-ref.md | 36 --- .../reference/static-configuration/env-ref.md | 36 --- .../reference/static-configuration/file.toml | 14 - .../reference/static-configuration/file.yaml | 14 - docs/mkdocs.yml | 1 - pkg/config/dynamic/fixtures/sample.toml | 8 - pkg/metrics/influxdb.go | 249 ---------------- pkg/metrics/influxdb2.go | 32 +++ pkg/metrics/influxdb2_test.go | 12 + pkg/metrics/influxdb_test.go | 267 ----------------- pkg/redactor/redactor_config_test.go | 11 - .../testdata/anonymized-static-config.json | 11 - pkg/server/server.go | 1 - pkg/types/metrics.go | 25 -- 19 files changed, 55 insertions(+), 959 deletions(-) delete mode 100644 docs/content/observability/metrics/influxdb.md delete mode 100644 pkg/metrics/influxdb.go delete mode 100644 pkg/metrics/influxdb_test.go diff --git a/README.md b/README.md index 6e967ab06..7d0faa8ce 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t - Circuit breakers, retry - See the magic through its clean web UI - Websocket, HTTP/2, gRPC ready -- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB) +- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB 2.X) - Keeps access logs (JSON, CLF) - Fast - Exposes a Rest API diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 89580c553..434144db5 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -523,16 +523,6 @@ func registerMetricClients(metricsConfig *types.Metrics) []metrics.Registry { Msg("Configured StatsD metrics") } - if metricsConfig.InfluxDB != nil { - logger := log.With().Str(logs.MetricsProviderName, "influxdb").Logger() - - registries = append(registries, metrics.RegisterInfluxDB(logger.WithContext(context.Background()), metricsConfig.InfluxDB)) - logger.Debug(). - Str("address", metricsConfig.InfluxDB.Address). - Str("pushInterval", metricsConfig.InfluxDB.PushInterval.String()). - Msg("Configured InfluxDB metrics") - } - if metricsConfig.InfluxDB2 != nil { logger := log.With().Str(logs.MetricsProviderName, "influxdb2").Logger() diff --git a/docs/content/migration/v2-to-v3.md b/docs/content/migration/v2-to-v3.md index 6c8d36e5e..3a9c7e4c4 100644 --- a/docs/content/migration/v2-to-v3.md +++ b/docs/content/migration/v2-to-v3.md @@ -29,7 +29,7 @@ In v3, the reported status code for gRPC requests is now the value of the `Grpc- - The `tls.caOptional` option has been removed from the ForwardAuth middleware, as well as from the HTTP, Consul, Etcd, Redis, ZooKeeper, Consul Catalog, and Docker providers. - `sslRedirect`, `sslTemporaryRedirect`, `sslHost`, `sslForceHost` and `featurePolicy` options of the Headers middleware have been removed. - The `forceSlash` option of the StripPrefix middleware has been removed. -- the `preferServerCipherSuites` option has been removed. +- The `preferServerCipherSuites` option has been removed. ## Matchers @@ -76,3 +76,7 @@ As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](../provi ## Marathon provider In v3, the Marathon provider has been removed. + +## InfluxDB v1 + +In v3, the InfluxDB v1 metrics provider has been removed because InfluxDB v1.x maintenance [ended in 2021](https://www.influxdata.com/blog/influxdb-oss-and-enterprise-roadmap-update-from-influxdays-emea/). diff --git a/docs/content/observability/metrics/influxdb.md b/docs/content/observability/metrics/influxdb.md deleted file mode 100644 index 0eb05e23c..000000000 --- a/docs/content/observability/metrics/influxdb.md +++ /dev/null @@ -1,268 +0,0 @@ ---- -title: "Traefik InfluxDB Documentation" -description: "Traefik supports several metrics backends, including InfluxDB. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation." ---- - -# InfluxDB - -To enable the InfluxDB: - -```yaml tab="File (YAML)" -metrics: - influxDB: {} -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] -``` - -```bash tab="CLI" ---metrics.influxdb=true -``` - -#### `address` - -_Required, Default="localhost:8089"_ - -Address instructs exporter to send metrics to influxdb at this address. - -```yaml tab="File (YAML)" -metrics: - influxDB: - address: localhost:8089 -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - address = "localhost:8089" -``` - -```bash tab="CLI" ---metrics.influxdb.address=localhost:8089 -``` - -#### `protocol` - -_Required, Default="udp"_ - -InfluxDB's address protocol (udp or http). - -```yaml tab="File (YAML)" -metrics: - influxDB: - protocol: udp -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - protocol = "udp" -``` - -```bash tab="CLI" ---metrics.influxdb.protocol=udp -``` - -#### `database` - -_Optional, Default=""_ - -InfluxDB database used when protocol is http. - -```yaml tab="File (YAML)" -metrics: - influxDB: - database: db -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - database = "db" -``` - -```bash tab="CLI" ---metrics.influxdb.database=db -``` - -#### `retentionPolicy` - -_Optional, Default=""_ - -InfluxDB retention policy used when protocol is http. - -```yaml tab="File (YAML)" -metrics: - influxDB: - retentionPolicy: two_hours -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - retentionPolicy = "two_hours" -``` - -```bash tab="CLI" ---metrics.influxdb.retentionPolicy=two_hours -``` - -#### `username` - -_Optional, Default=""_ - -InfluxDB username (only with http). - -```yaml tab="File (YAML)" -metrics: - influxDB: - username: john -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - username = "john" -``` - -```bash tab="CLI" ---metrics.influxdb.username=john -``` - -#### `password` - -_Optional, Default=""_ - -InfluxDB password (only with http). - -```yaml tab="File (YAML)" -metrics: - influxDB: - password: secret -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - password = "secret" -``` - -```bash tab="CLI" ---metrics.influxdb.password=secret -``` - -#### `addEntryPointsLabels` - -_Optional, Default=true_ - -Enable metrics on entry points. - -```yaml tab="File (YAML)" -metrics: - influxDB: - addEntryPointsLabels: true -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - addEntryPointsLabels = true -``` - -```bash tab="CLI" ---metrics.influxdb.addEntryPointsLabels=true -``` - -#### `addRoutersLabels` - -_Optional, Default=false_ - -Enable metrics on routers. - -```yaml tab="File (YAML)" -metrics: - influxDB: - addRoutersLabels: true -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - addRoutersLabels = true -``` - -```bash tab="CLI" ---metrics.influxdb.addrouterslabels=true -``` - -#### `addServicesLabels` - -_Optional, Default=true_ - -Enable metrics on services. - -```yaml tab="File (YAML)" -metrics: - influxDB: - addServicesLabels: true -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - addServicesLabels = true -``` - -```bash tab="CLI" ---metrics.influxdb.addServicesLabels=true -``` - -#### `pushInterval` - -_Optional, Default=10s_ - -The interval used by the exporter to push metrics to influxdb. - -```yaml tab="File (YAML)" -metrics: - influxDB: - pushInterval: 10s -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - pushInterval = "10s" -``` - -```bash tab="CLI" ---metrics.influxdb.pushInterval=10s -``` - -#### `additionalLabels` - -_Optional, Default={}_ - -Additional labels (influxdb tags) on all metrics. - -```yaml tab="File (YAML)" -metrics: - influxDB: - additionalLabels: - host: example.com - environment: production -``` - -```toml tab="File (TOML)" -[metrics] - [metrics.influxDB] - [metrics.influxDB.additionalLabels] - host = "example.com" - environment = "production" -``` - -```bash tab="CLI" ---metrics.influxdb.additionallabels.host=example.com --metrics.influxdb.additionallabels.environment=production -``` diff --git a/docs/content/observability/metrics/overview.md b/docs/content/observability/metrics/overview.md index 0fce7e76c..2a3e1d9c7 100644 --- a/docs/content/observability/metrics/overview.md +++ b/docs/content/observability/metrics/overview.md @@ -1,6 +1,6 @@ --- title: "Traefik Metrics Overview" -description: "Traefik Proxy supports these metrics backend systems: Datadog, InfluxDB, Prometheus, and StatsD. Read the full documentation to get started." +description: "Traefik Proxy supports these metrics backend systems: Datadog, InfluxDB 2.X, Prometheus, and StatsD. Read the full documentation to get started." --- # Metrics @@ -8,7 +8,6 @@ description: "Traefik Proxy supports these metrics backend systems: Datadog, Inf Traefik supports these metrics backends: - [Datadog](./datadog.md) -- [InfluxDB](./influxdb.md) - [InfluxDB2](./influxdb2.md) - [Prometheus](./prometheus.md) - [StatsD](./statsd.md) @@ -35,7 +34,7 @@ config.reload.lastSuccessTimestamp tls.certs.notAfterTimestamp ``` -```influxdb tab="InfluxDB / InfluxDB2" +```influxdb tab="InfluxDB2" traefik.config.reload.total traefik.config.reload.lastSuccessTimestamp traefik.tls.certs.notAfterTimestamp @@ -77,7 +76,7 @@ entrypoint.requests.bytes.total entrypoint.responses.bytes.total ``` -```influxdb tab="InfluxDB / InfluxDB2" +```influxdb tab="InfluxDB2" traefik.entrypoint.requests.total traefik.entrypoint.requests.tls.total traefik.entrypoint.request.duration @@ -125,7 +124,7 @@ router.requests.bytes.total router.responses.bytes.total ``` -```influxdb tab="InfluxDB / InfluxDB2" +```influxdb tab="InfluxDB2" traefik.router.requests.total traefik.router.requests.tls.total traefik.router.request.duration @@ -179,7 +178,7 @@ service.requests.bytes.total service.responses.bytes.total ``` -```influxdb tab="InfluxDB / InfluxDB2" +```influxdb tab="InfluxDB2" traefik.service.requests.total traefik.service.requests.tls.total traefik.service.request.duration diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 1a95f346b..00bb3af7f 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -288,42 +288,6 @@ Prefix to use for metrics collection. (Default: ```traefik```) `--metrics.datadog.pushinterval`: Datadog push interval. (Default: ```10```) -`--metrics.influxdb`: -InfluxDB metrics exporter type. (Default: ```false```) - -`--metrics.influxdb.addentrypointslabels`: -Enable metrics on entry points. (Default: ```true```) - -`--metrics.influxdb.additionallabels.`: -Additional labels (influxdb tags) on all metrics - -`--metrics.influxdb.address`: -InfluxDB address. (Default: ```localhost:8089```) - -`--metrics.influxdb.addrouterslabels`: -Enable metrics on routers. (Default: ```false```) - -`--metrics.influxdb.addserviceslabels`: -Enable metrics on services. (Default: ```true```) - -`--metrics.influxdb.database`: -InfluxDB database used when protocol is http. - -`--metrics.influxdb.password`: -InfluxDB password (only with http). - -`--metrics.influxdb.protocol`: -InfluxDB address protocol (udp or http). (Default: ```udp```) - -`--metrics.influxdb.pushinterval`: -InfluxDB push interval. (Default: ```10```) - -`--metrics.influxdb.retentionpolicy`: -InfluxDB retention policy used when protocol is http. - -`--metrics.influxdb.username`: -InfluxDB username (only with http). - `--metrics.influxdb2`: InfluxDB v2 metrics exporter type. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 065ae8bff..b6a7429a8 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -288,9 +288,6 @@ Prefix to use for metrics collection. (Default: ```traefik```) `TRAEFIK_METRICS_DATADOG_PUSHINTERVAL`: Datadog push interval. (Default: ```10```) -`TRAEFIK_METRICS_INFLUXDB`: -InfluxDB metrics exporter type. (Default: ```false```) - `TRAEFIK_METRICS_INFLUXDB2`: InfluxDB v2 metrics exporter type. (Default: ```false```) @@ -321,39 +318,6 @@ InfluxDB v2 push interval. (Default: ```10```) `TRAEFIK_METRICS_INFLUXDB2_TOKEN`: InfluxDB v2 access token. -`TRAEFIK_METRICS_INFLUXDB_ADDENTRYPOINTSLABELS`: -Enable metrics on entry points. (Default: ```true```) - -`TRAEFIK_METRICS_INFLUXDB_ADDITIONALLABELS_`: -Additional labels (influxdb tags) on all metrics - -`TRAEFIK_METRICS_INFLUXDB_ADDRESS`: -InfluxDB address. (Default: ```localhost:8089```) - -`TRAEFIK_METRICS_INFLUXDB_ADDROUTERSLABELS`: -Enable metrics on routers. (Default: ```false```) - -`TRAEFIK_METRICS_INFLUXDB_ADDSERVICESLABELS`: -Enable metrics on services. (Default: ```true```) - -`TRAEFIK_METRICS_INFLUXDB_DATABASE`: -InfluxDB database used when protocol is http. - -`TRAEFIK_METRICS_INFLUXDB_PASSWORD`: -InfluxDB password (only with http). - -`TRAEFIK_METRICS_INFLUXDB_PROTOCOL`: -InfluxDB address protocol (udp or http). (Default: ```udp```) - -`TRAEFIK_METRICS_INFLUXDB_PUSHINTERVAL`: -InfluxDB push interval. (Default: ```10```) - -`TRAEFIK_METRICS_INFLUXDB_RETENTIONPOLICY`: -InfluxDB retention policy used when protocol is http. - -`TRAEFIK_METRICS_INFLUXDB_USERNAME`: -InfluxDB username (only with http). - `TRAEFIK_METRICS_OPENTELEMETRY`: OpenTelemetry metrics exporter type. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 5b68317a9..29ccadce7 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -269,20 +269,6 @@ addRoutersLabels = true addServicesLabels = true prefix = "foobar" - [metrics.influxDB] - address = "foobar" - protocol = "foobar" - pushInterval = "42s" - database = "foobar" - retentionPolicy = "foobar" - username = "foobar" - password = "foobar" - addEntryPointsLabels = true - addRoutersLabels = true - addServicesLabels = true - [metrics.influxDB.additionalLabels] - name0 = "foobar" - name1 = "foobar" [metrics.influxDB2] address = "foobar" token = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 1ce4ec6c1..10284c874 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -298,20 +298,6 @@ metrics: addRoutersLabels: true addServicesLabels: true prefix: foobar - influxDB: - address: foobar - protocol: foobar - pushInterval: 42s - database: foobar - retentionPolicy: foobar - username: foobar - password: foobar - addEntryPointsLabels: true - addRoutersLabels: true - addServicesLabels: true - additionalLabels: - name0: foobar - name1: foobar influxDB2: address: foobar token: foobar diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 4819e16c8..179be7ae5 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -151,7 +151,6 @@ nav: - 'Metrics': - 'Overview': 'observability/metrics/overview.md' - 'Datadog': 'observability/metrics/datadog.md' - - 'InfluxDB': 'observability/metrics/influxdb.md' - 'InfluxDB2': 'observability/metrics/influxdb2.md' - 'OpenTelemetry': 'observability/metrics/opentelemetry.md' - 'Prometheus': 'observability/metrics/prometheus.md' diff --git a/pkg/config/dynamic/fixtures/sample.toml b/pkg/config/dynamic/fixtures/sample.toml index 58534c553..6d37b8ab7 100644 --- a/pkg/config/dynamic/fixtures/sample.toml +++ b/pkg/config/dynamic/fixtures/sample.toml @@ -93,14 +93,6 @@ [metrics.statsD] address = "foobar" pushInterval = "10s" - [metrics.influxDB] - address = "foobar" - protocol = "foobar" - pushInterval = "10s" - database = "foobar" - retentionPolicy = "foobar" - username = "foobar" - password = "foobar" [ping] entryPoint = "foobar" diff --git a/pkg/metrics/influxdb.go b/pkg/metrics/influxdb.go deleted file mode 100644 index d90ec75fc..000000000 --- a/pkg/metrics/influxdb.go +++ /dev/null @@ -1,249 +0,0 @@ -package metrics - -import ( - "bytes" - "context" - "fmt" - "net/url" - "regexp" - "time" - - "github.com/go-kit/kit/metrics/influx" - influxdb "github.com/influxdata/influxdb1-client/v2" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/types" -) - -var ( - influxDBClient *influx.Influx - influxDBTicker *time.Ticker -) - -const ( - influxDBConfigReloadsName = "traefik.config.reload.total" - influxDBConfigReloadsFailureName = influxDBConfigReloadsName + ".failure" - influxDBLastConfigReloadSuccessName = "traefik.config.reload.lastSuccessTimestamp" - influxDBLastConfigReloadFailureName = "traefik.config.reload.lastFailureTimestamp" - - influxDBTLSCertsNotAfterTimestampName = "traefik.tls.certs.notAfterTimestamp" - - influxDBEntryPointReqsName = "traefik.entrypoint.requests.total" - influxDBEntryPointReqsTLSName = "traefik.entrypoint.requests.tls.total" - influxDBEntryPointReqDurationName = "traefik.entrypoint.request.duration" - influxDBEntryPointOpenConnsName = "traefik.entrypoint.connections.open" - influxDBEntryPointReqsBytesName = "traefik.entrypoint.requests.bytes.total" - influxDBEntryPointRespsBytesName = "traefik.entrypoint.responses.bytes.total" - - influxDBRouterReqsName = "traefik.router.requests.total" - influxDBRouterReqsTLSName = "traefik.router.requests.tls.total" - influxDBRouterReqsDurationName = "traefik.router.request.duration" - influxDBORouterOpenConnsName = "traefik.router.connections.open" - influxDBRouterReqsBytesName = "traefik.router.requests.bytes.total" - influxDBRouterRespsBytesName = "traefik.router.responses.bytes.total" - - influxDBServiceReqsName = "traefik.service.requests.total" - influxDBServiceReqsTLSName = "traefik.service.requests.tls.total" - influxDBServiceReqsDurationName = "traefik.service.request.duration" - influxDBServiceRetriesTotalName = "traefik.service.retries.total" - influxDBServiceOpenConnsName = "traefik.service.connections.open" - influxDBServiceServerUpName = "traefik.service.server.up" - influxDBServiceReqsBytesName = "traefik.service.requests.bytes.total" - influxDBServiceRespsBytesName = "traefik.service.responses.bytes.total" -) - -const ( - protocolHTTP = "http" - protocolUDP = "udp" -) - -// RegisterInfluxDB registers the metrics pusher if this didn't happen yet and creates a InfluxDB Registry instance. -func RegisterInfluxDB(ctx context.Context, config *types.InfluxDB) Registry { - if influxDBClient == nil { - influxDBClient = initInfluxDBClient(ctx, config) - } - if influxDBTicker == nil { - influxDBTicker = initInfluxDBTicker(ctx, config) - } - - registry := &standardRegistry{ - configReloadsCounter: influxDBClient.NewCounter(influxDBConfigReloadsName), - configReloadsFailureCounter: influxDBClient.NewCounter(influxDBConfigReloadsFailureName), - lastConfigReloadSuccessGauge: influxDBClient.NewGauge(influxDBLastConfigReloadSuccessName), - lastConfigReloadFailureGauge: influxDBClient.NewGauge(influxDBLastConfigReloadFailureName), - tlsCertsNotAfterTimestampGauge: influxDBClient.NewGauge(influxDBTLSCertsNotAfterTimestampName), - } - - if config.AddEntryPointsLabels { - registry.epEnabled = config.AddEntryPointsLabels - registry.entryPointReqsCounter = influxDBClient.NewCounter(influxDBEntryPointReqsName) - registry.entryPointReqsTLSCounter = influxDBClient.NewCounter(influxDBEntryPointReqsTLSName) - registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBEntryPointReqDurationName), time.Second) - registry.entryPointOpenConnsGauge = influxDBClient.NewGauge(influxDBEntryPointOpenConnsName) - registry.entryPointReqsBytesCounter = influxDBClient.NewCounter(influxDBEntryPointReqsBytesName) - registry.entryPointRespsBytesCounter = influxDBClient.NewCounter(influxDBEntryPointRespsBytesName) - } - - if config.AddRoutersLabels { - registry.routerEnabled = config.AddRoutersLabels - registry.routerReqsCounter = influxDBClient.NewCounter(influxDBRouterReqsName) - registry.routerReqsTLSCounter = influxDBClient.NewCounter(influxDBRouterReqsTLSName) - registry.routerReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBRouterReqsDurationName), time.Second) - registry.routerOpenConnsGauge = influxDBClient.NewGauge(influxDBORouterOpenConnsName) - registry.routerReqsBytesCounter = influxDBClient.NewCounter(influxDBRouterReqsBytesName) - registry.routerRespsBytesCounter = influxDBClient.NewCounter(influxDBRouterRespsBytesName) - } - - if config.AddServicesLabels { - registry.svcEnabled = config.AddServicesLabels - registry.serviceReqsCounter = influxDBClient.NewCounter(influxDBServiceReqsName) - registry.serviceReqsTLSCounter = influxDBClient.NewCounter(influxDBServiceReqsTLSName) - registry.serviceReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBServiceReqsDurationName), time.Second) - registry.serviceRetriesCounter = influxDBClient.NewCounter(influxDBServiceRetriesTotalName) - registry.serviceOpenConnsGauge = influxDBClient.NewGauge(influxDBServiceOpenConnsName) - registry.serviceServerUpGauge = influxDBClient.NewGauge(influxDBServiceServerUpName) - registry.serviceReqsBytesCounter = influxDBClient.NewCounter(influxDBServiceReqsBytesName) - registry.serviceRespsBytesCounter = influxDBClient.NewCounter(influxDBServiceRespsBytesName) - } - - return registry -} - -// initInfluxDBClient creates a influxDBClient. -func initInfluxDBClient(ctx context.Context, config *types.InfluxDB) *influx.Influx { - logger := log.Ctx(ctx) - - // TODO deprecated: move this switch into configuration.SetEffectiveConfiguration when web provider will be removed. - switch config.Protocol { - case protocolUDP: - if len(config.Database) > 0 || len(config.RetentionPolicy) > 0 { - logger.Warn().Msg("Database and RetentionPolicy options have no effect with UDP.") - config.Database = "" - config.RetentionPolicy = "" - } - case protocolHTTP: - if u, err := url.Parse(config.Address); err == nil { - if u.Scheme != "http" && u.Scheme != "https" { - logger.Warn().Msgf("InfluxDB address %s should specify a scheme (http or https): falling back on HTTP.", config.Address) - config.Address = "http://" + config.Address - } - } else { - logger.Error().Err(err).Msg("Unable to parse the InfluxDB address: falling back on UDP.") - config.Protocol = protocolUDP - config.Database = "" - config.RetentionPolicy = "" - } - default: - logger.Warn().Msgf("Unsupported protocol %s: falling back on UDP.", config.Protocol) - config.Protocol = protocolUDP - config.Database = "" - config.RetentionPolicy = "" - } - - return influx.New( - config.AdditionalLabels, - influxdb.BatchPointsConfig{ - Database: config.Database, - RetentionPolicy: config.RetentionPolicy, - }, - logs.NewGoKitWrapper(*logger), - ) -} - -// initInfluxDBTicker initializes metrics pusher. -func initInfluxDBTicker(ctx context.Context, config *types.InfluxDB) *time.Ticker { - report := time.NewTicker(time.Duration(config.PushInterval)) - - safe.Go(func() { - var buf bytes.Buffer - influxDBClient.WriteLoop(ctx, report.C, &influxDBWriter{buf: buf, config: config}) - }) - - return report -} - -// StopInfluxDB stops internal influxDBTicker which controls the pushing of metrics to InfluxDB Agent and resets it to `nil`. -func StopInfluxDB() { - if influxDBTicker != nil { - influxDBTicker.Stop() - } - influxDBTicker = nil -} - -type influxDBWriter struct { - buf bytes.Buffer - config *types.InfluxDB -} - -// Write creates a http or udp client and attempts to write BatchPoints. -// If a "database not found" error is encountered, a CREATE DATABASE -// query is attempted when using protocol http. -func (w *influxDBWriter) Write(bp influxdb.BatchPoints) error { - c, err := w.initWriteClient() - if err != nil { - return err - } - - defer c.Close() - - if writeErr := c.Write(bp); writeErr != nil { - logger := log.With().Str(logs.MetricsProviderName, "influxdb").Logger() - logger.Error().Err(writeErr).Msg("Error while writing to InfluxDB") - - if handleErr := w.handleWriteError(logger.WithContext(context.Background()), c, writeErr); handleErr != nil { - return handleErr - } - // Retry write after successful handling of writeErr - return c.Write(bp) - } - return nil -} - -func (w *influxDBWriter) initWriteClient() (influxdb.Client, error) { - if w.config.Protocol == "http" { - return influxdb.NewHTTPClient(influxdb.HTTPConfig{ - Addr: w.config.Address, - Username: w.config.Username, - Password: w.config.Password, - }) - } - - return influxdb.NewUDPClient(influxdb.UDPConfig{ - Addr: w.config.Address, - }) -} - -func (w *influxDBWriter) handleWriteError(ctx context.Context, c influxdb.Client, writeErr error) error { - if w.config.Protocol != protocolHTTP { - return writeErr - } - - match, matchErr := regexp.MatchString("database not found", writeErr.Error()) - - if matchErr != nil || !match { - return writeErr - } - - qStr := fmt.Sprintf("CREATE DATABASE \"%s\"", w.config.Database) - if w.config.RetentionPolicy != "" { - qStr = fmt.Sprintf("%s WITH NAME \"%s\"", qStr, w.config.RetentionPolicy) - } - - logger := log.Ctx(ctx) - - logger.Debug().Msgf("InfluxDB database not found: attempting to create one with %s", qStr) - - q := influxdb.NewQuery(qStr, "", "") - response, queryErr := c.Query(q) - if queryErr == nil && response.Error() != nil { - queryErr = response.Error() - } - if queryErr != nil { - logger.Error().Err(queryErr).Msg("Error while creating the InfluxDB database") - return queryErr - } - - logger.Debug().Msgf("Successfully created the InfluxDB database %s", w.config.Database) - return nil -} diff --git a/pkg/metrics/influxdb2.go b/pkg/metrics/influxdb2.go index 6cf02e8f7..b23bcc31e 100644 --- a/pkg/metrics/influxdb2.go +++ b/pkg/metrics/influxdb2.go @@ -23,6 +23,38 @@ var ( influxDB2Client influxdb2.Client ) +const ( + influxDBConfigReloadsName = "traefik.config.reload.total" + influxDBConfigReloadsFailureName = influxDBConfigReloadsName + ".failure" + influxDBLastConfigReloadSuccessName = "traefik.config.reload.lastSuccessTimestamp" + influxDBLastConfigReloadFailureName = "traefik.config.reload.lastFailureTimestamp" + + influxDBTLSCertsNotAfterTimestampName = "traefik.tls.certs.notAfterTimestamp" + + influxDBEntryPointReqsName = "traefik.entrypoint.requests.total" + influxDBEntryPointReqsTLSName = "traefik.entrypoint.requests.tls.total" + influxDBEntryPointReqDurationName = "traefik.entrypoint.request.duration" + influxDBEntryPointOpenConnsName = "traefik.entrypoint.connections.open" + influxDBEntryPointReqsBytesName = "traefik.entrypoint.requests.bytes.total" + influxDBEntryPointRespsBytesName = "traefik.entrypoint.responses.bytes.total" + + influxDBRouterReqsName = "traefik.router.requests.total" + influxDBRouterReqsTLSName = "traefik.router.requests.tls.total" + influxDBRouterReqsDurationName = "traefik.router.request.duration" + influxDBORouterOpenConnsName = "traefik.router.connections.open" + influxDBRouterReqsBytesName = "traefik.router.requests.bytes.total" + influxDBRouterRespsBytesName = "traefik.router.responses.bytes.total" + + influxDBServiceReqsName = "traefik.service.requests.total" + influxDBServiceReqsTLSName = "traefik.service.requests.tls.total" + influxDBServiceReqsDurationName = "traefik.service.request.duration" + influxDBServiceRetriesTotalName = "traefik.service.retries.total" + influxDBServiceOpenConnsName = "traefik.service.connections.open" + influxDBServiceServerUpName = "traefik.service.server.up" + influxDBServiceReqsBytesName = "traefik.service.requests.bytes.total" + influxDBServiceRespsBytesName = "traefik.service.responses.bytes.total" +) + // RegisterInfluxDB2 creates metrics exporter for InfluxDB2. func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry { logger := log.Ctx(ctx) diff --git a/pkg/metrics/influxdb2_test.go b/pkg/metrics/influxdb2_test.go index 3fc628d67..441137999 100644 --- a/pkg/metrics/influxdb2_test.go +++ b/pkg/metrics/influxdb2_test.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "net/http/httptest" + "regexp" "strconv" "testing" "time" @@ -155,3 +156,14 @@ func TestInfluxDB2(t *testing.T) { assertMessage(t, *msgServiceOpenConns, expectedServiceOpenConns) } + +func assertMessage(t *testing.T, msg string, patterns []string) { + t.Helper() + for _, pattern := range patterns { + re := regexp.MustCompile(pattern) + match := re.FindStringSubmatch(msg) + if len(match) != 2 { + t.Errorf("Got %q %v, want %q", msg, match, pattern) + } + } +} diff --git a/pkg/metrics/influxdb_test.go b/pkg/metrics/influxdb_test.go deleted file mode 100644 index 38a146697..000000000 --- a/pkg/metrics/influxdb_test.go +++ /dev/null @@ -1,267 +0,0 @@ -package metrics - -import ( - "context" - "fmt" - "io" - "net/http" - "net/http/httptest" - "regexp" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/stvp/go-udp-testing" - ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/types" -) - -func TestInfluxDB(t *testing.T) { - udp.SetAddr(":8089") - // This is needed to make sure that UDP Listener listens for data a bit longer, otherwise it will quit after a millisecond - udp.Timeout = 5 * time.Second - - influxDBClient = nil - influxDBRegistry := RegisterInfluxDB(context.Background(), - &types.InfluxDB{ - Address: ":8089", - PushInterval: ptypes.Duration(time.Second), - AddEntryPointsLabels: true, - AddRoutersLabels: true, - AddServicesLabels: true, - AdditionalLabels: map[string]string{"tag1": "val1"}, - }) - defer StopInfluxDB() - - if !influxDBRegistry.IsEpEnabled() || !influxDBRegistry.IsRouterEnabled() || !influxDBRegistry.IsSvcEnabled() { - t.Fatalf("InfluxDBRegistry should return true for IsEnabled(), IsRouterEnabled() and IsSvcEnabled()") - } - - expectedServer := []string{ - `(traefik\.config\.reload\.total,tag1=val1 count=1) [\d]{19}`, - `(traefik\.config\.reload\.total\.failure,tag1=val1 count=1) [\d]{19}`, - `(traefik\.config\.reload\.lastSuccessTimestamp,tag1=val1 value=1) [\d]{19}`, - `(traefik\.config\.reload\.lastFailureTimestamp,tag1=val1 value=1) [\d]{19}`, - } - - msgServer := udp.ReceiveString(t, func() { - influxDBRegistry.ConfigReloadsCounter().Add(1) - influxDBRegistry.ConfigReloadsFailureCounter().Add(1) - influxDBRegistry.LastConfigReloadSuccessGauge().Set(1) - influxDBRegistry.LastConfigReloadFailureGauge().Set(1) - }) - - assertMessage(t, msgServer, expectedServer) - - expectedTLS := []string{ - `(traefik\.tls\.certs\.notAfterTimestamp,key=value,tag1=val1 value=1) [\d]{19}`, - } - - msgTLS := udp.ReceiveString(t, func() { - influxDBRegistry.TLSCertsNotAfterTimestampGauge().With("key", "value").Set(1) - }) - - assertMessage(t, msgTLS, expectedTLS) - - expectedEntrypoint := []string{ - `(traefik\.entrypoint\.requests\.total,code=200,entrypoint=test,method=GET,tag1=val1 count=1) [\d]{19}`, - `(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`, - `(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`, - `(traefik\.entrypoint\.connections\.open,entrypoint=test,tag1=val1 value=1) [\d]{19}`, - `(traefik\.entrypoint\.requests\.bytes\.total,code=200,entrypoint=test,method=GET,tag1=val1 count=1) [\d]{19}`, - `(traefik\.entrypoint\.responses\.bytes\.total,code=200,entrypoint=test,method=GET,tag1=val1 count=1) [\d]{19}`, - } - - msgEntrypoint := udp.ReceiveString(t, func() { - influxDBRegistry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) - influxDBRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000) - influxDBRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1) - influxDBRegistry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - }) - - assertMessage(t, msgEntrypoint, expectedEntrypoint) - - expectedRouter := []string{ - `(traefik\.router\.requests\.total,code=200,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`, - `(traefik\.router\.requests\.total,code=404,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`, - `(traefik\.router\.requests\.tls\.total,router=demo,service=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`, - `(traefik\.router\.request\.duration,code=200,router=demo,service=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`, - `(traefik\.router\.connections\.open,router=demo,service=test,tag1=val1 value=1) [\d]{19}`, - `(traefik\.router\.requests\.bytes\.total,code=200,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`, - `(traefik\.router\.responses\.bytes\.total,code=200,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`, - } - - msgRouter := udp.ReceiveString(t, func() { - influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) - influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) - influxDBRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - influxDBRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1) - influxDBRegistry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - }) - - assertMessage(t, msgRouter, expectedRouter) - - expectedService := []string{ - `(traefik\.service\.requests\.total,code=200,method=GET,service=test,tag1=val1 count=1) [\d]{19}`, - `(traefik\.service\.requests\.total,code=404,method=GET,service=test,tag1=val1 count=1) [\d]{19}`, - `(traefik\.service\.requests\.tls\.total,service=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`, - `(traefik\.service\.request\.duration,code=200,service=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`, - `(traefik\.service\.retries\.total(?:,code=[\d]{3},method=GET)?,service=test,tag1=val1 count=2) [\d]{19}`, - `(traefik\.service\.server\.up,service=test,tag1=val1,url=http://127.0.0.1 value=1) [\d]{19}`, - `(traefik\.service\.connections\.open,service=test,tag1=val1 value=1) [\d]{19}`, - `(traefik\.service\.requests\.bytes\.total,code=200,method=GET,service=test,tag1=val1 count=1) [\d]{19}`, - `(traefik\.service\.responses\.bytes\.total,code=200,method=GET,service=test,tag1=val1 count=1) [\d]{19}`, - } - - msgService := udp.ReceiveString(t, func() { - influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) - influxDBRegistry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) - influxDBRegistry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - influxDBRegistry.ServiceOpenConnsGauge().With("service", "test").Set(1) - influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1) - influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1) - influxDBRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1) - influxDBRegistry.ServiceReqsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.ServiceRespsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - }) - - assertMessage(t, msgService, expectedService) -} - -func TestInfluxDBHTTP(t *testing.T) { - c := make(chan *string) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - require.NoError(t, err) - - bodyStr := string(body) - c <- &bodyStr - _, _ = fmt.Fprintln(w, "ok") - })) - defer ts.Close() - - influxDBClient = nil - influxDBRegistry := RegisterInfluxDB(context.Background(), - &types.InfluxDB{ - Address: ts.URL, - Protocol: "http", - PushInterval: ptypes.Duration(10 * time.Millisecond), - Database: "test", - RetentionPolicy: "autogen", - AddEntryPointsLabels: true, - AddServicesLabels: true, - AddRoutersLabels: true, - }) - defer StopInfluxDB() - - if !influxDBRegistry.IsEpEnabled() || !influxDBRegistry.IsRouterEnabled() || !influxDBRegistry.IsSvcEnabled() { - t.Fatalf("InfluxDB registry must be epEnabled") - } - - expectedServer := []string{ - `(traefik\.config\.reload\.total count=1) [\d]{19}`, - `(traefik\.config\.reload\.total\.failure count=1) [\d]{19}`, - `(traefik\.config\.reload\.lastSuccessTimestamp value=1) [\d]{19}`, - `(traefik\.config\.reload\.lastFailureTimestamp value=1) [\d]{19}`, - } - - influxDBRegistry.ConfigReloadsCounter().Add(1) - influxDBRegistry.ConfigReloadsFailureCounter().Add(1) - influxDBRegistry.LastConfigReloadSuccessGauge().Set(1) - influxDBRegistry.LastConfigReloadFailureGauge().Set(1) - msgServer := <-c - - assertMessage(t, *msgServer, expectedServer) - - expectedTLS := []string{ - `(traefik\.tls\.certs\.notAfterTimestamp,key=value value=1) [\d]{19}`, - } - - influxDBRegistry.TLSCertsNotAfterTimestampGauge().With("key", "value").Set(1) - msgTLS := <-c - - assertMessage(t, *msgTLS, expectedTLS) - - expectedEntrypoint := []string{ - `(traefik\.entrypoint\.requests\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`, - `(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`, - `(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`, - `(traefik\.entrypoint\.connections\.open,entrypoint=test value=1) [\d]{19}`, - `(traefik\.entrypoint\.requests\.bytes\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`, - `(traefik\.entrypoint\.responses\.bytes\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`, - } - - influxDBRegistry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) - influxDBRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000) - influxDBRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1) - influxDBRegistry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - msgEntrypoint := <-c - - assertMessage(t, *msgEntrypoint, expectedEntrypoint) - - expectedRouter := []string{ - `(traefik\.router\.requests\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`, - `(traefik\.router\.requests\.total,code=404,method=GET,router=demo,service=test count=1) [\d]{19}`, - `(traefik\.router\.requests\.tls\.total,router=demo,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`, - `(traefik\.router\.request\.duration,code=200,router=demo,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`, - `(traefik\.router\.connections\.open,router=demo,service=test value=1) [\d]{19}`, - `(traefik\.router\.requests\.bytes\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`, - `(traefik\.router\.responses\.bytes\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`, - } - - influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) - influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) - influxDBRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - influxDBRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1) - influxDBRegistry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - msgRouter := <-c - - assertMessage(t, *msgRouter, expectedRouter) - - expectedService := []string{ - `(traefik\.service\.requests\.total,code=200,method=GET,service=test count=1) [\d]{19}`, - `(traefik\.service\.requests\.total,code=404,method=GET,service=test count=1) [\d]{19}`, - `(traefik\.service\.requests\.tls\.total,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`, - `(traefik\.service\.request\.duration,code=200,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`, - `(traefik\.service\.retries\.total(?:,code=[\d]{3},method=GET)?,service=test count=2) [\d]{19}`, - `(traefik\.service\.server\.up,service=test,url=http://127.0.0.1 value=1) [\d]{19}`, - `(traefik\.service\.connections\.open,service=test value=1) [\d]{19}`, - `(traefik\.service\.requests\.bytes\.total,code=200,method=GET,service=test count=1) [\d]{19}`, - `(traefik\.service\.responses\.bytes\.total,code=200,method=GET,service=test count=1) [\d]{19}`, - } - - influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) - influxDBRegistry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) - influxDBRegistry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - influxDBRegistry.ServiceOpenConnsGauge().With("service", "test").Set(1) - influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1) - influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1) - influxDBRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1) - influxDBRegistry.ServiceReqsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDBRegistry.ServiceRespsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - msgService := <-c - - assertMessage(t, *msgService, expectedService) -} - -func assertMessage(t *testing.T, msg string, patterns []string) { - t.Helper() - for _, pattern := range patterns { - re := regexp.MustCompile(pattern) - match := re.FindStringSubmatch(msg) - if len(match) != 2 { - t.Errorf("Got %q %v, want %q", msg, match, pattern) - } - } -} diff --git a/pkg/redactor/redactor_config_test.go b/pkg/redactor/redactor_config_test.go index 468b34251..49a4a292d 100644 --- a/pkg/redactor/redactor_config_test.go +++ b/pkg/redactor/redactor_config_test.go @@ -784,17 +784,6 @@ func TestDo_staticConfiguration(t *testing.T) { AddServicesLabels: true, Prefix: "MyPrefix", }, - InfluxDB: &types.InfluxDB{ - Address: "localhost:8183", - Protocol: "http", - PushInterval: 42, - Database: "myDB", - RetentionPolicy: "12", - Username: "a", - Password: "aaaa", - AddEntryPointsLabels: true, - AddServicesLabels: true, - }, } config.Ping = &ping.Handler{ diff --git a/pkg/redactor/testdata/anonymized-static-config.json b/pkg/redactor/testdata/anonymized-static-config.json index 35a447ef4..14d587559 100644 --- a/pkg/redactor/testdata/anonymized-static-config.json +++ b/pkg/redactor/testdata/anonymized-static-config.json @@ -284,17 +284,6 @@ "addEntryPointsLabels": true, "addServicesLabels": true, "prefix": "MyPrefix" - }, - "influxDB": { - "address": "xxxx", - "protocol": "xxxx", - "pushInterval": "42ns", - "database": "myDB", - "retentionPolicy": "12", - "username": "xxxx", - "password": "xxxx", - "addEntryPointsLabels": true, - "addServicesLabels": true } }, "ping": { diff --git a/pkg/server/server.go b/pkg/server/server.go index 421437a38..962cf6c28 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -111,7 +111,6 @@ func (s *Server) Close() { func stopMetricsClients() { metrics.StopDatadog() metrics.StopStatsd() - metrics.StopInfluxDB() metrics.StopInfluxDB2() metrics.StopOpenTelemetry() } diff --git a/pkg/types/metrics.go b/pkg/types/metrics.go index ddcf71d96..775dc7a16 100644 --- a/pkg/types/metrics.go +++ b/pkg/types/metrics.go @@ -13,7 +13,6 @@ type Metrics struct { Prometheus *Prometheus `description:"Prometheus metrics exporter type." json:"prometheus,omitempty" toml:"prometheus,omitempty" yaml:"prometheus,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` Datadog *Datadog `description:"Datadog metrics exporter type." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` StatsD *Statsd `description:"StatsD metrics exporter type." json:"statsD,omitempty" toml:"statsD,omitempty" yaml:"statsD,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` - InfluxDB *InfluxDB `description:"InfluxDB metrics exporter type." json:"influxDB,omitempty" toml:"influxDB,omitempty" yaml:"influxDB,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` InfluxDB2 *InfluxDB2 `description:"InfluxDB v2 metrics exporter type." json:"influxDB2,omitempty" toml:"influxDB2,omitempty" yaml:"influxDB2,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` OpenTelemetry *OpenTelemetry `description:"OpenTelemetry metrics exporter type." json:"openTelemetry,omitempty" toml:"openTelemetry,omitempty" yaml:"openTelemetry,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` } @@ -83,30 +82,6 @@ func (s *Statsd) SetDefaults() { s.Prefix = "traefik" } -// InfluxDB contains address, login and metrics pushing interval configuration. -type InfluxDB struct { - Address string `description:"InfluxDB address." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` - Protocol string `description:"InfluxDB address protocol (udp or http)." json:"protocol,omitempty" toml:"protocol,omitempty" yaml:"protocol,omitempty"` - PushInterval types.Duration `description:"InfluxDB push interval." json:"pushInterval,omitempty" toml:"pushInterval,omitempty" yaml:"pushInterval,omitempty" export:"true"` - Database string `description:"InfluxDB database used when protocol is http." json:"database,omitempty" toml:"database,omitempty" yaml:"database,omitempty" export:"true"` - RetentionPolicy string `description:"InfluxDB retention policy used when protocol is http." json:"retentionPolicy,omitempty" toml:"retentionPolicy,omitempty" yaml:"retentionPolicy,omitempty" export:"true"` - Username string `description:"InfluxDB username (only with http)." json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty" loggable:"false"` - Password string `description:"InfluxDB password (only with http)." json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty" loggable:"false"` - AddEntryPointsLabels bool `description:"Enable metrics on entry points." json:"addEntryPointsLabels,omitempty" toml:"addEntryPointsLabels,omitempty" yaml:"addEntryPointsLabels,omitempty" export:"true"` - AddRoutersLabels bool `description:"Enable metrics on routers." json:"addRoutersLabels,omitempty" toml:"addRoutersLabels,omitempty" yaml:"addRoutersLabels,omitempty" export:"true"` - AddServicesLabels bool `description:"Enable metrics on services." json:"addServicesLabels,omitempty" toml:"addServicesLabels,omitempty" yaml:"addServicesLabels,omitempty" export:"true"` - AdditionalLabels map[string]string `description:"Additional labels (influxdb tags) on all metrics" json:"additionalLabels,omitempty" toml:"additionalLabels,omitempty" yaml:"additionalLabels,omitempty" export:"true"` -} - -// SetDefaults sets the default values. -func (i *InfluxDB) SetDefaults() { - i.Address = "localhost:8089" - i.Protocol = "udp" - i.PushInterval = types.Duration(10 * time.Second) - i.AddEntryPointsLabels = true - i.AddServicesLabels = true -} - // InfluxDB2 contains address, token and metrics pushing interval configuration. type InfluxDB2 struct { Address string `description:"InfluxDB v2 address." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` From d046af2e91e733db1f909c7108f24865d07a2a8f Mon Sep 17 00:00:00 2001 From: Roman Tomjak <6570684+romantomjak@users.noreply.github.com> Date: Thu, 22 Dec 2022 14:02:05 +0000 Subject: [PATCH 14/74] Add support for HTTPRequestRedirectFilter in k8s Gateway API --- .../httproute/filter_http_to_https.yml | 52 +++++++ ...r_http_to_https_with_hostname_and_port.yml | 52 +++++++ pkg/provider/kubernetes/gateway/kubernetes.go | 100 +++++++++++++ .../kubernetes/gateway/kubernetes_test.go | 135 ++++++++++++++++++ 4 files changed, 339 insertions(+) create mode 100644 pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml create mode 100644 pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml new file mode 100644 index 000000000..5b8d1607d --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml @@ -0,0 +1,52 @@ +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway-class +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + +--- +kind: HTTPRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: http-app-1 + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - "example.org" + rules: + - backendRefs: + - name: whoami + port: 80 + weight: 1 + kind: Service + group: "" + filters: + - type: RequestRedirect + requestRedirect: + scheme: https + statusCode: 301 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml new file mode 100644 index 000000000..79e875be1 --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml @@ -0,0 +1,52 @@ +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway-class +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + kinds: + - kind: HTTPRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + +--- +kind: HTTPRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: http-app-1 + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - "example.org" + rules: + - backendRefs: + - name: whoami + port: 80 + weight: 1 + kind: Service + group: "" + filters: + - type: RequestRedirect + requestRedirect: + hostname: example.com + port: 443 diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index 847d1c09b..8f25399f6 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "net" + "net/http" "os" "regexp" "sort" @@ -756,6 +757,26 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha continue } + middlewares, err := loadMiddlewares(listener, routerKey, routeRule.Filters) + if err != nil { + // update "ResolvedRefs" status true with "InvalidFilters" reason + conditions = append(conditions, metav1.Condition{ + Type: string(v1alpha2.ListenerConditionResolvedRefs), + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: "InvalidFilters", // TODO check the spec if a proper reason is introduced at some point + Message: fmt.Sprintf("Cannot load HTTPRoute filter %s/%s: %v", route.Namespace, route.Name, err), + }) + + // TODO update the RouteStatus condition / deduplicate conditions on listener + continue + } + + for middlewareName, middleware := range middlewares { + conf.HTTP.Middlewares[middlewareName] = middleware + router.Middlewares = append(router.Middlewares, middlewareName) + } + if len(routeRule.BackendRefs) == 0 { continue } @@ -1663,6 +1684,85 @@ func loadTCPServices(client Client, namespace string, backendRefs []v1alpha2.Bac return wrrSvc, services, nil } +func loadMiddlewares(listener v1alpha2.Listener, prefix string, filters []v1alpha2.HTTPRouteFilter) (map[string]*dynamic.Middleware, error) { + middlewares := make(map[string]*dynamic.Middleware) + + // The spec allows for an empty string in which case we should use the + // scheme of the request which in this case is the listener scheme. + var listenerScheme string + switch listener.Protocol { + case v1alpha2.HTTPProtocolType: + listenerScheme = "http" + case v1alpha2.HTTPSProtocolType: + listenerScheme = "https" + default: + return nil, fmt.Errorf("invalid listener protocol %s", listener.Protocol) + } + + for i, filter := range filters { + var middleware *dynamic.Middleware + switch filter.Type { + case v1alpha2.HTTPRouteFilterRequestRedirect: + var err error + middleware, err = createRedirectRegexMiddleware(listenerScheme, filter.RequestRedirect) + if err != nil { + return nil, fmt.Errorf("creating RedirectRegex middleware: %w", err) + } + default: + // As per the spec: + // https://gateway-api.sigs.k8s.io/api-types/httproute/#filters-optional + // In all cases where incompatible or unsupported filters are + // specified, implementations MUST add a warning condition to + // status. + return nil, fmt.Errorf("unsupported filter %s", filter.Type) + } + + middlewareName := provider.Normalize(fmt.Sprintf("%s-%s-%d", prefix, strings.ToLower(string(filter.Type)), i)) + middlewares[middlewareName] = middleware + } + + return middlewares, nil +} + +func createRedirectRegexMiddleware(scheme string, filter *v1alpha2.HTTPRequestRedirectFilter) (*dynamic.Middleware, error) { + // Use the HTTPRequestRedirectFilter scheme if defined. + filterScheme := scheme + if filter.Scheme != nil { + filterScheme = *filter.Scheme + } + + if filterScheme != "http" && filterScheme != "https" { + return nil, fmt.Errorf("invalid scheme %s", filterScheme) + } + + statusCode := http.StatusFound + if filter.StatusCode != nil { + statusCode = *filter.StatusCode + } + + if statusCode != http.StatusMovedPermanently && statusCode != http.StatusFound { + return nil, fmt.Errorf("invalid status code %d", statusCode) + } + + port := "${port}" + if filter.Port != nil { + port = fmt.Sprintf(":%d", *filter.Port) + } + + hostname := "${hostname}" + if filter.Hostname != nil && *filter.Hostname != "" { + hostname = string(*filter.Hostname) + } + + return &dynamic.Middleware{ + RedirectRegex: &dynamic.RedirectRegex{ + Regex: `^[a-z]+:\/\/(?P.+@)?(?P\[[\w:\.]+\]|[\w\._-]+)(?P:\d+)?\/(?P.*)`, + Replacement: fmt.Sprintf("%s://${userinfo}%s%s/${path}", filterScheme, hostname, port), + Permanent: statusCode == http.StatusMovedPermanently, + }, + }, nil +} + func getProtocol(portSpec corev1.ServicePort) string { protocol := "http" if portSpec.Port == 443 || strings.HasPrefix(portSpec.Name, "https") { diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index 28946ba7b..068d37d3b 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -1555,6 +1555,141 @@ func TestLoadHTTPRoutes(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "Simple HTTPRoute, redirect HTTP to HTTPS", + paths: []string{"services.yml", "httproute/filter_http_to_https.yml"}, + entryPoints: map[string]Entrypoint{"web": { + Address: ":80", + }}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4": { + EntryPoints: []string{"web"}, + Service: "default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4-wrr", + Rule: "Host(`example.org`) && PathPrefix(`/`)", + Middlewares: []string{"default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4-requestredirect-0"}, + }, + }, + Middlewares: map[string]*dynamic.Middleware{ + "default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4-requestredirect-0": { + RedirectRegex: &dynamic.RedirectRegex{ + Regex: "^[a-z]+:\\/\\/(?P.+@)?(?P\\[[\\w:\\.]+\\]|[\\w\\._-]+)(?P:\\d+)?\\/(?P.*)", + Replacement: "https://${userinfo}${hostname}${port}/${path}", + Permanent: true, + }, + }, + }, + Services: map[string]*dynamic.Service{ + "default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4-wrr": { + Weighted: &dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { + Name: "default-whoami-80", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-whoami-80": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:80", + }, + { + URL: "http://10.10.0.2:80", + }, + }, + PassHostHeader: pointer.Bool(true), + ResponseForwarding: &dynamic.ResponseForwarding{ + FlushInterval: ptypes.Duration(100 * time.Millisecond), + }, + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "Simple HTTPRoute, redirect HTTP to HTTPS with hostname", + paths: []string{"services.yml", "httproute/filter_http_to_https_with_hostname_and_port.yml"}, + entryPoints: map[string]Entrypoint{"web": { + Address: ":80", + }}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4": { + EntryPoints: []string{"web"}, + Service: "default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4-wrr", + Rule: "Host(`example.org`) && PathPrefix(`/`)", + Middlewares: []string{"default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4-requestredirect-0"}, + }, + }, + Middlewares: map[string]*dynamic.Middleware{ + "default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4-requestredirect-0": { + RedirectRegex: &dynamic.RedirectRegex{ + Regex: "^[a-z]+:\\/\\/(?P.+@)?(?P\\[[\\w:\\.]+\\]|[\\w\\._-]+)(?P:\\d+)?\\/(?P.*)", + Replacement: "http://${userinfo}example.com:443/${path}", + }, + }, + }, + Services: map[string]*dynamic.Service{ + "default-http-app-1-my-gateway-web-364ce6ec04c3d49b19c4-wrr": { + Weighted: &dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { + Name: "default-whoami-80", + Weight: func(i int) *int { return &i }(1), + }, + }, + }, + }, + "default-whoami-80": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:80", + }, + { + URL: "http://10.10.0.2:80", + }, + }, + PassHostHeader: pointer.Bool(true), + ResponseForwarding: &dynamic.ResponseForwarding{ + FlushInterval: ptypes.Duration(100 * time.Millisecond), + }, + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, } for _, test := range testCases { From 8c98234c07395f3397b2b49921b496b83b2be1ae Mon Sep 17 00:00:00 2001 From: jandillenkofer <56083248+jandillenkofer@users.noreply.github.com> Date: Thu, 22 Dec 2022 16:30:05 +0100 Subject: [PATCH 15/74] Add option to the Ingress provider to disable IngressClass lookup --- docs/content/providers/kubernetes-ingress.md | 29 +++++ .../reference/static-configuration/cli-ref.md | 3 + .../reference/static-configuration/env-ref.md | 3 + .../reference/static-configuration/file.toml | 1 + .../reference/static-configuration/file.yaml | 1 + .../fixtures/k8s_ingressclass_disabled.toml | 18 +++ integration/k8s_test.go | 11 ++ .../rawdata-ingressclass-disabled.json | 74 +++++++++++ pkg/provider/kubernetes/ingress/client.go | 21 ++-- pkg/provider/kubernetes/ingress/kubernetes.go | 4 +- .../kubernetes/ingress/kubernetes_test.go | 115 +++++++++++++++++- 11 files changed, 263 insertions(+), 17 deletions(-) create mode 100644 integration/fixtures/k8s_ingressclass_disabled.toml create mode 100644 integration/testdata/rawdata-ingressclass-disabled.json diff --git a/docs/content/providers/kubernetes-ingress.md b/docs/content/providers/kubernetes-ingress.md index a35017cc5..4d915a596 100644 --- a/docs/content/providers/kubernetes-ingress.md +++ b/docs/content/providers/kubernetes-ingress.md @@ -344,6 +344,35 @@ providers: --providers.kubernetesingress.ingressclass=traefik-internal ``` +### `disableIngressClassLookup` + +_Optional, Default: false_ + +If the parameter is set to `true`, +Traefik will not discover IngressClasses in the cluster. +By doing so, it alleviates the requirement of giving Traefik the rights to look IngressClasses up. +Furthermore, when this option is set to `true`, +Traefik is not able to handle Ingresses with IngressClass references, +therefore such Ingresses will be ignored. +Please note that annotations are not affected by this option. + +```yaml tab="File (YAML)" +providers: + kubernetesIngress: + disableIngressClassLookup: true + # ... +``` + +```toml tab="File (TOML)" +[providers.kubernetesIngress] + disableIngressClassLookup = true + # ... +``` + +```bash tab="CLI" +--providers.kubernetesingress.disableingressclasslookup=true +``` + ### `ingressEndpoint` #### `hostname` diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 00bb3af7f..fa5c9759f 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -735,6 +735,9 @@ Allow ExternalName services. (Default: ```false```) `--providers.kubernetesingress.certauthfilepath`: Kubernetes certificate authority file path (not needed for in-cluster client). +`--providers.kubernetesingress.disableingressclasslookup`: +Disables the lookup of IngressClasses. (Default: ```false```) + `--providers.kubernetesingress.endpoint`: Kubernetes server endpoint (required for external cluster client). diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index b6a7429a8..4a951b462 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -735,6 +735,9 @@ Allow ExternalName services. (Default: ```false```) `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_CERTAUTHFILEPATH`: Kubernetes certificate authority file path (not needed for in-cluster client). +`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_DISABLEINGRESSCLASSLOOKUP`: +Disables the lookup of IngressClasses. (Default: ```false```) + `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_ENDPOINT`: Kubernetes server endpoint (required for external cluster client). diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 29ccadce7..8bff3f0a2 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -108,6 +108,7 @@ throttleDuration = "42s" allowEmptyServices = true allowExternalNameServices = true + disableIngressClassLookup = true [providers.kubernetesIngress.ingressEndpoint] ip = "foobar" hostname = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 10284c874..e6b100632 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -117,6 +117,7 @@ providers: throttleDuration: 42s allowEmptyServices: true allowExternalNameServices: true + disableIngressClassLookup: true ingressEndpoint: ip: foobar hostname: foobar diff --git a/integration/fixtures/k8s_ingressclass_disabled.toml b/integration/fixtures/k8s_ingressclass_disabled.toml new file mode 100644 index 000000000..8afc19e97 --- /dev/null +++ b/integration/fixtures/k8s_ingressclass_disabled.toml @@ -0,0 +1,18 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[log] + level = "DEBUG" + noColor = true + +[api] + insecure = true + +[entryPoints] + [entryPoints.web] + address = ":8000" + +[providers.kubernetesIngress] + ingressClass = "traefik-keep" + disableIngressClassLookup = true diff --git a/integration/k8s_test.go b/integration/k8s_test.go index bfb73d93c..13c64a2e0 100644 --- a/integration/k8s_test.go +++ b/integration/k8s_test.go @@ -128,6 +128,17 @@ func (s *K8sSuite) TestIngressclass(c *check.C) { testConfiguration(c, "testdata/rawdata-ingressclass.json", "8080") } +func (s *K8sSuite) TestDisableIngressclassLookup(c *check.C) { + cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_ingressclass_disabled.toml")) + defer display(c) + + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer s.killCmd(cmd) + + testConfiguration(c, "testdata/rawdata-ingressclass-disabled.json", "8080") +} + func testConfiguration(c *check.C, path, apiPort string) { err := try.GetRequest("http://127.0.0.1:"+apiPort+"/api/entrypoints", 20*time.Second, try.BodyContains(`"name":"web"`)) c.Assert(err, checker.IsNil) diff --git a/integration/testdata/rawdata-ingressclass-disabled.json b/integration/testdata/rawdata-ingressclass-disabled.json new file mode 100644 index 000000000..14649419c --- /dev/null +++ b/integration/testdata/rawdata-ingressclass-disabled.json @@ -0,0 +1,74 @@ +{ + "routers": { + "api@internal": { + "entryPoints": [ + "traefik" + ], + "service": "api@internal", + "rule": "PathPrefix(`/api`)", + "priority": 2147483646, + "status": "enabled", + "using": [ + "traefik" + ] + }, + "dashboard@internal": { + "entryPoints": [ + "traefik" + ], + "middlewares": [ + "dashboard_redirect@internal", + "dashboard_stripprefix@internal" + ], + "service": "dashboard@internal", + "rule": "PathPrefix(`/`)", + "priority": 2147483645, + "status": "enabled", + "using": [ + "traefik" + ] + } + }, + "middlewares": { + "dashboard_redirect@internal": { + "redirectRegex": { + "regex": "^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$", + "replacement": "${1}/dashboard/", + "permanent": true + }, + "status": "enabled", + "usedBy": [ + "dashboard@internal" + ] + }, + "dashboard_stripprefix@internal": { + "stripPrefix": { + "prefixes": [ + "/dashboard/", + "/dashboard" + ] + }, + "status": "enabled", + "usedBy": [ + "dashboard@internal" + ] + } + }, + "services": { + "api@internal": { + "status": "enabled", + "usedBy": [ + "api@internal" + ] + }, + "dashboard@internal": { + "status": "enabled", + "usedBy": [ + "dashboard@internal" + ] + }, + "noop@internal": { + "status": "enabled" + } + } +} \ No newline at end of file diff --git a/pkg/provider/kubernetes/ingress/client.go b/pkg/provider/kubernetes/ingress/client.go index eccd39657..2ac486724 100644 --- a/pkg/provider/kubernetes/ingress/client.go +++ b/pkg/provider/kubernetes/ingress/client.go @@ -50,15 +50,16 @@ type Client interface { } type clientWrapper struct { - clientset kubernetes.Interface - factoriesKube map[string]informers.SharedInformerFactory - factoriesSecret map[string]informers.SharedInformerFactory - factoriesIngress map[string]informers.SharedInformerFactory - clusterFactory informers.SharedInformerFactory - ingressLabelSelector string - isNamespaceAll bool - watchedNamespaces []string - serverVersion *version.Version + clientset kubernetes.Interface + factoriesKube map[string]informers.SharedInformerFactory + factoriesSecret map[string]informers.SharedInformerFactory + factoriesIngress map[string]informers.SharedInformerFactory + clusterFactory informers.SharedInformerFactory + ingressLabelSelector string + isNamespaceAll bool + disableIngressClassInformer bool + watchedNamespaces []string + serverVersion *version.Version } // newInClusterClient returns a new Provider client that is expected to run @@ -214,7 +215,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (< } } - if supportsIngressClass(serverVersion) { + if !c.disableIngressClassInformer && supportsIngressClass(serverVersion) { c.clusterFactory = informers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod) if supportsNetworkingV1Ingress(serverVersion) { diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index 95a71c12d..54a4be395 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -48,6 +48,7 @@ type Provider struct { ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"` AllowEmptyServices bool `description:"Allow creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"` AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"` + DisableIngressClassLookup bool `description:"Disables the lookup of IngressClasses." json:"disableIngressClassLookup,omitempty" toml:"disableIngressClassLookup,omitempty" yaml:"disableIngressClassLookup,omitempty" export:"true"` lastConfiguration safe.Safe } @@ -91,6 +92,7 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) { } cl.ingressLabelSelector = p.LabelSelector + cl.disableIngressClassInformer = p.DisableIngressClassLookup return cl, nil } @@ -195,7 +197,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl var ingressClasses []*networkingv1.IngressClass - if supportsIngressClass(serverVersion) { + if !p.DisableIngressClassLookup && supportsIngressClass(serverVersion) { ics, err := client.GetIngressClasses() if err != nil { log.Ctx(ctx).Warn().Err(err).Msg("Failed to list ingress classes") diff --git a/pkg/provider/kubernetes/ingress/kubernetes_test.go b/pkg/provider/kubernetes/ingress/kubernetes_test.go index 3b032f996..3c21f1519 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes_test.go +++ b/pkg/provider/kubernetes/ingress/kubernetes_test.go @@ -26,11 +26,12 @@ func Bool(v bool) *bool { return &v } func TestLoadConfigurationFromIngresses(t *testing.T) { testCases := []struct { - desc string - ingressClass string - serverVersion string - expected *dynamic.Configuration - allowEmptyServices bool + desc string + ingressClass string + serverVersion string + expected *dynamic.Configuration + allowEmptyServices bool + disableIngressClassLookup bool }{ { desc: "Empty ingresses", @@ -1392,6 +1393,40 @@ func TestLoadConfigurationFromIngresses(t *testing.T) { }, }, }, + { + // Duplicate test case with the same fixture as the one above, but with the disableIngressClassLookup option to true. + // Showing that disabling the ingressClass discovery still allow the discovery of ingresses with ingress annotation. + desc: "v18 Ingress with ingress annotation", + serverVersion: "v1.18", + disableIngressClassLookup: true, + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{}, + HTTP: &dynamic.HTTPConfiguration{ + Middlewares: map[string]*dynamic.Middleware{}, + Routers: map[string]*dynamic.Router{ + "testing-bar": { + Rule: "PathPrefix(`/bar`)", + Service: "testing-service1-80", + }, + }, + Services: map[string]*dynamic.Service{ + "testing-service1-80": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + PassHostHeader: Bool(true), + ResponseForwarding: &dynamic.ResponseForwarding{ + FlushInterval: ptypes.Duration(100 * time.Millisecond), + }, + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:8080", + }, + }, + }, + }, + }, + }, + }, + }, { desc: "v18 Ingress with ingressClasses filter", serverVersion: "v1.18", @@ -1424,6 +1459,22 @@ func TestLoadConfigurationFromIngresses(t *testing.T) { }, }, }, + { + // Duplicate test case with the same fixture as the one above, but with the disableIngressClassLookup option to true. + // Showing that disabling the ingressClass discovery avoid discovering Ingresses with an IngressClass. + desc: "v18 Ingress with ingressClasses filter", + serverVersion: "v1.18", + ingressClass: "traefik-lb2", + disableIngressClassLookup: true, + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{}, + HTTP: &dynamic.HTTPConfiguration{ + Middlewares: map[string]*dynamic.Middleware{}, + Routers: map[string]*dynamic.Router{}, + Services: map[string]*dynamic.Service{}, + }, + }, + }, { desc: "v19 Ingress with prefix pathType", serverVersion: "v1.19", @@ -1610,6 +1661,39 @@ func TestLoadConfigurationFromIngresses(t *testing.T) { }, }, }, + { + // Duplicate test case with the same fixture as the one above, but with the disableIngressClassLookup option to true. + // Showing that disabling the ingressClass discovery still allow the discovery of ingresses with ingress annotation. + desc: "v19 Ingress with ingress annotation", + serverVersion: "v1.19", + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{}, + HTTP: &dynamic.HTTPConfiguration{ + Middlewares: map[string]*dynamic.Middleware{}, + Routers: map[string]*dynamic.Router{ + "testing-bar": { + Rule: "PathPrefix(`/bar`)", + Service: "testing-service1-80", + }, + }, + Services: map[string]*dynamic.Service{ + "testing-service1-80": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + PassHostHeader: Bool(true), + ResponseForwarding: &dynamic.ResponseForwarding{ + FlushInterval: ptypes.Duration(100 * time.Millisecond), + }, + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:8080", + }, + }, + }, + }, + }, + }, + }, + }, { desc: "v19 Ingress with ingressClass", serverVersion: "v1.19", @@ -1641,6 +1725,21 @@ func TestLoadConfigurationFromIngresses(t *testing.T) { }, }, }, + { + // Duplicate test case with the same fixture as the one above, but with the disableIngressClassLookup option to true. + // Showing that disabling the ingressClass discovery avoid discovering Ingresses with an IngressClass. + desc: "v19 Ingress with ingressClass", + disableIngressClassLookup: true, + serverVersion: "v1.19", + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{}, + HTTP: &dynamic.HTTPConfiguration{ + Middlewares: map[string]*dynamic.Middleware{}, + Routers: map[string]*dynamic.Router{}, + Services: map[string]*dynamic.Service{}, + }, + }, + }, { desc: "v19 Ingress with ingressClassv1", serverVersion: "v1.19", @@ -1783,7 +1882,11 @@ func TestLoadConfigurationFromIngresses(t *testing.T) { } clientMock := newClientMock(serverVersion, paths...) - p := Provider{IngressClass: test.ingressClass, AllowEmptyServices: test.allowEmptyServices} + p := Provider{ + IngressClass: test.ingressClass, + AllowEmptyServices: test.allowEmptyServices, + DisableIngressClassLookup: test.disableIngressClassLookup, + } conf := p.loadConfigurationFromIngresses(context.Background(), clientMock) assert.Equal(t, test.expected, conf) From c38d405cfd8bc652374ba38229a5cf26ad1cfa8d Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Thu, 22 Dec 2022 17:16:04 +0100 Subject: [PATCH 16/74] Remove containous/mux from HTTP muxer Co-authored-by: Simon Delicata --- go.mod | 1 - go.sum | 7 +- pkg/muxer/http/matcher.go | 106 ++++++++++------ pkg/muxer/http/matcher_test.go | 35 +++++- pkg/muxer/http/mux.go | 221 +++++++++++++++++++-------------- pkg/muxer/http/mux_test.go | 2 - pkg/muxer/tcp/mux.go | 134 ++++++++++---------- pkg/server/router/router.go | 2 - 8 files changed, 299 insertions(+), 209 deletions(-) diff --git a/go.mod b/go.mod index bca864e5b..c2aa3ba61 100644 --- a/go.mod +++ b/go.mod @@ -385,7 +385,6 @@ require ( replace ( github.com/abbot/go-http-auth => github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e github.com/go-check/check => github.com/containous/check v0.0.0-20170915194414-ca0bf163426a - github.com/gorilla/mux => github.com/containous/mux v0.0.0-20220627093034-b2dd784e613f github.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595 ) diff --git a/go.sum b/go.sum index 8d94db2f0..d94e2248a 100644 --- a/go.sum +++ b/go.sum @@ -457,8 +457,6 @@ github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e h1:D+uTE github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e/go.mod h1:s8kLgBQolDbsJOPVIGCEEv9zGAKUUf/685Gi0Qqg8z8= github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595 h1:aPspFRO6b94To3gl4yTDOEtpjFwXI7V2W+z0JcNljQ4= github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595/go.mod h1:+lHFbEasIiQVGzhVDVw/cn0ZaOzde2OwNncp1NhXV4c= -github.com/containous/mux v0.0.0-20220627093034-b2dd784e613f h1:1uEtynq2C0ljy3630jt7EAxg8jZY2gy6YHdGwdqEpWw= -github.com/containous/mux v0.0.0-20220627093034-b2dd784e613f/go.mod h1:z8WW7n06n8/1xF9Jl9WmuDeZuHAhfL+bwarNjsciwwg= github.com/coredns/coredns v1.1.2/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -936,6 +934,11 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= diff --git a/pkg/muxer/http/matcher.go b/pkg/muxer/http/matcher.go index d30e6df61..124761fd2 100644 --- a/pkg/muxer/http/matcher.go +++ b/pkg/muxer/http/matcher.go @@ -7,14 +7,13 @@ import ( "strings" "unicode/utf8" - "github.com/gorilla/mux" "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/ip" "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" "golang.org/x/exp/slices" ) -var httpFuncs = map[string]func(*mux.Route, ...string) error{ +var httpFuncs = map[string]func(*matchersTree, ...string) error{ "ClientIP": expectNParameters(clientIP, 1), "Method": expectNParameters(method, 1), "Host": expectNParameters(host, 1), @@ -28,17 +27,17 @@ var httpFuncs = map[string]func(*mux.Route, ...string) error{ "QueryRegexp": expectNParameters(queryRegexp, 1, 2), } -func expectNParameters(fn func(*mux.Route, ...string) error, n ...int) func(*mux.Route, ...string) error { - return func(route *mux.Route, s ...string) error { +func expectNParameters(fn func(*matchersTree, ...string) error, n ...int) func(*matchersTree, ...string) error { + return func(tree *matchersTree, s ...string) error { if !slices.Contains(n, len(s)) { return fmt.Errorf("unexpected number of parameters; got %d, expected one of %v", len(s), n) } - return fn(route, s...) + return fn(tree, s...) } } -func clientIP(route *mux.Route, clientIP ...string) error { +func clientIP(tree *matchersTree, clientIP ...string) error { checker, err := ip.NewChecker(clientIP) if err != nil { return fmt.Errorf("initializing IP checker for ClientIP matcher: %w", err) @@ -46,7 +45,7 @@ func clientIP(route *mux.Route, clientIP ...string) error { strategy := ip.RemoteAddrStrategy{} - route.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool { + tree.matcher = func(req *http.Request) bool { ok, err := checker.Contains(strategy.GetIP(req)) if err != nil { log.Ctx(req.Context()).Warn().Err(err).Msg("ClientIP matcher: could not match remote address") @@ -54,16 +53,22 @@ func clientIP(route *mux.Route, clientIP ...string) error { } return ok - }) + } return nil } -func method(route *mux.Route, methods ...string) error { - return route.Methods(methods...).GetError() +func method(tree *matchersTree, methods ...string) error { + method := strings.ToUpper(methods[0]) + + tree.matcher = func(req *http.Request) bool { + return method == req.Method + } + + return nil } -func host(route *mux.Route, hosts ...string) error { +func host(tree *matchersTree, hosts ...string) error { host := hosts[0] if !IsASCII(host) { @@ -72,7 +77,7 @@ func host(route *mux.Route, hosts ...string) error { host = strings.ToLower(host) - route.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool { + tree.matcher = func(req *http.Request) bool { reqHost := requestdecorator.GetCanonizedHost(req.Context()) if len(reqHost) == 0 { return false @@ -104,12 +109,12 @@ func host(route *mux.Route, hosts ...string) error { } return false - }) + } return nil } -func hostRegexp(route *mux.Route, hosts ...string) error { +func hostRegexp(tree *matchersTree, hosts ...string) error { host := hosts[0] if !IsASCII(host) { @@ -121,29 +126,29 @@ func hostRegexp(route *mux.Route, hosts ...string) error { return fmt.Errorf("compiling HostRegexp matcher: %w", err) } - route.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool { + tree.matcher = func(req *http.Request) bool { return re.MatchString(requestdecorator.GetCanonizedHost(req.Context())) || re.MatchString(requestdecorator.GetCNAMEFlatten(req.Context())) - }) + } return nil } -func path(route *mux.Route, paths ...string) error { +func path(tree *matchersTree, paths ...string) error { path := paths[0] if !strings.HasPrefix(path, "/") { return fmt.Errorf("path %q does not start with a '/'", path) } - route.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool { + tree.matcher = func(req *http.Request) bool { return req.URL.Path == path - }) + } return nil } -func pathRegexp(route *mux.Route, paths ...string) error { +func pathRegexp(tree *matchersTree, paths ...string) error { path := paths[0] re, err := regexp.Compile(path) @@ -151,36 +156,65 @@ func pathRegexp(route *mux.Route, paths ...string) error { return fmt.Errorf("compiling PathPrefix matcher: %w", err) } - route.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool { + tree.matcher = func(req *http.Request) bool { return re.MatchString(req.URL.Path) - }) + } return nil } -func pathPrefix(route *mux.Route, paths ...string) error { +func pathPrefix(tree *matchersTree, paths ...string) error { path := paths[0] if !strings.HasPrefix(path, "/") { return fmt.Errorf("path %q does not start with a '/'", path) } - route.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool { + tree.matcher = func(req *http.Request) bool { return strings.HasPrefix(req.URL.Path, path) - }) + } return nil } -func header(route *mux.Route, headers ...string) error { - return route.Headers(headers...).GetError() +func header(tree *matchersTree, headers ...string) error { + key, value := http.CanonicalHeaderKey(headers[0]), headers[1] + + tree.matcher = func(req *http.Request) bool { + for _, headerValue := range req.Header[key] { + if headerValue == value { + return true + } + } + + return false + } + + return nil } -func headerRegexp(route *mux.Route, headers ...string) error { - return route.HeadersRegexp(headers...).GetError() +func headerRegexp(tree *matchersTree, headers ...string) error { + key, value := http.CanonicalHeaderKey(headers[0]), headers[1] + + re, err := regexp.Compile(value) + if err != nil { + return fmt.Errorf("compiling HeaderRegexp matcher: %w", err) + } + + tree.matcher = func(req *http.Request) bool { + for _, headerValue := range req.Header[key] { + if re.MatchString(headerValue) { + return true + } + } + + return false + } + + return nil } -func query(route *mux.Route, queries ...string) error { +func query(tree *matchersTree, queries ...string) error { key := queries[0] var value string @@ -188,21 +222,21 @@ func query(route *mux.Route, queries ...string) error { value = queries[1] } - route.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool { + tree.matcher = func(req *http.Request) bool { values, ok := req.URL.Query()[key] if !ok { return false } return slices.Contains(values, value) - }) + } return nil } -func queryRegexp(route *mux.Route, queries ...string) error { +func queryRegexp(tree *matchersTree, queries ...string) error { if len(queries) == 1 { - return query(route, queries...) + return query(tree, queries...) } key, value := queries[0], queries[1] @@ -212,7 +246,7 @@ func queryRegexp(route *mux.Route, queries ...string) error { return fmt.Errorf("compiling QueryRegexp matcher: %w", err) } - route.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool { + tree.matcher = func(req *http.Request) bool { values, ok := req.URL.Query()[key] if !ok { return false @@ -223,7 +257,7 @@ func queryRegexp(route *mux.Route, queries ...string) error { }) return idx >= 0 - }) + } return nil } diff --git a/pkg/muxer/http/matcher_test.go b/pkg/muxer/http/matcher_test.go index 2d31d8dc8..0c3d6dc9f 100644 --- a/pkg/muxer/http/matcher_test.go +++ b/pkg/muxer/http/matcher_test.go @@ -3,6 +3,7 @@ package http import ( "net/http" "net/http/httptest" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -121,16 +122,18 @@ func TestMethodMatcher(t *testing.T) { desc: "valid Method matcher", rule: "Method(`GET`)", expected: map[string]int{ - http.MethodGet: http.StatusOK, - http.MethodPost: http.StatusMethodNotAllowed, + http.MethodGet: http.StatusOK, + http.MethodPost: http.StatusNotFound, + strings.ToLower(http.MethodGet): http.StatusNotFound, }, }, { desc: "valid Method matcher (lower case)", rule: "Method(`get`)", expected: map[string]int{ - http.MethodGet: http.StatusOK, - http.MethodPost: http.StatusMethodNotAllowed, + http.MethodGet: http.StatusOK, + http.MethodPost: http.StatusNotFound, + strings.ToLower(http.MethodGet): http.StatusNotFound, }, }, } @@ -200,6 +203,7 @@ func TestHostMatcher(t *testing.T) { "https://example.com": http.StatusOK, "https://example.com:8080": http.StatusOK, "https://example.com/path": http.StatusOK, + "https://EXAMPLE.COM/path": http.StatusOK, "https://example.org": http.StatusNotFound, "https://example.org/path": http.StatusNotFound, }, @@ -665,6 +669,17 @@ func TestHeaderMatcher(t *testing.T) { {"X-Forwarded-Host": []string{"example.com"}}: http.StatusNotFound, }, }, + { + desc: "valid Header matcher (non-canonical form)", + rule: "Header(`x-forwarded-proto`, `https`)", + expected: map[*http.Header]int{ + {"X-Forwarded-Proto": []string{"https"}}: http.StatusOK, + {"x-forwarded-proto": []string{"https"}}: http.StatusNotFound, + {"X-Forwarded-Proto": []string{"http", "https"}}: http.StatusOK, + {"X-Forwarded-Proto": []string{"https", "http"}}: http.StatusOK, + {"X-Forwarded-Host": []string{"example.com"}}: http.StatusNotFound, + }, + }, } for _, test := range testCases { @@ -747,6 +762,18 @@ func TestHeaderRegexpMatcher(t *testing.T) { {"X-Forwarded-Host": []string{"example.com"}}: http.StatusNotFound, }, }, + { + desc: "valid HeaderRegexp matcher (non-canonical form)", + rule: "HeaderRegexp(`x-forwarded-proto`, `^https?$`)", + expected: map[*http.Header]int{ + {"X-Forwarded-Proto": []string{"http"}}: http.StatusOK, + {"x-forwarded-proto": []string{"http"}}: http.StatusNotFound, + {"X-Forwarded-Proto": []string{"https"}}: http.StatusOK, + {"X-Forwarded-Proto": []string{"HTTPS"}}: http.StatusNotFound, + {"X-Forwarded-Proto": []string{"ws", "https"}}: http.StatusOK, + {"X-Forwarded-Host": []string{"example.com"}}: http.StatusNotFound, + }, + }, { desc: "valid HeaderRegexp matcher with Traefik v2 syntax", rule: "HeaderRegexp(`X-Forwarded-Proto`, `http{secure:s?}`)", diff --git a/pkg/muxer/http/mux.go b/pkg/muxer/http/mux.go index 237977044..3039075ee 100644 --- a/pkg/muxer/http/mux.go +++ b/pkg/muxer/http/mux.go @@ -3,15 +3,16 @@ package http import ( "fmt" "net/http" + "sort" - "github.com/gorilla/mux" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/rules" "github.com/vulcand/predicate" ) // Muxer handles routing with rules. type Muxer struct { - *mux.Router + routes routes parser predicate.Parser } @@ -24,18 +25,30 @@ func NewMuxer() (*Muxer, error) { parser, err := rules.NewParser(matchers) if err != nil { - return nil, err + return nil, fmt.Errorf("error while creating parser: %w", err) } return &Muxer{ - Router: mux.NewRouter().SkipClean(true), parser: parser, }, nil } +// ServeHTTP forwards the connection to the matching HTTP handler. +// Serves 404 if no handler is found. +func (m *Muxer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + for _, route := range m.routes { + if route.matchers.match(req) { + route.handler.ServeHTTP(rw, req) + return + } + } + + http.NotFoundHandler().ServeHTTP(rw, req) +} + // AddRoute add a new route to the router. -func (r *Muxer) AddRoute(rule string, priority int, handler http.Handler) error { - parse, err := r.parser.Parse(rule) +func (m *Muxer) AddRoute(rule string, priority int, handler http.Handler) error { + parse, err := m.parser.Parse(rule) if err != nil { return fmt.Errorf("error while parsing rule %s: %w", rule, err) } @@ -45,101 +58,27 @@ func (r *Muxer) AddRoute(rule string, priority int, handler http.Handler) error return fmt.Errorf("error while parsing rule %s", rule) } + var matchers matchersTree + err = matchers.addRule(buildTree()) + if err != nil { + return fmt.Errorf("error while adding rule %s: %w", rule, err) + } + if priority == 0 { priority = len(rule) } - route := r.NewRoute().Handler(handler).Priority(priority) + m.routes = append(m.routes, &route{ + handler: handler, + matchers: matchers, + priority: priority, + }) - err = addRuleOnRoute(route, buildTree()) - if err != nil { - route.BuildOnly() - return err - } + sort.Sort(m.routes) return nil } -func addRuleOnRouter(router *mux.Router, rule *rules.Tree) error { - switch rule.Matcher { - case "and": - route := router.NewRoute() - err := addRuleOnRoute(route, rule.RuleLeft) - if err != nil { - return err - } - - return addRuleOnRoute(route, rule.RuleRight) - case "or": - err := addRuleOnRouter(router, rule.RuleLeft) - if err != nil { - return err - } - - return addRuleOnRouter(router, rule.RuleRight) - default: - err := rules.CheckRule(rule) - if err != nil { - return err - } - - if rule.Not { - return not(httpFuncs[rule.Matcher])(router.NewRoute(), rule.Value...) - } - - return httpFuncs[rule.Matcher](router.NewRoute(), rule.Value...) - } -} - -func addRuleOnRoute(route *mux.Route, rule *rules.Tree) error { - switch rule.Matcher { - case "and": - err := addRuleOnRoute(route, rule.RuleLeft) - if err != nil { - return err - } - - return addRuleOnRoute(route, rule.RuleRight) - case "or": - subRouter := route.Subrouter() - - err := addRuleOnRouter(subRouter, rule.RuleLeft) - if err != nil { - return err - } - - return addRuleOnRouter(subRouter, rule.RuleRight) - default: - err := rules.CheckRule(rule) - if err != nil { - return err - } - - if rule.Not { - return not(httpFuncs[rule.Matcher])(route, rule.Value...) - } - - return httpFuncs[rule.Matcher](route, rule.Value...) - } -} - -func not(m func(*mux.Route, ...string) error) func(*mux.Route, ...string) error { - return func(r *mux.Route, v ...string) error { - router := mux.NewRouter() - - err := m(router.NewRoute(), v...) - if err != nil { - return err - } - - r.MatcherFunc(func(req *http.Request, ma *mux.RouteMatch) bool { - return !router.Match(req, ma) - }) - - return nil - } -} - // ParseDomains extract domains from rule. func ParseDomains(rule string) ([]string, error) { var matchers []string @@ -149,12 +88,12 @@ func ParseDomains(rule string) ([]string, error) { parser, err := rules.NewParser(matchers) if err != nil { - return nil, err + return nil, fmt.Errorf("error while creating parser: %w", err) } parse, err := parser.Parse(rule) if err != nil { - return nil, err + return nil, fmt.Errorf("error while parsing rule %s: %w", rule, err) } buildTree, ok := parse.(rules.TreeBuilder) @@ -164,3 +103,97 @@ func ParseDomains(rule string) ([]string, error) { return buildTree().ParseMatchers([]string{"Host"}), nil } + +// routes implements sort.Interface. +type routes []*route + +// Len implements sort.Interface. +func (r routes) Len() int { return len(r) } + +// Swap implements sort.Interface. +func (r routes) Swap(i, j int) { r[i], r[j] = r[j], r[i] } + +// Less implements sort.Interface. +func (r routes) Less(i, j int) bool { return r[i].priority > r[j].priority } + +// route holds the matchers to match HTTP route, +// and the handler that will serve the request. +type route struct { + // matchers tree structure reflecting the rule. + matchers matchersTree + // handler responsible for handling the route. + handler http.Handler + // priority is used to disambiguate between two (or more) rules that would all match for a given request. + // Computed from the matching rule length, if not user-set. + priority int +} + +// matchersTree represents the matchers tree structure. +type matchersTree struct { + // matcher is a matcher func used to match HTTP request properties. + // If matcher is not nil, it means that this matcherTree is a leaf of the tree. + // It is therefore mutually exclusive with left and right. + matcher func(*http.Request) bool + // operator to combine the evaluation of left and right leaves. + operator string + // Mutually exclusive with matcher. + left *matchersTree + right *matchersTree +} + +func (m *matchersTree) match(req *http.Request) bool { + if m == nil { + // This should never happen as it should have been detected during parsing. + log.Warn().Msg("Rule matcher is nil") + return false + } + + if m.matcher != nil { + return m.matcher(req) + } + + switch m.operator { + case "or": + return m.left.match(req) || m.right.match(req) + case "and": + return m.left.match(req) && m.right.match(req) + default: + // This should never happen as it should have been detected during parsing. + log.Warn().Str("operator", m.operator).Msg("Invalid rule operator") + return false + } +} + +func (m *matchersTree) addRule(rule *rules.Tree) error { + switch rule.Matcher { + case "and", "or": + m.operator = rule.Matcher + m.left = &matchersTree{} + err := m.left.addRule(rule.RuleLeft) + if err != nil { + return fmt.Errorf("error while adding rule %s: %w", rule.Matcher, err) + } + + m.right = &matchersTree{} + return m.right.addRule(rule.RuleRight) + default: + err := rules.CheckRule(rule) + if err != nil { + return fmt.Errorf("error while checking rule %s: %w", rule.Matcher, err) + } + + err = httpFuncs[rule.Matcher](m, rule.Value...) + if err != nil { + return fmt.Errorf("error while adding rule %s: %w", rule.Matcher, err) + } + + if rule.Not { + matcherFunc := m.matcher + m.matcher = func(req *http.Request) bool { + return !matcherFunc(req) + } + } + } + + return nil +} diff --git a/pkg/muxer/http/mux_test.go b/pkg/muxer/http/mux_test.go index bdc98df37..0c1903de9 100644 --- a/pkg/muxer/http/mux_test.go +++ b/pkg/muxer/http/mux_test.go @@ -380,8 +380,6 @@ func Test_addRoutePriority(t *testing.T) { require.NoError(t, err, route.rule) } - muxer.SortRoutes() - w := httptest.NewRecorder() req := testhelpers.MustNewRequest(http.MethodGet, test.path, http.NoBody) diff --git a/pkg/muxer/tcp/mux.go b/pkg/muxer/tcp/mux.go index 3c5abffaf..00ec577af 100644 --- a/pkg/muxer/tcp/mux.go +++ b/pkg/muxer/tcp/mux.go @@ -13,32 +13,6 @@ import ( "github.com/vulcand/predicate" ) -// ParseHostSNI extracts the HostSNIs declared in a rule. -// This is a first naive implementation used in TCP routing. -func ParseHostSNI(rule string) ([]string, error) { - var matchers []string - for matcher := range tcpFuncs { - matchers = append(matchers, matcher) - } - - parser, err := rules.NewParser(matchers) - if err != nil { - return nil, err - } - - parse, err := parser.Parse(rule) - if err != nil { - return nil, err - } - - buildTree, ok := parse.(rules.TreeBuilder) - if !ok { - return nil, fmt.Errorf("error while parsing rule %s", rule) - } - - return buildTree().ParseMatchers([]string{"HostSNI"}), nil -} - // ConnData contains TCP connection metadata. type ConnData struct { serverName string @@ -67,7 +41,7 @@ func NewConnData(serverName string, conn tcp.WriteCloser, alpnProtos []string) ( // Muxer defines a muxer that handles TCP routing with rules. type Muxer struct { - routes []*route + routes routes parser predicate.Parser } @@ -114,9 +88,9 @@ func (m *Muxer) AddRoute(rule string, priority int, handler tcp.Handler) error { ruleTree := buildTree() var matchers matchersTree - err = addRule(&matchers, ruleTree) + err = matchers.addRule(ruleTree) if err != nil { - return err + return fmt.Errorf("error while adding rule %s: %w", rule, err) } var catchAll bool @@ -144,41 +118,7 @@ func (m *Muxer) AddRoute(rule string, priority int, handler tcp.Handler) error { } m.routes = append(m.routes, newRoute) - sort.Sort(routes(m.routes)) - - return nil -} - -func addRule(tree *matchersTree, rule *rules.Tree) error { - switch rule.Matcher { - case "and", "or": - tree.operator = rule.Matcher - tree.left = &matchersTree{} - err := addRule(tree.left, rule.RuleLeft) - if err != nil { - return err - } - - tree.right = &matchersTree{} - return addRule(tree.right, rule.RuleRight) - default: - err := rules.CheckRule(rule) - if err != nil { - return err - } - - err = tcpFuncs[rule.Matcher](tree, rule.Value...) - if err != nil { - return err - } - - if rule.Not { - matcherFunc := tree.matcher - tree.matcher = func(meta ConnData) bool { - return !matcherFunc(meta) - } - } - } + sort.Sort(m.routes) return nil } @@ -188,6 +128,32 @@ func (m *Muxer) HasRoutes() bool { return len(m.routes) > 0 } +// ParseHostSNI extracts the HostSNIs declared in a rule. +// This is a first naive implementation used in TCP routing. +func ParseHostSNI(rule string) ([]string, error) { + var matchers []string + for matcher := range tcpFuncs { + matchers = append(matchers, matcher) + } + + parser, err := rules.NewParser(matchers) + if err != nil { + return nil, err + } + + parse, err := parser.Parse(rule) + if err != nil { + return nil, err + } + + buildTree, ok := parse.(rules.TreeBuilder) + if !ok { + return nil, fmt.Errorf("error while parsing rule %s", rule) + } + + return buildTree().ParseMatchers([]string{"HostSNI"}), nil +} + // routes implements sort.Interface. type routes []*route @@ -215,14 +181,12 @@ type route struct { priority int } -// matcher is a matcher func used to match connection properties. -type matcher func(meta ConnData) bool - // matchersTree represents the matchers tree structure. type matchersTree struct { + // matcher is a matcher func used to match connection properties. // If matcher is not nil, it means that this matcherTree is a leaf of the tree. // It is therefore mutually exclusive with left and right. - matcher matcher + matcher func(ConnData) bool // operator to combine the evaluation of left and right leaves. operator string // Mutually exclusive with matcher. @@ -252,3 +216,37 @@ func (m *matchersTree) match(meta ConnData) bool { return false } } + +func (m *matchersTree) addRule(rule *rules.Tree) error { + switch rule.Matcher { + case "and", "or": + m.operator = rule.Matcher + m.left = &matchersTree{} + err := m.left.addRule(rule.RuleLeft) + if err != nil { + return err + } + + m.right = &matchersTree{} + return m.right.addRule(rule.RuleRight) + default: + err := rules.CheckRule(rule) + if err != nil { + return err + } + + err = tcpFuncs[rule.Matcher](m, rule.Value...) + if err != nil { + return err + } + + if rule.Not { + matcherFunc := m.matcher + m.matcher = func(meta ConnData) bool { + return !matcherFunc(meta) + } + } + } + + return nil +} diff --git a/pkg/server/router/router.go b/pkg/server/router/router.go index 388e792d3..f19a46eb5 100644 --- a/pkg/server/router/router.go +++ b/pkg/server/router/router.go @@ -134,8 +134,6 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string } } - muxer.SortRoutes() - chain := alice.New() chain = chain.Append(func(next http.Handler) (http.Handler, error) { return recovery.New(ctx, next) From a2016a295332e24101307aca112a37f54689fa3d Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Thu, 29 Dec 2022 09:46:04 +0100 Subject: [PATCH 17/74] Detect dashboard assets content types Co-authored-by: Romain --- pkg/api/dashboard/dashboard.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/api/dashboard/dashboard.go b/pkg/api/dashboard/dashboard.go index 49f531f23..059917484 100644 --- a/pkg/api/dashboard/dashboard.go +++ b/pkg/api/dashboard/dashboard.go @@ -51,6 +51,11 @@ func (g Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // allow iframes from our domains only // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src w.Header().Set("Content-Security-Policy", "frame-src 'self' https://traefik.io https://*.traefik.io;") + + // The content type must be guessed by the file server. + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options + w.Header().Del("Content-Type") + http.FileServer(http.FS(assets)).ServeHTTP(w, r) } From b9a175f5c22671684c296d993dbf276f26ad15b5 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Mon, 2 Jan 2023 12:12:05 +0100 Subject: [PATCH 18/74] Update copyright for 2023 --- LICENSE.md | 2 +- docs/mkdocs.yml | 2 +- pkg/config/dynamic/zz_generated.deepcopy.go | 2 +- .../kubernetes/crd/generated/clientset/versioned/clientset.go | 2 +- .../kubernetes/crd/generated/clientset/versioned/doc.go | 2 +- .../generated/clientset/versioned/fake/clientset_generated.go | 2 +- .../kubernetes/crd/generated/clientset/versioned/fake/doc.go | 2 +- .../crd/generated/clientset/versioned/fake/register.go | 2 +- .../kubernetes/crd/generated/clientset/versioned/scheme/doc.go | 2 +- .../crd/generated/clientset/versioned/scheme/register.go | 2 +- .../generated/clientset/versioned/typed/traefik/v1alpha1/doc.go | 2 +- .../clientset/versioned/typed/traefik/v1alpha1/fake/doc.go | 2 +- .../versioned/typed/traefik/v1alpha1/fake/fake_ingressroute.go | 2 +- .../typed/traefik/v1alpha1/fake/fake_ingressroutetcp.go | 2 +- .../typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go | 2 +- .../versioned/typed/traefik/v1alpha1/fake/fake_middleware.go | 2 +- .../versioned/typed/traefik/v1alpha1/fake/fake_middlewaretcp.go | 2 +- .../typed/traefik/v1alpha1/fake/fake_serverstransport.go | 2 +- .../versioned/typed/traefik/v1alpha1/fake/fake_tlsoption.go | 2 +- .../versioned/typed/traefik/v1alpha1/fake/fake_tlsstore.go | 2 +- .../typed/traefik/v1alpha1/fake/fake_traefik_client.go | 2 +- .../typed/traefik/v1alpha1/fake/fake_traefikservice.go | 2 +- .../versioned/typed/traefik/v1alpha1/generated_expansion.go | 2 +- .../clientset/versioned/typed/traefik/v1alpha1/ingressroute.go | 2 +- .../versioned/typed/traefik/v1alpha1/ingressroutetcp.go | 2 +- .../versioned/typed/traefik/v1alpha1/ingressrouteudp.go | 2 +- .../clientset/versioned/typed/traefik/v1alpha1/middleware.go | 2 +- .../clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go | 2 +- .../versioned/typed/traefik/v1alpha1/serverstransport.go | 2 +- .../clientset/versioned/typed/traefik/v1alpha1/tlsoption.go | 2 +- .../clientset/versioned/typed/traefik/v1alpha1/tlsstore.go | 2 +- .../versioned/typed/traefik/v1alpha1/traefik_client.go | 2 +- .../versioned/typed/traefik/v1alpha1/traefikservice.go | 2 +- .../crd/generated/informers/externalversions/factory.go | 2 +- .../crd/generated/informers/externalversions/generic.go | 2 +- .../externalversions/internalinterfaces/factory_interfaces.go | 2 +- .../generated/informers/externalversions/traefik/interface.go | 2 +- .../informers/externalversions/traefik/v1alpha1/ingressroute.go | 2 +- .../externalversions/traefik/v1alpha1/ingressroutetcp.go | 2 +- .../externalversions/traefik/v1alpha1/ingressrouteudp.go | 2 +- .../informers/externalversions/traefik/v1alpha1/interface.go | 2 +- .../informers/externalversions/traefik/v1alpha1/middleware.go | 2 +- .../externalversions/traefik/v1alpha1/middlewaretcp.go | 2 +- .../externalversions/traefik/v1alpha1/serverstransport.go | 2 +- .../informers/externalversions/traefik/v1alpha1/tlsoption.go | 2 +- .../informers/externalversions/traefik/v1alpha1/tlsstore.go | 2 +- .../externalversions/traefik/v1alpha1/traefikservice.go | 2 +- .../generated/listers/traefik/v1alpha1/expansion_generated.go | 2 +- .../crd/generated/listers/traefik/v1alpha1/ingressroute.go | 2 +- .../crd/generated/listers/traefik/v1alpha1/ingressroutetcp.go | 2 +- .../crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go | 2 +- .../crd/generated/listers/traefik/v1alpha1/middleware.go | 2 +- .../crd/generated/listers/traefik/v1alpha1/middlewaretcp.go | 2 +- .../crd/generated/listers/traefik/v1alpha1/serverstransport.go | 2 +- .../crd/generated/listers/traefik/v1alpha1/tlsoption.go | 2 +- .../crd/generated/listers/traefik/v1alpha1/tlsstore.go | 2 +- .../crd/generated/listers/traefik/v1alpha1/traefikservice.go | 2 +- .../kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go | 2 +- pkg/tls/zz_generated.deepcopy.go | 2 +- pkg/types/zz_generated.deepcopy.go | 2 +- 60 files changed, 60 insertions(+), 60 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 62a996205..d56287566 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 87ad026fc..15faf47d3 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -27,7 +27,7 @@ theme: prev: 'Previous' next: 'Next' -copyright: "Copyright © 2016-2020 Containous; 2020-2022 Traefik Labs" +copyright: "Copyright © 2016-2020 Containous; 2020-2023 Traefik Labs" extra_javascript: - assets/js/hljs/highlight.pack.js # Download from https://highlightjs.org/download/ and enable YAML, TOML and Dockerfile diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index 587048180..7b51c92c7 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -4,7 +4,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go index 334f5de4c..6f2c4b79b 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/doc.go index c5b70f22f..b6f98d475 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/clientset_generated.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/clientset_generated.go index 3b0aad3ce..d35e64391 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/clientset_generated.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/clientset_generated.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/doc.go index f0c4f5bd0..081d07edb 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/register.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/register.go index 3ab7c4b73..bdf7af3d7 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/register.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/register.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/doc.go index faef00f1a..87af68273 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/register.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/register.go index 55a7726a9..0351d8a0e 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/register.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/register.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/doc.go index 0a5631907..e39212eab 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/doc.go index 076d4e4ce..24ecc2be0 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroute.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroute.go index 76aa065c4..bbf76c75b 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroutetcp.go index c98c593a6..879a239b3 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go index e81872b0d..434998761 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middleware.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middleware.go index e1bcc7603..9371d16b6 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middleware.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middlewaretcp.go index cb9adaae8..f4032c916 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_serverstransport.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_serverstransport.go index b144f0c65..8bd86a2bd 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsoption.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsoption.go index bfcab1e9e..8340c4235 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsstore.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsstore.go index 8fe3e1fb0..0a90d563d 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go index c593b1ccd..e00a74455 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefikservice.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefikservice.go index d30335386..386b03315 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go index a252692a7..aeaaec294 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroute.go index 32021452e..6f1461514 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroutetcp.go index e32f1622a..ec4a6b344 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go index 9c2db2a10..3126460c1 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middleware.go index b6b895ed1..adb790512 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go index 563b2c6da..f74054815 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransport.go index 89f015e9a..d2444b2d3 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsoption.go index bc9556934..358ff20e8 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsstore.go index e90d79e45..16a53fa25 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go index 2682dbad5..9ce24afa2 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefikservice.go index ad5f093f4..0384e4a97 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go index d198621df..1b0085df0 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go index a062e290d..60b20411c 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces/factory_interfaces.go index 0809220e6..5abe4a64d 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/interface.go index 8bc5dfcd2..8edcc5d82 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/interface.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroute.go index 49c8df238..d99082380 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroutetcp.go index 4fecc2bdd..544bf98a9 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go index 4b4b00743..073dcbf81 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go index 563e81956..9edba3953 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middleware.go index 80e2679ba..b630ff64c 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go index 2285d4a4b..6fce3ca24 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransport.go index dfd10f485..7801f4b8d 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsoption.go index 7e1f3ad68..4a2a1bf36 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsstore.go index c017915f3..ba37932c7 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/traefikservice.go index 8a3dce49c..57bce7683 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go index c338fb976..341744ace 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroute.go index 532620c79..ab4878d03 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroutetcp.go index 8bdd6c94c..408a153c2 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go index 4c8166d94..dcd7fae3d 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middleware.go index 89ec6190f..30bd9e988 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go index 597cbcd97..a9df604cf 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransport.go index 1d18bf9fc..c9ec99871 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsoption.go index 1d6fc9049..bec59e6c6 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsstore.go index 8c79402c1..358bc5193 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/traefikservice.go index 89e8f4d85..47a5ba557 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go index 5cc7903fc..03ddabec3 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go @@ -4,7 +4,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/tls/zz_generated.deepcopy.go b/pkg/tls/zz_generated.deepcopy.go index c85405a37..95438c468 100644 --- a/pkg/tls/zz_generated.deepcopy.go +++ b/pkg/tls/zz_generated.deepcopy.go @@ -4,7 +4,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/types/zz_generated.deepcopy.go b/pkg/types/zz_generated.deepcopy.go index 1770e4ef4..8c55ace87 100644 --- a/pkg/types/zz_generated.deepcopy.go +++ b/pkg/types/zz_generated.deepcopy.go @@ -4,7 +4,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From e1e86763e3353cf6d3df59d7d5c39ad24eeb5ebe Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Mon, 2 Jan 2023 17:00:05 +0100 Subject: [PATCH 19/74] Prevents superfluous WriteHeader call in the error middleware Co-authored-by: LandryBe --- integration/error_pages_test.go | 33 ++++++++++++++++++- integration/fixtures/error_pages/simple.toml | 2 +- pkg/middlewares/customerrors/custom_errors.go | 9 +++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/integration/error_pages_test.go b/integration/error_pages_test.go index 436b2cc96..a9bd1c7a1 100644 --- a/integration/error_pages_test.go +++ b/integration/error_pages_test.go @@ -2,6 +2,7 @@ package integration import ( "net/http" + "net/http/httptest" "os" "time" @@ -29,7 +30,7 @@ func (s *ErrorPagesSuite) TestSimpleConfiguration(c *check.C) { file := s.adaptFile(c, "fixtures/error_pages/simple.toml", struct { Server1 string Server2 string - }{s.BackendIP, s.ErrorPageIP}) + }{"http://" + s.BackendIP + ":80", s.ErrorPageIP}) defer os.Remove(file) cmd, display := s.traefikCmd(withConfigFile(file)) @@ -67,3 +68,33 @@ func (s *ErrorPagesSuite) TestErrorPage(c *check.C) { err = try.Request(frontendReq, 2*time.Second, try.BodyContains("An error occurred.")) c.Assert(err, checker.IsNil) } + +func (s *ErrorPagesSuite) TestErrorPageFlush(c *check.C) { + srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.Header().Add("Transfer-Encoding", "chunked") + rw.WriteHeader(http.StatusInternalServerError) + _, _ = rw.Write([]byte("KO")) + })) + + file := s.adaptFile(c, "fixtures/error_pages/simple.toml", struct { + Server1 string + Server2 string + }{srv.URL, s.ErrorPageIP}) + defer os.Remove(file) + + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer s.killCmd(cmd) + + frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080", nil) + c.Assert(err, checker.IsNil) + frontendReq.Host = "test.local" + + err = try.Request(frontendReq, 2*time.Second, + try.BodyContains("An error occurred."), + try.HasHeaderValue("Content-Type", "text/html", true), + ) + c.Assert(err, checker.IsNil) +} diff --git a/integration/fixtures/error_pages/simple.toml b/integration/fixtures/error_pages/simple.toml index a734098b9..298b66a42 100644 --- a/integration/fixtures/error_pages/simple.toml +++ b/integration/fixtures/error_pages/simple.toml @@ -30,7 +30,7 @@ [http.services.service1.loadBalancer] passHostHeader = true [[http.services.service1.loadBalancer.servers]] - url = "http://{{.Server1}}:80" + url = "{{.Server1}}" [http.services.error.loadBalancer] [[http.services.error.loadBalancer.servers]] diff --git a/pkg/middlewares/customerrors/custom_errors.go b/pkg/middlewares/customerrors/custom_errors.go index 58b36d115..b24a6b04c 100644 --- a/pkg/middlewares/customerrors/custom_errors.go +++ b/pkg/middlewares/customerrors/custom_errors.go @@ -233,6 +233,15 @@ func (cc *codeCatcher) Flush() { // Otherwise, cc.code is actually a 200 here. cc.WriteHeader(cc.code) + // We don't care about the contents of the response, + // since we want to serve the ones from the error page, + // so we just don't flush. + // (e.g., To prevent superfluous WriteHeader on request with a + // `Transfert-Encoding: chunked` header). + if cc.caughtFilteredCode { + return + } + if flusher, ok := cc.responseWriter.(http.Flusher); ok { flusher.Flush() } From 8bf68b7efd9ce97c20a13ba35d236bcf1f57e974 Mon Sep 17 00:00:00 2001 From: Baptiste Mayelle Date: Mon, 2 Jan 2023 17:34:04 +0100 Subject: [PATCH 20/74] Grafana dashboard showing ms instead of s --- contrib/grafana/traefik-kubernetes.json | 4 ++-- contrib/grafana/traefik.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/grafana/traefik-kubernetes.json b/contrib/grafana/traefik-kubernetes.json index 6774af097..ed7deaac4 100644 --- a/contrib/grafana/traefik-kubernetes.json +++ b/contrib/grafana/traefik-kubernetes.json @@ -472,7 +472,7 @@ } ] }, - "unit": "ms" + "unit": "s" }, "overrides": [] }, @@ -1607,6 +1607,6 @@ "timezone": "", "title": "Traefik Official Kubernetes Dashboard", "uid": "n5bu_kv4k", - "version": 5, + "version": 6, "weekStart": "" } diff --git a/contrib/grafana/traefik.json b/contrib/grafana/traefik.json index 34a1e8127..e4dbf5220 100644 --- a/contrib/grafana/traefik.json +++ b/contrib/grafana/traefik.json @@ -472,7 +472,7 @@ } ] }, - "unit": "ms" + "unit": "s" }, "overrides": [] }, @@ -1599,6 +1599,6 @@ "timezone": "", "title": "Traefik Official Standalone Dashboard", "uid": "n5bu_kv45", - "version": 5, + "version": 6, "weekStart": "" } From 0861c47e54f3386e0734f9ab0f61376ff4acf2d3 Mon Sep 17 00:00:00 2001 From: Witold Duranek Date: Tue, 3 Jan 2023 16:16:05 +0100 Subject: [PATCH 21/74] fix no rate limiting if average is 0 --- pkg/middlewares/ratelimiter/rate_limiter.go | 12 +++++------- pkg/middlewares/ratelimiter/rate_limiter_test.go | 13 +++++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/pkg/middlewares/ratelimiter/rate_limiter.go b/pkg/middlewares/ratelimiter/rate_limiter.go index 312595bfc..e06679787 100644 --- a/pkg/middlewares/ratelimiter/rate_limiter.go +++ b/pkg/middlewares/ratelimiter/rate_limiter.go @@ -79,10 +79,12 @@ func New(ctx context.Context, next http.Handler, config dynamic.RateLimit, name period = time.Second } - // if config.Average == 0, in that case, - // the value of maxDelay does not matter since the reservation will (buggily) give us a delay of 0 anyway. + // Initialized at rate.Inf to enforce no rate limiting when config.Average == 0 + rtl := float64(rate.Inf) + // No need to set any particular value for maxDelay as the reservation's delay + // will be <= 0 in the Inf case (i.e. the average == 0 case). var maxDelay time.Duration - var rtl float64 + if config.Average > 0 { rtl = float64(config.Average*int64(time.Second)) / float64(period) // maxDelay does not scale well for rates below 1, @@ -153,10 +155,6 @@ func (rl *rateLimiter) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - // time/rate is bugged, since a rate.Limiter with a 0 Limit not only allows a Reservation to take place, - // but also gives a 0 delay below (because of a division by zero, followed by a multiplication that flips into the negatives), - // regardless of the current load. - // However, for now we take advantage of this behavior to provide the no-limit ratelimiter when config.Average is 0. res := bucket.Reserve() if !res.OK() { http.Error(w, "No bursty traffic allowed", http.StatusTooManyRequests) diff --git a/pkg/middlewares/ratelimiter/rate_limiter_test.go b/pkg/middlewares/ratelimiter/rate_limiter_test.go index ac73fc2ec..670561774 100644 --- a/pkg/middlewares/ratelimiter/rate_limiter_test.go +++ b/pkg/middlewares/ratelimiter/rate_limiter_test.go @@ -15,6 +15,7 @@ import ( "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/testhelpers" "github.com/vulcand/oxy/v2/utils" + "golang.org/x/time/rate" ) func TestNewRateLimiter(t *testing.T) { @@ -25,7 +26,16 @@ func TestNewRateLimiter(t *testing.T) { expectedSourceIP string requestHeader string expectedError string + expectedRTL rate.Limit }{ + { + desc: "no ratelimit on Average == 0", + config: dynamic.RateLimit{ + Average: 0, + Burst: 10, + }, + expectedRTL: rate.Inf, + }, { desc: "maxDelay computation", config: dynamic.RateLimit{ @@ -120,6 +130,9 @@ func TestNewRateLimiter(t *testing.T) { assert.NoError(t, err) assert.Equal(t, test.requestHeader, hd) } + if test.expectedRTL != 0 { + assert.Equal(t, test.expectedRTL, rtl.rate) + } }) } } From c9e9e8dee21fd9c8f84929667cab3e6376739ea9 Mon Sep 17 00:00:00 2001 From: hcooper Date: Wed, 4 Jan 2023 03:10:05 -0800 Subject: [PATCH 22/74] Further Let's Encrypt ratelimit warnings --- docs/content/https/acme.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/content/https/acme.md b/docs/content/https/acme.md index d3fc20997..7d942b1a2 100644 --- a/docs/content/https/acme.md +++ b/docs/content/https/acme.md @@ -11,7 +11,11 @@ Automatic HTTPS You can configure Traefik to use an ACME provider (like Let's Encrypt) for automatic certificate generation. !!! warning "Let's Encrypt and Rate Limiting" - Note that Let's Encrypt API has [rate limiting](https://letsencrypt.org/docs/rate-limits). + Note that Let's Encrypt API has [rate limiting](https://letsencrypt.org/docs/rate-limits). These last up to __one week__, and can not be overridden. + + When running Traefik in a container this file should be persisted across restarts. + If Traefik requests new certificates each time it starts up, a crash-looping container can quickly reach Let's Encrypt's ratelimits. + To configure where certificates are stored, please take a look at the [storage](#storage) configuration. Use Let's Encrypt staging server with the [`caServer`](#caserver) configuration option when experimenting to avoid hitting this limit too fast. From f0f5f41fb95b44d244a62c84bd3eb761287e34a6 Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Fri, 6 Jan 2023 09:10:05 +0100 Subject: [PATCH 23/74] Fix OpenTelemetry service name Co-authored-by: Kevin Pollet --- .../observability/metrics/opentelemetry.md | 8 +- pkg/metrics/opentelemetry.go | 13 +++ pkg/metrics/opentelemetry_test.go | 59 ++++++++----- pkg/tracing/opentelemetry/opentelemetry.go | 17 +++- .../opentelemetry/opentelemetry_test.go | 88 +++++++++++++------ 5 files changed, 129 insertions(+), 56 deletions(-) diff --git a/docs/content/observability/metrics/opentelemetry.md b/docs/content/observability/metrics/opentelemetry.md index e3abed40a..af0ba7b20 100644 --- a/docs/content/observability/metrics/opentelemetry.md +++ b/docs/content/observability/metrics/opentelemetry.md @@ -208,7 +208,7 @@ metrics: #### `path` -_Required, Default="/v1/traces"_ +_Required, Default="/v1/metrics"_ Allows to override the default URL path used for sending metrics. This option has no effect when using gRPC transport. @@ -216,17 +216,17 @@ This option has no effect when using gRPC transport. ```yaml tab="File (YAML)" metrics: openTelemetry: - path: /foo/v1/traces + path: /foo/v1/metrics ``` ```toml tab="File (TOML)" [metrics] [metrics.openTelemetry] - path = "/foo/v1/traces" + path = "/foo/v1/metrics" ``` ```bash tab="CLI" ---metrics.openTelemetry.path=/foo/v1/traces +--metrics.openTelemetry.path=/foo/v1/metrics ``` #### `tls` diff --git a/pkg/metrics/opentelemetry.go b/pkg/metrics/opentelemetry.go index 94f170132..000018d67 100644 --- a/pkg/metrics/opentelemetry.go +++ b/pkg/metrics/opentelemetry.go @@ -23,6 +23,8 @@ import ( "go.opentelemetry.io/otel/metric/unit" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/metric/aggregation" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.12.0" "google.golang.org/grpc/credentials" "google.golang.org/grpc/encoding/gzip" ) @@ -139,11 +141,22 @@ func newOpenTelemetryMeterProvider(ctx context.Context, config *types.OpenTeleme return nil, fmt.Errorf("creating exporter: %w", err) } + res, err := resource.New(ctx, + resource.WithAttributes(semconv.ServiceNameKey.String("traefik")), + resource.WithAttributes(semconv.ServiceVersionKey.String(version.Version)), + resource.WithFromEnv(), + resource.WithTelemetrySDK(), + ) + if err != nil { + return nil, fmt.Errorf("building resource: %w", err) + } + opts := []sdkmetric.PeriodicReaderOption{ sdkmetric.WithInterval(time.Duration(config.PushInterval)), } meterProvider := sdkmetric.NewMeterProvider( + sdkmetric.WithResource(res), sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter, opts...)), // View to customize histogram buckets and rename a single histogram instrument. sdkmetric.WithView(sdkmetric.NewView( diff --git a/pkg/metrics/opentelemetry_test.go b/pkg/metrics/opentelemetry_test.go index 16890b6ba..2f1a35354 100644 --- a/pkg/metrics/opentelemetry_test.go +++ b/pkg/metrics/opentelemetry_test.go @@ -4,7 +4,6 @@ import ( "compress/gzip" "context" "encoding/json" - "fmt" "io" "net/http" "net/http/httptest" @@ -17,6 +16,7 @@ import ( "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v2/pkg/version" "go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp" "go.opentelemetry.io/otel/attribute" ) @@ -308,8 +308,7 @@ func TestOpenTelemetry(t *testing.T) { bodyStr := string(marshalledReq) c <- &bodyStr - _, err = fmt.Fprintln(w, "ok") - require.NoError(t, err) + w.WriteHeader(http.StatusOK) })) defer ts.Close() @@ -330,13 +329,21 @@ func TestOpenTelemetry(t *testing.T) { t.Fatalf("registry should return true for IsEnabled(), IsRouterEnabled() and IsSvcEnabled()") } + expected := []string{ + `({"key":"service.name","value":{"stringValue":"traefik"}})`, + `({"key":"service.version","value":{"stringValue":"` + version.Version + `"}})`, + } + msgMisc := <-c + + assertMessage(t, *msgMisc, expected) + // TODO: the len of startUnixNano is no supposed to be 20, it should be 19 - expectedServer := []string{ + expected = append(expected, `({"name":"traefik_config_reloads_total","description":"Config reloads","unit":"1","sum":{"dataPoints":\[{"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1}\],"aggregationTemporality":2,"isMonotonic":true}})`, `({"name":"traefik_config_reloads_failure_total","description":"Config reload failures","unit":"1","sum":{"dataPoints":\[{"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1}\],"aggregationTemporality":2,"isMonotonic":true}})`, `({"name":"traefik_config_last_reload_success","description":"Last config reload success","unit":"ms","gauge":{"dataPoints":\[{"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":1}\]}})`, `({"name":"traefik_config_last_reload_failure","description":"Last config reload failure","unit":"ms","gauge":{"dataPoints":\[{"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":1}\]}})`, - } + ) registry.ConfigReloadsCounter().Add(1) registry.ConfigReloadsFailureCounter().Add(1) @@ -344,23 +351,23 @@ func TestOpenTelemetry(t *testing.T) { registry.LastConfigReloadFailureGauge().Set(1) msgServer := <-c - assertMessage(t, *msgServer, expectedServer) + assertMessage(t, *msgServer, expected) - expectedTLS := []string{ + expected = append(expected, `({"name":"traefik_tls_certs_not_after","description":"Certificate expiration timestamp","unit":"ms","gauge":{"dataPoints":\[{"attributes":\[{"key":"key","value":{"stringValue":"value"}}\],"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":1}\]}})`, - } + ) registry.TLSCertsNotAfterTimestampGauge().With("key", "value").Set(1) msgTLS := <-c - assertMessage(t, *msgTLS, expectedTLS) + assertMessage(t, *msgTLS, expected) - expectedEntrypoint := []string{ + expected = append(expected, `({"name":"traefik_entrypoint_requests_total","description":"How many HTTP requests processed on an entrypoint, partitioned by status code, protocol, and method.","unit":"1","sum":{"dataPoints":\[{"attributes":\[{"key":"code","value":{"stringValue":"200"}},{"key":"entrypoint","value":{"stringValue":"test1"}},{"key":"method","value":{"stringValue":"GET"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1}\],"aggregationTemporality":2,"isMonotonic":true}})`, `({"name":"traefik_entrypoint_requests_tls_total","description":"How many HTTP requests with TLS processed on an entrypoint, partitioned by TLS Version and TLS cipher Used.","unit":"1","sum":{"dataPoints":\[{"attributes":\[{"key":"entrypoint","value":{"stringValue":"test2"}},{"key":"tls_cipher","value":{"stringValue":"bar"}},{"key":"tls_version","value":{"stringValue":"foo"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1}\],"aggregationTemporality":2,"isMonotonic":true}})`, `({"name":"traefik_entrypoint_request_duration_seconds","description":"How long it took to process the request on an entrypoint, partitioned by status code, protocol, and method.","unit":"ms","histogram":{"dataPoints":\[{"attributes":\[{"key":"entrypoint","value":{"stringValue":"test3"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","count":"1","sum":10000,"bucketCounts":\["0","0","0","0","0","0","0","0","0","0","0","1"\],"explicitBounds":\[0.005,0.01,0.025,0.05,0.1,0.25,0.5,1,2.5,5,10\],"min":10000,"max":10000}\],"aggregationTemporality":2}})`, `({"name":"traefik_entrypoint_open_connections","description":"How many open connections exist on an entrypoint, partitioned by method and protocol.","unit":"1","gauge":{"dataPoints":\[{"attributes":\[{"key":"entrypoint","value":{"stringValue":"test4"}}\],"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":1}\]}})`, - } + ) registry.EntryPointReqsCounter().With("entrypoint", "test1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) registry.EntryPointReqsTLSCounter().With("entrypoint", "test2", "tls_version", "foo", "tls_cipher", "bar").Add(1) @@ -368,14 +375,14 @@ func TestOpenTelemetry(t *testing.T) { registry.EntryPointOpenConnsGauge().With("entrypoint", "test4").Set(1) msgEntrypoint := <-c - assertMessage(t, *msgEntrypoint, expectedEntrypoint) + assertMessage(t, *msgEntrypoint, expected) - expectedRouter := []string{ + expected = append(expected, `({"name":"traefik_router_requests_total","description":"How many HTTP requests are processed on a router, partitioned by service, status code, protocol, and method.","unit":"1","sum":{"dataPoints":\[{"attributes":\[{"key":"code","value":{"stringValue":"(?:200|404)"}},{"key":"method","value":{"stringValue":"GET"}},{"key":"router","value":{"stringValue":"RouterReqsCounter"}},{"key":"service","value":{"stringValue":"test"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1},{"attributes":\[{"key":"code","value":{"stringValue":"(?:200|404)"}},{"key":"method","value":{"stringValue":"GET"}},{"key":"router","value":{"stringValue":"RouterReqsCounter"}},{"key":"service","value":{"stringValue":"test"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1}\],"aggregationTemporality":2,"isMonotonic":true}})`, `({"name":"traefik_router_requests_tls_total","description":"How many HTTP requests with TLS are processed on a router, partitioned by service, TLS Version, and TLS cipher Used.","unit":"1","sum":{"dataPoints":\[{"attributes":\[{"key":"router","value":{"stringValue":"demo"}},{"key":"service","value":{"stringValue":"test"}},{"key":"tls_cipher","value":{"stringValue":"bar"}},{"key":"tls_version","value":{"stringValue":"foo"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1}\],"aggregationTemporality":2,"isMonotonic":true}})`, `({"name":"traefik_router_request_duration_seconds","description":"How long it took to process the request on a router, partitioned by service, status code, protocol, and method.","unit":"ms","histogram":{"dataPoints":\[{"attributes":\[{"key":"code","value":{"stringValue":"200"}},{"key":"router","value":{"stringValue":"demo"}},{"key":"service","value":{"stringValue":"test"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","count":"1","sum":10000,"bucketCounts":\["0","0","0","0","0","0","0","0","0","0","0","1"\],"explicitBounds":\[0.005,0.01,0.025,0.05,0.1,0.25,0.5,1,2.5,5,10\],"min":10000,"max":10000}\],"aggregationTemporality":2}})`, `({"name":"traefik_router_open_connections","description":"How many open connections exist on a router, partitioned by service, method, and protocol.","unit":"1","gauge":{"dataPoints":\[{"attributes":\[{"key":"router","value":{"stringValue":"demo"}},{"key":"service","value":{"stringValue":"test"}}\],"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":1}\]}})`, - } + ) registry.RouterReqsCounter().With("router", "RouterReqsCounter", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) registry.RouterReqsCounter().With("router", "RouterReqsCounter", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) @@ -384,14 +391,14 @@ func TestOpenTelemetry(t *testing.T) { registry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1) msgRouter := <-c - assertMessage(t, *msgRouter, expectedRouter) + assertMessage(t, *msgRouter, expected) - expectedService := []string{ + expected = append(expected, `({"name":"traefik_service_requests_total","description":"How many HTTP requests processed on a service, partitioned by status code, protocol, and method.","unit":"1","sum":{"dataPoints":\[{"attributes":\[{"key":"code","value":{"stringValue":"(?:200|404)"}},{"key":"method","value":{"stringValue":"GET"}},{"key":"service","value":{"stringValue":"ServiceReqsCounter"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1},{"attributes":\[{"key":"code","value":{"stringValue":"(?:200|404)"}},{"key":"method","value":{"stringValue":"GET"}},{"key":"service","value":{"stringValue":"ServiceReqsCounter"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1}\],"aggregationTemporality":2,"isMonotonic":true}})`, `({"name":"traefik_service_requests_tls_total","description":"How many HTTP requests with TLS processed on a service, partitioned by TLS version and TLS cipher.","unit":"1","sum":{"dataPoints":\[{"attributes":\[{"key":"service","value":{"stringValue":"test"}},{"key":"tls_cipher","value":{"stringValue":"bar"}},{"key":"tls_version","value":{"stringValue":"foo"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1}\],"aggregationTemporality":2,"isMonotonic":true}})`, `({"name":"traefik_service_request_duration_seconds","description":"How long it took to process the request on a service, partitioned by status code, protocol, and method.","unit":"ms","histogram":{"dataPoints":\[{"attributes":\[{"key":"code","value":{"stringValue":"200"}},{"key":"service","value":{"stringValue":"test"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","count":"1","sum":10000,"bucketCounts":\["0","0","0","0","0","0","0","0","0","0","0","1"\],"explicitBounds":\[0.005,0.01,0.025,0.05,0.1,0.25,0.5,1,2.5,5,10\],"min":10000,"max":10000}\],"aggregationTemporality":2}})`, `({"name":"traefik_service_server_up","description":"service server is up, described by gauge value of 0 or 1.","unit":"1","gauge":{"dataPoints":\[{"attributes":\[{"key":"service","value":{"stringValue":"test"}},{"key":"url","value":{"stringValue":"http://127.0.0.1"}}\],"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":1}\]}})`, - } + ) registry.ServiceReqsCounter().With("service", "ServiceReqsCounter", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) registry.ServiceReqsCounter().With("service", "ServiceReqsCounter", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) @@ -400,24 +407,24 @@ func TestOpenTelemetry(t *testing.T) { registry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1) msgService := <-c - assertMessage(t, *msgService, expectedService) + assertMessage(t, *msgService, expected) - expectedServiceRetries := []string{ + expected = append(expected, `({"attributes":\[{"key":"service","value":{"stringValue":"foobar"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":1})`, `({"attributes":\[{"key":"service","value":{"stringValue":"test"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","asDouble":2})`, - } + ) registry.ServiceRetriesCounter().With("service", "test").Add(1) registry.ServiceRetriesCounter().With("service", "test").Add(1) registry.ServiceRetriesCounter().With("service", "foobar").Add(1) msgServiceRetries := <-c - assertMessage(t, *msgServiceRetries, expectedServiceRetries) + assertMessage(t, *msgServiceRetries, expected) - expectedServiceOpenConns := []string{ + expected = append(expected, `({"attributes":\[{"key":"service","value":{"stringValue":"test"}}\],"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":3})`, `({"attributes":\[{"key":"service","value":{"stringValue":"foobar"}}\],"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":1})`, - } + ) registry.ServiceOpenConnsGauge().With("service", "test").Set(1) registry.ServiceOpenConnsGauge().With("service", "test").Add(1) @@ -425,8 +432,12 @@ func TestOpenTelemetry(t *testing.T) { registry.ServiceOpenConnsGauge().With("service", "foobar").Add(1) msgServiceOpenConns := <-c - assertMessage(t, *msgServiceOpenConns, expectedServiceOpenConns) + assertMessage(t, *msgServiceOpenConns, expected) + // We cannot rely on the previous expected pattern, + // because this pattern was for matching only one dataPoint in the histogram, + // and as soon as the EntryPointReqDurationHistogram.Observe is called, + // it adds a new dataPoint to the histogram. expectedEntryPointReqDuration := []string{ `({"attributes":\[{"key":"entrypoint","value":{"stringValue":"myEntrypoint"}}\],"startTimeUnixNano":"[\d]{19}","timeUnixNano":"[\d]{19}","count":"2","sum":30000,"bucketCounts":\["0","0","0","0","0","0","0","0","0","0","0","2"\],"explicitBounds":\[0.005,0.01,0.025,0.05,0.1,0.25,0.5,1,2.5,5,10\],"min":10000,"max":20000})`, } diff --git a/pkg/tracing/opentelemetry/opentelemetry.go b/pkg/tracing/opentelemetry/opentelemetry.go index d42770ae3..6c568b050 100644 --- a/pkg/tracing/opentelemetry/opentelemetry.go +++ b/pkg/tracing/opentelemetry/opentelemetry.go @@ -16,7 +16,9 @@ import ( "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.12.0" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc/credentials" "google.golang.org/grpc/encoding/gzip" @@ -60,7 +62,20 @@ func (c *Config) Setup(componentName string) (opentracing.Tracer, io.Closer, err bt.SetOpenTelemetryTracer(otel.Tracer(componentName, trace.WithInstrumentationVersion(version.Version))) opentracing.SetGlobalTracer(bt) - tracerProvider := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter)) + res, err := resource.New(context.Background(), + resource.WithAttributes(semconv.ServiceNameKey.String("traefik")), + resource.WithAttributes(semconv.ServiceVersionKey.String(version.Version)), + resource.WithFromEnv(), + resource.WithTelemetrySDK(), + ) + if err != nil { + return nil, nil, fmt.Errorf("building resource: %w", err) + } + + tracerProvider := sdktrace.NewTracerProvider( + sdktrace.WithResource(res), + sdktrace.WithBatcher(exporter), + ) otel.SetTracerProvider(tracerProvider) log.Debug().Msg("OpenTelemetry tracer configured") diff --git a/pkg/tracing/opentelemetry/opentelemetry_test.go b/pkg/tracing/opentelemetry/opentelemetry_test.go index 9d76f71d3..9921586ee 100644 --- a/pkg/tracing/opentelemetry/opentelemetry_test.go +++ b/pkg/tracing/opentelemetry/opentelemetry_test.go @@ -9,6 +9,7 @@ import ( "net/http/httptest" "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -17,10 +18,39 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" ) -func TestTraceContextPropagation(t *testing.T) { - t.Parallel() +func TestTracing(t *testing.T) { + tests := []struct { + desc string + headers map[string]string + assertFn func(*testing.T, string) + }{ + { + desc: "service name and version", + assertFn: func(t *testing.T, trace string) { + t.Helper() - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Regexp(t, `({"key":"service.name","value":{"stringValue":"traefik"}})`, trace) + assert.Regexp(t, `({"key":"service.version","value":{"stringValue":"dev"}})`, trace) + }, + }, + { + desc: "context propagation", + headers: map[string]string{ + "traceparent": "00-00000000000000000000000000000001-0000000000000001-01", + "tracestate": "foo=bar", + }, + assertFn: func(t *testing.T, trace string) { + t.Helper() + + assert.Regexp(t, `("traceId":"00000000000000000000000000000001")`, trace) + assert.Regexp(t, `("parentSpanId":"0000000000000001")`, trace) + assert.Regexp(t, `("traceState":"foo=bar")`, trace) + }, + }, + } + + traceCh := make(chan string) + collector := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { gzr, err := gzip.NewReader(r.Body) require.NoError(t, err) @@ -34,34 +64,38 @@ func TestTraceContextPropagation(t *testing.T) { marshalledReq, err := json.Marshal(req) require.NoError(t, err) - bodyStr := string(marshalledReq) - assert.Regexp(t, `("traceId":"00000000000000000000000000000001")`, bodyStr) - assert.Regexp(t, `("parentSpanId":"0000000000000001")`, bodyStr) - assert.Regexp(t, `("traceState":"foo=bar")`, bodyStr) + traceCh <- string(marshalledReq) })) - defer ts.Close() + t.Cleanup(collector.Close) - cfg := Config{ - Address: strings.TrimPrefix(ts.URL, "http://"), + newTracing, err := tracing.NewTracing("", 0, &Config{ Insecure: true, - } - - newTracing, err := tracing.NewTracing("", 0, &cfg) - require.NoError(t, err) - defer newTracing.Close() - - req := httptest.NewRequest(http.MethodGet, "http://www.test.com", nil) - req.Header.Set("traceparent", "00-00000000000000000000000000000001-0000000000000001-00") - req.Header.Set("tracestate", "foo=bar") - rw := httptest.NewRecorder() - - var forwarded bool - next := http.HandlerFunc(func(http.ResponseWriter, *http.Request) { - forwarded = true + Address: strings.TrimPrefix(collector.URL, "http://"), }) + require.NoError(t, err) + t.Cleanup(newTracing.Close) - handler := mtracing.NewEntryPoint(context.Background(), newTracing, "test", next) - handler.ServeHTTP(rw, req) + epHandler := mtracing.NewEntryPoint(context.Background(), newTracing, "test", http.NotFoundHandler()) - require.True(t, forwarded) + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "http://www.test.com", nil) + for k, v := range test.headers { + req.Header.Set(k, v) + } + + rw := httptest.NewRecorder() + + epHandler.ServeHTTP(rw, req) + + select { + case <-time.After(10 * time.Second): + t.Error("Trace not exported") + + case trace := <-traceCh: + assert.Equal(t, http.StatusNotFound, rw.Code) + test.assertFn(t, trace) + } + }) + } } From e82976e001448f3304b4c6f3608a44c7617283f4 Mon Sep 17 00:00:00 2001 From: sven Date: Mon, 9 Jan 2023 16:07:09 +0100 Subject: [PATCH 24/74] Add info admonition about routing to k8 services --- docs/content/providers/docker.md | 2 +- docs/content/routing/providers/kubernetes-ingress.md | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/content/providers/docker.md b/docs/content/providers/docker.md index b34752eec..155803608 100644 --- a/docs/content/providers/docker.md +++ b/docs/content/providers/docker.md @@ -95,7 +95,7 @@ and [Docker Swarm Mode](https://docs.docker.com/engine/swarm/). ## Routing Configuration When using Docker as a [provider](./overview.md), -Traefik uses [container labels](https://docs.docker.com/engine/reference/commandline/run/#set-metadata-on-container--l---label---label-file) to retrieve its routing configuration. +Traefik uses [container labels](https://docs.docker.com/engine/reference/commandline/run/#-set-metadata-on-container--l---label---label-file) to retrieve its routing configuration. See the list of labels in the dedicated [routing](../routing/providers/docker.md) section. diff --git a/docs/content/routing/providers/kubernetes-ingress.md b/docs/content/routing/providers/kubernetes-ingress.md index c7c8ab914..a82f602eb 100644 --- a/docs/content/routing/providers/kubernetes-ingress.md +++ b/docs/content/routing/providers/kubernetes-ingress.md @@ -888,14 +888,20 @@ TLS certificates can be managed in Secrets objects. ### Communication Between Traefik and Pods +!!! info "It is not possible to route requests directly to [Kubernetes services](https://kubernetes.io/docs/concepts/services-networking/service/ "Link to Kubernetes service docs")" + + You can use an `ExternalName` service to forward requests to the Kubernetes service through DNS. + + For doing so, you have to [allow external name services](https://doc.traefik.io/traefik/providers/kubernetes-ingress/#allowexternalnameservices "Link to docs about allowing external name services"). + Traefik automatically requests endpoint information based on the service provided in the ingress spec. Although Traefik will connect directly to the endpoints (pods), it still checks the service port to see if TLS communication is required. -There are 3 ways to configure Traefik to use https to communicate with pods: +There are 3 ways to configure Traefik to use HTTPS to communicate with pods: 1. If the service port defined in the ingress spec is `443` (note that you can still use `targetPort` to use a different port on your pod). -1. If the service port defined in the ingress spec has a name that starts with https (such as `https-api`, `https-web` or just `https`). +1. If the service port defined in the ingress spec has a name that starts with `https` (such as `https-api`, `https-web` or just `https`). 1. If the service spec includes the annotation `traefik.ingress.kubernetes.io/service.serversscheme: https`. If either of those configuration options exist, then the backend communication protocol is assumed to be TLS, From 8cd4923e7212b3992620725df62042a576da63f2 Mon Sep 17 00:00:00 2001 From: bendre90 Date: Mon, 9 Jan 2023 17:24:05 +0100 Subject: [PATCH 25/74] Added router priority to webui's list and detail page --- .../testdata/rawdata-crd-label-selector.json | 1 + integration/testdata/rawdata-crd.json | 6 + integration/testdata/rawdata-gateway.json | 5 + .../rawdata-ingress-label-selector.json | 1 + integration/testdata/rawdata-ingress.json | 4 + .../testdata/rawdata-ingressclass.json | 1 + pkg/api/criterion.go | 45 +- pkg/api/handler_http.go | 27 +- pkg/api/handler_http_test.go | 78 + pkg/api/handler_tcp.go | 27 +- pkg/api/handler_tcp_test.go | 83 + pkg/api/handler_udp.go | 19 +- pkg/api/handler_udp_test.go | 34 + pkg/api/sort.go | 386 ++++ pkg/api/sort_test.go | 1689 +++++++++++++++++ .../routers-filtered-middlewareName.json | 36 + .../routers-filtered-serviceName.json | 32 + .../tcprouters-filtered-middlewareName.json | 36 + .../tcprouters-filtered-serviceName.json | 31 + .../udprouters-filtered-serviceName.json | 26 + pkg/muxer/http/mux.go | 10 +- pkg/muxer/http/mux_test.go | 27 + pkg/muxer/tcp/mux.go | 44 +- pkg/muxer/tcp/mux_test.go | 33 + pkg/server/router/router.go | 7 +- pkg/server/router/tcp/manager.go | 14 +- pkg/server/router/tcp/router.go | 3 +- webui/src/_mixins/GetTableProps.js | 26 +- webui/src/_services/HttpService.js | 6 +- webui/src/_services/TcpService.js | 6 +- webui/src/_services/UdpService.js | 4 +- webui/src/components/_commons/MainTable.vue | 37 +- .../_commons/PanelRouterDetails.vue | 12 + webui/src/pages/_commons/MiddlewareDetail.vue | 64 +- webui/src/pages/_commons/ServiceDetail.vue | 66 +- webui/src/pages/http/Middlewares.vue | 14 +- webui/src/pages/http/Routers.vue | 16 +- webui/src/pages/http/Services.vue | 14 +- webui/src/pages/tcp/Middlewares.vue | 14 +- webui/src/pages/tcp/Routers.vue | 16 +- webui/src/pages/tcp/Services.vue | 14 +- webui/src/pages/udp/Routers.vue | 16 +- webui/src/pages/udp/Services.vue | 14 +- 43 files changed, 2913 insertions(+), 131 deletions(-) create mode 100644 pkg/api/sort.go create mode 100644 pkg/api/sort_test.go create mode 100644 pkg/api/testdata/routers-filtered-middlewareName.json create mode 100644 pkg/api/testdata/routers-filtered-serviceName.json create mode 100644 pkg/api/testdata/tcprouters-filtered-middlewareName.json create mode 100644 pkg/api/testdata/tcprouters-filtered-serviceName.json create mode 100644 pkg/api/testdata/udprouters-filtered-serviceName.json diff --git a/integration/testdata/rawdata-crd-label-selector.json b/integration/testdata/rawdata-crd-label-selector.json index 63ace05eb..4e9df8d33 100644 --- a/integration/testdata/rawdata-crd-label-selector.json +++ b/integration/testdata/rawdata-crd-label-selector.json @@ -6,6 +6,7 @@ ], "service": "api@internal", "rule": "PathPrefix(`/api`)", + "priority": 18, "status": "enabled", "using": [ "web" diff --git a/integration/testdata/rawdata-crd.json b/integration/testdata/rawdata-crd.json index 2e5c308bd..5afe2f0a8 100644 --- a/integration/testdata/rawdata-crd.json +++ b/integration/testdata/rawdata-crd.json @@ -6,6 +6,7 @@ ], "service": "api@internal", "rule": "PathPrefix(`/api`)", + "priority": 18, "status": "enabled", "using": [ "web" @@ -35,6 +36,7 @@ ], "service": "default-test2-route-23c7f4c450289ee29016", "rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/tobestripped`)", + "priority": 46, "status": "enabled", "using": [ "web" @@ -46,6 +48,7 @@ ], "service": "default-wrr1", "rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/wrr1`)", + "priority": 38, "status": "enabled", "using": [ "web" @@ -57,6 +60,7 @@ ], "service": "default-testst-route-60ad45fcb5fc1f5f3629", "rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/serverstransport`)", + "priority": 50, "status": "enabled", "using": [ "web" @@ -68,6 +72,7 @@ ], "service": "other-ns-wrr3", "rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/c`)", + "priority": 35, "error": [ "the service \"other-ns-wrr3@kubernetescrd\" does not exist" ], @@ -261,6 +266,7 @@ ], "service": "default-test3.route-673acf455cb2dab0b43a", "rule": "HostSNI(`*`)", + "priority": -1, "tls": { "passthrough": false, "options": "default-mytlsoption" diff --git a/integration/testdata/rawdata-gateway.json b/integration/testdata/rawdata-gateway.json index 46a60e58f..9c695ef06 100644 --- a/integration/testdata/rawdata-gateway.json +++ b/integration/testdata/rawdata-gateway.json @@ -34,6 +34,7 @@ ], "service": "default-http-app-1-my-gateway-web-1c0cf64bde37d9d0df06-wrr", "rule": "Host(`foo.com`) \u0026\u0026 Path(`/bar`)", + "priority": 31, "status": "enabled", "using": [ "web" @@ -45,6 +46,7 @@ ], "service": "default-http-app-1-my-https-gateway-websecure-1c0cf64bde37d9d0df06-wrr", "rule": "Host(`foo.com`) \u0026\u0026 Path(`/bar`)", + "priority": 31, "tls": {}, "status": "enabled", "using": [ @@ -150,6 +152,7 @@ ], "service": "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb-wrr-0", "rule": "HostSNI(`*`)", + "priority": -1, "status": "enabled", "using": [ "footcp" @@ -161,6 +164,7 @@ ], "service": "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb-wrr-0", "rule": "HostSNI(`*`)", + "priority": -1, "tls": { "passthrough": false }, @@ -175,6 +179,7 @@ ], "service": "default-tls-app-1-my-tls-gateway-footlspassthrough-2279fe75c5156dc5eb26-wrr-0", "rule": "HostSNI(`foo.bar`)", + "priority": 18, "tls": { "passthrough": true }, diff --git a/integration/testdata/rawdata-ingress-label-selector.json b/integration/testdata/rawdata-ingress-label-selector.json index 54fbae930..d72826ae7 100644 --- a/integration/testdata/rawdata-ingress-label-selector.json +++ b/integration/testdata/rawdata-ingress-label-selector.json @@ -34,6 +34,7 @@ ], "service": "default-whoami-http", "rule": "Host(`whoami.test`) \u0026\u0026 PathPrefix(`/whoami`)", + "priority": 44, "status": "enabled", "using": [ "web" diff --git a/integration/testdata/rawdata-ingress.json b/integration/testdata/rawdata-ingress.json index a912d1ea0..ecfa38ee6 100644 --- a/integration/testdata/rawdata-ingress.json +++ b/integration/testdata/rawdata-ingress.json @@ -34,6 +34,7 @@ ], "service": "default-whoami-http", "rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)", + "priority": 50, "status": "enabled", "using": [ "web" @@ -45,6 +46,7 @@ ], "service": "default-whoami-http", "rule": "Host(`whoami.test`) \u0026\u0026 PathPrefix(`/whoami`)", + "priority": 44, "status": "enabled", "using": [ "web" @@ -56,6 +58,7 @@ ], "service": "default-whoami-80", "rule": "Host(`whoami.test.drop`) \u0026\u0026 PathPrefix(`/drop`)", + "priority": 47, "status": "enabled", "using": [ "web" @@ -67,6 +70,7 @@ ], "service": "default-whoami-80", "rule": "Host(`whoami.test.keep`) \u0026\u0026 PathPrefix(`/keep`)", + "priority": 47, "status": "enabled", "using": [ "web" diff --git a/integration/testdata/rawdata-ingressclass.json b/integration/testdata/rawdata-ingressclass.json index e592135bc..4215504c0 100644 --- a/integration/testdata/rawdata-ingressclass.json +++ b/integration/testdata/rawdata-ingressclass.json @@ -34,6 +34,7 @@ ], "service": "default-whoami-80", "rule": "Host(`whoami.test.keep`) \u0026\u0026 PathPrefix(`/keep`)", + "priority": 47, "status": "enabled", "using": [ "web" diff --git a/pkg/api/criterion.go b/pkg/api/criterion.go index d81a9f717..2e3d2f7e6 100644 --- a/pkg/api/criterion.go +++ b/pkg/api/criterion.go @@ -22,8 +22,10 @@ type pageInfo struct { } type searchCriterion struct { - Search string `url:"search"` - Status string `url:"status"` + Search string `url:"search"` + Status string `url:"status"` + ServiceName string `url:"serviceName"` + MiddlewareName string `url:"middlewareName"` } func newSearchCriterion(query url.Values) *searchCriterion { @@ -33,12 +35,19 @@ func newSearchCriterion(query url.Values) *searchCriterion { search := query.Get("search") status := query.Get("status") + serviceName := query.Get("serviceName") + middlewareName := query.Get("middlewareName") - if status == "" && search == "" { + if status == "" && search == "" && serviceName == "" && middlewareName == "" { return nil } - return &searchCriterion{Search: search, Status: status} + return &searchCriterion{ + Search: search, + Status: status, + ServiceName: serviceName, + MiddlewareName: middlewareName, + } } func (c *searchCriterion) withStatus(name string) bool { @@ -59,6 +68,34 @@ func (c *searchCriterion) searchIn(values ...string) bool { return false } +func (c *searchCriterion) filterService(name string) bool { + if c.ServiceName == "" { + return true + } + + if strings.Contains(name, "@") { + return c.ServiceName == name + } + + before, _, _ := strings.Cut(c.ServiceName, "@") + + return before == name +} + +func (c *searchCriterion) filterMiddleware(mns []string) bool { + if c.MiddlewareName == "" { + return true + } + + for _, mn := range mns { + if c.MiddlewareName == mn { + return true + } + } + + return false +} + func pagination(request *http.Request, max int) (pageInfo, error) { perPage, err := getIntParam(request, "per_page", defaultPerPage) if err != nil { diff --git a/pkg/api/handler_http.go b/pkg/api/handler_http.go index ebf35d206..9ee716e2d 100644 --- a/pkg/api/handler_http.go +++ b/pkg/api/handler_http.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - "sort" "strconv" "strings" @@ -69,7 +68,8 @@ func newMiddlewareRepresentation(name string, mi *runtime.MiddlewareInfo) middle func (h Handler) getRouters(rw http.ResponseWriter, request *http.Request) { results := make([]routerRepresentation, 0, len(h.runtimeConfiguration.Routers)) - criterion := newSearchCriterion(request.URL.Query()) + query := request.URL.Query() + criterion := newSearchCriterion(query) for name, rt := range h.runtimeConfiguration.Routers { if keepRouter(name, rt, criterion) { @@ -77,9 +77,7 @@ func (h Handler) getRouters(rw http.ResponseWriter, request *http.Request) { } } - sort.Slice(results, func(i, j int) bool { - return results[i].Name < results[j].Name - }) + sortRouters(query, results) rw.Header().Set("Content-Type", "application/json") @@ -121,7 +119,8 @@ func (h Handler) getRouter(rw http.ResponseWriter, request *http.Request) { func (h Handler) getServices(rw http.ResponseWriter, request *http.Request) { results := make([]serviceRepresentation, 0, len(h.runtimeConfiguration.Services)) - criterion := newSearchCriterion(request.URL.Query()) + query := request.URL.Query() + criterion := newSearchCriterion(query) for name, si := range h.runtimeConfiguration.Services { if keepService(name, si, criterion) { @@ -129,9 +128,7 @@ func (h Handler) getServices(rw http.ResponseWriter, request *http.Request) { } } - sort.Slice(results, func(i, j int) bool { - return results[i].Name < results[j].Name - }) + sortServices(query, results) rw.Header().Set("Content-Type", "application/json") @@ -173,7 +170,8 @@ func (h Handler) getService(rw http.ResponseWriter, request *http.Request) { func (h Handler) getMiddlewares(rw http.ResponseWriter, request *http.Request) { results := make([]middlewareRepresentation, 0, len(h.runtimeConfiguration.Middlewares)) - criterion := newSearchCriterion(request.URL.Query()) + query := request.URL.Query() + criterion := newSearchCriterion(query) for name, mi := range h.runtimeConfiguration.Middlewares { if keepMiddleware(name, mi, criterion) { @@ -181,9 +179,7 @@ func (h Handler) getMiddlewares(rw http.ResponseWriter, request *http.Request) { } } - sort.Slice(results, func(i, j int) bool { - return results[i].Name < results[j].Name - }) + sortMiddlewares(query, results) rw.Header().Set("Content-Type", "application/json") @@ -227,7 +223,10 @@ func keepRouter(name string, item *runtime.RouterInfo, criterion *searchCriterio return true } - return criterion.withStatus(item.Status) && criterion.searchIn(item.Rule, name) + return criterion.withStatus(item.Status) && + criterion.searchIn(item.Rule, name) && + criterion.filterService(item.Service) && + criterion.filterMiddleware(item.Middlewares) } func keepService(name string, item *runtime.ServiceInfo, criterion *searchCriterion) bool { diff --git a/pkg/api/handler_http_test.go b/pkg/api/handler_http_test.go index f6137f202..238b59454 100644 --- a/pkg/api/handler_http_test.go +++ b/pkg/api/handler_http_test.go @@ -202,6 +202,84 @@ func TestHandler_HTTP(t *testing.T) { jsonFile: "testdata/routers-filtered-search.json", }, }, + { + desc: "routers filtered by service", + path: "/api/http/routers?serviceName=fii-service@myprovider", + conf: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ + "test@myprovider": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "fii-service@myprovider", + Rule: "Host(`fii.bar.other`)", + Middlewares: []string{"addPrefixTest", "auth"}, + }, + Status: runtime.StatusEnabled, + }, + "foo@otherprovider": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "fii-service", + Rule: "Host(`fii.foo.other`)", + }, + Status: runtime.StatusEnabled, + }, + "bar@myprovider": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar`)", + Middlewares: []string{"auth", "addPrefixTest@anotherprovider"}, + }, + Status: runtime.StatusDisabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/routers-filtered-serviceName.json", + }, + }, + { + desc: "routers filtered by middleware", + path: "/api/http/routers?middlewareName=auth", + conf: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ + "test@myprovider": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "fii-service@myprovider", + Rule: "Host(`fii.bar.other`)", + Middlewares: []string{"addPrefixTest", "auth"}, + }, + Status: runtime.StatusEnabled, + }, + "foo@otherprovider": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "fii-service", + Rule: "Host(`fii.foo.other`)", + }, + Status: runtime.StatusEnabled, + }, + "bar@myprovider": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar`)", + Middlewares: []string{"auth", "addPrefixTest@anotherprovider"}, + }, + Status: runtime.StatusDisabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/routers-filtered-middlewareName.json", + }, + }, { desc: "one router by id", path: "/api/http/routers/bar@myprovider", diff --git a/pkg/api/handler_tcp.go b/pkg/api/handler_tcp.go index 8efb13068..43aeb9be0 100644 --- a/pkg/api/handler_tcp.go +++ b/pkg/api/handler_tcp.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - "sort" "strconv" "strings" @@ -62,7 +61,8 @@ func newTCPMiddlewareRepresentation(name string, mi *runtime.TCPMiddlewareInfo) func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) { results := make([]tcpRouterRepresentation, 0, len(h.runtimeConfiguration.TCPRouters)) - criterion := newSearchCriterion(request.URL.Query()) + query := request.URL.Query() + criterion := newSearchCriterion(query) for name, rt := range h.runtimeConfiguration.TCPRouters { if keepTCPRouter(name, rt, criterion) { @@ -70,9 +70,7 @@ func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) { } } - sort.Slice(results, func(i, j int) bool { - return results[i].Name < results[j].Name - }) + sortRouters(query, results) rw.Header().Set("Content-Type", "application/json") @@ -114,7 +112,8 @@ func (h Handler) getTCPRouter(rw http.ResponseWriter, request *http.Request) { func (h Handler) getTCPServices(rw http.ResponseWriter, request *http.Request) { results := make([]tcpServiceRepresentation, 0, len(h.runtimeConfiguration.TCPServices)) - criterion := newSearchCriterion(request.URL.Query()) + query := request.URL.Query() + criterion := newSearchCriterion(query) for name, si := range h.runtimeConfiguration.TCPServices { if keepTCPService(name, si, criterion) { @@ -122,9 +121,7 @@ func (h Handler) getTCPServices(rw http.ResponseWriter, request *http.Request) { } } - sort.Slice(results, func(i, j int) bool { - return results[i].Name < results[j].Name - }) + sortServices(query, results) rw.Header().Set("Content-Type", "application/json") @@ -166,7 +163,8 @@ func (h Handler) getTCPService(rw http.ResponseWriter, request *http.Request) { func (h Handler) getTCPMiddlewares(rw http.ResponseWriter, request *http.Request) { results := make([]tcpMiddlewareRepresentation, 0, len(h.runtimeConfiguration.Middlewares)) - criterion := newSearchCriterion(request.URL.Query()) + query := request.URL.Query() + criterion := newSearchCriterion(query) for name, mi := range h.runtimeConfiguration.TCPMiddlewares { if keepTCPMiddleware(name, mi, criterion) { @@ -174,9 +172,7 @@ func (h Handler) getTCPMiddlewares(rw http.ResponseWriter, request *http.Request } } - sort.Slice(results, func(i, j int) bool { - return results[i].Name < results[j].Name - }) + sortMiddlewares(query, results) rw.Header().Set("Content-Type", "application/json") @@ -220,7 +216,10 @@ func keepTCPRouter(name string, item *runtime.TCPRouterInfo, criterion *searchCr return true } - return criterion.withStatus(item.Status) && criterion.searchIn(item.Rule, name) + return criterion.withStatus(item.Status) && + criterion.searchIn(item.Rule, name) && + criterion.filterService(item.Service) && + criterion.filterMiddleware(item.Middlewares) } func keepTCPService(name string, item *runtime.TCPServiceInfo, criterion *searchCriterion) bool { diff --git a/pkg/api/handler_tcp_test.go b/pkg/api/handler_tcp_test.go index 18ac7708c..d8a6e0867 100644 --- a/pkg/api/handler_tcp_test.go +++ b/pkg/api/handler_tcp_test.go @@ -193,6 +193,89 @@ func TestHandler_TCP(t *testing.T) { jsonFile: "testdata/tcprouters-filtered-search.json", }, }, + { + desc: "TCP routers filtered by service", + path: "/api/tcp/routers?serviceName=foo-service@myprovider", + conf: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ + "test@myprovider": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar.other`)", + TLS: &dynamic.RouterTCPTLSConfig{ + Passthrough: false, + }, + }, + Status: runtime.StatusEnabled, + }, + "bar@myprovider": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service", + Rule: "Host(`foo.bar`)", + }, + Status: runtime.StatusWarning, + }, + "foo@myprovider": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "bar-service@myprovider", + Rule: "Host(`foo.bar`)", + }, + Status: runtime.StatusDisabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/tcprouters-filtered-serviceName.json", + }, + }, + { + desc: "TCP routers filtered by middleware", + path: "/api/tcp/routers?middlewareName=auth", + conf: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ + "test@myprovider": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar.other`)", + Middlewares: []string{"inflightconn@myprovider"}, + TLS: &dynamic.RouterTCPTLSConfig{ + Passthrough: false, + }, + }, + Status: runtime.StatusEnabled, + }, + "bar@myprovider": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service", + Rule: "Host(`foo.bar`)", + Middlewares: []string{"auth", "inflightconn@myprovider"}, + }, + Status: runtime.StatusWarning, + }, + "foo@myprovider": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "bar-service@myprovider", + Rule: "Host(`foo.bar`)", + Middlewares: []string{"inflightconn@myprovider", "auth"}, + }, + Status: runtime.StatusDisabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/tcprouters-filtered-middlewareName.json", + }, + }, { desc: "one TCP router by id", path: "/api/tcp/routers/bar@myprovider", diff --git a/pkg/api/handler_udp.go b/pkg/api/handler_udp.go index 13adfafea..72bffc80e 100644 --- a/pkg/api/handler_udp.go +++ b/pkg/api/handler_udp.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - "sort" "strconv" "strings" @@ -46,7 +45,8 @@ func newUDPServiceRepresentation(name string, si *runtime.UDPServiceInfo) udpSer func (h Handler) getUDPRouters(rw http.ResponseWriter, request *http.Request) { results := make([]udpRouterRepresentation, 0, len(h.runtimeConfiguration.UDPRouters)) - criterion := newSearchCriterion(request.URL.Query()) + query := request.URL.Query() + criterion := newSearchCriterion(query) for name, rt := range h.runtimeConfiguration.UDPRouters { if keepUDPRouter(name, rt, criterion) { @@ -54,9 +54,7 @@ func (h Handler) getUDPRouters(rw http.ResponseWriter, request *http.Request) { } } - sort.Slice(results, func(i, j int) bool { - return results[i].Name < results[j].Name - }) + sortRouters(query, results) rw.Header().Set("Content-Type", "application/json") @@ -98,7 +96,8 @@ func (h Handler) getUDPRouter(rw http.ResponseWriter, request *http.Request) { func (h Handler) getUDPServices(rw http.ResponseWriter, request *http.Request) { results := make([]udpServiceRepresentation, 0, len(h.runtimeConfiguration.UDPServices)) - criterion := newSearchCriterion(request.URL.Query()) + query := request.URL.Query() + criterion := newSearchCriterion(query) for name, si := range h.runtimeConfiguration.UDPServices { if keepUDPService(name, si, criterion) { @@ -106,9 +105,7 @@ func (h Handler) getUDPServices(rw http.ResponseWriter, request *http.Request) { } } - sort.Slice(results, func(i, j int) bool { - return results[i].Name < results[j].Name - }) + sortServices(query, results) rw.Header().Set("Content-Type", "application/json") @@ -152,7 +149,9 @@ func keepUDPRouter(name string, item *runtime.UDPRouterInfo, criterion *searchCr return true } - return criterion.withStatus(item.Status) && criterion.searchIn(name) + return criterion.withStatus(item.Status) && + criterion.searchIn(name) && + criterion.filterService(item.Service) } func keepUDPService(name string, item *runtime.UDPServiceInfo, criterion *searchCriterion) bool { diff --git a/pkg/api/handler_udp_test.go b/pkg/api/handler_udp_test.go index 4a5c0116f..2c7842fae 100644 --- a/pkg/api/handler_udp_test.go +++ b/pkg/api/handler_udp_test.go @@ -172,6 +172,40 @@ func TestHandler_UDP(t *testing.T) { jsonFile: "testdata/udprouters-filtered-search.json", }, }, + { + desc: "UDP routers filtered by service", + path: "/api/udp/routers?serviceName=foo-service@myprovider", + conf: runtime.Configuration{ + UDPRouters: map[string]*runtime.UDPRouterInfo{ + "test@myprovider": { + UDPRouter: &dynamic.UDPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + }, + Status: runtime.StatusEnabled, + }, + "bar@myprovider": { + UDPRouter: &dynamic.UDPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service", + }, + Status: runtime.StatusWarning, + }, + "foo@myprovider": { + UDPRouter: &dynamic.UDPRouter{ + EntryPoints: []string{"web"}, + Service: "bar-service@myprovider", + }, + Status: runtime.StatusDisabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/udprouters-filtered-serviceName.json", + }, + }, { desc: "one UDP router by id", path: "/api/udp/routers/bar@myprovider", diff --git a/pkg/api/sort.go b/pkg/api/sort.go new file mode 100644 index 000000000..58e1cde28 --- /dev/null +++ b/pkg/api/sort.go @@ -0,0 +1,386 @@ +package api + +import ( + "net/url" + "sort" + + "golang.org/x/exp/constraints" +) + +const ( + sortByParam = "sortBy" + directionParam = "direction" +) + +const ( + ascendantSorting = "asc" + descendantSorting = "desc" +) + +type orderedWithName interface { + name() string +} + +type orderedRouter interface { + orderedWithName + + provider() string + priority() int + status() string + rule() string + service() string + entryPointsCount() int +} + +func sortRouters[T orderedRouter](values url.Values, routers []T) { + sortBy := values.Get(sortByParam) + + direction := values.Get(directionParam) + if direction == "" { + direction = ascendantSorting + } + + switch sortBy { + case "name": + sortByName(direction, routers) + + case "provider": + sortByFunc(direction, routers, func(i int) string { return routers[i].provider() }) + + case "priority": + sortByFunc(direction, routers, func(i int) int { return routers[i].priority() }) + + case "status": + sortByFunc(direction, routers, func(i int) string { return routers[i].status() }) + + case "rule": + sortByFunc(direction, routers, func(i int) string { return routers[i].rule() }) + + case "service": + sortByFunc(direction, routers, func(i int) string { return routers[i].service() }) + + case "entryPoints": + sortByFunc(direction, routers, func(i int) int { return routers[i].entryPointsCount() }) + + default: + sortByName(direction, routers) + } +} + +func (r routerRepresentation) name() string { + return r.Name +} + +func (r routerRepresentation) provider() string { + return r.Provider +} + +func (r routerRepresentation) priority() int { + return r.Priority +} + +func (r routerRepresentation) status() string { + return r.Status +} + +func (r routerRepresentation) rule() string { + return r.Rule +} + +func (r routerRepresentation) service() string { + return r.Service +} + +func (r routerRepresentation) entryPointsCount() int { + return len(r.EntryPoints) +} + +func (r tcpRouterRepresentation) name() string { + return r.Name +} + +func (r tcpRouterRepresentation) provider() string { + return r.Provider +} + +func (r tcpRouterRepresentation) priority() int { + return r.Priority +} + +func (r tcpRouterRepresentation) status() string { + return r.Status +} + +func (r tcpRouterRepresentation) rule() string { + return r.Rule +} + +func (r tcpRouterRepresentation) service() string { + return r.Service +} + +func (r tcpRouterRepresentation) entryPointsCount() int { + return len(r.EntryPoints) +} + +func (r udpRouterRepresentation) name() string { + return r.Name +} + +func (r udpRouterRepresentation) provider() string { + return r.Provider +} + +func (r udpRouterRepresentation) priority() int { + // noop + return 0 +} + +func (r udpRouterRepresentation) status() string { + return r.Status +} + +func (r udpRouterRepresentation) rule() string { + // noop + return "" +} + +func (r udpRouterRepresentation) service() string { + return r.Service +} + +func (r udpRouterRepresentation) entryPointsCount() int { + return len(r.EntryPoints) +} + +type orderedService interface { + orderedWithName + + resourceType() string + serversCount() int + provider() string + status() string +} + +func sortServices[T orderedService](values url.Values, services []T) { + sortBy := values.Get(sortByParam) + + direction := values.Get(directionParam) + if direction == "" { + direction = ascendantSorting + } + + switch sortBy { + case "name": + sortByName(direction, services) + + case "type": + sortByFunc(direction, services, func(i int) string { return services[i].resourceType() }) + + case "servers": + sortByFunc(direction, services, func(i int) int { return services[i].serversCount() }) + + case "provider": + sortByFunc(direction, services, func(i int) string { return services[i].provider() }) + + case "status": + sortByFunc(direction, services, func(i int) string { return services[i].status() }) + + default: + sortByName(direction, services) + } +} + +func (s serviceRepresentation) name() string { + return s.Name +} + +func (s serviceRepresentation) resourceType() string { + return s.Type +} + +func (s serviceRepresentation) serversCount() int { + // TODO: maybe disable that data point altogether, + // if we can't/won't compute a fully correct (recursive) result. + // Or "redefine" it as only the top-level count? + // Note: The current algo is equivalent to the webui one. + if s.LoadBalancer == nil { + return 0 + } + + return len(s.LoadBalancer.Servers) +} + +func (s serviceRepresentation) provider() string { + return s.Provider +} + +func (s serviceRepresentation) status() string { + return s.Status +} + +func (s tcpServiceRepresentation) name() string { + return s.Name +} + +func (s tcpServiceRepresentation) resourceType() string { + return s.Type +} + +func (s tcpServiceRepresentation) serversCount() int { + // TODO: maybe disable that data point altogether, + // if we can't/won't compute a fully correct (recursive) result. + // Or "redefine" it as only the top-level count? + // Note: The current algo is equivalent to the webui one. + if s.LoadBalancer == nil { + return 0 + } + + return len(s.LoadBalancer.Servers) +} + +func (s tcpServiceRepresentation) provider() string { + return s.Provider +} + +func (s tcpServiceRepresentation) status() string { + return s.Status +} + +func (s udpServiceRepresentation) name() string { + return s.Name +} + +func (s udpServiceRepresentation) resourceType() string { + return s.Type +} + +func (s udpServiceRepresentation) serversCount() int { + // TODO: maybe disable that data point altogether, + // if we can't/won't compute a fully correct (recursive) result. + // Or "redefine" it as only the top-level count? + // Note: The current algo is equivalent to the webui one. + if s.LoadBalancer == nil { + return 0 + } + + return len(s.LoadBalancer.Servers) +} + +func (s udpServiceRepresentation) provider() string { + return s.Provider +} + +func (s udpServiceRepresentation) status() string { + return s.Status +} + +type orderedMiddleware interface { + orderedWithName + + resourceType() string + provider() string + status() string +} + +func sortMiddlewares[T orderedMiddleware](values url.Values, middlewares []T) { + sortBy := values.Get(sortByParam) + + direction := values.Get(directionParam) + if direction == "" { + direction = ascendantSorting + } + + switch sortBy { + case "name": + sortByName(direction, middlewares) + + case "type": + sortByFunc(direction, middlewares, func(i int) string { return middlewares[i].resourceType() }) + + case "provider": + sortByFunc(direction, middlewares, func(i int) string { return middlewares[i].provider() }) + + case "status": + sortByFunc(direction, middlewares, func(i int) string { return middlewares[i].status() }) + + default: + sortByName(direction, middlewares) + } +} + +func (m middlewareRepresentation) name() string { + return m.Name +} + +func (m middlewareRepresentation) resourceType() string { + return m.Type +} + +func (m middlewareRepresentation) provider() string { + return m.Provider +} + +func (m middlewareRepresentation) status() string { + return m.Status +} + +func (m tcpMiddlewareRepresentation) name() string { + return m.Name +} + +func (m tcpMiddlewareRepresentation) resourceType() string { + return m.Type +} + +func (m tcpMiddlewareRepresentation) provider() string { + return m.Provider +} + +func (m tcpMiddlewareRepresentation) status() string { + return m.Status +} + +type orderedByName interface { + orderedWithName +} + +func sortByName[T orderedByName](direction string, results []T) { + // Ascending + if direction == ascendantSorting { + sort.Slice(results, func(i, j int) bool { + return results[i].name() < results[j].name() + }) + + return + } + + // Descending + sort.Slice(results, func(i, j int) bool { + return results[i].name() > results[j].name() + }) +} + +func sortByFunc[T orderedWithName, U constraints.Ordered](direction string, results []T, fn func(int) U) { + // Ascending + if direction == ascendantSorting { + sort.Slice(results, func(i, j int) bool { + if fn(i) == fn(j) { + return results[i].name() < results[j].name() + } + + return fn(i) < fn(j) + }) + + return + } + + // Descending + sort.Slice(results, func(i, j int) bool { + if fn(i) == fn(j) { + return results[i].name() > results[j].name() + } + + return fn(i) > fn(j) + }) +} diff --git a/pkg/api/sort_test.go b/pkg/api/sort_test.go new file mode 100644 index 000000000..5acab875b --- /dev/null +++ b/pkg/api/sort_test.go @@ -0,0 +1,1689 @@ +package api + +import ( + "fmt" + "net/url" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/config/runtime" +) + +func TestSortRouters(t *testing.T) { + testCases := []struct { + direction string + sortBy string + elements []orderedRouter + expected []orderedRouter + }{ + { + direction: ascendantSorting, + sortBy: "name", + elements: []orderedRouter{ + routerRepresentation{ + Name: "b", + }, + routerRepresentation{ + Name: "a", + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "a", + }, + routerRepresentation{ + Name: "b", + }, + }, + }, + { + direction: descendantSorting, + sortBy: "name", + elements: []orderedRouter{ + routerRepresentation{ + Name: "a", + }, + routerRepresentation{ + Name: "b", + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "b", + }, + routerRepresentation{ + Name: "a", + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "provider", + elements: []orderedRouter{ + routerRepresentation{ + Name: "b", + Provider: "b", + }, + routerRepresentation{ + Name: "b", + Provider: "a", + }, + routerRepresentation{ + Name: "a", + Provider: "b", + }, + routerRepresentation{ + Name: "a", + Provider: "a", + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "a", + Provider: "a", + }, + routerRepresentation{ + Name: "b", + Provider: "a", + }, + routerRepresentation{ + Name: "a", + Provider: "b", + }, + routerRepresentation{ + Name: "b", + Provider: "b", + }, + }, + }, + { + direction: descendantSorting, + sortBy: "provider", + elements: []orderedRouter{ + routerRepresentation{ + Name: "a", + Provider: "a", + }, + routerRepresentation{ + Name: "a", + Provider: "b", + }, + routerRepresentation{ + Name: "b", + Provider: "a", + }, + routerRepresentation{ + Name: "b", + Provider: "b", + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "b", + Provider: "b", + }, + routerRepresentation{ + Name: "a", + Provider: "b", + }, + routerRepresentation{ + Name: "b", + Provider: "a", + }, + routerRepresentation{ + Name: "a", + Provider: "a", + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "priority", + elements: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 2, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 2, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 1, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 1, + }, + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 1, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 1, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 2, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 2, + }, + }, + }, + }, + }, + { + direction: descendantSorting, + sortBy: "priority", + elements: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 1, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 1, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 2, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 2, + }, + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 2, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 2, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 1, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Priority: 1, + }, + }, + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "status", + elements: []orderedRouter{ + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Status: "b", + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Status: "b", + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Status: "a", + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Status: "a", + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Status: "a", + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Status: "a", + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Status: "b", + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Status: "b", + }, + }, + }, + }, + { + direction: descendantSorting, + sortBy: "status", + elements: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Status: "a", + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Status: "a", + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Status: "b", + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Status: "b", + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Status: "b", + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Status: "b", + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Status: "a", + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Status: "a", + }, + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "rule", + elements: []orderedRouter{ + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "b", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "b", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "a", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "a", + }, + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "a", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "a", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "b", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "b", + }, + }, + }, + }, + }, + { + direction: descendantSorting, + sortBy: "rule", + elements: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "a", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "a", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "b", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "b", + }, + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "b", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "b", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "a", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Rule: "a", + }, + }, + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "service", + elements: []orderedRouter{ + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "b", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "b", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "a", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "a", + }, + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "a", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "a", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "b", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "b", + }, + }, + }, + }, + }, + { + direction: descendantSorting, + sortBy: "service", + elements: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "a", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "a", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "b", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "b", + }, + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "b", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "b", + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "a", + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + Service: "a", + }, + }, + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "entryPoints", + elements: []orderedRouter{ + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a", "b"}, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a", "b"}, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a"}, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a"}, + }, + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a"}, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a"}, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a", "b"}, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a", "b"}, + }, + }, + }, + }, + }, + { + direction: descendantSorting, + sortBy: "entryPoints", + elements: []orderedRouter{ + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a"}, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a"}, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a", "b"}, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a", "b"}, + }, + }, + }, + }, + expected: []orderedRouter{ + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a", "b"}, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a", "b"}, + }, + }, + }, + routerRepresentation{ + Name: "b", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a"}, + }, + }, + }, + routerRepresentation{ + Name: "a", + RouterInfo: &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"a"}, + }, + }, + }, + }, + }, + } + for _, test := range testCases { + test := test + t.Run(fmt.Sprintf("%s-%s", test.direction, test.sortBy), func(t *testing.T) { + t.Parallel() + + u, err := url.Parse(fmt.Sprintf("/?direction=%s&sortBy=%s", test.direction, test.sortBy)) + require.NoError(t, err) + + sortRouters(u.Query(), test.elements) + + assert.Equal(t, test.expected, test.elements) + }) + } +} + +func TestSortServices(t *testing.T) { + testCases := []struct { + direction string + sortBy string + elements []orderedService + expected []orderedService + }{ + { + direction: ascendantSorting, + sortBy: "name", + elements: []orderedService{ + serviceRepresentation{ + Name: "b", + }, + serviceRepresentation{ + Name: "a", + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "a", + }, + serviceRepresentation{ + Name: "b", + }, + }, + }, + { + direction: descendantSorting, + sortBy: "name", + elements: []orderedService{ + serviceRepresentation{ + Name: "a", + }, + serviceRepresentation{ + Name: "b", + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "b", + }, + serviceRepresentation{ + Name: "a", + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "type", + elements: []orderedService{ + serviceRepresentation{ + Name: "b", + Type: "b", + }, + serviceRepresentation{ + Name: "a", + Type: "b", + }, + serviceRepresentation{ + Name: "b", + Type: "a", + }, + serviceRepresentation{ + Name: "a", + Type: "a", + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "a", + Type: "a", + }, + serviceRepresentation{ + Name: "b", + Type: "a", + }, + serviceRepresentation{ + Name: "a", + Type: "b", + }, + serviceRepresentation{ + Name: "b", + Type: "b", + }, + }, + }, + { + direction: descendantSorting, + sortBy: "type", + elements: []orderedService{ + serviceRepresentation{ + Name: "a", + Type: "a", + }, + serviceRepresentation{ + Name: "b", + Type: "a", + }, + serviceRepresentation{ + Name: "a", + Type: "b", + }, + serviceRepresentation{ + Name: "b", + Type: "b", + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "b", + Type: "b", + }, + serviceRepresentation{ + Name: "a", + Type: "b", + }, + serviceRepresentation{ + Name: "b", + Type: "a", + }, + serviceRepresentation{ + Name: "a", + Type: "a", + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "servers", + elements: []orderedService{ + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 2), + }, + }, + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 2), + }, + }, + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 1), + }, + }, + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 1), + }, + }, + }, + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 1), + }, + }, + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 1), + }, + }, + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 2), + }, + }, + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 2), + }, + }, + }, + }, + }, + }, + { + direction: descendantSorting, + sortBy: "servers", + elements: []orderedService{ + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 1), + }, + }, + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 1), + }, + }, + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 2), + }, + }, + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 2), + }, + }, + }, + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 2), + }, + }, + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 2), + }, + }, + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 1), + }, + }, + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: make([]dynamic.Server, 1), + }, + }, + }, + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "provider", + elements: []orderedService{ + serviceRepresentation{ + Name: "b", + Provider: "b", + }, + serviceRepresentation{ + Name: "b", + Provider: "a", + }, + serviceRepresentation{ + Name: "a", + Provider: "b", + }, + serviceRepresentation{ + Name: "a", + Provider: "a", + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "a", + Provider: "a", + }, + serviceRepresentation{ + Name: "b", + Provider: "a", + }, + serviceRepresentation{ + Name: "a", + Provider: "b", + }, + serviceRepresentation{ + Name: "b", + Provider: "b", + }, + }, + }, + { + direction: descendantSorting, + sortBy: "provider", + elements: []orderedService{ + serviceRepresentation{ + Name: "a", + Provider: "a", + }, + serviceRepresentation{ + Name: "a", + Provider: "b", + }, + serviceRepresentation{ + Name: "b", + Provider: "a", + }, + serviceRepresentation{ + Name: "b", + Provider: "b", + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "b", + Provider: "b", + }, + serviceRepresentation{ + Name: "a", + Provider: "b", + }, + serviceRepresentation{ + Name: "b", + Provider: "a", + }, + serviceRepresentation{ + Name: "a", + Provider: "a", + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "status", + elements: []orderedService{ + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Status: "b", + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Status: "b", + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Status: "a", + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Status: "a", + }, + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Status: "a", + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Status: "a", + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Status: "b", + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Status: "b", + }, + }, + }, + }, + { + direction: descendantSorting, + sortBy: "status", + elements: []orderedService{ + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Status: "a", + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Status: "a", + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Status: "b", + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Status: "b", + }, + }, + }, + expected: []orderedService{ + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Status: "b", + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Status: "b", + }, + }, + serviceRepresentation{ + Name: "b", + ServiceInfo: &runtime.ServiceInfo{ + Status: "a", + }, + }, + serviceRepresentation{ + Name: "a", + ServiceInfo: &runtime.ServiceInfo{ + Status: "a", + }, + }, + }, + }, + } + for _, test := range testCases { + test := test + t.Run(fmt.Sprintf("%s-%s", test.direction, test.sortBy), func(t *testing.T) { + t.Parallel() + + u, err := url.Parse(fmt.Sprintf("/?direction=%s&sortBy=%s", test.direction, test.sortBy)) + require.NoError(t, err) + + sortServices(u.Query(), test.elements) + + assert.Equal(t, test.expected, test.elements) + }) + } +} + +func TestSortMiddlewares(t *testing.T) { + testCases := []struct { + direction string + sortBy string + elements []orderedMiddleware + expected []orderedMiddleware + }{ + { + direction: ascendantSorting, + sortBy: "name", + elements: []orderedMiddleware{ + middlewareRepresentation{ + Name: "b", + }, + middlewareRepresentation{ + Name: "a", + }, + }, + expected: []orderedMiddleware{ + middlewareRepresentation{ + Name: "a", + }, + middlewareRepresentation{ + Name: "b", + }, + }, + }, + { + direction: descendantSorting, + sortBy: "name", + elements: []orderedMiddleware{ + middlewareRepresentation{ + Name: "a", + }, + middlewareRepresentation{ + Name: "b", + }, + }, + expected: []orderedMiddleware{ + middlewareRepresentation{ + Name: "b", + }, + middlewareRepresentation{ + Name: "a", + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "type", + elements: []orderedMiddleware{ + middlewareRepresentation{ + Name: "b", + Type: "b", + }, + middlewareRepresentation{ + Name: "a", + Type: "b", + }, + middlewareRepresentation{ + Name: "b", + Type: "a", + }, + middlewareRepresentation{ + Name: "a", + Type: "a", + }, + }, + expected: []orderedMiddleware{ + middlewareRepresentation{ + Name: "a", + Type: "a", + }, + middlewareRepresentation{ + Name: "b", + Type: "a", + }, + middlewareRepresentation{ + Name: "a", + Type: "b", + }, + middlewareRepresentation{ + Name: "b", + Type: "b", + }, + }, + }, + { + direction: descendantSorting, + sortBy: "type", + elements: []orderedMiddleware{ + middlewareRepresentation{ + Name: "a", + Type: "a", + }, + middlewareRepresentation{ + Name: "b", + Type: "a", + }, + middlewareRepresentation{ + Name: "a", + Type: "b", + }, + middlewareRepresentation{ + Name: "b", + Type: "b", + }, + }, + expected: []orderedMiddleware{ + middlewareRepresentation{ + Name: "b", + Type: "b", + }, + middlewareRepresentation{ + Name: "a", + Type: "b", + }, + middlewareRepresentation{ + Name: "b", + Type: "a", + }, + middlewareRepresentation{ + Name: "a", + Type: "a", + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "provider", + elements: []orderedMiddleware{ + middlewareRepresentation{ + Name: "b", + Provider: "b", + }, + middlewareRepresentation{ + Name: "b", + Provider: "a", + }, + middlewareRepresentation{ + Name: "a", + Provider: "b", + }, + middlewareRepresentation{ + Name: "a", + Provider: "a", + }, + }, + expected: []orderedMiddleware{ + middlewareRepresentation{ + Name: "a", + Provider: "a", + }, + middlewareRepresentation{ + Name: "b", + Provider: "a", + }, + middlewareRepresentation{ + Name: "a", + Provider: "b", + }, + middlewareRepresentation{ + Name: "b", + Provider: "b", + }, + }, + }, + { + direction: descendantSorting, + sortBy: "provider", + elements: []orderedMiddleware{ + middlewareRepresentation{ + Name: "a", + Provider: "a", + }, + middlewareRepresentation{ + Name: "a", + Provider: "b", + }, + middlewareRepresentation{ + Name: "b", + Provider: "a", + }, + middlewareRepresentation{ + Name: "b", + Provider: "b", + }, + }, + expected: []orderedMiddleware{ + middlewareRepresentation{ + Name: "b", + Provider: "b", + }, + middlewareRepresentation{ + Name: "a", + Provider: "b", + }, + middlewareRepresentation{ + Name: "b", + Provider: "a", + }, + middlewareRepresentation{ + Name: "a", + Provider: "a", + }, + }, + }, + { + direction: ascendantSorting, + sortBy: "status", + elements: []orderedMiddleware{ + middlewareRepresentation{ + Name: "b", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "b", + }, + }, + middlewareRepresentation{ + Name: "a", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "b", + }, + }, + middlewareRepresentation{ + Name: "b", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "a", + }, + }, + middlewareRepresentation{ + Name: "a", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "a", + }, + }, + }, + expected: []orderedMiddleware{ + middlewareRepresentation{ + Name: "a", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "a", + }, + }, + middlewareRepresentation{ + Name: "b", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "a", + }, + }, + middlewareRepresentation{ + Name: "a", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "b", + }, + }, + middlewareRepresentation{ + Name: "b", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "b", + }, + }, + }, + }, + { + direction: descendantSorting, + sortBy: "status", + elements: []orderedMiddleware{ + middlewareRepresentation{ + Name: "a", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "a", + }, + }, + middlewareRepresentation{ + Name: "b", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "a", + }, + }, + middlewareRepresentation{ + Name: "a", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "b", + }, + }, + middlewareRepresentation{ + Name: "b", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "b", + }, + }, + }, + expected: []orderedMiddleware{ + middlewareRepresentation{ + Name: "b", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "b", + }, + }, + middlewareRepresentation{ + Name: "a", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "b", + }, + }, + middlewareRepresentation{ + Name: "b", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "a", + }, + }, + middlewareRepresentation{ + Name: "a", + MiddlewareInfo: &runtime.MiddlewareInfo{ + Status: "a", + }, + }, + }, + }, + } + for _, test := range testCases { + test := test + t.Run(fmt.Sprintf("%s-%s", test.direction, test.sortBy), func(t *testing.T) { + t.Parallel() + + u, err := url.Parse(fmt.Sprintf("/?direction=%s&sortBy=%s", test.direction, test.sortBy)) + require.NoError(t, err) + + sortMiddlewares(u.Query(), test.elements) + + assert.Equal(t, test.expected, test.elements) + }) + } +} diff --git a/pkg/api/testdata/routers-filtered-middlewareName.json b/pkg/api/testdata/routers-filtered-middlewareName.json new file mode 100644 index 000000000..d227748c5 --- /dev/null +++ b/pkg/api/testdata/routers-filtered-middlewareName.json @@ -0,0 +1,36 @@ +[ + { + "entryPoints": [ + "web" + ], + "middlewares": [ + "auth", + "addPrefixTest@anotherprovider" + ], + "name": "bar@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar`)", + "service": "foo-service@myprovider", + "status": "disabled", + "using": [ + "web" + ] + }, + { + "entryPoints": [ + "web" + ], + "middlewares": [ + "addPrefixTest", + "auth" + ], + "name": "test@myprovider", + "provider": "myprovider", + "rule": "Host(`fii.bar.other`)", + "service": "fii-service@myprovider", + "status": "enabled", + "using": [ + "web" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/routers-filtered-serviceName.json b/pkg/api/testdata/routers-filtered-serviceName.json new file mode 100644 index 000000000..7d50bc03a --- /dev/null +++ b/pkg/api/testdata/routers-filtered-serviceName.json @@ -0,0 +1,32 @@ +[ + { + "entryPoints": [ + "web" + ], + "name": "foo@otherprovider", + "provider": "otherprovider", + "rule": "Host(`fii.foo.other`)", + "service": "fii-service", + "status": "enabled", + "using": [ + "web" + ] + }, + { + "entryPoints": [ + "web" + ], + "middlewares": [ + "addPrefixTest", + "auth" + ], + "name": "test@myprovider", + "provider": "myprovider", + "rule": "Host(`fii.bar.other`)", + "service": "fii-service@myprovider", + "status": "enabled", + "using": [ + "web" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/tcprouters-filtered-middlewareName.json b/pkg/api/testdata/tcprouters-filtered-middlewareName.json new file mode 100644 index 000000000..e3f5352ec --- /dev/null +++ b/pkg/api/testdata/tcprouters-filtered-middlewareName.json @@ -0,0 +1,36 @@ +[ + { + "entryPoints": [ + "web" + ], + "middlewares": [ + "auth", + "inflightconn@myprovider" + ], + "name": "bar@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar`)", + "service": "foo-service", + "status": "warning", + "using": [ + "web" + ] + }, + { + "entryPoints": [ + "web" + ], + "middlewares": [ + "inflightconn@myprovider", + "auth" + ], + "name": "foo@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar`)", + "service": "bar-service@myprovider", + "status": "disabled", + "using": [ + "web" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/tcprouters-filtered-serviceName.json b/pkg/api/testdata/tcprouters-filtered-serviceName.json new file mode 100644 index 000000000..6bf20f9db --- /dev/null +++ b/pkg/api/testdata/tcprouters-filtered-serviceName.json @@ -0,0 +1,31 @@ +[ + { + "entryPoints": [ + "web" + ], + "name": "bar@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar`)", + "service": "foo-service", + "status": "warning", + "using": [ + "web" + ] + }, + { + "entryPoints": [ + "web" + ], + "name": "test@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar.other`)", + "service": "foo-service@myprovider", + "status": "enabled", + "using": [ + "web" + ], + "tls": { + "passthrough": false + } + } +] \ No newline at end of file diff --git a/pkg/api/testdata/udprouters-filtered-serviceName.json b/pkg/api/testdata/udprouters-filtered-serviceName.json new file mode 100644 index 000000000..bf387bfbc --- /dev/null +++ b/pkg/api/testdata/udprouters-filtered-serviceName.json @@ -0,0 +1,26 @@ +[ + { + "entryPoints": [ + "web" + ], + "name": "bar@myprovider", + "provider": "myprovider", + "service": "foo-service", + "status": "warning", + "using": [ + "web" + ] + }, + { + "entryPoints": [ + "web" + ], + "name": "test@myprovider", + "provider": "myprovider", + "service": "foo-service@myprovider", + "status": "enabled", + "using": [ + "web" + ] + } +] \ No newline at end of file diff --git a/pkg/muxer/http/mux.go b/pkg/muxer/http/mux.go index 3039075ee..6111af74c 100644 --- a/pkg/muxer/http/mux.go +++ b/pkg/muxer/http/mux.go @@ -46,6 +46,12 @@ func (m *Muxer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { http.NotFoundHandler().ServeHTTP(rw, req) } +// GetRulePriority computes the priority for a given rule. +// The priority is calculated using the length of rule. +func GetRulePriority(rule string) int { + return len(rule) +} + // AddRoute add a new route to the router. func (m *Muxer) AddRoute(rule string, priority int, handler http.Handler) error { parse, err := m.parser.Parse(rule) @@ -64,10 +70,6 @@ func (m *Muxer) AddRoute(rule string, priority int, handler http.Handler) error return fmt.Errorf("error while adding rule %s: %w", rule, err) } - if priority == 0 { - priority = len(rule) - } - m.routes = append(m.routes, &route{ handler: handler, matchers: matchers, diff --git a/pkg/muxer/http/mux_test.go b/pkg/muxer/http/mux_test.go index 0c1903de9..e11502b1b 100644 --- a/pkg/muxer/http/mux_test.go +++ b/pkg/muxer/http/mux_test.go @@ -376,6 +376,10 @@ func Test_addRoutePriority(t *testing.T) { w.Header().Set("X-From", route.xFrom) }) + if route.priority == 0 { + route.priority = GetRulePriority(route.rule) + } + err := muxer.AddRoute(route.rule, route.priority, handler) require.NoError(t, err, route.rule) } @@ -517,3 +521,26 @@ func TestEmptyHost(t *testing.T) { }) } } + +func TestGetRulePriority(t *testing.T) { + testCases := []struct { + desc string + rule string + expected int + }{ + { + desc: "simple rule", + rule: "Host(`example.org`)", + expected: 19, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + assert.Equal(t, test.expected, GetRulePriority(test.rule)) + }) + } +} diff --git a/pkg/muxer/tcp/mux.go b/pkg/muxer/tcp/mux.go index 00ec577af..0c6ef3fd6 100644 --- a/pkg/muxer/tcp/mux.go +++ b/pkg/muxer/tcp/mux.go @@ -72,6 +72,38 @@ func (m Muxer) Match(meta ConnData) (tcp.Handler, bool) { return nil, false } +// GetRulePriority computes the priority for a given rule. +// The priority is calculated using the length of rule. +// There is a special case where the HostSNI(`*`) has a priority of -1. +func GetRulePriority(rule string) int { + catchAllParser, err := rules.NewParser([]string{"HostSNI"}) + if err != nil { + return len(rule) + } + + parse, err := catchAllParser.Parse(rule) + if err != nil { + return len(rule) + } + + buildTree, ok := parse.(rules.TreeBuilder) + if !ok { + return len(rule) + } + + ruleTree := buildTree() + + // Special case for when the catchAll fallback is present. + // When no user-defined priority is found, the lowest computable priority minus one is used, + // in order to make the fallback the last to be evaluated. + if ruleTree.RuleLeft == nil && ruleTree.RuleRight == nil && len(ruleTree.Value) == 1 && + ruleTree.Value[0] == "*" && strings.EqualFold(ruleTree.Matcher, "HostSNI") { + return -1 + } + + return len(rule) +} + // AddRoute adds a new route, associated to the given handler, at the given // priority, to the muxer. func (m *Muxer) AddRoute(rule string, priority int, handler tcp.Handler) error { @@ -98,18 +130,6 @@ func (m *Muxer) AddRoute(rule string, priority int, handler tcp.Handler) error { catchAll = ruleTree.Value[0] == "*" && strings.EqualFold(ruleTree.Matcher, "HostSNI") } - // Special case for when the catchAll fallback is present. - // When no user-defined priority is found, the lowest computable priority minus one is used, - // in order to make the fallback the last to be evaluated. - if priority == 0 && catchAll { - priority = -1 - } - - // Default value, which means the user has not set it, so we'll compute it. - if priority == 0 { - priority = len(rule) - } - newRoute := &route{ handler: handler, matchers: matchers, diff --git a/pkg/muxer/tcp/mux_test.go b/pkg/muxer/tcp/mux_test.go index 95e84a245..54cd976cf 100644 --- a/pkg/muxer/tcp/mux_test.go +++ b/pkg/muxer/tcp/mux_test.go @@ -444,6 +444,39 @@ func Test_Priority(t *testing.T) { } } +func TestGetRulePriority(t *testing.T) { + testCases := []struct { + desc string + rule string + expected int + }{ + { + desc: "simple rule", + rule: "HostSNI(`example.org`)", + expected: 22, + }, + { + desc: "HostSNI(`*`) rule", + rule: "HostSNI(`*`)", + expected: -1, + }, + { + desc: "strange HostSNI(`*`) rule", + rule: " HostSNI ( `*` ) ", + expected: -1, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + assert.Equal(t, test.expected, GetRulePriority(test.rule)) + }) + } +} + type fakeConn struct { call map[string]int remoteAddr net.Addr diff --git a/pkg/server/router/router.go b/pkg/server/router/router.go index f19a46eb5..067dc9f20 100644 --- a/pkg/server/router/router.go +++ b/pkg/server/router/router.go @@ -119,6 +119,10 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string logger := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger() ctxRouter := logger.WithContext(provider.AddInContext(ctx, routerName)) + if routerConfig.Priority == 0 { + routerConfig.Priority = httpmuxer.GetRulePriority(routerConfig.Rule) + } + handler, err := m.buildRouterHandler(ctxRouter, routerName, routerConfig) if err != nil { routerConfig.AddError(err, true) @@ -126,8 +130,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string continue } - err = muxer.AddRoute(routerConfig.Rule, routerConfig.Priority, handler) - if err != nil { + if err = muxer.AddRoute(routerConfig.Rule, routerConfig.Priority, handler); err != nil { routerConfig.AddError(err, true) logger.Error().Err(err).Send() continue diff --git a/pkg/server/router/tcp/manager.go b/pkg/server/router/tcp/manager.go index 9bbadbc20..05a451131 100644 --- a/pkg/server/router/tcp/manager.go +++ b/pkg/server/router/tcp/manager.go @@ -264,6 +264,10 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim logger := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger() ctxRouter := logger.WithContext(provider.AddInContext(ctx, routerName)) + if routerConfig.Priority == 0 { + routerConfig.Priority = tcpmuxer.GetRulePriority(routerConfig.Rule) + } + if routerConfig.Service == "" { err := errors.New("the service is missing on the router") routerConfig.AddError(err, true) @@ -306,6 +310,7 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim if routerConfig.TLS == nil { logger.Debug().Msgf("Adding route for %q", routerConfig.Rule) + if err := router.AddRoute(routerConfig.Rule, routerConfig.Priority, handler); err != nil { routerConfig.AddError(err, true) logger.Error().Err(err).Send() @@ -315,6 +320,7 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim if routerConfig.TLS.Passthrough { logger.Debug().Msgf("Adding Passthrough route for %q", routerConfig.Rule) + if err := router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, handler); err != nil { routerConfig.AddError(err, true) logger.Error().Err(err).Send() @@ -349,11 +355,11 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim logger.Debug().Msgf("Adding special TLS closing route for %q because broken TLS options %s", routerConfig.Rule, tlsOptionsName) - err = router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, &brokenTLSRouter{}) - if err != nil { + if err := router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, &brokenTLSRouter{}); err != nil { routerConfig.AddError(err, true) logger.Error().Err(err).Send() } + continue } @@ -383,10 +389,10 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim logger.Debug().Msgf("Adding TLS route for %q", routerConfig.Rule) - err = router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, handler) - if err != nil { + if err := router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, handler); err != nil { routerConfig.AddError(err, true) logger.Error().Err(err).Send() + continue } } } diff --git a/pkg/server/router/tcp/router.go b/pkg/server/router/tcp/router.go index b3f34ee0d..2f0f11af8 100644 --- a/pkg/server/router/tcp/router.go +++ b/pkg/server/router/tcp/router.go @@ -268,8 +268,7 @@ func (r *Router) SetHTTPSForwarder(handler tcp.Handler) { // muxerHTTPS only contains single HostSNI rules (and no other kind of rules), // so there's no need for specifying a priority for them. - err := r.muxerHTTPS.AddRoute("HostSNI(`"+sniHost+"`)", 0, tcpHandler) - if err != nil { + if err := r.muxerHTTPS.AddRoute("HostSNI(`"+sniHost+"`)", 0, tcpHandler); err != nil { log.Error().Err(err).Msg("Error while adding route for host") } } diff --git a/webui/src/_mixins/GetTableProps.js b/webui/src/_mixins/GetTableProps.js index 014a397bb..5ca70949d 100644 --- a/webui/src/_mixins/GetTableProps.js +++ b/webui/src/_mixins/GetTableProps.js @@ -11,6 +11,7 @@ const allColumns = [ required: true, label: 'Status', align: 'left', + sortable: true, fieldToProps: row => ({ state: row.status === 'enabled' ? 'positive' : 'negative' }), @@ -20,6 +21,7 @@ const allColumns = [ name: 'tls', align: 'left', label: 'TLS', + sortable: false, fieldToProps: row => ({ isTLS: row.tls }), component: TLSState }, @@ -27,6 +29,7 @@ const allColumns = [ name: 'rule', align: 'left', label: 'Rule', + sortable: true, component: QChip, fieldToProps: () => ({ class: 'app-chip app-chip-rule', dense: true }), content: row => row.rule @@ -35,6 +38,7 @@ const allColumns = [ name: 'entryPoints', align: 'left', label: 'Entrypoints', + sortable: true, component: Chips, fieldToProps: row => ({ classNames: 'app-chip app-chip-entry-points', @@ -46,6 +50,7 @@ const allColumns = [ name: 'name', align: 'left', label: 'Name', + sortable: true, component: QChip, fieldToProps: () => ({ class: 'app-chip app-chip-name', dense: true }), content: row => row.name @@ -54,6 +59,7 @@ const allColumns = [ name: 'type', align: 'left', label: 'Type', + sortable: true, component: QChip, fieldToProps: () => ({ class: 'app-chip app-chip-entry-points', @@ -65,6 +71,7 @@ const allColumns = [ name: 'servers', align: 'right', label: 'Servers', + sortable: true, fieldToProps: () => ({ class: 'servers-label' }), content: function (value) { if (value.loadBalancer && value.loadBalancer.servers) { @@ -78,6 +85,7 @@ const allColumns = [ align: 'left', label: 'Service', component: QChip, + sortable: true, fieldToProps: () => ({ class: 'app-chip app-chip-service', dense: true }), content: row => row.service }, @@ -85,8 +93,23 @@ const allColumns = [ name: 'provider', align: 'center', label: 'Provider', + sortable: true, fieldToProps: row => ({ name: row.provider }), component: ProviderIcon + }, + { + name: 'priority', + align: 'left', + label: 'Priority', + sortable: true, + component: QChip, + fieldToProps: () => ({ class: 'app-chip app-chip-accent', dense: true }), + content: row => { + return { + short: String(row.priority).length > 10 ? String(row.priority).substring(0, 10) + '...' : row.priority, + long: row.priority + } + } } ] @@ -98,7 +121,8 @@ const columnsByResource = { 'name', 'service', 'tls', - 'provider' + 'provider', + 'priority' ], udpRouters: ['status', 'entryPoints', 'name', 'service', 'provider'], services: ['status', 'name', 'type', 'servers', 'provider'], diff --git a/webui/src/_services/HttpService.js b/webui/src/_services/HttpService.js index 0e206b24d..9a1228285 100644 --- a/webui/src/_services/HttpService.js +++ b/webui/src/_services/HttpService.js @@ -4,7 +4,7 @@ import { getTotal } from './utils' const apiBase = '/http' function getAllRouters (params) { - return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}&sortBy=${params.sortBy}&direction=${params.direction}&serviceName=${params.serviceName}&middlewareName=${params.middlewareName}`) .then(response => { const { data = [], headers } = response const total = getTotal(headers, params) @@ -22,7 +22,7 @@ function getRouterByName (name) { } function getAllServices (params) { - return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}&sortBy=${params.sortBy}&direction=${params.direction}`) .then(response => { const { data = [], headers } = response const total = getTotal(headers, params) @@ -40,7 +40,7 @@ function getServiceByName (name) { } function getAllMiddlewares (params) { - return APP.api.get(`${apiBase}/middlewares?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + return APP.api.get(`${apiBase}/middlewares?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}&sortBy=${params.sortBy}&direction=${params.direction}`) .then(response => { const { data = [], headers } = response const total = getTotal(headers, params) diff --git a/webui/src/_services/TcpService.js b/webui/src/_services/TcpService.js index e5645e9b1..ca33b0120 100644 --- a/webui/src/_services/TcpService.js +++ b/webui/src/_services/TcpService.js @@ -4,7 +4,7 @@ import { getTotal } from './utils' const apiBase = '/tcp' function getAllRouters (params) { - return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}&sortBy=${params.sortBy}&direction=${params.direction}&serviceName=${params.serviceName}&middlewareName=${params.middlewareName}`) .then(response => { const { data = [], headers } = response const total = getTotal(headers, params) @@ -22,7 +22,7 @@ function getRouterByName (name) { } function getAllServices (params) { - return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}&sortBy=${params.sortBy}&direction=${params.direction}`) .then(response => { const { data = [], headers } = response const total = getTotal(headers, params) @@ -40,7 +40,7 @@ function getServiceByName (name) { } function getAllMiddlewares (params) { - return APP.api.get(`${apiBase}/middlewares?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + return APP.api.get(`${apiBase}/middlewares?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}&sortBy=${params.sortBy}&direction=${params.direction}`) .then(response => { const { data = [], headers } = response const total = getTotal(headers, params) diff --git a/webui/src/_services/UdpService.js b/webui/src/_services/UdpService.js index fd641d357..549a99c1b 100644 --- a/webui/src/_services/UdpService.js +++ b/webui/src/_services/UdpService.js @@ -4,7 +4,7 @@ import { getTotal } from './utils' const apiBase = '/udp' function getAllRouters (params) { - return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}&sortBy=${params.sortBy}&direction=${params.direction}&serviceName=${params.serviceName}`) .then(response => { const { data = [], headers } = response const total = getTotal(headers, params) @@ -22,7 +22,7 @@ function getRouterByName (name) { } function getAllServices (params) { - return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}&sortBy=${params.sortBy}&direction=${params.direction}`) .then(response => { const { data = [], headers } = response const total = getTotal(headers, params) diff --git a/webui/src/components/_commons/MainTable.vue b/webui/src/components/_commons/MainTable.vue index 85ae32e55..6119b33da 100644 --- a/webui/src/components/_commons/MainTable.vue +++ b/webui/src/components/_commons/MainTable.vue @@ -6,9 +6,12 @@ + v-bind:class="getColumn(column.name).sortable ? `text-${column.align} cursor-pointer`: `text-${column.align}`" + v-bind:key="column.name" + @click="getColumn(column.name).sortable ? onSortClick(column.name) : null"> {{ column.label }} + {{currentSortDir === 'asc' ? 'arrow_drop_down' : 'arrow_drop_up'}} + {{currentSortDir === 'asc' ? 'arrow_drop_down' : 'arrow_drop_up'}} @@ -27,9 +30,19 @@ v-bind:is="getColumn(column.name).component" v-bind="getColumn(column.name).fieldToProps(row)" > -