diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0df46760d..6f48169bb 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,11 +2,11 @@ PLEASE READ THIS MESSAGE. Documentation fixes or enhancements: -- for Traefik v2: use branch v2.9 +- for Traefik v2: use branch v2.10 - for Traefik v3: use branch master Bug fixes: -- for Traefik v2: use branch v2.9 +- for Traefik v2: use branch v2.10 - for Traefik v3: use branch master Enhancements: diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 110edf6cb..a219162d1 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,7 +6,7 @@ on: - '*' env: - GO_VERSION: 1.19 + GO_VERSION: '1.20' CGO_ENABLED: 0 IN_DOCKER: "" diff --git a/.github/workflows/check_doc.yml b/.github/workflows/check_doc.yml index ee7465fcb..c800ad248 100644 --- a/.github/workflows/check_doc.yml +++ b/.github/workflows/check_doc.yml @@ -19,3 +19,7 @@ jobs: - name: Check documentation run: make docs-pull-images docs + env: + # These variables are not passed to workflows that are triggered by a pull request from a fork. + DOCS_VERIFY_SKIP: ${{ vars.DOCS_VERIFY_SKIP }} + DOCS_LINT_SKIP: ${{ vars.DOCS_LINT_SKIP }} diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 66227331f..7ef7f7ed3 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -7,7 +7,7 @@ on: - v* env: - STRUCTOR_VERSION: v1.11.2 + STRUCTOR_VERSION: v1.13.1 MIXTUS_VERSION: v0.4.1 jobs: @@ -41,12 +41,12 @@ jobs: - name: Build documentation run: $HOME/bin/structor -o traefik -r traefik --dockerfile-url="https://raw.githubusercontent.com/traefik/traefik/v1.7/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/traefik/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/traefik/structor/master/requirements-override.txt" --force-edit-url --exp-branch=master --debug env: - STRUCTOR_LATEST_TAG: ${{ secrets.STRUCTOR_LATEST_TAG }} + STRUCTOR_LATEST_TAG: ${{ vars.STRUCTOR_LATEST_TAG }} - name: Apply seo run: $HOME/bin/seo -path=./site -product=traefik - name: Publish documentation - run: $HOME/bin/mixtus --dst-doc-path="./traefik" --dst-owner=traefik --dst-repo-name=doc --git-user-email="30906710+traefiker@users.noreply.github.com" --git-user-name=traefiker --src-doc-path="./site" --src-owner=containous --src-repo-name=traefik + run: $HOME/bin/mixtus --dst-doc-path="./traefik" --dst-owner=traefik --dst-repo-name=doc --git-user-email="30906710+traefiker@users.noreply.github.com" --git-user-name=traefiker --src-doc-path="./site" --src-owner=traefik --src-repo-name=traefik env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN_REPO }} diff --git a/.github/workflows/test-unit.yaml b/.github/workflows/test-unit.yaml index c819cd1aa..ad9edcf41 100644 --- a/.github/workflows/test-unit.yaml +++ b/.github/workflows/test-unit.yaml @@ -6,7 +6,7 @@ on: - '*' env: - GO_VERSION: 1.19 + GO_VERSION: '1.20' IN_DOCKER: "" jobs: diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index beb87eec1..69de25cf4 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -6,8 +6,8 @@ on: - '*' env: - GO_VERSION: 1.19 - GOLANGCI_LINT_VERSION: v1.50.0 + GO_VERSION: '1.20' + GOLANGCI_LINT_VERSION: v1.51.2 MISSSPELL_VERSION: v0.4.0 IN_DOCKER: "" 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/.goreleaser.yml b/.goreleaser.yml index 9194b4a1e..a6fc323d3 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -11,7 +11,7 @@ builds: env: - CGO_ENABLED=0 ldflags: - - -s -w -X github.com/traefik/traefik/v2/pkg/version.Version={{.Version}} -X github.com/traefik/traefik/v2/pkg/version.Codename={{.Env.CODENAME}} -X github.com/traefik/traefik/v2/pkg/version.BuildDate={{.Date}} + - -s -w -X github.com/traefik/traefik/v3/pkg/version.Version={{.Version}} -X github.com/traefik/traefik/v3/pkg/version.Codename={{.Env.CODENAME}} -X github.com/traefik/traefik/v3/pkg/version.BuildDate={{.Date}} flags: - -trimpath goos: diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 2aab6ab3e..95ea73ed1 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -19,7 +19,7 @@ global_job_config: prologue: commands: - curl -sSfL https://raw.githubusercontent.com/ldez/semgo/master/godownloader.sh | sudo sh -s -- -b "/usr/local/bin" - - sudo semgo go1.19 + - sudo semgo go1.20 - export "GOPATH=$(go env GOPATH)" - export "SEMAPHORE_GIT_DIR=${GOPATH}/src/github.com/traefik/${SEMAPHORE_PROJECT_NAME}" - export "PATH=${GOPATH}/bin:${PATH}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a393f217..cc9a911ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,69 @@ +## [v2.10.0-rc1](https://github.com/traefik/traefik/tree/v2.10.0-rc1) (2023-03-22) +[All Commits](https://github.com/traefik/traefik/compare/b3f162a8a61d89beaa9edc8adc12cc4cb3e1de0f...v2.10.0-rc1) + +**Enhancements:** +- **[docker]** Expose ContainerName in Docker provider ([#9770](https://github.com/traefik/traefik/pull/9770) by [quinot](https://github.com/quinot)) +- **[hub]** hub: get out of experimental. ([#9792](https://github.com/traefik/traefik/pull/9792) by [mpl](https://github.com/mpl)) +- **[k8s/crd]** Introduce traefik.io API Group CRDs ([#9765](https://github.com/traefik/traefik/pull/9765) by [rtribotte](https://github.com/rtribotte)) +- **[k8s/ingress,k8s/crd,k8s]** Native Kubernetes service load-balancing ([#9740](https://github.com/traefik/traefik/pull/9740) by [rtribotte](https://github.com/rtribotte)) +- **[middleware,metrics]** Add prometheus metric requests_total with headers ([#9783](https://github.com/traefik/traefik/pull/9783) by [rtribotte](https://github.com/rtribotte)) +- **[nomad]** Support multiple namespaces in the Nomad Provider ([#9794](https://github.com/traefik/traefik/pull/9794) by [rtribotte](https://github.com/rtribotte)) +- **[tracing]** Add support to send DataDog traces via Unix Socket ([#9714](https://github.com/traefik/traefik/pull/9714) by [der-eismann](https://github.com/der-eismann)) + +**Documentation:** +- docs: update order of log levels ([#9791](https://github.com/traefik/traefik/pull/9791) by [svx](https://github.com/svx)) + +**Misc:** +- Merge current v2.9 into v2.10 ([#9798](https://github.com/traefik/traefik/pull/9798) by [ldez](https://github.com/ldez)) + +## [v2.9.9](https://github.com/traefik/traefik/tree/v2.9.9) (2023-03-21) +[All Commits](https://github.com/traefik/traefik/compare/v2.9.8...v2.9.9) + +**Bug fixes:** +- **[acme]** Update go-acme/lego to v4.10.2 ([#9749](https://github.com/traefik/traefik/pull/9749) by [ldez](https://github.com/ldez)) +- **[http3]** Update quic-go to v0.33.0 ([#9737](https://github.com/traefik/traefik/pull/9737) by [ldez](https://github.com/ldez)) +- **[metrics]** Include user-defined default cert for traefik_tls_certs_not_after metric ([#9742](https://github.com/traefik/traefik/pull/9742) by [rtribotte](https://github.com/rtribotte)) +- **[middleware]** Update vulcand/oxy to a0e9f7ff1040 ([#9750](https://github.com/traefik/traefik/pull/9750) by [ldez](https://github.com/ldez)) +- **[nomad]** Fix default configuration settings for Nomad Provider ([#9758](https://github.com/traefik/traefik/pull/9758) by [aofei](https://github.com/aofei)) +- **[nomad]** Fix Nomad client TLS defaults ([#9795](https://github.com/traefik/traefik/pull/9795) by [rtribotte](https://github.com/rtribotte)) +- **[server]** Remove User-Agent header removal from ReverseProxy director func ([#9752](https://github.com/traefik/traefik/pull/9752) by [rtribotte](https://github.com/rtribotte)) + +**Documentation:** +- **[middleware]** Clarify ratelimit middleware ([#9777](https://github.com/traefik/traefik/pull/9777) by [mpl](https://github.com/mpl)) +- **[tcp]** Correcting variable name 'server address' in TCP Router ([#9743](https://github.com/traefik/traefik/pull/9743) by [ralphg6](https://github.com/ralphg6)) + +## [v2.9.8](https://github.com/traefik/traefik/tree/v2.9.8) (2023-02-15) +[All Commits](https://github.com/traefik/traefik/compare/v2.9.7...v2.9.8) + +**Bug fixes:** +- **[server]** Update golang.org/x/net to v0.7.0 ([#9716](https://github.com/traefik/traefik/pull/9716) by [ldez](https://github.com/ldez)) + +## [v2.9.7](https://github.com/traefik/traefik/tree/v2.9.7) (2023-02-14) +[All Commits](https://github.com/traefik/traefik/compare/v2.9.6...v2.9.7) + +**Bug fixes:** +- **[acme]** Update go-acme/lego to v4.10.0 ([#9705](https://github.com/traefik/traefik/pull/9705) by [ldez](https://github.com/ldez)) +- **[ecs]** Prevent panicking when a container has no network interfaces ([#9661](https://github.com/traefik/traefik/pull/9661) by [rtribotte](https://github.com/rtribotte)) +- **[file]** Make file provider more resilient wrt first configuration ([#9595](https://github.com/traefik/traefik/pull/9595) by [mpl](https://github.com/mpl)) +- **[logs]** Differentiate UDP stream and TCP connection in logs ([#9687](https://github.com/traefik/traefik/pull/9687) by [rtribotte](https://github.com/rtribotte)) +- **[middleware]** Prevent from no rate limiting when average is zero ([#9621](https://github.com/traefik/traefik/pull/9621) by [witalisoft](https://github.com/witalisoft)) +- **[middleware]** Prevents superfluous WriteHeader call in the error middleware ([#9620](https://github.com/traefik/traefik/pull/9620) by [tomMoulard](https://github.com/tomMoulard)) +- **[middleware]** Sanitize X-Forwarded-Proto header in RedirectScheme middleware ([#9598](https://github.com/traefik/traefik/pull/9598) by [ldez](https://github.com/ldez)) +- **[plugins]** Update paerser to v0.2.0 ([#9671](https://github.com/traefik/traefik/pull/9671) by [ldez](https://github.com/ldez)) +- **[plugins]** Update Yaegi to v0.15.0 ([#9700](https://github.com/traefik/traefik/pull/9700) by [ldez](https://github.com/ldez)) +- **[tls,http3]** Bump quic-go to 89769f409f ([#9685](https://github.com/traefik/traefik/pull/9685) by [mpl](https://github.com/mpl)) +- **[tls,tcp]** Adds the support for IPv6 in the TCP HostSNI matcher ([#9692](https://github.com/traefik/traefik/pull/9692) by [rtribotte](https://github.com/rtribotte)) + +**Documentation:** +- **[acme]** Add CNAME support and gotchas ([#9698](https://github.com/traefik/traefik/pull/9698) by [mpl](https://github.com/mpl)) +- **[acme]** Further Let's Encrypt ratelimit warnings ([#9627](https://github.com/traefik/traefik/pull/9627) by [hcooper](https://github.com/hcooper)) +- **[k8s]** Add info admonition about routing to k8 services ([#9645](https://github.com/traefik/traefik/pull/9645) by [svx](https://github.com/svx)) +- **[k8s]** Improve TLSStore CRD documentation ([#9579](https://github.com/traefik/traefik/pull/9579) by [mloiseleur](https://github.com/mloiseleur)) +- **[middleware]** doc: add note about remoteaddr strategy ([#9701](https://github.com/traefik/traefik/pull/9701) by [mpl](https://github.com/mpl)) +- Update copyright to match new standard ([#9651](https://github.com/traefik/traefik/pull/9651) by [paulocfjunior](https://github.com/paulocfjunior)) +- Update copyright for 2023 ([#9631](https://github.com/traefik/traefik/pull/9631) by [kevinpollet](https://github.com/kevinpollet)) +- Update submitting pull requests to include language about drafts ([#9609](https://github.com/traefik/traefik/pull/9609) by [tfny](https://github.com/tfny)) + ## [v3.0.0-beta2](https://github.com/traefik/traefik/tree/v3.0.0-beta2) (2022-12-07) [All Commits](https://github.com/traefik/traefik/compare/v3.0.0-beta1...v3.0.0-beta2) @@ -142,13 +208,7 @@ Release canceled. - **[acme]** Fix ACME panic ([#9365](https://github.com/traefik/traefik/pull/9365) by [ldez](https://github.com/ldez)) **Documentation:** -- Prepare release v2.9.0 ([#9409](https://github.com/traefik/traefik/pull/9409) by [tomMoulard](https://github.com/tomMoulard)) - **[metrics]** Rework metrics overview page ([#9366](https://github.com/traefik/traefik/pull/9366) by [ddtmachado](https://github.com/ddtmachado)) -- Prepare release v2.9.0-rc5 ([#9402](https://github.com/traefik/traefik/pull/9402) by [ldez](https://github.com/ldez)) -- Prepare release v2.9.0-rc4 ([#9372](https://github.com/traefik/traefik/pull/9372) by [kevinpollet](https://github.com/kevinpollet)) -- Prepare release v2.9.0-rc3 ([#9344](https://github.com/traefik/traefik/pull/9344) by [kevinpollet](https://github.com/kevinpollet)) -- Prepare release v2.9.0-rc2 ([6c2c561](https://github.com/traefik/traefik/commit/6c2c561d8f935d76ccd07d28e1455c7768adc153) by [ldez](https://github.com/ldez)) -- Prepare release v2.9.0-rc1 ([#9334](https://github.com/traefik/traefik/pull/9334) by [rtribotte](https://github.com/rtribotte)) **Misc:** - Merge current v2.8 into v2.9 ([#9400](https://github.com/traefik/traefik/pull/9400) by [ldez](https://github.com/ldez)) 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/README.md b/README.md index 544eddb92..7d0faa8ce 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), [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. --- @@ -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 @@ -68,8 +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/) -- [Rancher](https://doc.traefik.io/traefik/providers/rancher/) (Metadata) - [File](https://doc.traefik.io/traefik/providers/file/) ## Quickstart diff --git a/build.Dockerfile b/build.Dockerfile index cf4ab8608..6d4ba8625 100644 --- a/build.Dockerfile +++ b/build.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19-alpine +FROM golang:1.20-alpine RUN apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ && update-ca-certificates \ diff --git a/cmd/configuration.go b/cmd/configuration.go index 3e4f38f92..d65bdf04d 100644 --- a/cmd/configuration.go +++ b/cmd/configuration.go @@ -4,7 +4,7 @@ import ( "time" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/static" ) // TraefikCmdConfiguration wraps the static configuration and extra parameters. @@ -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/healthcheck/healthcheck.go b/cmd/healthcheck/healthcheck.go index fbeaee566..a3b720eb6 100644 --- a/cmd/healthcheck/healthcheck.go +++ b/cmd/healthcheck/healthcheck.go @@ -8,7 +8,7 @@ import ( "time" "github.com/traefik/paerser/cli" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/static" ) // NewCmd builds a new HealthCheck command. diff --git a/cmd/internal/gen/main.go b/cmd/internal/gen/main.go index 8e9c3735a..f5fd5bb35 100644 --- a/cmd/internal/gen/main.go +++ b/cmd/internal/gen/main.go @@ -11,7 +11,7 @@ import ( "strings" ) -const rootPkg = "github.com/traefik/traefik/v2/pkg/config/dynamic" +const rootPkg = "github.com/traefik/traefik/v3/pkg/config/dynamic" const ( destModuleName = "github.com/traefik/genconf" @@ -57,8 +57,8 @@ func run(dest string) error { } centrifuge.IncludedImports = []string{ - "github.com/traefik/traefik/v2/pkg/tls", - "github.com/traefik/traefik/v2/pkg/types", + "github.com/traefik/traefik/v3/pkg/tls", + "github.com/traefik/traefik/v3/pkg/types", } centrifuge.ExcludedTypes = []string{ @@ -71,8 +71,8 @@ func run(dest string) error { } centrifuge.ExcludedFiles = []string{ - "github.com/traefik/traefik/v2/pkg/types/logs.go", - "github.com/traefik/traefik/v2/pkg/types/metrics.go", + "github.com/traefik/traefik/v3/pkg/types/logs.go", + "github.com/traefik/traefik/v3/pkg/types/metrics.go", } centrifuge.TypeCleaner = cleanType @@ -87,11 +87,11 @@ func run(dest string) error { } func cleanType(typ types.Type, base string) string { - if typ.String() == "github.com/traefik/traefik/v2/pkg/tls.FileOrContent" { + if typ.String() == "github.com/traefik/traefik/v3/pkg/tls.FileOrContent" { return "string" } - if typ.String() == "[]github.com/traefik/traefik/v2/pkg/tls.FileOrContent" { + if typ.String() == "[]github.com/traefik/traefik/v3/pkg/tls.FileOrContent" { return "[]string" } @@ -103,8 +103,8 @@ func cleanType(typ types.Type, base string) string { return strings.ReplaceAll(typ.String(), base+".", "") } - if strings.Contains(typ.String(), "github.com/traefik/traefik/v2/pkg/") { - return strings.ReplaceAll(typ.String(), "github.com/traefik/traefik/v2/pkg/", "") + if strings.Contains(typ.String(), "github.com/traefik/traefik/v3/pkg/") { + return strings.ReplaceAll(typ.String(), "github.com/traefik/traefik/v3/pkg/", "") } return typ.String() @@ -114,9 +114,9 @@ func cleanPackage(src string) string { switch src { case "github.com/traefik/paerser/types": return "" - case "github.com/traefik/traefik/v2/pkg/tls": + case "github.com/traefik/traefik/v3/pkg/tls": return path.Join(destModuleName, destPkg, "tls") - case "github.com/traefik/traefik/v2/pkg/types": + case "github.com/traefik/traefik/v3/pkg/types": return path.Join(destModuleName, destPkg, "types") default: return src diff --git a/cmd/traefik/logger.go b/cmd/traefik/logger.go index 27f319170..4a3a10893 100644 --- a/cmd/traefik/logger.go +++ b/cmd/traefik/logger.go @@ -11,8 +11,8 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/sirupsen/logrus" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/logs" ) func init() { diff --git a/cmd/traefik/plugins.go b/cmd/traefik/plugins.go index f94535f92..41c9bff60 100644 --- a/cmd/traefik/plugins.go +++ b/cmd/traefik/plugins.go @@ -3,8 +3,8 @@ package main import ( "fmt" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/plugins" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/plugins" ) const outputDir = "./plugins-storage/" diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 9d0256795..bd3daf14f 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -21,31 +21,32 @@ import ( "github.com/sirupsen/logrus" "github.com/spiffe/go-spiffe/v2/workloadapi" "github.com/traefik/paerser/cli" - "github.com/traefik/traefik/v2/cmd" - "github.com/traefik/traefik/v2/cmd/healthcheck" - cmdVersion "github.com/traefik/traefik/v2/cmd/version" - tcli "github.com/traefik/traefik/v2/pkg/cli" - "github.com/traefik/traefik/v2/pkg/collector" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - "github.com/traefik/traefik/v2/pkg/provider/acme" - "github.com/traefik/traefik/v2/pkg/provider/aggregator" - "github.com/traefik/traefik/v2/pkg/provider/hub" - "github.com/traefik/traefik/v2/pkg/provider/tailscale" - "github.com/traefik/traefik/v2/pkg/provider/traefik" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/server" - "github.com/traefik/traefik/v2/pkg/server/middleware" - "github.com/traefik/traefik/v2/pkg/server/service" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/tracing" - "github.com/traefik/traefik/v2/pkg/tracing/jaeger" - "github.com/traefik/traefik/v2/pkg/types" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/cmd" + "github.com/traefik/traefik/v3/cmd/healthcheck" + cmdVersion "github.com/traefik/traefik/v3/cmd/version" + tcli "github.com/traefik/traefik/v3/pkg/cli" + "github.com/traefik/traefik/v3/pkg/collector" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" + "github.com/traefik/traefik/v3/pkg/provider/acme" + "github.com/traefik/traefik/v3/pkg/provider/aggregator" + "github.com/traefik/traefik/v3/pkg/provider/hub" + "github.com/traefik/traefik/v3/pkg/provider/tailscale" + "github.com/traefik/traefik/v3/pkg/provider/traefik" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/server" + "github.com/traefik/traefik/v3/pkg/server/middleware" + "github.com/traefik/traefik/v3/pkg/server/service" + "github.com/traefik/traefik/v3/pkg/tcp" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/tracing/jaeger" + "github.com/traefik/traefik/v3/pkg/types" + "github.com/traefik/traefik/v3/pkg/version" ) func main() { @@ -192,9 +193,14 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err tsProviders := initTailscaleProviders(staticConfiguration, &providerAggregator) + // Metrics + + metricRegistries := registerMetricClients(staticConfiguration.Metrics) + metricsRegistry := metrics.NewMultiRegistry(metricRegistries) + // Entrypoints - serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints, staticConfiguration.HostResolver) + serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints, staticConfiguration.HostResolver, metricsRegistry) if err != nil { return nil, err } @@ -242,11 +248,6 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err } } - // Metrics - - metricRegistries := registerMetricClients(staticConfiguration.Metrics) - metricsRegistry := metrics.NewMultiRegistry(metricRegistries) - // Service manager factory var spiffeX509Source *workloadapi.X509Source @@ -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 @@ -295,7 +297,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err tlsManager.UpdateConfigs(ctx, conf.TLS.Stores, conf.TLS.Options, conf.TLS.Certificates) gauge := metricsRegistry.TLSCertsNotAfterTimestampGauge() - for _, certificate := range tlsManager.GetCertificates() { + for _, certificate := range tlsManager.GetServerCertificates() { appendCertMetric(gauge, certificate) } }) @@ -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 @@ -520,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/cmd/traefik/traefik_test.go b/cmd/traefik/traefik_test.go index c1d677058..6dacb7507 100644 --- a/cmd/traefik/traefik_test.go +++ b/cmd/traefik/traefik_test.go @@ -9,7 +9,7 @@ import ( "github.com/go-kit/kit/metrics" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/static" ) // FooCert is a PEM-encoded TLS cert. diff --git a/cmd/version/version.go b/cmd/version/version.go index 03557ff58..172dfb338 100644 --- a/cmd/version/version.go +++ b/cmd/version/version.go @@ -8,7 +8,7 @@ import ( "text/template" "github.com/traefik/paerser/cli" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/version" ) var versionTemplate = `Version: {{.Version}} diff --git a/contrib/grafana/traefik-kubernetes.json b/contrib/grafana/traefik-kubernetes.json index 75cf074fb..4e463b502 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": { @@ -470,7 +472,7 @@ } ] }, - "unit": "ms" + "unit": "s" }, "overrides": [] }, @@ -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, @@ -1444,7 +1545,8 @@ "hide": 0, "includeAll": false, "multi": false, - "name": "datasource", + "name": "DS_PROMETHEUS", + "label": "datasource", "options": [], "query": "prometheus", "refresh": 1, @@ -1504,8 +1606,8 @@ }, "timepicker": {}, "timezone": "", - "title": "Traefik Official Standalone Dashboard", + "title": "Traefik Official Kubernetes Dashboard", "uid": "n5bu_kv4k", - "version": 3, + "version": 6, "weekStart": "" } diff --git a/contrib/grafana/traefik.json b/contrib/grafana/traefik.json index 75cf074fb..5c3d140ee 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": { @@ -470,7 +472,7 @@ } ] }, - "unit": "ms" + "unit": "s" }, "overrides": [] }, @@ -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": { @@ -1444,7 +1537,8 @@ "hide": 0, "includeAll": false, "multi": false, - "name": "datasource", + "name": "DS_PROMETHEUS", + "label": "datasource", "options": [], "query": "prometheus", "refresh": 1, @@ -1491,7 +1585,7 @@ "refId": "StandardVariableQuery" }, "refresh": 2, - "regex": "/([^-]+-[^-]+).*/", + "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" @@ -1505,7 +1599,7 @@ "timepicker": {}, "timezone": "", "title": "Traefik Official Standalone Dashboard", - "uid": "n5bu_kv4k", - "version": 3, + "uid": "n5bu_kv45", + "version": 6, "weekStart": "" } 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/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. diff --git a/docs/content/deprecation/features.md b/docs/content/deprecation/features.md index 6e8c1f740..fa41c56b0 100644 --- a/docs/content/deprecation/features.md +++ b/docs/content/deprecation/features.md @@ -2,4 +2,12 @@ This page is maintained and updated periodically to reflect our roadmap and any decisions around feature deprecation. -There is no feature deprecation in Traefik v3 for now. +| Feature | Deprecated | End of Support | Removal | +|-----------------------------------------------------------------------------------------------------|------------|----------------|---------| +| [Kubernetes CRDs API Version `traefik.io/v1alpha1`](#kubernetes-crds-api-version-traefikiov1alpha1) | N/A | N/A | 3.0 | + +## Impact + +### Kubernetes CRDs API Version `traefik.io/v1alpha1` + +The newly introduced Kubernetes CRD API Version `traefik.io/v1alpha1` will subsequently be removed in Traefik v3. The following version will be `traefik.io/v1`. diff --git a/docs/content/getting-started/faq.md b/docs/content/getting-started/faq.md index 01b33f639..1ae3def8e 100644 --- a/docs/content/getting-started/faq.md +++ b/docs/content/getting-started/faq.md @@ -181,3 +181,23 @@ and the message should help in figuring out the mistake(s) in the configuration, When using the file provider, one easy way to check if the dynamic configuration is well-formed is to validate it with the [JSON Schema of the dynamic configuration](https://json.schemastore.org/traefik-v2-file-provider.json). + +## Why does Let's Encrypt wildcard certificate renewal/generation with DNS challenge fail? + +If you're trying to renew wildcard certificates, with DNS challenge, +and you're getting errors such as: + +```txt +msg="Error renewing certificate from LE: {example.com [*.example.com]}" +providerName=letsencrypt.acme error="error: one or more domains had a problem: +[example.com] acme: error presenting token: gandiv5: unexpected authZone example.com. for fqdn example.com." +``` + +then it could be due to `CNAME` support. + +In which case, you should make sure your infrastructure is properly set up for a +`DNS` challenge that does not rely on `CNAME`, and you should try disabling `CNAME` support with: + +```bash +LEGO_DISABLE_CNAME_SUPPORT=true +``` diff --git a/docs/content/getting-started/install-traefik.md b/docs/content/getting-started/install-traefik.md index 9e4926fc0..a0a5df6ea 100644 --- a/docs/content/getting-started/install-traefik.md +++ b/docs/content/getting-started/install-traefik.md @@ -16,8 +16,8 @@ You can install Traefik with the following flavors: Choose one of the [official Docker images](https://hub.docker.com/_/traefik) and run it with one sample configuration file: -* [YAML](https://raw.githubusercontent.com/traefik/traefik/v2.9/traefik.sample.yml) -* [TOML](https://raw.githubusercontent.com/traefik/traefik/v2.9/traefik.sample.toml) +* [YAML](https://raw.githubusercontent.com/traefik/traefik/v3.0/traefik.sample.yml) +* [TOML](https://raw.githubusercontent.com/traefik/traefik/v3.0/traefik.sample.toml) ```bash docker run -d -p 8080:8080 -p 80:80 \ @@ -121,7 +121,7 @@ by defining and applying an IngressRoute CRD (`kubectl apply -f dashboard.yaml`) ```yaml # dashboard.yaml -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: dashboard diff --git a/docs/content/getting-started/quick-start.md b/docs/content/getting-started/quick-start.md index e1883040d..e4007910d 100644 --- a/docs/content/getting-started/quick-start.md +++ b/docs/content/getting-started/quick-start.md @@ -1,11 +1,11 @@ --- title: "Traefik Getting Started Quickly" -description: "Looking to get started with Traefik Proxy quickly? Read the technical documentation to learn a simple use case that leverages Docker." +description: "Looking to get started with Traefik Proxy quickly? Read the technical documentation to see a basic use case that leverages Docker." --- # Quick Start -A Simple Use Case Using Docker +A Basic Use Case Using Docker {: .subtitle } ![quickstart-diagram](../assets/img/quickstart-diagram.png) @@ -19,9 +19,9 @@ version: '3' services: reverse-proxy: - # The official v2 Traefik docker image + # The official v3 Traefik Docker image image: traefik:v3.0 - # Enables the web UI and tells Traefik to listen to docker + # Enables the web UI and tells Traefik to listen to Docker command: --api.insecure=true --providers.docker ports: # The HTTP port @@ -63,7 +63,7 @@ services: - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" ``` -The above defines `whoami`: a simple web service that outputs information about the machine it is deployed on (its IP address, host, and so on). +The above defines [`whoami`](https://github.com/traefik/whoami "Link to whoami app on GitHub"), a web service that outputs information about the machine it is deployed on (its IP address, host, etc.). Start the `whoami` service with the following command: @@ -71,9 +71,9 @@ Start the `whoami` service with the following command: docker-compose up -d whoami ``` -Go back to your browser (`http://localhost:8080/api/rawdata`) and see that Traefik has automatically detected the new container and updated its own configuration. +Browse `http://localhost:8080/api/rawdata` and see that Traefik has automatically detected the new container and updated its own configuration. -When Traefik detects new services, it creates the corresponding routes so you can call them ... _let's see!_ (Here, we're using curl) +When Traefik detects new services, it creates the corresponding routes, so you can call them ... _let's see!_ (Here, we're using curl) ```shell curl -H Host:whoami.docker.localhost http://127.0.0.1 @@ -95,7 +95,7 @@ Run more instances of your `whoami` service with the following command: docker-compose up -d --scale whoami=2 ``` -Go back to your browser (`http://localhost:8080/api/rawdata`) and see that Traefik has automatically detected the new instance of the container. +Browse to `http://localhost:8080/api/rawdata` and see that Traefik has automatically detected the new instance of the container. Finally, see that Traefik load-balances between the two instances of your service by running the following command twice: @@ -119,6 +119,6 @@ IP: 172.27.0.4 !!! question "Where to Go Next?" - Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it is time to dive into [the documentation](/) and let Traefik work for you! + Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it is time to dive into [the documentation](/ "Link to the docs landing page") and let Traefik work for you! {!traefik-for-business-applications.md!} diff --git a/docs/content/https/acme.md b/docs/content/https/acme.md index d3fc20997..640e0098a 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. @@ -279,8 +283,19 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni # ... ``` - !!! important - A `provider` is mandatory. +!!! warning "`CNAME` support" + + `CNAME` are supported (and sometimes even [encouraged](https://letsencrypt.org/2019/10/09/onboarding-your-customers-with-lets-encrypt-and-acme.html#the-advantages-of-a-cname)), + but there are a few cases where they can be [problematic](../../getting-started/faq/#why-does-lets-encrypt-wildcard-certificate-renewalgeneration-with-dns-challenge-fail). + + If needed, `CNAME` support can be disabled with the following environment variable: + + ```bash + LEGO_DISABLE_CNAME_SUPPORT=true + ``` + +!!! important + A `provider` is mandatory. #### `providers` @@ -315,6 +330,7 @@ For complete details, refer to your provider's _Additional configuration_ link. | [deSEC](https://desec.io) | `desec` | `DESEC_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/desec) | | [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean) | | [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy) | +| [dnsHome.de](https://www.dnshome.de) | `dnsHomede` | `DNSHOMEDE_CREDENTIALS` | [Additional configuration](https://go-acme.github.io/lego/dns/dnshomede) | | [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple) | | [DNSPod](https://www.dnspod.com/) | `dnspod` | `DNSPOD_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dnspod) | | [Domain Offensive (do.de)](https://www.do.de/) | `dode` | `DODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/dode) | @@ -350,6 +366,7 @@ For complete details, refer to your provider's _Additional configuration_ link. | [ionos](https://ionos.com/) | `ionos` | `IONOS_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ionos) | | [iwantmyname](https://iwantmyname.com) | `iwantmyname` | `IWANTMYNAME_USERNAME` , `IWANTMYNAME_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/iwantmyname) | | [Joker.com](https://joker.com) | `joker` | `JOKER_API_MODE` with `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/joker) | +| [Liara](https://liara.ir) | `liara` | `LIARA_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/liara) | | [Lightsail](https://aws.amazon.com/lightsail/) | `lightsail` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/lightsail) | | [Linode v4](https://www.linode.com) | `linode` | `LINODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/linode) | | [Liquid Web](https://www.liquidweb.com/) | `liquidweb` | `LIQUID_WEB_PASSWORD`, `LIQUID_WEB_USERNAME`, `LIQUID_WEB_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/liquidweb) | @@ -388,6 +405,7 @@ For complete details, refer to your provider's _Additional configuration_ link. | [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) | | [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) | | [UKFast SafeDNS](https://www.ans.co.uk/cloud-and-infrastructure/dedicated-servers/dns-management/) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) | +| [Ultradns](https://neustarsecurityservices.com/dns-services) | `ultradns` | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns) | | [Variomedia](https://www.variomedia.de/) | `variomedia` | `VARIOMEDIA_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/variomedia) | | [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) | | [Vercel](https://vercel.com) | `vercel` | `VERCEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vercel) | @@ -396,6 +414,7 @@ For complete details, refer to your provider's _Additional configuration_ link. | [VK Cloud](https://mcs.mail.ru/) | `vkcloud` | `VK_CLOUD_PASSWORD`, `VK_CLOUD_PROJECT_ID`, `VK_CLOUD_USERNAME` | [Additional configuration](https://go-acme.github.io/lego/dns/vkcloud) | | [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vscale) | | [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/vultr) | +| [Websupport](https://websupport.sk) | `websupport` | `WEBSUPPORT_API_KEY`, `WEBSUPPORT_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/websupport) | | [WEDOS](https://www.wedos.com) | `wedos` | `WEDOS_USERNAME`, `WEDOS_WAPI_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/wedos) | | [Yandex Cloud](https://cloud.yandex.com/en/) | `yandexcloud` | `YANDEX_CLOUD_FOLDER_ID`, `YANDEX_CLOUD_IAM_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/yandexcloud) | | [Yandex](https://yandex.com) | `yandex` | `YANDEX_PDD_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/yandex) | diff --git a/docs/content/https/include-acme-multiple-domains-example.md b/docs/content/https/include-acme-multiple-domains-example.md index 8107eb24f..e60d08f1c 100644 --- a/docs/content/https/include-acme-multiple-domains-example.md +++ b/docs/content/https/include-acme-multiple-domains-example.md @@ -22,7 +22,7 @@ deploy: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: blogtls @@ -43,27 +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="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..1052228c3 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 @@ -18,7 +18,7 @@ deploy: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: blogtls @@ -35,23 +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="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..f6fad9af9 100644 --- a/docs/content/https/include-acme-single-domain-example.md +++ b/docs/content/https/include-acme-single-domain-example.md @@ -18,7 +18,7 @@ deploy: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: blogtls @@ -35,23 +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="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/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/https/tailscale.md b/docs/content/https/tailscale.md index abc742b83..6cb2f3e6c 100644 --- a/docs/content/https/tailscale.md +++ b/docs/content/https/tailscale.md @@ -103,7 +103,7 @@ A certificate resolver requests certificates for a set of domain names inferred ``` ```yaml tab="Kubernetes" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: blogtls @@ -120,20 +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="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: @@ -173,7 +159,7 @@ A certificate resolver requests certificates for a set of domain names inferred ``` ```yaml tab="Kubernetes" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: blogtls @@ -192,22 +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="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/https/tls.md b/docs/content/https/tls.md index dd756dd44..075c562c5 100644 --- a/docs/content/https/tls.md +++ b/docs/content/https/tls.md @@ -134,7 +134,7 @@ tls: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSStore metadata: name: default @@ -195,7 +195,7 @@ tls: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSStore metadata: name: default @@ -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. @@ -277,7 +269,7 @@ tls: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default @@ -287,7 +279,7 @@ spec: minVersion: VersionTLS12 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: mintls13 @@ -328,7 +320,7 @@ tls: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default @@ -338,7 +330,7 @@ spec: maxVersion: VersionTLS13 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: maxtls12 @@ -373,7 +365,7 @@ tls: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default @@ -418,7 +410,7 @@ tls: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default @@ -454,7 +446,7 @@ tls: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default @@ -493,7 +485,7 @@ tls: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default @@ -545,7 +537,7 @@ tls: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default 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 9f909aa8f..e6f458f31 100644 --- a/docs/content/middlewares/http/addprefix.md +++ b/docs/content/middlewares/http/addprefix.md @@ -22,7 +22,7 @@ labels: ```yaml tab="Kubernetes" # Prefixing with /foo -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: add-foo @@ -36,18 +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="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..d5118f855 100644 --- a/docs/content/middlewares/http/basicauth.md +++ b/docs/content/middlewares/http/basicauth.md @@ -28,7 +28,7 @@ labels: ```yaml tab="Kubernetes" # Declaring the user list -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -41,18 +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="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: @@ -114,7 +102,7 @@ labels: ```yaml tab="Kubernetes" # Declaring the user list -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -157,18 +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="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: @@ -207,7 +183,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -232,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -274,7 +239,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -287,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -322,7 +276,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: my-auth @@ -336,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: @@ -367,7 +315,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -380,17 +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="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..85c21a62b 100644 --- a/docs/content/middlewares/http/buffering.md +++ b/docs/content/middlewares/http/buffering.md @@ -26,7 +26,7 @@ labels: ```yaml tab="Kubernetes" # Sets the maximum request body to 2MB -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: limit @@ -40,18 +40,6 @@ spec: - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" -} -``` - -```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: @@ -84,7 +72,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: limit @@ -97,17 +85,6 @@ spec: - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" -} -``` - -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -134,7 +111,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: limit @@ -147,17 +124,6 @@ spec: - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes": "2000000" -} -``` - -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -186,7 +152,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: limit @@ -199,17 +165,6 @@ spec: - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes": "2000000" -} -``` - -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -236,7 +191,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: limit @@ -249,17 +204,6 @@ spec: - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes": "2000000" -} -``` - -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -288,7 +232,7 @@ You can have the Buffering middleware replay the request using `retryExpression` ``` ```yaml tab="Kubernetes" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: limit @@ -301,17 +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="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..de0074426 100644 --- a/docs/content/middlewares/http/chain.md +++ b/docs/content/middlewares/http/chain.md @@ -30,7 +30,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test @@ -47,7 +47,7 @@ spec: middlewares: - name: secured --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: secured @@ -58,7 +58,7 @@ spec: - name: known-ips - name: auth-users --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: auth-users @@ -67,7 +67,7 @@ spec: users: - test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/ --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: https-only @@ -75,7 +75,7 @@ spec: redirectScheme: scheme: https --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: known-ips @@ -97,31 +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="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..6edaedbe9 100644 --- a/docs/content/middlewares/http/circuitbreaker.md +++ b/docs/content/middlewares/http/circuitbreaker.md @@ -38,7 +38,7 @@ labels: ```yaml tab="Kubernetes" # Latency Check -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: latency-check @@ -52,18 +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="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..4618fb245 100644 --- a/docs/content/middlewares/http/compress.md +++ b/docs/content/middlewares/http/compress.md @@ -23,7 +23,7 @@ labels: ```yaml tab="Kubernetes" # Enable compression -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-compress @@ -36,18 +36,6 @@ spec: - "traefik.http.middlewares.test-compress.compress=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-compress.compress": "true" -} -``` - -```yaml tab="Rancher" -# Enable compression -labels: - - "traefik.http.middlewares.test-compress.compress=true" -``` - ```yaml tab="File (YAML)" # Enable compression http: @@ -100,7 +88,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-compress @@ -114,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -154,7 +131,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-compress @@ -167,17 +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="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..c4d78a359 100644 --- a/docs/content/middlewares/http/contenttype.md +++ b/docs/content/middlewares/http/contenttype.md @@ -26,7 +26,7 @@ labels: ```yaml tab="Kubernetes" # Enable auto-detection -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: autodetect @@ -39,18 +39,6 @@ spec: - "traefik.http.middlewares.autodetect.contenttype=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.autodetect.contenttype": "true" -} -``` - -```yaml tab="Rancher" -# Enable auto-detection -labels: - - "traefik.http.middlewares.autodetect.contenttype=true" -``` - ```yaml tab="File (YAML)" # Enable auto-detection http: @@ -63,4 +51,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..dcd9ca284 100644 --- a/docs/content/middlewares/http/digestauth.md +++ b/docs/content/middlewares/http/digestauth.md @@ -22,7 +22,7 @@ labels: ```yaml tab="Kubernetes" # Declaring the user list -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -36,18 +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="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: @@ -90,7 +78,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -114,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -161,7 +138,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -186,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -228,7 +194,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -241,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -276,7 +231,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: my-auth @@ -290,17 +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="Rancher" -labels: - - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -326,7 +270,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -339,17 +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="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..0f8b1798a 100644 --- a/docs/content/middlewares/http/errorpages.md +++ b/docs/content/middlewares/http/errorpages.md @@ -27,7 +27,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-errors @@ -48,22 +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="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..4738747b2 100644 --- a/docs/content/middlewares/http/forwardauth.md +++ b/docs/content/middlewares/http/forwardauth.md @@ -24,7 +24,7 @@ labels: ```yaml tab="Kubernetes" # Forward authentication to example.com -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -38,18 +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="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: @@ -90,7 +78,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -103,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -138,7 +115,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -152,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -190,7 +156,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -206,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -248,7 +203,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -262,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -307,7 +251,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -323,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -371,7 +304,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -397,17 +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="Rancher" -labels: - - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -440,7 +362,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -467,19 +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="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: @@ -518,7 +427,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -545,19 +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="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: @@ -594,7 +490,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-auth @@ -609,17 +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="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..8b14214a2 100644 --- a/docs/content/middlewares/http/grpcweb.md +++ b/docs/content/middlewares/http/grpcweb.md @@ -23,7 +23,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-grpcweb @@ -37,17 +37,6 @@ spec: - "traefik.http.middlewares.test-grpcweb.grpcWeb.allowOrigins=*" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-grpcweb.grpcweb.alloworigins": "*" -} -``` - -```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..de39548cb 100644 --- a/docs/content/middlewares/http/headers.md +++ b/docs/content/middlewares/http/headers.md @@ -27,7 +27,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-header @@ -44,19 +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="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: @@ -90,7 +77,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-header @@ -109,21 +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="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: @@ -158,7 +130,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-header @@ -173,19 +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="Rancher" -labels: - - "traefik.http.middlewares.testheader.headers.framedeny=true" - - "traefik.http.middlewares.testheader.headers.browserxssfilter=true" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -218,7 +177,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-header @@ -242,23 +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="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..b7eefd84d 100644 --- a/docs/content/middlewares/http/inflightreq.md +++ b/docs/content/middlewares/http/inflightreq.md @@ -20,7 +20,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-inflightreq @@ -34,18 +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="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: @@ -75,7 +63,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-inflightreq @@ -89,18 +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="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: @@ -127,6 +103,8 @@ If none are set, the default is to use the `requestHost`. The `ipStrategy` option defines two parameters that configures how Traefik determines the client IP: `depth`, and `excludedIPs`. +!!! important "As a middleware, InFlightReq happens before the actual proxying to the backend takes place. In addition, the previous network hop only gets appended to `X-Forwarded-For` during the last stages of proxying, i.e. after it has already passed through the middleware. Therefore, during InFlightReq, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be used and/or relied upon." + ##### `ipStrategy.depth` The `depth` option tells Traefik to use the `X-Forwarded-For` header and select the IP located at the `depth` position (starting from the right). @@ -150,7 +128,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-inflightreq @@ -165,17 +143,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="Rancher" -labels: - - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -215,7 +182,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-inflightreq @@ -232,17 +199,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="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: @@ -272,7 +228,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-inflightreq @@ -286,17 +242,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="Rancher" -labels: - - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -323,7 +268,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-inflightreq @@ -337,17 +282,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="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..8892b4fcd 100644 --- a/docs/content/middlewares/http/ipallowlist.md +++ b/docs/content/middlewares/http/ipallowlist.md @@ -19,7 +19,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ipallowlist @@ -35,18 +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="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: @@ -73,7 +61,10 @@ The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using ### `ipStrategy` -The `ipStrategy` option defines two parameters that set how Traefik determines the client IP: `depth`, and `excludedIPs`. +The `ipStrategy` option defines two parameters that set how Traefik determines the client IP: `depth`, and `excludedIPs`. +If no strategy is set, the default behavior is to match `sourceRange` against the Remote address found in the request. + +!!! important "As a middleware, whitelisting happens before the actual proxying to the backend takes place. In addition, the previous network hop only gets appended to `X-Forwarded-For` during the last stages of proxying, i.e. after it has already passed through whitelisting. Therefore, during whitelisting, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be matched against `sourceRange`." #### `ipStrategy.depth` @@ -101,7 +92,7 @@ labels: ```yaml tab="Kubernetes" # Allowlisting Based on `X-Forwarded-For` with `depth=2` -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ipallowlist @@ -120,20 +111,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="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: @@ -180,7 +157,7 @@ labels: ```yaml tab="Kubernetes" # Exclude from `X-Forwarded-For` -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ipallowlist @@ -197,18 +174,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="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..500e5d38d 100644 --- a/docs/content/middlewares/http/overview.md +++ b/docs/content/middlewares/http/overview.md @@ -29,9 +29,9 @@ whoami: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: middlewares.traefik.containo.us + name: middlewares.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: Middleware @@ -40,7 +40,7 @@ spec: scope: Namespaced --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: stripprefix @@ -50,7 +50,7 @@ spec: - /stripit --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroute @@ -69,22 +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" -} -``` - -```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..92c5cc83b 100644 --- a/docs/content/middlewares/http/passtlsclientcert.md +++ b/docs/content/middlewares/http/passtlsclientcert.md @@ -25,7 +25,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-passtlsclientcert @@ -39,18 +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="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: @@ -95,7 +83,7 @@ http: ```yaml tab="Kubernetes" # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-passtlsclientcert @@ -146,52 +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="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..9ae94a31a 100644 --- a/docs/content/middlewares/http/ratelimit.md +++ b/docs/content/middlewares/http/ratelimit.md @@ -10,6 +10,8 @@ To Control the Number of Requests Going to a Service The RateLimit middleware ensures that services will receive a _fair_ amount of requests, and allows one to define what fair is. +It is based on a [token bucket](https://en.wikipedia.org/wiki/Token_bucket) implementation. In this analogy, the [average](#average) parameter (defined below) is the rate at which the bucket refills, and the [burst](#burst) is the size (volume) of the bucket. + ## Configuration Example ```yaml tab="Docker" @@ -23,7 +25,7 @@ labels: ```yaml tab="Kubernetes" # Here, an average of 100 requests per second is allowed. # In addition, a burst of 50 requests is allowed. -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ratelimit @@ -40,21 +42,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="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. @@ -94,7 +81,7 @@ labels: ```yaml tab="Kubernetes" # 100 reqs/s -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ratelimit @@ -108,17 +95,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.average": "100", -} -``` - -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" -``` - ```yaml tab="File (YAML)" # 100 reqs/s http: @@ -154,7 +130,7 @@ labels: ```yaml tab="Kubernetes" # 6 reqs/minute -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ratelimit @@ -170,20 +146,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="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: @@ -214,7 +176,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ratelimit @@ -227,17 +189,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.burst": "100", -} -``` - -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -262,6 +213,8 @@ If none are set, the default is to use the request's remote address field (as an The `ipStrategy` option defines two parameters that configures how Traefik determines the client IP: `depth`, and `excludedIPs`. +!!! important "As a middleware, rate-limiting happens before the actual proxying to the backend takes place. In addition, the previous network hop only gets appended to `X-Forwarded-For` during the last stages of proxying, i.e. after it has already passed through rate-limiting. Therefore, during rate-limiting, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be found and/or relied upon." + ##### `ipStrategy.depth` The `depth` option tells Traefik to use the `X-Forwarded-For` header and select the IP located at the `depth` position (starting from the right). @@ -285,7 +238,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ratelimit @@ -300,17 +253,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="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -377,7 +319,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ratelimit @@ -394,17 +336,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="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: @@ -434,7 +365,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ratelimit @@ -448,17 +379,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="Rancher" -labels: - - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -485,7 +405,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-ratelimit @@ -499,17 +419,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="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..d2e146673 100644 --- a/docs/content/middlewares/http/redirectregex.md +++ b/docs/content/middlewares/http/redirectregex.md @@ -26,7 +26,7 @@ labels: ```yaml tab="Kubernetes" # Redirect with domain replacement -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-redirectregex @@ -43,21 +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="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..e32fecfbc 100644 --- a/docs/content/middlewares/http/redirectscheme.md +++ b/docs/content/middlewares/http/redirectscheme.md @@ -34,7 +34,7 @@ labels: ```yaml tab="Kubernetes" # Redirect to https -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-redirectscheme @@ -51,20 +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="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: @@ -98,7 +84,7 @@ labels: ```yaml tab="Kubernetes" # Redirect to https -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-redirectscheme @@ -115,20 +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="Rancher" -# Redirect to https -labels: - # ... - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -159,7 +131,7 @@ labels: ```yaml tab="Kubernetes" # Redirect to https -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-redirectscheme @@ -174,18 +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="Rancher" -# Redirect to https -labels: - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -215,7 +175,7 @@ labels: ```yaml tab="Kubernetes" # Redirect to https -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-redirectscheme @@ -232,20 +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="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..2c44e9f75 100644 --- a/docs/content/middlewares/http/replacepath.md +++ b/docs/content/middlewares/http/replacepath.md @@ -24,7 +24,7 @@ labels: ```yaml tab="Kubernetes" # Replace the path with /foo -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-replacepath @@ -38,18 +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="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..562d3d2f3 100644 --- a/docs/content/middlewares/http/replacepathregex.md +++ b/docs/content/middlewares/http/replacepathregex.md @@ -25,7 +25,7 @@ labels: ```yaml tab="Kubernetes" # Replace path with regex -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-replacepathregex @@ -41,20 +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="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..9706ec69f 100644 --- a/docs/content/middlewares/http/retry.md +++ b/docs/content/middlewares/http/retry.md @@ -27,7 +27,7 @@ labels: ```yaml tab="Kubernetes" # Retry 4 times with exponential backoff -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-retry @@ -43,20 +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="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..4d0d7d567 100644 --- a/docs/content/middlewares/http/stripprefix.md +++ b/docs/content/middlewares/http/stripprefix.md @@ -24,7 +24,7 @@ labels: ```yaml tab="Kubernetes" # Strip prefix /foobar and /fiibar -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-stripprefix @@ -40,18 +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="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..ba61de6fc 100644 --- a/docs/content/middlewares/http/stripprefixregex.md +++ b/docs/content/middlewares/http/stripprefixregex.md @@ -18,7 +18,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-stripprefixregex @@ -32,17 +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="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..c01423123 100644 --- a/docs/content/middlewares/overview.md +++ b/docs/content/middlewares/overview.md @@ -37,7 +37,7 @@ whoami: ```yaml tab="Kubernetes IngressRoute" --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: stripprefix @@ -47,7 +47,7 @@ spec: - /stripit --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroute @@ -66,22 +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="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..f9993a7f8 100644 --- a/docs/content/middlewares/tcp/inflightconn.md +++ b/docs/content/middlewares/tcp/inflightconn.md @@ -13,7 +13,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: test-inflightconn @@ -27,18 +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="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..8aa5be01c 100644 --- a/docs/content/middlewares/tcp/ipallowlist.md +++ b/docs/content/middlewares/tcp/ipallowlist.md @@ -19,7 +19,7 @@ labels: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: test-ipallowlist @@ -35,18 +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" -} -``` - -```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..ec28af85d 100644 --- a/docs/content/middlewares/tcp/overview.md +++ b/docs/content/middlewares/tcp/overview.md @@ -29,9 +29,9 @@ whoami: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: middlewaretcps.traefik.containo.us + name: middlewaretcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: MiddlewareTCP @@ -40,7 +40,7 @@ spec: scope: Namespaced --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: foo-ip-allowlist @@ -51,7 +51,7 @@ spec: - 192.168.1.7 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: ingressroute @@ -70,22 +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" -} -``` - -```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/v1-to-v2.md b/docs/content/migration/v1-to-v2.md index c020a9a85..8d93e48f3 100644 --- a/docs/content/migration/v1-to-v2.md +++ b/docs/content/migration/v1-to-v2.md @@ -110,7 +110,7 @@ Then any router can refer to an instance of the wanted middleware. ```yaml tab="K8s IngressRoute" # The definitions below require the definitions for the Middleware and IngressRoute kinds. # https://doc.traefik.io/traefik/reference/dynamic-configuration/kubernetes-crd/#definitions - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: basicauth @@ -123,7 +123,7 @@ Then any router can refer to an instance of the wanted middleware. - test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar @@ -281,7 +281,7 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o ```yaml tab="K8s IngressRoute" # The definitions below require the definitions for the TLSOption and IngressRoute kinds. # https://doc.traefik.io/traefik/reference/dynamic-configuration/kubernetes-crd/#definitions - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: mytlsoption @@ -297,7 +297,7 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar @@ -443,7 +443,7 @@ To apply a redirection: ``` ```yaml tab="K8s IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: http-redirect-ingressroute @@ -461,7 +461,7 @@ To apply a redirection: - name: https-redirect --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: https-ingressroute @@ -478,7 +478,7 @@ To apply a redirection: tls: {} --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: https-redirect @@ -597,7 +597,7 @@ with the path `/admin` stripped, e.g. to `http://:/`. In this case, yo ```yaml tab="Kubernetes IngressRoute" --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: http-redirect-ingressroute @@ -614,7 +614,7 @@ with the path `/admin` stripped, e.g. to `http://:/`. In this case, yo middlewares: - name: admin-stripprefix --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: admin-stripprefix diff --git a/docs/content/migration/v2-to-v3.md b/docs/content/migration/v2-to-v3.md index 27d38e953..4792467b0 100644 --- a/docs/content/migration/v2-to-v3.md +++ b/docs/content/migration/v2-to-v3.md @@ -26,20 +26,22 @@ 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. +- The `preferServerCipherSuites` option has been removed. ## Matchers In v3, the `Headers` and `HeadersRegexp` matchers have been renamed to `Header` and `HeaderRegexp` respectively. +`PathPrefix` no longer uses regular expressions to match path prefixes. + `QueryRegexp` has been introduced to match query values using a regular expression. `HeaderRegexp`, `HostRegexp`, `PathRegexp`, `QueryRegexp`, and `HostSNIRegexp` matchers now uses the [Go regexp syntax](https://golang.org/pkg/regexp/syntax/). -All matchers now take a single value (except `Headers`, `HeaderRegexp`, `Query`, and `QueryRegexp` which take two) +All matchers now take a single value (except `Header`, `HeaderRegexp`, `Query`, and `QueryRegexp` which take two) and should be explicitly combined using logical operators to mimic previous behavior. `Query` can take a single value to match is the query value that has no value (e.g. `/search?mobile`). @@ -55,3 +57,33 @@ 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) + +## 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. + +## 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/). + +### Kubernetes CRDs API Group `traefik.containo.us` + +In v3 the Kubernetes CRDs API Group `traefik.containo.us` has been removed. +Please use the API Group `traefik.io` instead. diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index 85634a0d9..60cb2b813 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -65,13 +65,19 @@ rules: verbs: - update - apiGroups: + - traefik.io - traefik.containo.us resources: - middlewares + - middlewaretcps - ingressroutes - traefikservices - ingressroutetcps + - ingressrouteudps - tlsoptions + - tlsstores + - serverstransports + - serverstransporttcps verbs: - get - list @@ -164,20 +170,23 @@ rules: verbs: - update - apiGroups: + - traefik.io - traefik.containo.us resources: - middlewares + - middlewaretcps - ingressroutes - traefikservices - ingressroutetcps - ingressrouteudps - tlsoptions - tlsstores + - serverstransports + - serverstransporttcps verbs: - get - list - watch - ``` After having both resources applied, Traefik will work properly. @@ -496,3 +505,18 @@ In `v2.9`, Traefik Pilot support has been removed. ### Nomad Namespace In `v2.10`, the `namespace` option of the Nomad provider is deprecated, please use the `namespaces` options instead. + +## v2.10 + +### Kubernetes CRDs + +In `v2.10`, the Kubernetes CRDs API Group `traefik.containo.us` is deprecated, and its support will end starting with Traefik v3. Please use the API Group `traefik.io` instead. + +As the Kubernetes CRD provider still works with both API Versions (`traefik.io/v1alpha1` and `traefik.containo.us/v1alpha1`), +it means that for the same kind, namespace and name, the provider will only keep the `traefik.io/v1alpha1` resource. + +In addition, the Kubernetes CRDs API Version `traefik.io/v1alpha1` will not be supported in Traefik v3 itself. + +### Traefik Hub + +In `v2.10`, Traefik Hub is GA and the `experimental.hub` flag is deprecated. diff --git a/docs/content/observability/logs.md b/docs/content/observability/logs.md index 806d37b05..5e22aa64d 100644 --- a/docs/content/observability/logs.md +++ b/docs/content/observability/logs.md @@ -64,7 +64,9 @@ log: #### `level` -By default, the `level` is set to `ERROR`. Alternative logging levels are `TRACE`, `DEBUG`, `PANIC`, `FATAL`, `ERROR`, `WARN`, and `INFO`. +By default, the `level` is set to `ERROR`. + +Alternative logging levels are `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`, and `PANIC`. ```yaml tab="File (YAML)" log: 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/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/docs/content/observability/metrics/overview.md b/docs/content/observability/metrics/overview.md index 0fce7e76c..795d1a377 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) @@ -17,27 +16,31 @@ Traefik Proxy hosts an official Grafana dashboard for both [on-premises](https:/ ## Global Metrics -| Metric | Type | Description | -|---------------------------------------------|---------|---------------------------------------------------------| -| Config reload total | Count | The total count of configuration reloads. | -| Config reload last success | Gauge | The timestamp of the last configuration reload success. | -| TLS certificates not after | Gauge | The expiration date of certificates. | +| Metric | Type | [Labels](#labels) | Description | +|----------------------------|-------|--------------------------|--------------------------------------------------------------------| +| Config reload total | Count | | The total count of configuration reloads. | +| Config reload last success | Gauge | | The timestamp of the last configuration reload success. | +| Open connections | Gauge | `entrypoint`, `protocol` | The current count of open connections, by entrypoint and protocol. | +| TLS certificates not after | Gauge | | The expiration date of certificates. | ```prom tab="Prometheus" traefik_config_reloads_total traefik_config_last_reload_success +traefik_open_connections traefik_tls_certs_not_after ``` ```dd tab="Datadog" config.reload.total config.reload.lastSuccessTimestamp +open.connections tls.certs.notAfterTimestamp ``` -```influxdb tab="InfluxDB / InfluxDB2" +```influxdb tab="InfluxDB2" traefik.config.reload.total traefik.config.reload.lastSuccessTimestamp +traefik.open.connections traefik.tls.certs.notAfterTimestamp ``` @@ -45,17 +48,35 @@ traefik.tls.certs.notAfterTimestamp # Default prefix: "traefik" {prefix}.config.reload.total {prefix}.config.reload.lastSuccessTimestamp +{prefix}.open.connections {prefix}.tls.certs.notAfterTimestamp ``` -## EntryPoint Metrics +```opentelemetry tab="OpenTelemetry" +traefik_config_reloads_total +traefik_config_last_reload_success +traefik_open_connections +traefik_tls_certs_not_after +``` + +### Labels + +Here is a comprehensive list of labels that are provided by the global metrics: + +| Label | Description | example | +|---------------|----------------------------------------|----------------------| +| `entrypoint` | Entrypoint that handled the connection | "example_entrypoint" | +| `protocol` | Connection protocol | "TCP" | + +## HTTP Metrics + +### EntryPoint Metrics | Metric | Type | [Labels](#labels) | Description | |-----------------------|-----------|--------------------------------------------|---------------------------------------------------------------------| | Requests total | Count | `code`, `method`, `protocol`, `entrypoint` | The total count of HTTP requests received by an entrypoint. | | Requests TLS total | Count | `tls_version`, `tls_cipher`, `entrypoint` | The total count of HTTPS requests received by an entrypoint. | | Request duration | Histogram | `code`, `method`, `protocol`, `entrypoint` | Request processing duration histogram on an entrypoint. | -| Open connections | Count | `method`, `protocol`, `entrypoint` | The current count of open connections on an entrypoint. | | Requests bytes total | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP requests in bytes handled by an entrypoint. | | Responses bytes total | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP responses in bytes handled by an entrypoint. | @@ -63,7 +84,6 @@ traefik.tls.certs.notAfterTimestamp traefik_entrypoint_requests_total traefik_entrypoint_requests_tls_total traefik_entrypoint_request_duration_seconds -traefik_entrypoint_open_connections traefik_entrypoint_requests_bytes_total traefik_entrypoint_responses_bytes_total ``` @@ -72,16 +92,14 @@ traefik_entrypoint_responses_bytes_total entrypoint.request.total entrypoint.request.tls.total entrypoint.request.duration -entrypoint.connections.open 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 -traefik.entrypoint.connections.open traefik.entrypoint.requests.bytes.total traefik.entrypoint.responses.bytes.total ``` @@ -91,19 +109,26 @@ traefik.entrypoint.responses.bytes.total {prefix}.entrypoint.request.total {prefix}.entrypoint.request.tls.total {prefix}.entrypoint.request.duration -{prefix}.entrypoint.connections.open {prefix}.entrypoint.requests.bytes.total {prefix}.entrypoint.responses.bytes.total ``` -## Router Metrics +```opentelemetry tab="OpenTelemetry" +traefik_entrypoint_requests_total +traefik_entrypoint_requests_tls_total +traefik_entrypoint_request_duration_seconds +traefik_entrypoint_open_connections +traefik_entrypoint_requests_bytes_total +traefik_entrypoint_responses_bytes_total +``` + +### Router Metrics | Metric | Type | [Labels](#labels) | Description | |-----------------------|-----------|---------------------------------------------------|----------------------------------------------------------------| | Requests total | Count | `code`, `method`, `protocol`, `router`, `service` | The total count of HTTP requests handled by a router. | | Requests TLS total | Count | `tls_version`, `tls_cipher`, `router`, `service` | The total count of HTTPS requests handled by a router. | | Request duration | Histogram | `code`, `method`, `protocol`, `router`, `service` | Request processing duration histogram on a router. | -| Open connections | Count | `method`, `protocol`, `router`, `service` | The current count of open connections on a router. | | Requests bytes total | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP requests in bytes handled by a router. | | Responses bytes total | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP responses in bytes handled by a router. | @@ -111,7 +136,6 @@ traefik.entrypoint.responses.bytes.total traefik_router_requests_total traefik_router_requests_tls_total traefik_router_request_duration_seconds -traefik_router_open_connections traefik_router_requests_bytes_total traefik_router_responses_bytes_total ``` @@ -120,16 +144,14 @@ traefik_router_responses_bytes_total router.request.total router.request.tls.total router.request.duration -router.connections.open 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 -traefik.router.connections.open traefik.router.requests.bytes.total traefik.router.responses.bytes.total ``` @@ -139,19 +161,26 @@ traefik.router.responses.bytes.total {prefix}.router.request.total {prefix}.router.request.tls.total {prefix}.router.request.duration -{prefix}.router.connections.open {prefix}.router.requests.bytes.total {prefix}.router.responses.bytes.total ``` -## Service Metrics +```opentelemetry tab="OpenTelemetry" +traefik_router_requests_total +traefik_router_requests_tls_total +traefik_router_request_duration_seconds +traefik_router_open_connections +traefik_router_requests_bytes_total +traefik_router_responses_bytes_total +``` + +### Service Metrics | Metric | Type | Labels | Description | |-----------------------|-----------|-----------------------------------------|-------------------------------------------------------------| | Requests total | Count | `code`, `method`, `protocol`, `service` | The total count of HTTP requests processed on a service. | | Requests TLS total | Count | `tls_version`, `tls_cipher`, `service` | The total count of HTTPS requests processed on a service. | | Request duration | Histogram | `code`, `method`, `protocol`, `service` | Request processing duration histogram on a service. | -| Open connections | Count | `method`, `protocol`, `service` | The current count of open connections on a service. | | Retries total | Count | `service` | The count of requests retries on a service. | | Server UP | Gauge | `service`, `url` | Current service's server status, 0 for a down or 1 for up. | | Requests bytes total | Count | `code`, `method`, `protocol`, `service` | The total size of requests in bytes received by a service. | @@ -161,7 +190,6 @@ traefik.router.responses.bytes.total traefik_service_requests_total traefik_service_requests_tls_total traefik_service_request_duration_seconds -traefik_service_open_connections traefik_service_retries_total traefik_service_server_up traefik_service_requests_bytes_total @@ -172,18 +200,16 @@ traefik_service_responses_bytes_total service.request.total router.service.tls.total service.request.duration -service.connections.open service.retries.total service.server.up 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 -traefik.service.connections.open traefik.service.retries.total traefik.service.server.up traefik.service.requests.bytes.total @@ -195,14 +221,24 @@ traefik.service.responses.bytes.total {prefix}.service.request.total {prefix}.service.request.tls.total {prefix}.service.request.duration -{prefix}.service.connections.open {prefix}.service.retries.total {prefix}.service.server.up {prefix}.service.requests.bytes.total {prefix}.service.responses.bytes.total ``` -## Labels +```opentelemetry tab="OpenTelemetry" +traefik_service_requests_total +traefik_service_requests_tls_total +traefik_service_request_duration_seconds +traefik_service_open_connections +traefik_service_retries_total +traefik_service_server_up +traefik_service_requests_bytes_total +traefik_service_responses_bytes_total +``` + +### Labels Here is a comprehensive list of labels that are provided by the metrics: diff --git a/docs/content/observability/metrics/prometheus.md b/docs/content/observability/metrics/prometheus.md index da7f73773..be3e29cb6 100644 --- a/docs/content/observability/metrics/prometheus.md +++ b/docs/content/observability/metrics/prometheus.md @@ -165,3 +165,66 @@ metrics: ```bash tab="CLI" --metrics.prometheus.manualrouting=true ``` + +#### `headerLabels` + +_Optional_ + +Defines the extra labels for the `requests_total` metrics, and for each of them, the request header containing the value for this label. +Please note that if the header is not present in the request it will be added nonetheless with an empty value. +In addition, the label should be a valid label name for Prometheus metrics, +otherwise, the Prometheus metrics provider will fail to serve any Traefik-related metric. + +```yaml tab="File (YAML)" +metrics: + prometheus: + headerLabels: + label: headerKey +``` + +```toml tab="File (TOML)" +[metrics] + [metrics.prometheus] + [metrics.prometheus.headerLabels] + label = "headerKey" +``` + +```bash tab="CLI" +--metrics.prometheus.headerlabels.label=headerKey +``` + +##### Example + +Here is an example of the entryPoint `requests_total` metric with an additional "useragent" label. + +When configuring the label in Static Configuration: + +```yaml tab="File (YAML)" +metrics: + prometheus: + headerLabels: + useragent: User-Agent +``` + +```toml tab="File (TOML)" +[metrics] + [metrics.prometheus] + [metrics.prometheus.headerLabels] + useragent = "User-Agent" +``` + +```bash tab="CLI" +--metrics.prometheus.headerlabels.useragent=User-Agent +``` + +And performing a request with a custom User-Agent: + +```bash +curl -H "User-Agent: foobar" http://localhost +``` + +The following metric is produced : + +```bash +traefik_entrypoint_requests_total{code="200",entrypoint="web",method="GET",protocol="http",useragent="foobar"} 1 +``` \ No newline at end of file diff --git a/docs/content/observability/tracing/datadog.md b/docs/content/observability/tracing/datadog.md index a6c93f22a..fe14bc72f 100644 --- a/docs/content/observability/tracing/datadog.md +++ b/docs/content/observability/tracing/datadog.md @@ -23,24 +23,46 @@ tracing: #### `localAgentHostPort` -_Required, Default="127.0.0.1:8126"_ +_Optional, Default="localhost:8126"_ Local Agent Host Port instructs the reporter to send spans to the Datadog Agent at this address (host:port). ```yaml tab="File (YAML)" tracing: datadog: - localAgentHostPort: 127.0.0.1:8126 + localAgentHostPort: localhost:8126 ``` ```toml tab="File (TOML)" [tracing] [tracing.datadog] - localAgentHostPort = "127.0.0.1:8126" + localAgentHostPort = "localhost:8126" ``` ```bash tab="CLI" ---tracing.datadog.localAgentHostPort=127.0.0.1:8126 +--tracing.datadog.localAgentHostPort=localhost:8126 +``` + +#### `localAgentSocket` + +_Optional, Default=""_ + +Local Agent Socket instructs the reporter to send spans to the Datadog Agent at this UNIX socket. + +```yaml tab="File (YAML)" +tracing: + datadog: + localAgentSocket: /var/run/datadog/apm.socket +``` + +```toml tab="File (TOML)" +[tracing] + [tracing.datadog] + localAgentSocket = "/var/run/datadog/apm.socket" +``` + +```bash tab="CLI" +--tracing.datadog.localAgentSocket=/var/run/datadog/apm.socket ``` #### `debug` diff --git a/docs/content/observability/tracing/overview.md b/docs/content/observability/tracing/overview.md index 73504a140..f4126274a 100644 --- a/docs/content/observability/tracing/overview.md +++ b/docs/content/observability/tracing/overview.md @@ -12,7 +12,7 @@ The tracing system allows developers to visualize call flows in their infrastruc Traefik uses OpenTracing, an open standard designed for distributed tracing. -Traefik supports six tracing backends: +Traefik supports seven tracing backends: - [Jaeger](./jaeger.md) - [Zipkin](./zipkin.md) @@ -20,6 +20,7 @@ Traefik supports six tracing backends: - [Instana](./instana.md) - [Haystack](./haystack.md) - [Elastic](./elastic.md) +- [OpenTelemetry](./opentelemetry.md) ## Configuration diff --git a/docs/content/operations/include-api-examples.md b/docs/content/operations/include-api-examples.md index 33fc71a09..d98db97a9 100644 --- a/docs/content/operations/include-api-examples.md +++ b/docs/content/operations/include-api-examples.md @@ -20,7 +20,7 @@ deploy: ``` ```yaml tab="Kubernetes CRD" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: traefik-dashboard @@ -34,7 +34,7 @@ spec: middlewares: - name: auth --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: auth @@ -51,24 +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="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..5965d7070 100644 --- a/docs/content/operations/include-dashboard-examples.md +++ b/docs/content/operations/include-dashboard-examples.md @@ -20,7 +20,7 @@ deploy: ``` ```yaml tab="Kubernetes CRD" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: traefik-dashboard @@ -34,7 +34,7 @@ spec: middlewares: - name: auth --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: auth @@ -51,24 +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="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/docker.md b/docs/content/providers/docker.md index 8fd567356..177a39702 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/#label) to retrieve its routing configuration. See the list of labels in the dedicated [routing](../routing/providers/docker.md) section. @@ -440,10 +440,11 @@ _Optional, Default=```Host(`{{ normalize .Name }}`)```_ 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 container service name can be accessed with the `Name` identifier, -and the template has access to all the labels defined on this container. +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 container name can be accessed with the `ContainerName` identifier. +The service name can be accessed with the `Name` identifier. +The template has access to all the labels defined on this container with the `Labels` identifier. ```yaml tab="File (YAML)" providers: diff --git a/docs/content/providers/kubernetes-crd.md b/docs/content/providers/kubernetes-crd.md index dccc60eb6..26579d758 100644 --- a/docs/content/providers/kubernetes-crd.md +++ b/docs/content/providers/kubernetes-crd.md @@ -35,10 +35,10 @@ the Traefik engineering team developed a [Custom Resource Definition](https://ku ```bash # Install Traefik Resource Definitions: - kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml + kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml # Install RBAC for Traefik: - kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml + kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml ``` ## Resource Configuration diff --git a/docs/content/providers/kubernetes-ingress.md b/docs/content/providers/kubernetes-ingress.md index a35017cc5..d6eb1b4e9 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` @@ -502,6 +531,6 @@ providers: ### Further To learn more about the various aspects of the Ingress specification that Traefik supports, -many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v2.9/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository. +many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v3.0/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository. {!traefik-for-business-applications.md!} 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/nomad.md b/docs/content/providers/nomad.md index 3bc27d3b2..90b3eeb4d 100644 --- a/docs/content/providers/nomad.md +++ b/docs/content/providers/nomad.md @@ -442,6 +442,36 @@ For additional information, refer to [Restrict the Scope of Service Discovery](. ### `namespaces` +??? warning "Deprecated in favor of the [`namespaces`](#namespaces) option." + + _Optional, Default=""_ + + The `namespace` option defines the namespace in which the Nomad services will be discovered. + + !!! warning + + One should only define either the `namespaces` option or the `namespace` option. + + ```yaml tab="File (YAML)" + providers: + nomad: + namespace: "production" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.nomad] + namespace = "production" + # ... + ``` + + ```bash tab="CLI" + --providers.nomad.namespace=production + # ... + ``` + +### `namespaces` + _Optional, Default=""_ The `namespaces` option defines the namespaces in which the nomad services will be discovered. diff --git a/docs/content/providers/overview.md b/docs/content/providers/overview.md index de0af45fe..fbb133589 100644 --- a/docs/content/providers/overview.md +++ b/docs/content/providers/overview.md @@ -82,7 +82,7 @@ For the list of the providers names, see the [supported providers](#supported-pr ``` ```yaml tab="Kubernetes Ingress Route" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutestripprefix @@ -104,7 +104,7 @@ For the list of the providers names, see the [supported providers](#supported-pr ``` ```yaml tab="Kubernetes Ingress" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: stripprefix @@ -141,8 +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` | -| [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,8 +214,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,8 +223,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) - [Kubernetes Gateway](./kubernetes-gateway.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/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..37849dedc 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: ingressroutes.traefik.containo.us + name: ingressroutes.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: IngressRoute listKind: IngressRouteList @@ -104,6 +104,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs + or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes @@ -274,9 +281,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: ingressroutetcps.traefik.containo.us + name: ingressroutetcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: IngressRouteTCP listKind: IngressRouteTCPList @@ -357,6 +364,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs + or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean port: anyOf: - type: integer @@ -373,15 +387,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. @@ -485,9 +500,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: ingressrouteudps.traefik.containo.us + name: ingressrouteudps.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: IngressRouteUDP listKind: IngressRouteUDPList @@ -542,6 +557,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs + or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean port: anyOf: - type: integer @@ -583,9 +605,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: middlewares.traefik.containo.us + name: middlewares.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: Middleware listKind: MiddlewareList @@ -818,6 +840,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if + the only child is the Kubernetes Service clusterIP. The + Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. @@ -1478,9 +1507,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: middlewaretcps.traefik.containo.us + name: middlewaretcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: MiddlewareTCP listKind: MiddlewareTCPList @@ -1550,9 +1579,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: serverstransports.traefik.containo.us + name: serverstransports.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: ServersTransport listKind: ServersTransportList @@ -1691,9 +1720,131 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: tlsoptions.traefik.containo.us + name: serverstransporttcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io + 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/v3.0/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 +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: tlsoptions.traefik.io +spec: + group: traefik.io names: kind: TLSOption listKind: TLSOptionList @@ -1798,9 +1949,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: tlsstores.traefik.containo.us + name: tlsstores.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: TLSStore listKind: TLSStoreList @@ -1897,9 +2048,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: traefikservices.traefik.containo.us + name: traefikservices.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: TraefikService listKind: TraefikServiceList @@ -1966,6 +2117,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or + if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. @@ -2057,6 +2215,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the + only child is the Kubernetes Service clusterIP. The Kubernetes + Service itself does load-balance to the pods. By default, NativeLB + is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. By default, @@ -2154,6 +2319,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or + if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1beta1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1beta1.yml index 8319e66aa..4fb320d42 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1beta1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1beta1.yml @@ -1,10 +1,10 @@ apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: ingressroutes.traefik.containo.us + name: ingressroutes.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: IngressRoute @@ -16,10 +16,10 @@ spec: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: middlewares.traefik.containo.us + name: middlewares.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: Middleware @@ -31,10 +31,10 @@ spec: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: middlewaretcps.traefik.containo.us + name: middlewaretcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: MiddlewareTCP @@ -46,10 +46,10 @@ spec: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: ingressroutetcps.traefik.containo.us + name: ingressroutetcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: IngressRouteTCP @@ -61,10 +61,10 @@ spec: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: ingressrouteudps.traefik.containo.us + name: ingressrouteudps.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: IngressRouteUDP @@ -76,10 +76,10 @@ spec: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: tlsoptions.traefik.containo.us + name: tlsoptions.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: TLSOption @@ -91,10 +91,10 @@ spec: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: tlsstores.traefik.containo.us + name: tlsstores.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: TLSStore @@ -106,10 +106,10 @@ spec: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: traefikservices.traefik.containo.us + name: traefikservices.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: TraefikService @@ -121,10 +121,10 @@ spec: apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: - name: serverstransports.traefik.containo.us + name: serverstransports.traefik.io spec: - group: traefik.containo.us + group: traefik.io version: v1alpha1 names: kind: ServersTransport diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml index 6237031f0..301ec5166 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml @@ -32,7 +32,7 @@ rules: verbs: - update - apiGroups: - - traefik.containo.us + - traefik.io resources: - middlewares - middlewaretcps @@ -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..93f1a95ff 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr2 @@ -17,7 +17,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -34,7 +34,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror1 @@ -53,7 +53,7 @@ spec: percent: 20 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror2 @@ -73,7 +73,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroute @@ -133,7 +133,7 @@ spec: namespace: default --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: ingressroutetcp.crd @@ -147,6 +147,7 @@ spec: services: - name: whoamitcp port: 8080 + serversTransport: mytransporttcp middlewares: - name: ipallowlist tls: @@ -157,7 +158,7 @@ spec: namespace: default --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: ingressrouteudp.crd @@ -172,7 +173,7 @@ spec: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: tlsoption @@ -198,7 +199,7 @@ spec: - foobar --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport @@ -213,9 +214,30 @@ spec: certificatesSecrets: - foobar - foobar + peerCertURI: foobar maxIdleConnsPerHost: 1 forwardingTimeouts: dialTimeout: 42s responseHeaderTimeout: 42s idleConnTimeout: 42s disableHTTP2: true + +--- +apiVersion: traefik.io/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/kubernetes-gateway-resource.yml b/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml index 55c394456..a22858a69 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml @@ -74,7 +74,7 @@ spec: value: /foo backendRefs: - - group: traefik.containo.us + - group: traefik.io kind: TraefikService name: myservice@file weight: 1 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 deleted file mode 100644 index 99cfaefb9..000000000 --- a/docs/content/reference/dynamic-configuration/marathon-labels.json +++ /dev/null @@ -1,209 +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.terminationdelay": "42", -"traefik.tcp.services.tcpservice01.loadbalancer.server.port": "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/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/dynamic-configuration/traefik.containo.us_ingressroutes.yaml b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml similarity index 96% rename from docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutes.yaml rename to docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml index b6c0eff29..8ea5b28c2 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutes.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: ingressroutes.traefik.containo.us + name: ingressroutes.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: IngressRoute listKind: IngressRouteList @@ -104,6 +104,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs + or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutetcps.yaml similarity index 88% rename from docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml rename to docs/content/reference/dynamic-configuration/traefik.io_ingressroutetcps.yaml index a73fde965..7acb7cd5f 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutetcps.yaml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: ingressroutetcps.traefik.containo.us + name: ingressroutetcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: IngressRouteTCP listKind: IngressRouteTCPList @@ -89,6 +89,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs + or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean port: anyOf: - type: integer @@ -105,15 +112,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_ingressrouteudps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_ingressrouteudps.yaml similarity index 87% rename from docs/content/reference/dynamic-configuration/traefik.containo.us_ingressrouteudps.yaml rename to docs/content/reference/dynamic-configuration/traefik.io_ingressrouteudps.yaml index 50a7e6298..59585a453 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressrouteudps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_ingressrouteudps.yaml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: ingressrouteudps.traefik.containo.us + name: ingressrouteudps.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: IngressRouteUDP listKind: IngressRouteUDPList @@ -63,6 +63,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs + or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean port: anyOf: - type: integer diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml similarity index 98% rename from docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml rename to docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml index 9994d3469..67b9e0b5d 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: middlewares.traefik.containo.us + name: middlewares.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: Middleware listKind: MiddlewareList @@ -241,6 +241,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if + the only child is the Kubernetes Service clusterIP. The + Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml similarity index 97% rename from docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml rename to docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml index 071b49cf8..ec5ee7e68 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: middlewaretcps.traefik.containo.us + name: middlewaretcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: MiddlewareTCP listKind: MiddlewareTCPList diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransports.yaml b/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml similarity index 98% rename from docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransports.yaml rename to docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml index 362db4f49..fff9f7006 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransports.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: serverstransports.traefik.containo.us + name: serverstransports.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: ServersTransport listKind: ServersTransportList diff --git a/docs/content/reference/dynamic-configuration/traefik.io_serverstransporttcps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_serverstransporttcps.yaml new file mode 100644 index 000000000..10e0a3f0e --- /dev/null +++ b/docs/content/reference/dynamic-configuration/traefik.io_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.io +spec: + group: traefik.io + 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/v3.0/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/dynamic-configuration/traefik.containo.us_tlsoptions.yaml b/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml similarity index 98% rename from docs/content/reference/dynamic-configuration/traefik.containo.us_tlsoptions.yaml rename to docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml index ffbd86ec1..ddf525ceb 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsoptions.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: tlsoptions.traefik.containo.us + name: tlsoptions.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: TLSOption listKind: TLSOptionList diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsstores.yaml b/docs/content/reference/dynamic-configuration/traefik.io_tlsstores.yaml similarity index 98% rename from docs/content/reference/dynamic-configuration/traefik.containo.us_tlsstores.yaml rename to docs/content/reference/dynamic-configuration/traefik.io_tlsstores.yaml index 9e35d6897..61d7063c0 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsstores.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_tlsstores.yaml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: tlsstores.traefik.containo.us + name: tlsstores.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: TLSStore listKind: TLSStoreList diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_traefikservices.yaml b/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml similarity index 93% rename from docs/content/reference/dynamic-configuration/traefik.containo.us_traefikservices.yaml rename to docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml index 3289806f9..870dfdf53 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_traefikservices.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: traefikservices.traefik.containo.us + name: traefikservices.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: TraefikService listKind: TraefikServiceList @@ -75,6 +75,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or + if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. @@ -166,6 +173,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the + only child is the Kubernetes Service clusterIP. The Kubernetes + Service itself does load-balance to the pods. By default, NativeLB + is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. By default, @@ -263,6 +277,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or + if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 39cb5d102..ac90226ce 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -189,9 +189,6 @@ WriteTimeout is the maximum duration before timing out writes of the response. I `--entrypoints..udp.timeout`: Timeout defines how long to wait on an idle session before releasing the related resources. (Default: ```3```) -`--experimental.hub`: -Enable the Traefik Hub provider. (Default: ```false```) - `--experimental.kubernetesgateway`: Allow the Kubernetes gateway api provider usage. (Default: ```false```) @@ -288,42 +285,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```) @@ -417,6 +378,9 @@ Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000 `--metrics.prometheus.entrypoint`: EntryPoint (Default: ```traefik```) +`--metrics.prometheus.headerlabels.`: +Defines the extra labels for the requests_total metrics, and for each of them, the request header containing the value for this label. + `--metrics.prometheus.manualrouting`: Manual routing (Default: ```false```) @@ -771,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). @@ -798,66 +765,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```) @@ -868,7 +775,7 @@ Constraints is an expression that Traefik matches against the Nomad service's ta Default rule. (Default: ```Host(`{{ normalize .Name }}`)```) `--providers.nomad.endpoint.address`: -The address of the Nomad server, including scheme and port. +The address of the Nomad server, including scheme and port. (Default: ```http://127.0.0.1:4646```) `--providers.nomad.endpoint.endpointwaittime`: WaitTime limits how long a Watch will block. If not provided, the agent default values will be used (Default: ```0```) @@ -912,33 +819,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```) @@ -1020,6 +900,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```) @@ -1038,6 +945,9 @@ Sets a list of key:value tags on all spans. `--tracing.datadog.localagenthostport`: Sets the Datadog Agent host:port. (Default: ```localhost:8126```) +`--tracing.datadog.localagentsocket`: +Sets the socket for the Datadog Agent. + `--tracing.datadog.parentidheadername`: Sets the header name used to store the parent ID. diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 08fb6bd7d..31748c91c 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -189,9 +189,6 @@ WriteTimeout is the maximum duration before timing out writes of the response. I `TRAEFIK_ENTRYPOINTS__UDP_TIMEOUT`: Timeout defines how long to wait on an idle session before releasing the related resources. (Default: ```3```) -`TRAEFIK_EXPERIMENTAL_HUB`: -Enable the Traefik Hub provider. (Default: ```false```) - `TRAEFIK_EXPERIMENTAL_KUBERNETESGATEWAY`: Allow the Kubernetes gateway api provider usage. (Default: ```false```) @@ -288,9 +285,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 +315,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```) @@ -417,6 +378,9 @@ Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000 `TRAEFIK_METRICS_PROMETHEUS_ENTRYPOINT`: EntryPoint (Default: ```traefik```) +`TRAEFIK_METRICS_PROMETHEUS_HEADERLABELS_`: +Defines the extra labels for the requests_total metrics, and for each of them, the request header containing the value for this label. + `TRAEFIK_METRICS_PROMETHEUS_MANUALROUTING`: Manual routing (Default: ```false```) @@ -771,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). @@ -798,66 +765,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```) @@ -868,7 +775,7 @@ Constraints is an expression that Traefik matches against the Nomad service's ta Default rule. (Default: ```Host(`{{ normalize .Name }}`)```) `TRAEFIK_PROVIDERS_NOMAD_ENDPOINT_ADDRESS`: -The address of the Nomad server, including scheme and port. +The address of the Nomad server, including scheme and port. (Default: ```http://127.0.0.1:4646```) `TRAEFIK_PROVIDERS_NOMAD_ENDPOINT_ENDPOINTWAITTIME`: WaitTime limits how long a Watch will block. If not provided, the agent default values will be used (Default: ```0```) @@ -912,33 +819,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```) @@ -1020,6 +900,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```) @@ -1038,6 +945,9 @@ Sets a list of key:value tags on all spans. `TRAEFIK_TRACING_DATADOG_LOCALAGENTHOSTPORT`: Sets the Datadog Agent host:port. (Default: ```localhost:8126```) +`TRAEFIK_TRACING_DATADOG_LOCALAGENTSOCKET`: +Sets the socket for the Datadog Agent. + `TRAEFIK_TRACING_DATADOG_PARENTIDHEADERNAME`: Sets the header name used to store the parent ID. diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 22420a806..b08074bb6 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] @@ -79,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" @@ -111,6 +108,7 @@ throttleDuration = "42s" allowEmptyServices = true allowExternalNameServices = true + disableIngressClassLookup = true [providers.kubernetesIngress.ingressEndpoint] ip = "foobar" hostname = "foobar" @@ -135,15 +133,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" @@ -267,6 +256,9 @@ addServicesLabels = true entryPoint = "foobar" manualRouting = true + [metrics.prometheus.headerLabels] + label1 = "foobar" + label2 = "foobar" [metrics.datadog] address = "foobar" pushInterval = "42s" @@ -281,20 +273,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" @@ -384,6 +362,7 @@ sampleRate = 42.0 [tracing.datadog] localAgentHostPort = "foobar" + localAgentSocket = "foobar" [tracing.datadog.globalTags] tag1 = "foobar" tag2 = "foobar" @@ -461,7 +440,7 @@ [experimental] kubernetesGateway = true - hub = true + http3 = true [experimental.plugins] [experimental.plugins.Descriptor0] moduleName = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 596f5ab4d..cb6f3c257 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 @@ -85,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 @@ -119,6 +117,7 @@ providers: throttleDuration: 42s allowEmptyServices: true allowExternalNameServices: true + disableIngressClassLookup: true ingressEndpoint: ip: foobar hostname: foobar @@ -147,15 +146,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 @@ -295,6 +285,9 @@ metrics: addServicesLabels: true entryPoint: foobar manualRouting: true + headerLabels: + label1: foobar + label2: foobar datadog: address: foobar pushInterval: 42s @@ -309,20 +302,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 @@ -413,6 +392,7 @@ tracing: sampleRate: 42 datadog: localAgentHostPort: foobar + localAgentSocket: foobar globalTags: tag1: foobar tag2: foobar @@ -489,7 +469,7 @@ hub: key: foobar experimental: kubernetesGateway: true - hub: true + http3: true plugins: Descriptor0: moduleName: foobar diff --git a/docs/content/routing/entrypoints.md b/docs/content/routing/entrypoints.md index ece0f2c0b..bc7ff18e9 100644 --- a/docs/content/routing/entrypoints.md +++ b/docs/content/routing/entrypoints.md @@ -320,7 +320,7 @@ this entryPoint is the same as the one used for TLS traffic. ```yaml tab="File (YAML)" entryPoints: name: - http3: {} + http3: {} ``` ```toml tab="File (TOML)" 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..c25070808 100644 --- a/docs/content/routing/providers/kubernetes-crd.md +++ b/docs/content/routing/providers/kubernetes-crd.md @@ -107,7 +107,7 @@ The Kubernetes Ingress Controller, The Custom Resource Way. ``` ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: myingressroute @@ -125,7 +125,7 @@ The Kubernetes Ingress Controller, The Custom Resource Way. port: 80 --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: ingressroute.tcp @@ -141,7 +141,7 @@ The Kubernetes Ingress Controller, The Custom Resource Way. port: 8080 --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: ingressroute.udp @@ -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` @@ -316,7 +317,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne !!! info "IngressRoute Attributes" ```yaml - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: foo @@ -349,15 +350,16 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne sameSite: none strategy: RoundRobin weight: 10 - tls: # [11] - secretName: supersecret # [12] - options: # [13] - name: opt # [14] - namespace: default # [15] - certResolver: foo # [16] - domains: # [17] - - main: example.net # [18] - sans: # [19] + nativeLB: true # [11] + tls: # [12] + secretName: supersecret # [13] + options: # [14] + name: opt # [15] + namespace: default # [16] + certResolver: foo # [17] + domains: # [18] + - main: example.net # [19] + sans: # [20] - a.example.net - b.example.net ``` @@ -374,21 +376,22 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne | [8] | `routes[n].services` | List of any combination of [TraefikService](#kind-traefikservice) and reference to a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) (See below for `ExternalName Service` setup) | | [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].serversTransport` | Defines the reference to a [ServersTransport](#kind-serverstransport). The ServersTransport namespace is assumed to be the [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) namespace (see [ServersTransport reference](#serverstransport-reference)). | -| [11] | `tls` | Defines [TLS](../routers/index.md#tls) certificate configuration | -| [12] | `tls.secretName` | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace) | -| [13] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) | -| [14] | `options.name` | Defines the [TLSOption](#kind-tlsoption) name | -| [15] | `options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace | -| [16] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver) | -| [17] | `tls.domains` | List of [domains](../routers/index.md#domains) | -| [18] | `domains[n].main` | Defines the main domain name | -| [19] | `domains[n].sans` | List of SANs (alternative domains) | +| [11] | `services[n].nativeLB` | Controls, when creating the load-balancer, whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. | +| [12] | `tls` | Defines [TLS](../routers/index.md#tls) certificate configuration | +| [13] | `tls.secretName` | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace) | +| [14] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) | +| [15] | `options.name` | Defines the [TLSOption](#kind-tlsoption) name | +| [16] | `options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace | +| [17] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver) | +| [18] | `tls.domains` | List of [domains](../routers/index.md#domains) | +| [19] | `domains[n].main` | Defines the main domain name | +| [20] | `domains[n].sans` | List of SANs (alternative domains) | ??? example "Declaring an IngressRoute" ```yaml tab="IngressRoute" # All resources definition must be declared - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test-name @@ -435,7 +438,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne ```yaml tab="Middlewares" # All resources definition must be declared # Prefixing with /foo - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: middleware1 @@ -446,7 +449,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne ``` ```yaml tab="TLSOption" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: opt @@ -492,7 +495,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne ```yaml tab="IngressRoute" --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route @@ -522,7 +525,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne ```yaml tab="ExternalName Service" --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route @@ -553,7 +556,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne ```yaml tab="Both sides" --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route @@ -590,7 +593,7 @@ More information in the dedicated server [load balancing](../services/index.md#l !!! info "Declaring and using Kubernetes Service Load Balancing" ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar @@ -639,6 +642,47 @@ More information in the dedicated server [load balancing](../services/index.md#l task: app2 ``` +!!! important "Kubernetes Service Native Load-Balancing" + + To avoid creating the server load-balancer with the pods IPs and use Kubernetes Service clusterIP directly, + one should set the service `NativeLB` option to true. + Please note that, by default, Traefik reuses the established connections to the backends for performance purposes. This can prevent the requests load balancing between the replicas from behaving as one would expect when the option is set. + By default, `NativeLB` is false. + + ??? example "Example" + + ```yaml + --- + apiVersion: traefik.io/v1alpha1 + kind: IngressRoute + metadata: + name: test.route + namespace: default + + spec: + entryPoints: + - foo + + routes: + - match: Host(`example.net`) + kind: Rule + services: + - name: svc + port: 80 + # Here, nativeLB instructs to build the servers load balancer with the Kubernetes Service clusterIP only. + nativeLB: true + + --- + apiVersion: v1 + kind: Service + metadata: + name: svc + namespace: default + spec: + type: ClusterIP + ... + ``` + ### Kind: `Middleware` `Middleware` is the CRD implementation of a [Traefik middleware](../../middlewares/http/overview.md). @@ -648,7 +692,7 @@ Register the `Middleware` [kind](../../reference/dynamic-configuration/kubernete ??? "Declaring and Referencing a Middleware" ```yaml tab="Middleware" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: stripprefix @@ -661,7 +705,7 @@ Register the `Middleware` [kind](../../reference/dynamic-configuration/kubernete ``` ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar @@ -719,7 +763,7 @@ More information in the dedicated [Weighted Round Robin](../services/index.md#we ??? "Declaring and Using Weighted Round Robin" ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar @@ -738,7 +782,7 @@ More information in the dedicated [Weighted Round Robin](../services/index.md#we ``` ```yaml tab="Weighted Round Robin" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -758,7 +802,7 @@ More information in the dedicated [Weighted Round Robin](../services/index.md#we weight: 1 --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr2 @@ -826,7 +870,7 @@ More information in the dedicated [mirroring](../services/index.md#mirroring-ser ??? "Declaring and Using Mirroring" ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar @@ -846,7 +890,7 @@ More information in the dedicated [mirroring](../services/index.md#mirroring-ser ```yaml tab="Mirroring k8s Service" # Mirroring from a k8s Service - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror1 @@ -867,7 +911,7 @@ More information in the dedicated [mirroring](../services/index.md#mirroring-ser ```yaml tab="Mirroring Traefik Service" # Mirroring from a Traefik Service - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror1 @@ -936,7 +980,7 @@ and there is a second level because each whoami service is a `replicaset` and is ??? "Stickiness on two load-balancing levels" ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar @@ -955,7 +999,7 @@ and there is a second level because each whoami service is a `replicaset` and is ``` ```yaml tab="Weighted Round Robin" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -1082,71 +1126,73 @@ Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kube !!! info "IngressRouteTCP Attributes" ```yaml - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: 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] + nativeLB: true # [14] + tls: # [15] + secretName: supersecret # [16] + options: # [17] + name: opt # [18] + namespace: default # [19] + certResolver: foo # [20] + domains: # [21] + - main: example.net # [22] + sans: # [23] - a.example.net - b.example.net - passthrough: false # [23] + passthrough: false # [24] ``` -| 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] | `services[n].nativeLB` | Controls, when creating the load-balancer, whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. | +| [15] | `tls` | Defines [TLS](../routers/index.md#tls_1) certificate configuration | +| [16] | `tls.secretName` | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace) | +| [17] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) | +| [18] | `tls.options.name` | Defines the [TLSOption](#kind-tlsoption) name | +| [19] | `tls.options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace | +| [20] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver_1) | +| [21] | `tls.domains` | List of [domains](../routers/index.md#domains_1) | +| [22] | `tls.domains[n].main` | Defines the main domain name | +| [23] | `tls.domains[n].sans` | List of SANs (alternative domains) | +| [24] | `tls.passthrough` | If `true`, delegates the TLS termination to the backend | ??? example "Declaring an IngressRouteTCP" ```yaml tab="IngressRouteTCP" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: ingressroutetcpfoo @@ -1161,11 +1207,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 @@ -1182,7 +1226,7 @@ Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kube ``` ```yaml tab="TLSOption" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: opt @@ -1217,7 +1261,7 @@ Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kube ```yaml tab="Only on IngressRouteTCP" --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route @@ -1246,7 +1290,7 @@ Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kube ```yaml tab="On both sides" --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route @@ -1275,6 +1319,45 @@ Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kube - port: 80 ``` +!!! important "Kubernetes Service Native Load-Balancing" + + To avoid creating the server load-balancer with the pods IPs and use Kubernetes Service clusterIP directly, + one should set the TCP service `NativeLB` option to true. + By default, `NativeLB` is false. + + ??? example "Examples" + + ```yaml + --- + apiVersion: traefik.io/v1alpha1 + kind: IngressRouteTCP + metadata: + name: test.route + namespace: default + + spec: + entryPoints: + - foo + + routes: + - match: HostSNI(`*`) + services: + - name: svc + port: 80 + # Here, nativeLB instructs to build the servers load balancer with the Kubernetes Service clusterIP only. + nativeLB: true + + --- + apiVersion: v1 + kind: Service + metadata: + name: svc + namespace: default + spec: + type: ClusterIP + ... + ``` + ### Kind: `MiddlewareTCP` `MiddlewareTCP` is the CRD implementation of a [Traefik TCP middleware](../../middlewares/tcp/overview.md). @@ -1284,7 +1367,7 @@ Register the `MiddlewareTCP` [kind](../../reference/dynamic-configuration/kubern ??? "Declaring and Referencing a MiddlewareTCP " ```yaml tab="Middleware" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: ipallowlist @@ -1296,7 +1379,7 @@ Register the `MiddlewareTCP` [kind](../../reference/dynamic-configuration/kubern ``` ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar @@ -1335,7 +1418,7 @@ Register the `IngressRouteUDP` [kind](../../reference/dynamic-configuration/kube !!! info "IngressRouteUDP Attributes" ```yaml - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: ingressrouteudpfoo @@ -1348,21 +1431,23 @@ Register the `IngressRouteUDP` [kind](../../reference/dynamic-configuration/kube - name: foo # [4] port: 8080 # [5] weight: 10 # [6] + nativeLB: true # [7] ``` -| Ref | Attribute | Purpose | -|------|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [1] | `entryPoints` | List of [entrypoints](../routers/index.md#entrypoints_1) names | -| [2] | `routes` | List of routes | -| [3] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions (See below for `ExternalName Service` setup) | -| [4] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) | -| [6] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port. | -| [7] | `services[n].weight` | Defines the weight to apply to the server load balancing | +| Ref | Attribute | Purpose | +|-----|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| +| [1] | `entryPoints` | List of [entrypoints](../routers/index.md#entrypoints_1) names | +| [2] | `routes` | List of routes | +| [3] | `routes[n].services` | List of [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) definitions (See below for `ExternalName Service` setup) | +| [4] | `services[n].name` | Defines the name of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) | +| [5] | `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. | +| [6] | `services[n].weight` | Defines the weight to apply to the server load balancing | +| [7] | `services[n].nativeLB` | Controls, when creating the load-balancer, whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. | ??? example "Declaring an IngressRouteUDP" ```yaml - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: ingressrouteudpfoo @@ -1394,7 +1479,7 @@ Register the `IngressRouteUDP` [kind](../../reference/dynamic-configuration/kube ```yaml tab="IngressRouteUDP" --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route @@ -1422,7 +1507,7 @@ Register the `IngressRouteUDP` [kind](../../reference/dynamic-configuration/kube ```yaml tab="ExternalName Service" --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route @@ -1451,7 +1536,7 @@ Register the `IngressRouteUDP` [kind](../../reference/dynamic-configuration/kube ```yaml tab="Both sides" --- - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route @@ -1479,6 +1564,44 @@ Register the `IngressRouteUDP` [kind](../../reference/dynamic-configuration/kube - port: 80 ``` +!!! important "Kubernetes Service Native Load-Balancing" + + To avoid creating the server load-balancer with the pods IPs and use Kubernetes Service clusterIP directly, + one should set the UDP service `NativeLB` option to true. + By default, `NativeLB` is false. + + ??? example "Example" + + ```yaml + --- + apiVersion: traefik.io/v1alpha1 + kind: IngressRouteUDP + metadata: + name: test.route + namespace: default + + spec: + entryPoints: + - foo + + routes: + - services: + - name: svc + port: 80 + # Here, nativeLB instructs to build the servers load balancer with the Kubernetes Service clusterIP only. + nativeLB: true + + --- + apiVersion: v1 + kind: Service + metadata: + name: svc + namespace: default + spec: + type: ClusterIP + ... + ``` + ### Kind: `TLSOption` `TLSOption` is the CRD implementation of a [Traefik "TLS Option"](../../https/tls.md#tls-options). @@ -1489,7 +1612,7 @@ or referencing TLS options in the [`IngressRoute`](#kind-ingressroute) / [`Ingre !!! info "TLSOption Attributes" ```yaml tab="TLSOption" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: mytlsoption # [1] @@ -1534,7 +1657,7 @@ or referencing TLS options in the [`IngressRoute`](#kind-ingressroute) / [`Ingre ??? example "Declaring and referencing a TLSOption" ```yaml tab="TLSOption" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: mytlsoption @@ -1554,7 +1677,7 @@ or referencing TLS options in the [`IngressRoute`](#kind-ingressroute) / [`Ingre ``` ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar @@ -1609,22 +1732,22 @@ 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" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TLSStore metadata: name: default - namespace: default + spec: certificates: # [1] - secretName: foo @@ -1641,35 +1764,32 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres ??? example "Declaring and referencing a TLSStore" ```yaml tab="TLSStore" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: TLSStore metadata: name: default - namespace: default - + spec: defaultCertificate: secretName: supersecret ``` ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutebar 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" @@ -1689,33 +1809,38 @@ 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" ```yaml tab="ServersTransport" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport 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 +1856,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" @@ -1739,7 +1867,7 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres ??? example "Declaring and referencing a ServersTransport" ```yaml tab="ServersTransport" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport @@ -1751,7 +1879,7 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres ``` ```yaml tab="IngressRoute" - apiVersion: traefik.containo.us/v1alpha1 + apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: testroute @@ -1775,10 +1903,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.io/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.io/v1alpha1 + kind: ServersTransportTCP + metadata: + name: mytransport + namespace: default + + spec: + tls: + serverName: example.org + insecureSkipVerify: true + ``` + + ```yaml tab="IngressRouteTCP" + apiVersion: traefik.io/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/kubernetes-gateway.md b/docs/content/routing/providers/kubernetes-gateway.md index f67f488fd..6c15acb4f 100644 --- a/docs/content/routing/providers/kubernetes-gateway.md +++ b/docs/content/routing/providers/kubernetes-gateway.md @@ -39,13 +39,13 @@ The Kubernetes Gateway API, The Experimental Way. {: .subtitle } You can find an excerpt of the supported Kubernetes Gateway API resources in the table below: -| Kind | Purpose | Concept Behind | -|------------------------------------|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------| -| [GatewayClass](#kind-gatewayclass) | Defines a set of Gateways that share a common configuration and behaviour | [GatewayClass](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gatewayclass) | -| [Gateway](#kind-gateway) | Describes how traffic can be translated to Services within the cluster | [Gateway](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gateway) | -| [HTTPRoute](#kind-httproute) | HTTP rules for mapping requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/httproute) | -| [TCPRoute](#kind-tcproute) | Allows mapping TCP requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/guides/tcp/)| -| [TLSRoute](#kind-tlsroute) | Allows mapping TLS requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/guides/tls/)| +| Kind | Purpose | Concept Behind | +|------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------------------------------------| +| [GatewayClass](#kind-gatewayclass) | Defines a set of Gateways that share a common configuration and behaviour | [GatewayClass](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gatewayclass) | +| [Gateway](#kind-gateway) | Describes how traffic can be translated to Services within the cluster | [Gateway](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gateway) | +| [HTTPRoute](#kind-httproute) | HTTP rules for mapping requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/httproute) | +| [TCPRoute](#kind-tcproute) | Allows mapping TCP requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/guides/tcp/) | +| [TLSRoute](#kind-tlsroute) | Allows mapping TLS requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/guides/tls/) | ### Kind: `GatewayClass` @@ -238,7 +238,7 @@ Kubernetes cluster before creating `HTTPRoute` objects. weight: 1 # [16] port: 8080 # [17] - name: api@internal - group: traefik.containo.us # [18] + group: traefik.io # [18] kind: TraefikService # [19] ``` @@ -261,7 +261,7 @@ Kubernetes cluster before creating `HTTPRoute` objects. | [15] | `name` | The name of the referent service. | | [16] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | | [17] | `port` | The port of the referent service. | -| [18] | `group` | Group is the group of the referent. Only `traefik.containo.us` and `gateway.networking.k8s.io` values are supported. | +| [18] | `group` | Group is the group of the referent. Only `traefik.io` and `gateway.networking.k8s.io` values are supported. | | [19] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. | ### Kind: `TCPRoute` @@ -290,23 +290,23 @@ Kubernetes cluster before creating `TCPRoute` objects. weight: 1 # [8] port: 8080 # [9] - name: api@internal - group: traefik.containo.us # [10] + group: traefik.io # [10] kind: TraefikService # [11] ``` -| Ref | Attribute | Description | -|------|---------------|----------------------------------------------------------------------------------------------------------------------| -| [1] | `parentRefs` | References the resources (usually Gateways) that a Route wants to be attached to. | -| [2] | `name` | Name of the referent. | -| [3] | `namespace` | Namespace of the referent. When unspecified (or empty string), this refers to the local namespace of the Route. | -| [4] | `sectionName` | Name of a section within the target resource (the Listener name). | -| [5] | `rules` | Rules are a list of TCP matchers and actions. | -| [6] | `backendRefs` | Defines the backend(s) where matching requests should be sent. | -| [7] | `name` | The name of the referent service. | -| [8] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | -| [9] | `port` | The port of the referent service. | -| [10] | `group` | Group is the group of the referent. Only `traefik.containo.us` and `gateway.networking.k8s.io` values are supported. | -| [11] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. | +| Ref | Attribute | Description | +|------|---------------|-----------------------------------------------------------------------------------------------------------------| +| [1] | `parentRefs` | References the resources (usually Gateways) that a Route wants to be attached to. | +| [2] | `name` | Name of the referent. | +| [3] | `namespace` | Namespace of the referent. When unspecified (or empty string), this refers to the local namespace of the Route. | +| [4] | `sectionName` | Name of a section within the target resource (the Listener name). | +| [5] | `rules` | Rules are a list of TCP matchers and actions. | +| [6] | `backendRefs` | Defines the backend(s) where matching requests should be sent. | +| [7] | `name` | The name of the referent service. | +| [8] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | +| [9] | `port` | The port of the referent service. | +| [10] | `group` | Group is the group of the referent. Only `traefik.io` and `gateway.networking.k8s.io` values are supported. | +| [11] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. | ### Kind: `TLSRoute` @@ -336,21 +336,21 @@ Kubernetes cluster before creating `TLSRoute` objects. weight: 1 # [9] port: 8080 # [10] - name: api@internal - group: traefik.containo.us # [11] + group: traefik.io # [11] kind: TraefikService # [12] ``` -| Ref | Attribute | Description | -|------|---------------|----------------------------------------------------------------------------------------------------------------------| -| [1] | `parentRefs` | References the resources (usually Gateways) that a Route wants to be attached to. | -| [2] | `name` | Name of the referent. | -| [3] | `namespace` | Namespace of the referent. When unspecified (or empty string), this refers to the local namespace of the Route. | -| [4] | `sectionName` | Name of a section within the target resource (the Listener name). | -| [5] | `hostnames` | Defines a set of SNI names that should match against the SNI attribute of TLS ClientHello message in TLS handshake. | -| [6] | `rules` | Rules are a list of TCP matchers and actions. | -| [7] | `backendRefs` | Defines the backend(s) where matching requests should be sent. | -| [8] | `name` | The name of the referent service. | -| [9] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | -| [10] | `port` | The port of the referent service. | -| [11] | `group` | Group is the group of the referent. Only `traefik.containo.us` and `gateway.networking.k8s.io` values are supported. | -| [12] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. | +| Ref | Attribute | Description | +|------|---------------|---------------------------------------------------------------------------------------------------------------------| +| [1] | `parentRefs` | References the resources (usually Gateways) that a Route wants to be attached to. | +| [2] | `name` | Name of the referent. | +| [3] | `namespace` | Namespace of the referent. When unspecified (or empty string), this refers to the local namespace of the Route. | +| [4] | `sectionName` | Name of a section within the target resource (the Listener name). | +| [5] | `hostnames` | Defines a set of SNI names that should match against the SNI attribute of TLS ClientHello message in TLS handshake. | +| [6] | `rules` | Rules are a list of TCP matchers and actions. | +| [7] | `backendRefs` | Defines the backend(s) where matching requests should be sent. | +| [8] | `name` | The name of the referent service. | +| [9] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). | +| [10] | `port` | The port of the referent service. | +| [11] | `group` | Group is the group of the referent. Only `traefik.io` and `gateway.networking.k8s.io` values are supported. | +| [12] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. | diff --git a/docs/content/routing/providers/kubernetes-ingress.md b/docs/content/routing/providers/kubernetes-ingress.md index 5720889d8..bb87501c4 100644 --- a/docs/content/routing/providers/kubernetes-ingress.md +++ b/docs/content/routing/providers/kubernetes-ingress.md @@ -299,6 +299,17 @@ which in turn will create the resulting routers, services, handlers, etc. #### On Service +??? info "`traefik.ingress.kubernetes.io/service.nativelb`" + + Controls, when creating the load-balancer, whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the pods. + Please note that, by default, Traefik reuses the established connections to the backends for performance purposes. This can prevent the requests load balancing between the replicas from behaving as one would expect when the option is set. + By default, NativeLB is false. + + ```yaml + traefik.ingress.kubernetes.io/service.nativelb: "true" + ``` + ??? info "`traefik.ingress.kubernetes.io/service.serversscheme`" Overrides the default scheme. @@ -888,14 +899,24 @@ TLS certificates can be managed in Secrets objects. ### Communication Between Traefik and Pods +!!! info "Routing directly to [Kubernetes services](https://kubernetes.io/docs/concepts/services-networking/service/ "Link to Kubernetes service docs")" + + To route directly to the Kubernetes service, + one can use the `traefik.ingress.kubernetes.io/service.nativelb` annotation on the Kubernetes service. + It controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + + One alternative is to use an `ExternalName` service to forward requests to the Kubernetes service through DNS. + To do so, one must [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, diff --git a/docs/content/routing/providers/kv.md b/docs/content/routing/providers/kv.md index bce4d7703..a54ef1c61 100644 --- a/docs/content/routing/providers/kv.md +++ b/docs/content/routing/providers/kv.md @@ -406,21 +406,13 @@ You can declare TCP Routers and/or Services using KV. #### TCP Services -??? info "`traefik/tcp/services//loadbalancer/servers//url`" +??? info "`traefik/tcp/services//loadbalancer/servers//address`" See [servers](../services/index.md#servers) for more information. | 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 deleted file mode 100644 index 19a8a8dde..000000000 --- a/docs/content/routing/providers/marathon.md +++ /dev/null @@ -1,536 +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.terminationdelay`" - - See [termination delay](../services/index.md#termination-delay) for more information. - - ```json - "traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay": "100" - ``` - -??? 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" - ``` - -### 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/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 deleted file mode 100644 index 7d392889e..000000000 --- a/docs/content/routing/providers/rancher.md +++ /dev/null @@ -1,536 +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.terminationdelay`" - - See [termination delay](../services/index.md#termination-delay) for more information. - - ```yaml - - "traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay=100" - ``` - -??? 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" - ``` - -### 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..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), [rancher](../providers/rancher.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/routing/services/index.md b/docs/content/routing/services/index.md index 5e2766f0e..c809392f4 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_ @@ -555,17 +555,17 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport namespace: default spec: - serverName: "test" + serverName: "test" ``` -#### `Certificates` +#### `certificates` _Optional_ @@ -590,14 +590,14 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport 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` @@ -632,14 +632,14 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport namespace: default spec: - insecureSkipVerify: true + insecureSkipVerify: true ``` #### `rootCAs` @@ -665,14 +665,14 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport 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` @@ -705,14 +705,14 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport 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,15 +729,21 @@ http: disableHTTP2: true ``` +```toml tab="File (TOML)" +## Dynamic configuration +[http.serversTransports.mytransport] + disableHTTP2 = true +``` + ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport 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,15 +760,21 @@ http: peerCertURI: foobar ``` +```toml tab="File (TOML)" +## Dynamic configuration +[http.serversTransports.mytransport] + peerCertURI = "foobar" +``` + ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport namespace: default spec: - peerCertURI: foobar + peerCertURI: foobar ``` #### `spiffe` @@ -807,7 +807,7 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport @@ -842,7 +842,7 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport @@ -880,7 +880,7 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport @@ -916,15 +916,15 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport namespace: default spec: - forwardingTimeouts: - responseHeaderTimeout: "1s" + forwardingTimeouts: + responseHeaderTimeout: "1s" ``` ##### `forwardingTimeouts.idleConnTimeout` @@ -950,15 +950,15 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport namespace: default spec: - forwardingTimeouts: - idleConnTimeout: "1s" + forwardingTimeouts: + idleConnTimeout: "1s" ``` ##### `forwardingTimeouts.readIdleTimeout` @@ -988,15 +988,15 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport namespace: default spec: - forwardingTimeouts: - readIdleTimeout: "1s" + forwardingTimeouts: + readIdleTimeout: "1s" ``` ##### `forwardingTimeouts.pingTimeout` @@ -1022,15 +1022,15 @@ http: ``` ```yaml tab="Kubernetes" -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport 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.io/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.io/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.io/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.io/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.io/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.io/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.io/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.io/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.io/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.io/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.io/v1alpha1 +kind: ServersTransportTCP +metadata: + name: mytransport + namespace: default + +spec: + spiffe: + trustDomain: "spiffe://trust-domain" +``` + ## Configuring UDP Services ### General diff --git a/docs/content/traefik-hub/index.md b/docs/content/traefik-hub/index.md index a6c57cee9..5c6698e9d 100644 --- a/docs/content/traefik-hub/index.md +++ b/docs/content/traefik-hub/index.md @@ -2,7 +2,7 @@ ## Overview -Once the Traefik Hub Experimental feature is enabled in Traefik, +Once the Traefik Hub feature is enabled in Traefik, Traefik and its local agent communicate together. This agent can: @@ -27,7 +27,6 @@ This agent can: * Traefik Hub is compatible with Traefik Proxy 2.7 or later. * The Traefik Hub Agent must be installed to connect to the Traefik Hub platform. - * Activate this feature in the experimental section of the static configuration. !!! information "Configuration Discovery" @@ -38,9 +37,6 @@ This agent can: !!! example "Minimal Static Configuration to Activate Traefik Hub for Docker" ```yaml tab="File (YAML)" - experimental: - hub: true - hub: tls: insecure: true @@ -51,9 +47,6 @@ This agent can: ``` ```toml tab="File (TOML)" - [experimental] - hub = true - [hub] [hub.tls] insecure = true @@ -64,7 +57,6 @@ This agent can: ``` ```bash tab="CLI" - --experimental.hub --hub.tls.insecure --metrics.prometheus.addrouterslabels ``` @@ -72,9 +64,6 @@ This agent can: !!! example "Minimal Static Configuration to Activate Traefik Hub for Kubernetes" ```yaml tab="File (YAML)" - experimental: - hub: true - hub: {} metrics: @@ -83,9 +72,6 @@ This agent can: ``` ```toml tab="File (TOML)" - [experimental] - hub = true - [hub] [metrics] @@ -94,7 +80,6 @@ This agent can: ``` ```bash tab="CLI" - --experimental.hub --hub --metrics.prometheus.addrouterslabels ``` diff --git a/docs/content/user-guides/crd-acme/04-ingressroutes.yml b/docs/content/user-guides/crd-acme/04-ingressroutes.yml index 6c4616365..6f57d99f5 100644 --- a/docs/content/user-guides/crd-acme/04-ingressroutes.yml +++ b/docs/content/user-guides/crd-acme/04-ingressroutes.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: simpleingressroute @@ -14,7 +14,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: ingressroutetls diff --git a/docs/content/user-guides/crd-acme/05-tlsoption.yml b/docs/content/user-guides/crd-acme/05-tlsoption.yml index f29d9bcd7..a94a610dc 100644 --- a/docs/content/user-guides/crd-acme/05-tlsoption.yml +++ b/docs/content/user-guides/crd-acme/05-tlsoption.yml @@ -1,5 +1,5 @@ --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default diff --git a/docs/content/user-guides/crd-acme/index.md b/docs/content/user-guides/crd-acme/index.md index 67953a85b..7eac2b9f8 100644 --- a/docs/content/user-guides/crd-acme/index.md +++ b/docs/content/user-guides/crd-acme/index.md @@ -49,10 +49,10 @@ and the RBAC authorization resources which will be referenced through the `servi ```bash # Install Traefik Resource Definitions: -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml # Install RBAC for Traefik: -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml ``` ### Services @@ -60,7 +60,7 @@ kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/con Then, the services. One for Traefik itself, and one for the app it routes for, i.e. in this case our demo HTTP server: [whoami](https://github.com/traefik/whoami). ```bash -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/content/user-guides/crd-acme/02-services.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/user-guides/crd-acme/02-services.yml ``` ```yaml @@ -73,7 +73,7 @@ Next, the deployments, i.e. the actual pods behind the services. Again, one pod for Traefik, and one for the whoami app. ```bash -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/content/user-guides/crd-acme/03-deployments.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/user-guides/crd-acme/03-deployments.yml ``` ```yaml @@ -100,7 +100,7 @@ Look it up. We can now finally apply the actual ingressRoutes, with: ```bash -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/content/user-guides/crd-acme/04-ingressroutes.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/user-guides/crd-acme/04-ingressroutes.yml ``` ```yaml @@ -126,7 +126,7 @@ Nowadays, TLS v1.0 and v1.1 are deprecated. In order to force TLS v1.2 or later on all your IngressRoute, you can define the `default` TLSOption: ```bash -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/content/user-guides/crd-acme/05-tlsoption.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.0/docs/content/user-guides/crd-acme/05-tlsoption.yml ``` ```yaml 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 91b163347..3237cc82e 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: 'Traefik Labs • Copyright © 2016-2023' extra_javascript: - assets/js/hljs/highlight.pack.js # Download from https://highlightjs.org/download/ and enable YAML, TOML and Dockerfile @@ -81,8 +81,6 @@ nav: - 'Consul Catalog': 'providers/consul-catalog.md' - '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' @@ -102,8 +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' - - 'Rancher': 'routing/providers/rancher.md' - 'KV': 'routing/providers/kv.md' - 'HTTPS & TLS': - 'Overview': 'https/overview.md' @@ -155,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' @@ -172,7 +167,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': @@ -208,8 +202,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' - - 'Rancher': 'reference/dynamic-configuration/rancher.md' - 'Deprecation Notices': - 'Releases': 'deprecation/releases.md' - 'Features': 'deprecation/features.md' diff --git a/docs/scripts/verify.sh b/docs/scripts/verify.sh index 830fb448e..970d18988 100755 --- a/docs/scripts/verify.sh +++ b/docs/scripts/verify.sh @@ -22,7 +22,7 @@ find "${PATH_TO_SITE}" -type f -not -path "/app/site/theme/*" \ --alt_ignore="/traefikproxy-vertical-logo-color.svg/" \ --http_status_ignore="0,500,501,503" \ --file_ignore="/404.html/" \ - --url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/,/www.cloudxns.net/,/www.vultr.com/,/vscale.io/,/hetzner.com/,/docs.github.com/,/njal.la/,/www.wedos.com/" \ + --url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/,/www.cloudxns.net/,/www.vultr.com/,/vscale.io/,/hetzner.com/,/docs.github.com/,/njal.la/,/www.wedos.com/,/www.reg.ru/" \ '{}' 1>/dev/null ## HTML-proofer options at https://github.com/gjtorikian/html-proofer#configuration diff --git a/exp.Dockerfile b/exp.Dockerfile index bb2fc4997..843f8ca0f 100644 --- a/exp.Dockerfile +++ b/exp.Dockerfile @@ -12,7 +12,7 @@ RUN yarn install RUN yarn build # BUILD -FROM golang:1.19-alpine as gobuild +FROM golang:1.20-alpine as gobuild RUN apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ && update-ca-certificates \ diff --git a/go.mod b/go.mod index 47c37943d..a083b62ce 100644 --- a/go.mod +++ b/go.mod @@ -1,33 +1,32 @@ -module github.com/traefik/traefik/v2 +module github.com/traefik/traefik/v3 -go 1.19 +go 1.20 require ( github.com/BurntSushi/toml v1.2.1 github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61 - github.com/Masterminds/sprig/v3 v3.2.2 + github.com/Masterminds/sprig/v3 v3.2.3 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 github.com/davecgh/go-spew v1.1.1 github.com/docker/cli v20.10.11+incompatible github.com/docker/compose/v2 v2.0.1 - github.com/docker/docker v20.10.7+incompatible + github.com/docker/docker v20.10.21+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-acme/lego/v4 v4.10.2 github.com/go-check/check v0.0.0-00010101000000-000000000000 github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea github.com/golang/protobuf v1.5.2 github.com/google/go-github/v28 v28.1.1 github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.5.0 - github.com/hashicorp/consul v1.10.4 + github.com/hashicorp/consul v1.10.12 github.com/hashicorp/consul/api v1.14.0 github.com/hashicorp/go-hclog v1.2.0 github.com/hashicorp/go-multierror v1.1.1 @@ -44,7 +43,6 @@ require ( github.com/kvtools/redis v1.0.2 github.com/kvtools/valkeyrie v1.0.0 github.com/kvtools/zookeeper v1.0.2 - github.com/lucas-clemente/quic-go v0.28.1 github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f github.com/miekg/dns v1.1.50 github.com/mitchellh/copystructure v1.2.0 @@ -59,43 +57,43 @@ 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/quic-go/quic-go v0.33.0 github.com/rs/zerolog v1.28.0 github.com/sirupsen/logrus v1.9.0 github.com/spiffe/go-spiffe/v2 v2.1.1 github.com/stretchr/testify v1.8.1 github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 github.com/tailscale/tscert v0.0.0-20220316030059-54bbcb9f74e2 - github.com/traefik/paerser v0.1.9 - github.com/traefik/yaegi v0.14.3 + github.com/traefik/paerser v0.2.0 + github.com/traefik/yaegi v0.15.0 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-lib v2.2.0+incompatible github.com/unrolled/render v1.0.2 github.com/unrolled/secure v1.0.9 github.com/vdemeester/shakers v0.1.0 - github.com/vulcand/oxy/v2 v2.0.0-20221121151423-d5cb734e4467 + github.com/vulcand/oxy/v2 v2.0.0-20230227135449-a0e9f7ff1040 github.com/vulcand/predicate v1.2.0 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 - golang.org/x/exp v0.0.0-20221114191408-850992195362 + 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-20221205204356-47842c84f3db golang.org/x/mod v0.6.0 - golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 - golang.org/x/text v0.5.0 - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 + golang.org/x/net v0.7.0 + golang.org/x/text v0.7.0 + golang.org/x/time v0.3.0 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 +107,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 @@ -129,9 +127,9 @@ require ( github.com/DataDog/sketches-go v1.2.1 // indirect github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect - github.com/Microsoft/hcsshim v0.8.23 // indirect + github.com/Microsoft/hcsshim v0.8.24 // indirect github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect @@ -147,16 +145,15 @@ require ( github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/buger/goterm v1.0.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/cheekybits/genny v1.0.0 // indirect github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect github.com/circonus-labs/circonusllhist v0.1.3 // indirect github.com/civo/civogo v0.3.11 // indirect github.com/cloudflare/cloudflare-go v0.49.0 // indirect github.com/compose-spec/godotenv v1.0.0 // indirect - github.com/containerd/cgroups v1.0.1 // indirect - github.com/containerd/console v1.0.2 // indirect - github.com/containerd/containerd v1.5.9 // indirect - github.com/containerd/continuity v0.1.0 // indirect + github.com/containerd/cgroups v1.0.3 // indirect + github.com/containerd/console v1.0.3 // indirect + github.com/containerd/containerd v1.5.16 // indirect + github.com/containerd/continuity v0.3.0 // indirect github.com/containerd/typeurl v1.0.2 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534 // indirect @@ -169,12 +166,11 @@ require ( github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e // indirect github.com/dnsimple/dnsimple-go v0.71.1 // indirect github.com/docker/buildx v0.5.2-0.20210422185057-908a856079fc // indirect - github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker-credential-helpers v0.6.4-0.20210125172408-38bea2ce277a // indirect 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 @@ -187,6 +183,7 @@ require ( github.com/fvbommel/sortorder v1.0.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.0.1 // indirect + github.com/go-jose/go-jose/v3 v3.0.0 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -209,14 +206,16 @@ require ( github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // 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 @@ -230,11 +229,11 @@ require ( github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/memberlist v0.3.1 // indirect - github.com/hashicorp/raft v1.3.2 // indirect + github.com/hashicorp/raft v1.3.6 // indirect github.com/hashicorp/raft-autopilot v0.1.5 // indirect github.com/hashicorp/serf v0.9.7 // indirect github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493 // indirect - github.com/huandu/xstrings v1.3.2 // indirect + github.com/huandu/xstrings v1.3.3 // indirect github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect @@ -262,15 +261,10 @@ require ( github.com/mailgun/multibuf v0.1.2 // indirect github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/marten-seemann/qpack v0.2.1 // indirect - github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect - github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect - github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect - github.com/marten-seemann/qtls-go1-19 v0.1.0-beta.1 // indirect github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/miekg/pkcs11 v1.0.3 // indirect github.com/mimuret/golang-iij-dpf v0.7.1 // indirect @@ -281,7 +275,7 @@ require ( github.com/moby/buildkit v0.8.2-0.20210401015549-df49b648c8bf // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/sys/mount v0.2.0 // indirect - github.com/moby/sys/mountinfo v0.4.1 // indirect + github.com/moby/sys/mountinfo v0.5.0 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -295,11 +289,10 @@ require ( github.com/nrdcg/goinwx v0.8.1 // indirect github.com/nrdcg/namesilo v0.2.1 // indirect github.com/nrdcg/porkbun v0.1.1 // indirect - github.com/nxadm/tail v1.4.8 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect + github.com/onsi/ginkgo/v2 v2.2.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect - github.com/opencontainers/runc v1.0.3 // indirect + github.com/opencontainers/runc v1.1.4 // indirect github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect github.com/ovh/go-ovh v1.1.0 // indirect @@ -308,6 +301,9 @@ require ( github.com/pquerna/otp v1.3.0 // indirect github.com/prometheus/common v0.35.0 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/quic-go/qpack v0.4.0 // indirect + github.com/quic-go/qtls-go1-19 v0.2.1 // indirect + github.com/quic-go/qtls-go1-20 v0.1.1 // indirect github.com/rs/cors v1.7.0 // indirect github.com/sacloud/api-client-go v0.2.1 // indirect github.com/sacloud/go-http v0.1.2 // indirect @@ -333,6 +329,7 @@ require ( github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect github.com/transip/gotransip/v6 v6.17.0 // indirect github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect + github.com/ultradns/ultradns-go-sdk v1.4.0-20221107152238-f3f1d1d // indirect github.com/vinyldns/go-vinyldns v0.9.16 // indirect github.com/vultr/govultr/v2 v2.17.2 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect @@ -347,8 +344,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 @@ -356,22 +353,21 @@ require ( go.uber.org/zap v1.21.0 // indirect go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect - golang.org/x/crypto v0.1.0 // indirect + golang.org/x/crypto v0.5.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/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/oauth2 v0.4.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect + google.golang.org/api v0.98.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 gopkg.in/ns1/ns1-go.v2 v2.6.5 // indirect - gopkg.in/square/go-jose.v2 v2.6.0 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect + gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect inet.af/netaddr v0.0.0-20220617031823-097006376321 // indirect @@ -387,7 +383,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 ) @@ -397,5 +392,3 @@ replace github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402 // ambiguous import: found package github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http in multiple modules // tencentcloud uses monorepo with multimodule but the go.mod files are incomplete. exclude github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible - -// replace github.com/go-logr/logr => github.com/go-logr/logr v0.4.0 diff --git a/go.sum b/go.sum index 629581f80..baf987523 100644 --- a/go.sum +++ b/go.sum @@ -2,9 +2,7 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxo bitbucket.org/liamstask/goose v0.0.0-20150115234039-8488cc47d90c/go.mod h1:hSVuE3qU7grINVSwrmzHfpg9k87ALBk+XaualNyUzI4= cloud.google.com/go v0.25.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= @@ -31,17 +29,30 @@ cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWc 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.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +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 v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +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/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +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= @@ -51,12 +62,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/AlecAivazis/survey/v2 v2.2.3 h1:utJR2X4Ibp2fBxdjalQUiMFf3zfQNjA15YE8+ftlKEs= github.com/AlecAivazis/survey/v2 v2.2.3/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= @@ -146,10 +153,10 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= -github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.4.3/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= @@ -171,8 +178,8 @@ github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2 github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.23 h1:47MSwtKGXet80aIn+7h4YI6fwPmwIghAnsx2aOUrG2M= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/hcsshim v0.8.24 h1:jP+GMeRXIR1sH1kG4lJr9ShmSjVrua5jmFZDtfYGkn4= +github.com/Microsoft/hcsshim v0.8.24/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -221,7 +228,6 @@ github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9or github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= @@ -261,7 +267,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= @@ -272,13 +277,11 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/goterm v1.0.0 h1:ZB6uUlY8+sjJyFGzz2WpRqX2XYPeXVgtZAOJMwOsTWM= github.com/buger/goterm v1.0.0/go.mod h1:16STi3LquiscTIHA8SXUNKEa/Cnu4ZHBH8NsCaWgso0= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/bugsnag-go v1.4.1/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/bugsnag-go v1.5.0 h1:tP8hiPv1pGGW3LA6LKy5lW6WG+y9J2xWUdPd3WC452k= @@ -294,8 +297,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= @@ -305,8 +308,7 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= -github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= -github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -315,6 +317,7 @@ github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLI github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= @@ -366,15 +369,17 @@ github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1 github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= +github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= github.com/containerd/console v1.0.0/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -392,8 +397,8 @@ github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09Zvgq github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= github.com/containerd/containerd v1.5.5/go.mod h1:oSTh0QpT1w6jYcGmbiSbxv9OSQYaa88mPyWIuU79zyo= -github.com/containerd/containerd v1.5.9 h1:rs6Xg1gtIxaeyG+Smsb/0xaSDu1VgFhOCKBXxMxbsF4= -github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= +github.com/containerd/containerd v1.5.16 h1:WsTS9tV0vQmRxkWAiiaoasHJ20jqVxVA15s93Bs4GIU= +github.com/containerd/containerd v1.5.16/go.mod h1:bVZZA+0blg2Lw6+I4xDml7L3gum0LsFKe3TnFELlSFw= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -401,8 +406,9 @@ github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= @@ -461,8 +467,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= @@ -476,7 +480,6 @@ github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmf github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -499,6 +502,7 @@ github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= @@ -556,15 +560,17 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.0.0-20200511152416-a93e9eb0e95c/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20180531152204-71cd53e4a197/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20181229214054-f76d6a078d88/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v17.12.0-ce-rc1.0.20200730172259-9f28837c1d93+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.21+incompatible h1:UTLdBmHk3bEY+w8qeO5KttOhy6OmXWsl/FEet9Uswog= +github.com/docker/docker v20.10.21+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/docker-credential-helpers v0.6.4-0.20210125172408-38bea2ce277a h1:1DndKi+f9qs3AexOfI6di7RkWcWlNHzdqHu1cX19/ac= github.com/docker/docker-credential-helpers v0.6.4-0.20210125172408-38bea2ce277a/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= @@ -593,8 +599,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= @@ -652,11 +656,9 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.0/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s= @@ -669,8 +671,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= @@ -683,10 +683,9 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-acme/lego/v4 v4.9.1 h1:n9Z5MQwANeGSQKlVE3bEh9SDvAySK9oVYOKCGCESqQE= -github.com/go-acme/lego/v4 v4.9.1/go.mod h1:g3JRUyWS3L/VObpp4bCxzJftKyf/Wba8QrSSnoiqjg4= +github.com/go-acme/lego/v4 v4.10.2 h1:5eW3qmda5v/LP21v1Hj70edKY1jeFZQwO617tdkwp6Q= +github.com/go-acme/lego/v4 v4.10.2/go.mod h1:EMbf0Jmqwv94nJ5WL9qWnSXIBZnvsS9gNypansHGc6U= github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= @@ -696,6 +695,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= +github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= @@ -782,6 +783,7 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6 github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= @@ -818,7 +820,6 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -877,10 +878,10 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.0.0-20191015185424-71da34e4d9b3/go.mod h1:ZXFeSndFcK4vB1NR4voH1Zm38K7ViUNiYtfIBDxrwf0= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo= github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI= @@ -912,6 +913,7 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe 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 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= 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= @@ -923,12 +925,19 @@ 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/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/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +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 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.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +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= @@ -936,6 +945,7 @@ github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTV github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= github.com/gophercloud/gophercloud v1.0.0 h1:9nTGx0jizmHxDobe4mck89FyQHVyA3CaXLIUSGJjP9k= @@ -946,6 +956,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= @@ -964,12 +979,12 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaD github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= 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= @@ -978,8 +993,8 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok= github.com/hanwen/go-fuse/v2 v2.0.4-0.20201208195215-4a458845028b/go.mod h1:0EQM6aH2ctVpvZ6a+onrQ/vaykxh2GH7hy3e13vzTUY= -github.com/hashicorp/consul v1.10.4 h1:rqKmYP49KnCSSxbiaJ4J2CnLA3zUAmI6KwASKxmPqFc= -github.com/hashicorp/consul v1.10.4/go.mod h1:3EJeqDz7W0LQJ2I4KzRtZZBgG5H80kZvgEtOLis/yCo= +github.com/hashicorp/consul v1.10.12 h1:xMazys3KaH5JsZS4Ra6KEAXO0nAj20EsTpsDyhd/3Do= +github.com/hashicorp/consul v1.10.12/go.mod h1:z9c9dZQI0/tKODT1x3s32wLbHyLfkG8G+FRYtn36UAc= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.10.0/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk= @@ -1069,7 +1084,6 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/memberlist v0.2.4/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.3.1 h1:MXgUXLqva1QvpVEDQW1IQLG0wivQAtmFlHRQ+1vWZfM= github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= @@ -1078,8 +1092,8 @@ github.com/hashicorp/nomad/api v0.0.0-20220506174431-b5665129cd1f h1:jSBbBJcPca4 github.com/hashicorp/nomad/api v0.0.0-20220506174431-b5665129cd1f/go.mod h1:b/AoT79m3PEpb6tKCFKva/M+q1rKJNUk5mdu1S8DymM= github.com/hashicorp/raft v1.1.1/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= -github.com/hashicorp/raft v1.3.2 h1:j2tqHqFnDdWCepLxzuo3b6WzS2krIweBrvEoqBbWMTo= -github.com/hashicorp/raft v1.3.2/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= +github.com/hashicorp/raft v1.3.6 h1:v5xW5KzByoerQlN/o31VJrFNiozgzGyDoMgDJgXpsto= +github.com/hashicorp/raft v1.3.6/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= github.com/hashicorp/raft-autopilot v0.1.5 h1:onEfMH5uHVdXQqtas36zXUHEZxLdsJVu/nXHLcLdL1I= github.com/hashicorp/raft-autopilot v0.1.5/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/UyyqIMj/pOISIfhArw= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= @@ -1097,9 +1111,8 @@ github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493/go.mod h1:CtWFDAQg github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= -github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -1140,7 +1153,6 @@ github.com/jcchavezs/porto v0.1.0 h1:Xmxxn25zQMmgE7/yHYmh19KcItG81hIwfbEEFnd6w/Q github.com/jcchavezs/porto v0.1.0/go.mod h1:fESH0gzDHiutHRdX2hv27ojnOVFco37hg1W6E9EZF4A= github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03 h1:FUwcHNlEqkqLjLBdCp5PRlCFijNjvcYANOZXzCfXwCM= github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/gorm v1.9.2/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= github.com/jinzhu/gorm v1.9.11 h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE= @@ -1219,7 +1231,6 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= @@ -1276,9 +1287,6 @@ github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHS github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/looplab/fsm v0.1.0 h1:Qte7Zdn/5hBNbXzP7yxVU4OIFHWXBovyTT2LaBTyC20= github.com/looplab/fsm v0.1.0/go.mod h1:m2VaOfDHxqXBBMgc26m6yUOwkFn8H2AlJDE+jd/uafI= -github.com/lucas-clemente/quic-go v0.28.1 h1:Uo0lvVxWg5la9gflIF9lwa39ONq85Xq2D91YNEIslzU= -github.com/lucas-clemente/quic-go v0.28.1/go.mod h1:oGz5DKK41cJt5+773+BSO9BXDsREY4HLf7+0odGAPO0= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1293,7 +1301,6 @@ github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51/go.mod h1:RYmqHb github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f h1:ZZYhg16XocqSKPGNQAe0aeweNtFxuedbwwb4fSlg7h4= github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f/go.mod h1:8heskWJ5c0v5J9WH89ADhyal1DOZcayll8fSbhB+/9A= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= @@ -1301,16 +1308,6 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs= -github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= -github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ= -github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ= -github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= -github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM= -github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= -github.com/marten-seemann/qtls-go1-19 v0.1.0-beta.1 h1:7m/WlWcSROrcK5NxuXaxYD32BZqe/LEEnBrWcH/cOqQ= -github.com/marten-seemann/qtls-go1-19 v0.1.0-beta.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -1330,8 +1327,8 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1343,11 +1340,11 @@ github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsO github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -1380,6 +1377,7 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y= github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -1408,8 +1406,9 @@ github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7s github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= @@ -1450,8 +1449,6 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= @@ -1488,13 +1485,12 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= +github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI= +github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -1504,12 +1500,11 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -1529,9 +1524,8 @@ github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rm github.com/opencontainers/runc v1.0.0-rc92/go.mod h1:X1zlU4p7wOlX4+WRCz+hvlRv8phdL7UqbYD+vQwNMmE= github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k= -github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg= +github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -1543,8 +1537,9 @@ github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.m github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= @@ -1555,7 +1550,6 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI= @@ -1608,7 +1602,6 @@ github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prY github.com/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs= github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= @@ -1632,7 +1625,6 @@ github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -1648,7 +1640,6 @@ github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+ github.com/prometheus/common v0.35.0 h1:Eyr+Pw2VymWejHqCugNaQXkAi6KayVNxaHeu6khmFBE= github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1668,8 +1659,14 @@ 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/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A= +github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= +github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= +github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= 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= @@ -1716,6 +1713,7 @@ github.com/sean-/pager v0.0.0-20180208200047-666be9bf53b5/go.mod h1:BeybITEsBEg6 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -1724,29 +1722,7 @@ github.com/shirou/gopsutil/v3 v3.20.10/go.mod h1:igHnfak0qnw1biGeI2qKQvu0ZkwvEkU github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -1772,8 +1748,6 @@ github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e h1:3OgWYFw7jxCZPc github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e/go.mod h1:fKZCUVdirrxrBpwd9wb+lSoVixvpwAu8eHzbQB2tums= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -1845,7 +1819,6 @@ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tailscale/tscert v0.0.0-20220316030059-54bbcb9f74e2 h1:xwMw7LFhV9dbvot9A7NLClP9udqbjrQlIwWMH8e7uiQ= github.com/tailscale/tscert v0.0.0-20220316030059-54bbcb9f74e2/go.mod h1:hL4gB6APAasMR2NNi/JHzqKkxW3EPQlFgLEq9PMi2t0= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 h1:mmz27tVi2r70JYnm5y0Zk8w0Qzsx+vfUw3oqSyrEfP8= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= @@ -1864,10 +1837,10 @@ github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/ github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305 h1:y/1cL5AL2oRcfzz8CAHHhR6kDDfIOT0WEyH5k40sccM= github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305/go.mod h1:gXOLibKqQTRAVuVZ9gX7G9Ykky8ll8yb4slxsEMoY0c= -github.com/traefik/paerser v0.1.9 h1:x5hZafOt/yogLvr6upoSOYIAn2nh2GsnLb236MOzd4I= -github.com/traefik/paerser v0.1.9/go.mod h1:Dk3Bfz6Zyj13/S8pJyRdx/FNvXlsVRVbtp0UK4ZSiA0= -github.com/traefik/yaegi v0.14.3 h1:LqA0k8DKwvRMc+msfQjNusphHJc+r6WC5tZU5TmUFOM= -github.com/traefik/yaegi v0.14.3/go.mod h1:AVRxhaI2G+nUsaM1zyktzwXn69G3t/AuTDrCiTds9p0= +github.com/traefik/paerser v0.2.0 h1:zqCLGSXoNlcBd+mzqSCLjon/I6phqIjeJL2xFB2ysgQ= +github.com/traefik/paerser v0.2.0/go.mod h1:afzaVcgF8A+MpTnPG4wBr4whjanCSYA6vK5RwaYVtRc= +github.com/traefik/yaegi v0.15.0 h1:ScDDfQXTT75rKvcsMcP84rOxHsZ8b6NiQJyGocGDB7g= +github.com/traefik/yaegi v0.15.0/go.mod h1:AVRxhaI2G+nUsaM1zyktzwXn69G3t/AuTDrCiTds9p0= github.com/transip/gotransip/v6 v6.17.0 h1:2RCyqYqz5+Ej8z96EyE4sf6tQrrfEBaFDO0LliSl6+8= github.com/transip/gotransip/v6 v6.17.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= @@ -1885,6 +1858,8 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= +github.com/ultradns/ultradns-go-sdk v1.4.0-20221107152238-f3f1d1d h1:pLMpEtrkiaeA2NY6CzA2+K75YnY6c5ka02SbxQ9YgSo= +github.com/ultradns/ultradns-go-sdk v1.4.0-20221107152238-f3f1d1d/go.mod h1:IgdoVzrGYzq4H4IGI0DAVnM3CbcuQDSxEP4s/j6cztI= github.com/unrolled/render v1.0.2 h1:dGS3EmChQP3yOi1YeFNO/Dx+MbWZhdvhQJTXochM5bs= github.com/unrolled/render v1.0.2/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= github.com/unrolled/secure v1.0.9 h1:BWRuEb1vDrBFFDdbCnKkof3gZ35I/bnHGyt0LB0TNyQ= @@ -1900,8 +1875,6 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vdemeester/shakers v0.1.0 h1:K+n9sSyUCg2ywmZkv+3c7vsYZfivcfKhMh8kRxCrONM= github.com/vdemeester/shakers v0.1.0/go.mod h1:IZ1HHynUOQt32iQ3rvAeVddXLd19h/6LWiKsh9RZtAQ= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/vinyldns/go-vinyldns v0.9.16 h1:GZJStDkcCk1F1AcRc64LuuMh+ENL8pHA0CVd4ulRMcQ= github.com/vinyldns/go-vinyldns v0.9.16/go.mod h1:5qIJOdmzAnatKjurI+Tl4uTus7GJKJxb+zitufjHs3Q= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= @@ -1914,8 +1887,8 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/vulcand/oxy/v2 v2.0.0-20221121151423-d5cb734e4467 h1:Dbv3KJLgwtDKLpCZzTf1ISeG5ZYudPaLfTdYi4O2dSU= -github.com/vulcand/oxy/v2 v2.0.0-20221121151423-d5cb734e4467/go.mod h1:0kOEB8mKzSeGHknF53gTM47UEvQnPoAPnM+58baqn2o= +github.com/vulcand/oxy/v2 v2.0.0-20230227135449-a0e9f7ff1040 h1:L+nLher4530BUkyOpxxBsl2SLbrD4fSlDH5rGZ8DRBM= +github.com/vulcand/oxy/v2 v2.0.0-20230227135449-a0e9f7ff1040/go.mod h1:A2voDnpONyqdplUDK0lt5y4XHLiBXPBw7iQES8+ZWRw= github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50= github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= @@ -1947,6 +1920,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= @@ -1985,7 +1959,6 @@ go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsX go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -1998,32 +1971,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= @@ -2035,6 +2008,7 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= @@ -2050,22 +2024,18 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE= go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA= go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4= go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -2076,15 +2046,14 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191028145041-f83a4685e152/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -2102,8 +2071,9 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2118,12 +2088,11 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20221114191408-850992195362 h1:NoHlPRbyl1VFI6FjwHtPQCN7wAMXI6cKcqrmXhOOfBQ= -golang.org/x/exp v0.0.0-20221114191408-850992195362/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -2149,6 +2118,7 @@ golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hM golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2158,8 +2128,6 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2167,7 +2135,6 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -2220,16 +2187,22 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 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= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2247,9 +2220,12 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ 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/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= 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= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2261,15 +2237,16 @@ 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-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/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= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2279,7 +2256,6 @@ golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2385,24 +2361,40 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc 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-20210906170528-6f6e22806c34/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-20211025201205-69cdffdb9359/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-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2413,8 +2405,9 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2424,14 +2417,13 @@ golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2503,13 +2495,17 @@ 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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= 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-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/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= @@ -2517,9 +2513,6 @@ gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -2550,11 +2543,22 @@ google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNe 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.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.98.0 h1:yxZrcxXESimy6r6mdL5Q6EnZwmewDJK2dVg3g75s5Dg= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= 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= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2565,10 +2569,6 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6 google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -2617,6 +2617,7 @@ google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 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-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= 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= @@ -2632,14 +2633,35 @@ google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEc 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-20210909211513-a8c4777a87af/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-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +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= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -2673,11 +2695,16 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ 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.40.1/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.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= 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 v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +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/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= @@ -2746,9 +2773,8 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= @@ -2772,7 +2798,6 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81 gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2902,6 +2927,4 @@ sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/integration/access_log_test.go b/integration/access_log_test.go index d2f5715db..272a1b371 100644 --- a/integration/access_log_test.go +++ b/integration/access_log_test.go @@ -13,8 +13,8 @@ import ( "github.com/go-check/check" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" checker "github.com/vdemeester/shakers" ) diff --git a/integration/acme_test.go b/integration/acme_test.go index 73e9958bb..fe5fc413b 100644 --- a/integration/acme_test.go +++ b/integration/acme_test.go @@ -12,11 +12,11 @@ import ( "github.com/go-check/check" "github.com/miekg/dns" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/provider/acme" - "github.com/traefik/traefik/v2/pkg/testhelpers" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/provider/acme" + "github.com/traefik/traefik/v3/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/types" checker "github.com/vdemeester/shakers" ) diff --git a/integration/conf_throttling_test.go b/integration/conf_throttling_test.go index 6c4333b35..3a7b89baa 100644 --- a/integration/conf_throttling_test.go +++ b/integration/conf_throttling_test.go @@ -11,8 +11,8 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/config/dynamic" checker "github.com/vdemeester/shakers" ) diff --git a/integration/consul_catalog_test.go b/integration/consul_catalog_test.go index bdefbd4cc..bf0db5da1 100644 --- a/integration/consul_catalog_test.go +++ b/integration/consul_catalog_test.go @@ -9,7 +9,7 @@ import ( "github.com/go-check/check" "github.com/hashicorp/consul/api" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/consul_test.go b/integration/consul_test.go index 357f03dea..441d56db7 100644 --- a/integration/consul_test.go +++ b/integration/consul_test.go @@ -16,8 +16,8 @@ import ( "github.com/kvtools/valkeyrie" "github.com/kvtools/valkeyrie/store" "github.com/pmezard/go-difflib/difflib" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/api" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/api" checker "github.com/vdemeester/shakers" ) diff --git a/integration/docker_compose_test.go b/integration/docker_compose_test.go index 2c2969fe0..39347dca5 100644 --- a/integration/docker_compose_test.go +++ b/integration/docker_compose_test.go @@ -8,9 +8,9 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/api" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/api" + "github.com/traefik/traefik/v3/pkg/testhelpers" checker "github.com/vdemeester/shakers" ) diff --git a/integration/docker_test.go b/integration/docker_test.go index fe7051f7f..dad1ef809 100644 --- a/integration/docker_test.go +++ b/integration/docker_test.go @@ -9,7 +9,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/error_pages_test.go b/integration/error_pages_test.go index 436b2cc96..8a6deba89 100644 --- a/integration/error_pages_test.go +++ b/integration/error_pages_test.go @@ -2,11 +2,12 @@ package integration import ( "net/http" + "net/http/httptest" "os" "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) @@ -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/etcd_test.go b/integration/etcd_test.go index 1ffd92252..a9e9bb532 100644 --- a/integration/etcd_test.go +++ b/integration/etcd_test.go @@ -15,8 +15,8 @@ import ( "github.com/kvtools/valkeyrie" "github.com/kvtools/valkeyrie/store" "github.com/pmezard/go-difflib/difflib" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/api" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/api" checker "github.com/vdemeester/shakers" ) diff --git a/integration/file_test.go b/integration/file_test.go index 5537638c2..38c30db35 100644 --- a/integration/file_test.go +++ b/integration/file_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/fixtures/error_pages/simple.toml b/integration/fixtures/error_pages/simple.toml index a60f7393d..9ff846f74 100644 --- a/integration/fixtures/error_pages/simple.toml +++ b/integration/fixtures/error_pages/simple.toml @@ -31,7 +31,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/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index 4a7f19a66..37849dedc 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -6,9 +6,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: ingressroutes.traefik.containo.us + name: ingressroutes.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: IngressRoute listKind: IngressRouteList @@ -104,6 +104,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs + or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes @@ -274,9 +281,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: ingressroutetcps.traefik.containo.us + name: ingressroutetcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: IngressRouteTCP listKind: IngressRouteTCPList @@ -357,6 +364,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs + or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean port: anyOf: - type: integer @@ -373,15 +387,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. @@ -485,9 +500,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: ingressrouteudps.traefik.containo.us + name: ingressrouteudps.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: IngressRouteUDP listKind: IngressRouteUDPList @@ -542,6 +557,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs + or if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean port: anyOf: - type: integer @@ -583,9 +605,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: middlewares.traefik.containo.us + name: middlewares.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: Middleware listKind: MiddlewareList @@ -818,6 +840,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if + the only child is the Kubernetes Service clusterIP. The + Kubernetes Service itself does load-balance to the pods. + By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. @@ -1478,9 +1507,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: middlewaretcps.traefik.containo.us + name: middlewaretcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: MiddlewareTCP listKind: MiddlewareTCPList @@ -1550,9 +1579,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: serverstransports.traefik.containo.us + name: serverstransports.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: ServersTransport listKind: ServersTransportList @@ -1691,9 +1720,131 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: tlsoptions.traefik.containo.us + name: serverstransporttcps.traefik.io spec: - group: traefik.containo.us + group: traefik.io + 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/v3.0/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 +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: tlsoptions.traefik.io +spec: + group: traefik.io names: kind: TLSOption listKind: TLSOptionList @@ -1798,9 +1949,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: tlsstores.traefik.containo.us + name: tlsstores.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: TLSStore listKind: TLSStoreList @@ -1897,9 +2048,9 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.2 creationTimestamp: null - name: traefikservices.traefik.containo.us + name: traefikservices.traefik.io spec: - group: traefik.containo.us + group: traefik.io names: kind: TraefikService listKind: TraefikServiceList @@ -1966,6 +2117,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or + if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. @@ -2057,6 +2215,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or if the + only child is the Kubernetes Service clusterIP. The Kubernetes + Service itself does load-balance to the pods. By default, NativeLB + is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. By default, @@ -2154,6 +2319,13 @@ spec: description: Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. type: string + nativeLB: + description: NativeLB controls, when creating the load-balancer, + whether the LB's children are directly the pods IPs or + if the only child is the Kubernetes Service clusterIP. + The Kubernetes Service itself does load-balance to the + pods. By default, NativeLB is false. + type: boolean passHostHeader: description: PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service. diff --git a/integration/fixtures/k8s/03-ingressroute.yml b/integration/fixtures/k8s/03-ingressroute.yml index c040988b5..d00f4e34e 100644 --- a/integration/fixtures/k8s/03-ingressroute.yml +++ b/integration/fixtures/k8s/03-ingressroute.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/integration/fixtures/k8s/03-tlsoption.yml b/integration/fixtures/k8s/03-tlsoption.yml index 7c5df10fc..1d57c5065 100644 --- a/integration/fixtures/k8s/03-tlsoption.yml +++ b/integration/fixtures/k8s/03-tlsoption.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: mytlsoption diff --git a/integration/fixtures/k8s/03-tlsstore.yml b/integration/fixtures/k8s/03-tlsstore.yml index 5dea5d0fd..add5979cc 100644 --- a/integration/fixtures/k8s/03-tlsstore.yml +++ b/integration/fixtures/k8s/03-tlsstore.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSStore metadata: name: mytlsstore diff --git a/integration/fixtures/k8s/04-ingressroute.yml b/integration/fixtures/k8s/04-ingressroute.yml index 85643e638..2d8670c4a 100644 --- a/integration/fixtures/k8s/04-ingressroute.yml +++ b/integration/fixtures/k8s/04-ingressroute.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: mychain @@ -10,7 +10,7 @@ spec: - name: stripprefix --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: stripprefix @@ -22,7 +22,7 @@ spec: - /tobestripped --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test2.route diff --git a/integration/fixtures/k8s/05-ingressroutetcp.yml b/integration/fixtures/k8s/05-ingressroutetcp.yml index a717a1999..1059648f0 100644 --- a/integration/fixtures/k8s/05-ingressroutetcp.yml +++ b/integration/fixtures/k8s/05-ingressroutetcp.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test3.route diff --git a/integration/fixtures/k8s/05-ingressrouteudp.yml b/integration/fixtures/k8s/05-ingressrouteudp.yml index 358559c23..54da9a2c9 100644 --- a/integration/fixtures/k8s/05-ingressrouteudp.yml +++ b/integration/fixtures/k8s/05-ingressrouteudp.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test3.route diff --git a/integration/fixtures/k8s/06-ingressroute-traefikservices.yml b/integration/fixtures/k8s/06-ingressroute-traefikservices.yml index 3e096d1a7..d979bc425 100644 --- a/integration/fixtures/k8s/06-ingressroute-traefikservices.yml +++ b/integration/fixtures/k8s/06-ingressroute-traefikservices.yml @@ -1,5 +1,5 @@ --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror1 @@ -14,7 +14,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -29,7 +29,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test3.route @@ -45,7 +45,7 @@ spec: - name: wrr1 kind: TraefikService --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: api.route diff --git a/integration/fixtures/k8s/07-ingressroute-cross-namespace.yml b/integration/fixtures/k8s/07-ingressroute-cross-namespace.yml index fbdeb88a4..ef437e25b 100644 --- a/integration/fixtures/k8s/07-ingressroute-cross-namespace.yml +++ b/integration/fixtures/k8s/07-ingressroute-cross-namespace.yml @@ -20,7 +20,7 @@ spec: task: whoami --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test6.route @@ -65,7 +65,7 @@ spec: - name: test-errorpage --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr2 @@ -78,7 +78,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr3 @@ -92,7 +92,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: stripprefix2 @@ -104,7 +104,7 @@ spec: - /tobestripped --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-errorpage diff --git a/integration/fixtures/k8s/07-ingressroute-serverstransport.yml b/integration/fixtures/k8s/07-ingressroute-serverstransport.yml index aa1ff9ecc..8ad736917 100644 --- a/integration/fixtures/k8s/07-ingressroute-serverstransport.yml +++ b/integration/fixtures/k8s/07-ingressroute-serverstransport.yml @@ -1,5 +1,5 @@ --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: testst.route @@ -17,7 +17,7 @@ spec: serversTransport: mytransport --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: mytransport diff --git a/integration/fixtures/marathon/simple.toml b/integration/fixtures/k8s_ingressclass_disabled.toml similarity index 54% rename from integration/fixtures/marathon/simple.toml rename to integration/fixtures/k8s_ingressclass_disabled.toml index d43cdbc2e..8afc19e97 100644 --- a/integration/fixtures/marathon/simple.toml +++ b/integration/fixtures/k8s_ingressclass_disabled.toml @@ -6,17 +6,13 @@ 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 +[entryPoints] + [entryPoints.web] + address = ":8000" + +[providers.kubernetesIngress] + ingressClass = "traefik-keep" + disableIngressClassLookup = true diff --git a/integration/grpc_test.go b/integration/grpc_test.go index a18975864..bf96e1ece 100644 --- a/integration/grpc_test.go +++ b/integration/grpc_test.go @@ -12,8 +12,8 @@ import ( "github.com/go-check/check" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/integration/helloworld" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/helloworld" + "github.com/traefik/traefik/v3/integration/try" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" diff --git a/integration/headers_test.go b/integration/headers_test.go index 6e4b7e9b9..60fd59578 100644 --- a/integration/headers_test.go +++ b/integration/headers_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/healthcheck_test.go b/integration/healthcheck_test.go index 128a447e8..86a93b96d 100644 --- a/integration/healthcheck_test.go +++ b/integration/healthcheck_test.go @@ -10,7 +10,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/hostresolver_test.go b/integration/hostresolver_test.go index d76552016..e69e33dd9 100644 --- a/integration/hostresolver_test.go +++ b/integration/hostresolver_test.go @@ -5,7 +5,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/http_test.go b/integration/http_test.go index 6e18fcb80..6e28fa2d7 100644 --- a/integration/http_test.go +++ b/integration/http_test.go @@ -8,8 +8,8 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/config/dynamic" checker "github.com/vdemeester/shakers" ) diff --git a/integration/https_test.go b/integration/https_test.go index f16b390db..981470841 100644 --- a/integration/https_test.go +++ b/integration/https_test.go @@ -12,9 +12,9 @@ import ( "github.com/BurntSushi/toml" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" checker "github.com/vdemeester/shakers" ) diff --git a/integration/integration_test.go b/integration/integration_test.go index d71409d38..6c13e75b3 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -31,7 +31,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/sirupsen/logrus" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/logs" checker "github.com/vdemeester/shakers" ) @@ -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/k8s_test.go b/integration/k8s_test.go index bfb73d93c..5d54bc3e1 100644 --- a/integration/k8s_test.go +++ b/integration/k8s_test.go @@ -16,8 +16,8 @@ import ( "github.com/go-check/check" "github.com/pmezard/go-difflib/difflib" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/api" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/api" checker "github.com/vdemeester/shakers" ) @@ -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) @@ -204,7 +215,7 @@ func matchesConfig(wantConfig string, buf *bytes.Buffer) try.ResponseCondition { // The pods IPs are dynamic, so we cannot predict them, // which is why we have to ignore them in the comparison. rxURL := regexp.MustCompile(`"(url|address)":\s+(".*")`) - sanitizedExpected := rxURL.ReplaceAll(expected, []byte(`"$1": "XXXX"`)) + sanitizedExpected := rxURL.ReplaceAll(bytes.TrimSpace(expected), []byte(`"$1": "XXXX"`)) sanitizedGot := rxURL.ReplaceAll(got, []byte(`"$1": "XXXX"`)) rxServerStatus := regexp.MustCompile(`"http://.*?":\s+(".*")`) diff --git a/integration/keepalive_test.go b/integration/keepalive_test.go index df3bef575..a56cbdd48 100644 --- a/integration/keepalive_test.go +++ b/integration/keepalive_test.go @@ -9,7 +9,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/log_rotation_test.go b/integration/log_rotation_test.go index 241e09353..c753dc7ff 100644 --- a/integration/log_rotation_test.go +++ b/integration/log_rotation_test.go @@ -13,7 +13,7 @@ import ( "github.com/go-check/check" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) 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/proxy_protocol_test.go b/integration/proxy_protocol_test.go index 7ed8300af..40640bae7 100644 --- a/integration/proxy_protocol_test.go +++ b/integration/proxy_protocol_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/ratelimit_test.go b/integration/ratelimit_test.go index 5d45e8086..5edbf64b8 100644 --- a/integration/ratelimit_test.go +++ b/integration/ratelimit_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/redis_test.go b/integration/redis_test.go index d696ad670..a5f45bff7 100644 --- a/integration/redis_test.go +++ b/integration/redis_test.go @@ -15,8 +15,8 @@ import ( "github.com/kvtools/valkeyrie" "github.com/kvtools/valkeyrie/store" "github.com/pmezard/go-difflib/difflib" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/api" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/api" checker "github.com/vdemeester/shakers" ) 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/integration/rest_test.go b/integration/rest_test.go index d72f16314..1178fbb94 100644 --- a/integration/rest_test.go +++ b/integration/rest_test.go @@ -10,8 +10,8 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/config/dynamic" checker "github.com/vdemeester/shakers" ) diff --git a/integration/retry_test.go b/integration/retry_test.go index 6a146e5ce..29fc0e7d0 100644 --- a/integration/retry_test.go +++ b/integration/retry_test.go @@ -7,7 +7,7 @@ import ( "github.com/go-check/check" "github.com/gorilla/websocket" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/simple_test.go b/integration/simple_test.go index 41751d6a6..367c9aa17 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -18,8 +18,8 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/config/dynamic" checker "github.com/vdemeester/shakers" ) diff --git a/integration/tcp_test.go b/integration/tcp_test.go index b7a8b84c9..43a7158d0 100644 --- a/integration/tcp_test.go +++ b/integration/tcp_test.go @@ -13,7 +13,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/testdata/rawdata-crd-label-selector.json b/integration/testdata/rawdata-crd-label-selector.json index 63ace05eb..b5c9f1669 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" @@ -44,7 +45,7 @@ "url": "http://10.42.0.3:80" }, { - "url": "http://10.42.0.4:80" + "url": "http://10.42.0.6:80" } ], "passHostHeader": true, @@ -58,7 +59,7 @@ ], "serverStatus": { "http://10.42.0.3:80": "UP", - "http://10.42.0.4:80": "UP" + "http://10.42.0.6:80": "UP" } }, "noop@internal": { diff --git a/integration/testdata/rawdata-crd.json b/integration/testdata/rawdata-crd.json index a49ebddb2..81f397196 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" ], @@ -131,7 +136,7 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.6:80" + "url": "http://10.42.0.3:80" }, { "url": "http://10.42.0.7:80" @@ -147,7 +152,7 @@ "default-test-route-6b204d94623b3df4370c@kubernetescrd" ], "serverStatus": { - "http://10.42.0.6:80": "UP", + "http://10.42.0.3:80": "UP", "http://10.42.0.7:80": "UP" } }, @@ -155,7 +160,7 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.6:80" + "url": "http://10.42.0.3:80" }, { "url": "http://10.42.0.7:80" @@ -171,7 +176,7 @@ "default-test2-route-23c7f4c450289ee29016@kubernetescrd" ], "serverStatus": { - "http://10.42.0.6:80": "UP", + "http://10.42.0.3:80": "UP", "http://10.42.0.7:80": "UP" } }, @@ -179,7 +184,7 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.6:80" + "url": "http://10.42.0.3:80" }, { "url": "http://10.42.0.7:80" @@ -196,7 +201,7 @@ "default-testst-route-60ad45fcb5fc1f5f3629@kubernetescrd" ], "serverStatus": { - "http://10.42.0.6:80": "UP", + "http://10.42.0.3:80": "UP", "http://10.42.0.7:80": "UP" } }, @@ -204,7 +209,7 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.6:80" + "url": "http://10.42.0.3:80" }, { "url": "http://10.42.0.7:80" @@ -217,7 +222,7 @@ }, "status": "enabled", "serverStatus": { - "http://10.42.0.6:80": "UP", + "http://10.42.0.3:80": "UP", "http://10.42.0.7:80": "UP" } }, @@ -261,6 +266,7 @@ ], "service": "default-test3.route-673acf455cb2dab0b43a", "rule": "HostSNI(`*`)", + "priority": -1, "tls": { "passthrough": false, "options": "default-mytlsoption" @@ -274,7 +280,6 @@ "tcpServices": { "default-test3.route-673acf455cb2dab0b43a-externalname-svc-9090@kubernetescrd": { "loadBalancer": { - "terminationDelay": 100, "servers": [ { "address": "domain.com:9090" @@ -285,13 +290,12 @@ }, "default-test3.route-673acf455cb2dab0b43a-whoamitcp-8080@kubernetescrd": { "loadBalancer": { - "terminationDelay": 100, "servers": [ { - "address": "10.42.0.10:8080" + "address": "10.42.0.2:8080" }, { - "address": "10.42.0.8:8080" + "address": "10.42.0.4:8080" } ] }, @@ -343,10 +347,10 @@ "loadBalancer": { "servers": [ { - "address": "10.42.0.4:8090" + "address": "10.42.0.5:8090" }, { - "address": "10.42.0.9:8090" + "address": "10.42.0.6:8090" } ] }, diff --git a/integration/testdata/rawdata-gateway.json b/integration/testdata/rawdata-gateway.json index 46c50efd6..d629cfc41 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": [ @@ -122,10 +124,10 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.6:80" + "url": "http://10.42.0.3:80" }, { - "url": "http://10.42.0.7:80" + "url": "http://10.42.0.4:80" } ], "passHostHeader": true, @@ -135,8 +137,8 @@ }, "status": "enabled", "serverStatus": { - "http://10.42.0.6:80": "UP", - "http://10.42.0.7:80": "UP" + "http://10.42.0.3:80": "UP", + "http://10.42.0.4:80": "UP" } }, "noop@internal": { @@ -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 }, @@ -229,13 +234,12 @@ }, "default-whoamitcp-8080@kubernetesgateway": { "loadBalancer": { - "terminationDelay": 100, "servers": [ { "address": "10.42.0.2:8080" }, { - "address": "10.42.0.4:8080" + "address": "10.42.0.6:8080" } ] }, 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-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/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/integration/timeout_test.go b/integration/timeout_test.go index 68c5886ca..457e2bcfb 100644 --- a/integration/timeout_test.go +++ b/integration/timeout_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/tls_client_headers_test.go b/integration/tls_client_headers_test.go index 3bc587acd..08f0c7ea5 100644 --- a/integration/tls_client_headers_test.go +++ b/integration/tls_client_headers_test.go @@ -7,7 +7,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/tracing_test.go b/integration/tracing_test.go index 2c9582b7b..f2a1f29ad 100644 --- a/integration/tracing_test.go +++ b/integration/tracing_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/udp_test.go b/integration/udp_test.go index c5ee868a1..3493af17e 100644 --- a/integration/udp_test.go +++ b/integration/udp_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) diff --git a/integration/websocket_test.go b/integration/websocket_test.go index 33425624f..c343c1b78 100644 --- a/integration/websocket_test.go +++ b/integration/websocket_test.go @@ -12,7 +12,7 @@ import ( "github.com/go-check/check" gorillawebsocket "github.com/gorilla/websocket" - "github.com/traefik/traefik/v2/integration/try" + "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" "golang.org/x/net/websocket" ) diff --git a/integration/zk_test.go b/integration/zk_test.go index 21f536cb6..1e5820cc5 100644 --- a/integration/zk_test.go +++ b/integration/zk_test.go @@ -15,8 +15,8 @@ import ( "github.com/kvtools/valkeyrie/store" "github.com/kvtools/zookeeper" "github.com/pmezard/go-difflib/difflib" - "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/api" + "github.com/traefik/traefik/v3/integration/try" + "github.com/traefik/traefik/v3/pkg/api" checker "github.com/vdemeester/shakers" ) diff --git a/internal/gendoc.go b/internal/gendoc.go index 397f700ee..d4fad3247 100644 --- a/internal/gendoc.go +++ b/internal/gendoc.go @@ -15,7 +15,7 @@ import ( "github.com/traefik/paerser/flag" "github.com/traefik/paerser/generator" "github.com/traefik/paerser/parser" - "github.com/traefik/traefik/v2/cmd" + "github.com/traefik/traefik/v3/cmd" ) func main() { 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/dashboard/dashboard.go b/pkg/api/dashboard/dashboard.go index ebcaf315e..b42d04247 100644 --- a/pkg/api/dashboard/dashboard.go +++ b/pkg/api/dashboard/dashboard.go @@ -6,7 +6,7 @@ import ( "net/url" "github.com/gorilla/mux" - "github.com/traefik/traefik/v2/webui" + "github.com/traefik/traefik/v3/webui" ) // Handler expose dashboard routes. @@ -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) }) } @@ -46,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) } diff --git a/pkg/api/handler.go b/pkg/api/handler.go index 01ec20361..9c135546a 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -8,10 +8,10 @@ import ( "github.com/gorilla/mux" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/version" ) type apiError struct { diff --git a/pkg/api/handler_entrypoint.go b/pkg/api/handler_entrypoint.go index 104ab3853..d21e83d0d 100644 --- a/pkg/api/handler_entrypoint.go +++ b/pkg/api/handler_entrypoint.go @@ -9,7 +9,7 @@ import ( "github.com/gorilla/mux" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/static" ) type entryPointRepresentation struct { diff --git a/pkg/api/handler_entrypoint_test.go b/pkg/api/handler_entrypoint_test.go index a3c31e583..f02821607 100644 --- a/pkg/api/handler_entrypoint_test.go +++ b/pkg/api/handler_entrypoint_test.go @@ -12,8 +12,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" ) func TestHandler_EntryPoints(t *testing.T) { diff --git a/pkg/api/handler_http.go b/pkg/api/handler_http.go index ebf35d206..a0f25d4a6 100644 --- a/pkg/api/handler_http.go +++ b/pkg/api/handler_http.go @@ -4,14 +4,13 @@ import ( "encoding/json" "fmt" "net/http" - "sort" "strconv" "strings" "github.com/gorilla/mux" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/tls" ) type routerRepresentation struct { @@ -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..0a9cedc5c 100644 --- a/pkg/api/handler_http_test.go +++ b/pkg/api/handler_http_test.go @@ -13,9 +13,9 @@ import ( "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" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" ) func Bool(v bool) *bool { return &v } @@ -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_overview.go b/pkg/api/handler_overview.go index 7f423b09f..0856f69fc 100644 --- a/pkg/api/handler_overview.go +++ b/pkg/api/handler_overview.go @@ -6,8 +6,8 @@ import ( "reflect" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" ) type schemeOverview struct { diff --git a/pkg/api/handler_overview_test.go b/pkg/api/handler_overview_test.go index b7f96c6b9..d76dd55e5 100644 --- a/pkg/api/handler_overview_test.go +++ b/pkg/api/handler_overview_test.go @@ -10,19 +10,17 @@ import ( "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" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/provider/docker" - "github.com/traefik/traefik/v2/pkg/provider/file" - "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/rancher" - "github.com/traefik/traefik/v2/pkg/provider/rest" - "github.com/traefik/traefik/v2/pkg/tracing/jaeger" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/provider/docker" + "github.com/traefik/traefik/v3/pkg/provider/file" + "github.com/traefik/traefik/v3/pkg/provider/hub" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/ingress" + "github.com/traefik/traefik/v3/pkg/provider/rest" + "github.com/traefik/traefik/v3/pkg/tracing/jaeger" + "github.com/traefik/traefik/v3/pkg/types" ) func TestHandler_Overview(t *testing.T) { @@ -238,11 +236,9 @@ 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{}, - Rancher: &rancher.Provider{}, Plugin: map[string]static.PluginConf{ "test": map[string]interface{}{}, }, diff --git a/pkg/api/handler_tcp.go b/pkg/api/handler_tcp.go index 8efb13068..7c6a6fe67 100644 --- a/pkg/api/handler_tcp.go +++ b/pkg/api/handler_tcp.go @@ -4,13 +4,12 @@ import ( "encoding/json" "fmt" "net/http" - "sort" "strconv" "strings" "github.com/gorilla/mux" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/runtime" ) type tcpRouterRepresentation struct { @@ -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..f2fd35ad1 100644 --- a/pkg/api/handler_tcp_test.go +++ b/pkg/api/handler_tcp_test.go @@ -11,9 +11,9 @@ import ( "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" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" ) func TestHandler_TCP(t *testing.T) { @@ -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_test.go b/pkg/api/handler_test.go index 1dd55ebdb..02889161b 100644 --- a/pkg/api/handler_test.go +++ b/pkg/api/handler_test.go @@ -11,9 +11,9 @@ import ( "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" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" ) var updateExpected = flag.Bool("update_expected", false, "Update expected files in testdata") diff --git a/pkg/api/handler_udp.go b/pkg/api/handler_udp.go index 13adfafea..bf637ee72 100644 --- a/pkg/api/handler_udp.go +++ b/pkg/api/handler_udp.go @@ -4,13 +4,12 @@ import ( "encoding/json" "fmt" "net/http" - "sort" "strconv" "strings" "github.com/gorilla/mux" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/runtime" ) type udpRouterRepresentation struct { @@ -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..b875b2dc8 100644 --- a/pkg/api/handler_udp_test.go +++ b/pkg/api/handler_udp_test.go @@ -11,9 +11,9 @@ import ( "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" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" ) func TestHandler_UDP(t *testing.T) { @@ -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..30a9c3a62 --- /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/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/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/overview-providers.json b/pkg/api/testdata/overview-providers.json index 95d4d10d2..20f134354 100644 --- a/pkg/api/testdata/overview-providers.json +++ b/pkg/api/testdata/overview-providers.json @@ -25,11 +25,9 @@ "providers": [ "Docker", "File", - "Marathon", "KubernetesIngress", "KubernetesCRD", "Rest", - "Rancher", "plugin-test" ], "tcp": { 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/collector/collector.go b/pkg/collector/collector.go index 49f679a93..1de1934ba 100644 --- a/pkg/collector/collector.go +++ b/pkg/collector/collector.go @@ -11,15 +11,17 @@ import ( "github.com/mitchellh/hashstructure" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/redactor" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/redactor" + "github.com/traefik/traefik/v3/pkg/version" ) // collectorURL URL where the stats are sent. const collectorURL = "https://collect.traefik.io/9vxmmkcdmalbdi635d4jgc5p5rx0h7h8" // Collected data. +// +//nolint:musttag // cannot be changed for historical reasons. type data struct { Version string Codename string diff --git a/pkg/collector/collector_test.go b/pkg/collector/collector_test.go index b091f0c4f..44c1ecef7 100644 --- a/pkg/collector/collector_test.go +++ b/pkg/collector/collector_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/config/static" ) func Test_createBody(t *testing.T) { diff --git a/pkg/config/dynamic/config.go b/pkg/config/dynamic/config.go index d23315d6b..af9f657af 100644 --- a/pkg/config/dynamic/config.go +++ b/pkg/config/dynamic/config.go @@ -1,7 +1,7 @@ package dynamic import ( - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/tls" ) // +k8s:deepcopy-gen=true diff --git a/pkg/config/dynamic/fixtures/sample.toml b/pkg/config/dynamic/fixtures/sample.toml index 6f5137f4c..2cbbf5a60 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" @@ -96,15 +74,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" @@ -124,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" @@ -180,6 +141,7 @@ sampleRate = 42.0 [tracing.datadog] localAgentHostPort = "foobar" + localAgentSocket = "foobar" debug = true prioritySampling = true traceIDHeaderName = "foobar" diff --git a/pkg/config/dynamic/http_config.go b/pkg/config/dynamic/http_config.go index 746ced781..4f3df4d8a 100644 --- a/pkg/config/dynamic/http_config.go +++ b/pkg/config/dynamic/http_config.go @@ -5,8 +5,8 @@ import ( "time" ptypes "github.com/traefik/paerser/types" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" ) const ( @@ -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/middlewares.go b/pkg/config/dynamic/middlewares.go index 97981ae8a..748a205bc 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -4,8 +4,8 @@ import ( "time" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/ip" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/ip" + "github.com/traefik/traefik/v3/pkg/types" ) // +k8s:deepcopy-gen=true diff --git a/pkg/config/dynamic/tcp_config.go b/pkg/config/dynamic/tcp_config.go index 19007fa8c..e4639a1ea 100644 --- a/pkg/config/dynamic/tcp_config.go +++ b/pkg/config/dynamic/tcp_config.go @@ -2,17 +2,21 @@ package dynamic import ( "reflect" + "time" - "github.com/traefik/traefik/v2/pkg/types" + ptypes "github.com/traefik/paerser/types" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" ) // +k8s:deepcopy-gen=true // 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..29251247e 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 @@ -30,8 +30,8 @@ THE SOFTWARE. package dynamic import ( - tls "github.com/traefik/traefik/v2/pkg/tls" - types "github.com/traefik/traefik/v2/pkg/types" + tls "github.com/traefik/traefik/v3/pkg/tls" + types "github.com/traefik/traefik/v3/pkg/types" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -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.go b/pkg/config/label/label.go index 1791f735f..f6089a23f 100644 --- a/pkg/config/label/label.go +++ b/pkg/config/label/label.go @@ -3,7 +3,7 @@ package label import ( "github.com/traefik/paerser/parser" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) // DecodeConfiguration converts the labels to a configuration. diff --git a/pkg/config/label/label_test.go b/pkg/config/label/label_test.go index 820bea328..334297edc 100644 --- a/pkg/config/label/label_test.go +++ b/pkg/config/label/label_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/types" ) func TestDecodeConfiguration(t *testing.T) { @@ -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/runtime/runtime.go b/pkg/config/runtime/runtime.go index 842072279..2738b7c60 100644 --- a/pkg/config/runtime/runtime.go +++ b/pkg/config/runtime/runtime.go @@ -5,8 +5,8 @@ import ( "strings" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" ) // Status of the router/service. diff --git a/pkg/config/runtime/runtime_http.go b/pkg/config/runtime/runtime_http.go index 788a23a26..6b9a4a3fb 100644 --- a/pkg/config/runtime/runtime_http.go +++ b/pkg/config/runtime/runtime_http.go @@ -7,8 +7,8 @@ import ( "sync" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" ) // GetRoutersByEntryPoints returns all the http routers by entry points name and routers name. diff --git a/pkg/config/runtime/runtime_http_test.go b/pkg/config/runtime/runtime_http_test.go index 9ac028bfb..6080e770f 100644 --- a/pkg/config/runtime/runtime_http_test.go +++ b/pkg/config/runtime/runtime_http_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestGetRoutersByEntryPoints(t *testing.T) { diff --git a/pkg/config/runtime/runtime_tcp.go b/pkg/config/runtime/runtime_tcp.go index 665da4525..c188cd2d0 100644 --- a/pkg/config/runtime/runtime_tcp.go +++ b/pkg/config/runtime/runtime_tcp.go @@ -5,8 +5,8 @@ import ( "fmt" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" ) // GetTCPRoutersByEntryPoints returns all the tcp routers by entry points name and routers name. diff --git a/pkg/config/runtime/runtime_tcp_test.go b/pkg/config/runtime/runtime_tcp_test.go index 067e9ee09..8263d5626 100644 --- a/pkg/config/runtime/runtime_tcp_test.go +++ b/pkg/config/runtime/runtime_tcp_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestGetTCPRoutersByEntryPoints(t *testing.T) { diff --git a/pkg/config/runtime/runtime_test.go b/pkg/config/runtime/runtime_test.go index e952cb20c..54e34e854 100644 --- a/pkg/config/runtime/runtime_test.go +++ b/pkg/config/runtime/runtime_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" ) // all the Routers/Middlewares/Services are considered fully qualified. diff --git a/pkg/config/runtime/runtime_udp.go b/pkg/config/runtime/runtime_udp.go index ed9a44814..b0eb30e50 100644 --- a/pkg/config/runtime/runtime_udp.go +++ b/pkg/config/runtime/runtime_udp.go @@ -5,8 +5,8 @@ import ( "fmt" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" ) // GetUDPRoutersByEntryPoints returns all the UDP routers by entry points name and routers name. diff --git a/pkg/config/runtime/runtime_udp_test.go b/pkg/config/runtime/runtime_udp_test.go index 87fe2476f..5e83dff05 100644 --- a/pkg/config/runtime/runtime_udp_test.go +++ b/pkg/config/runtime/runtime_udp_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestGetUDPRoutersByEntryPoints(t *testing.T) { diff --git a/pkg/config/static/entrypoints.go b/pkg/config/static/entrypoints.go index 7863f1bcb..db3fb231e 100644 --- a/pkg/config/static/entrypoints.go +++ b/pkg/config/static/entrypoints.go @@ -6,7 +6,7 @@ import ( "strings" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/types" ) // EntryPoint holds the entry point configuration. diff --git a/pkg/config/static/experimental.go b/pkg/config/static/experimental.go index 5f16f9898..7428f6a08 100644 --- a/pkg/config/static/experimental.go +++ b/pkg/config/static/experimental.go @@ -1,6 +1,6 @@ package static -import "github.com/traefik/traefik/v2/pkg/plugins" +import "github.com/traefik/traefik/v3/pkg/plugins" // Experimental experimental Traefik features. type Experimental struct { @@ -8,5 +8,4 @@ type Experimental struct { LocalPlugins map[string]plugins.LocalDescriptor `description:"Local plugins configuration." json:"localPlugins,omitempty" toml:"localPlugins,omitempty" yaml:"localPlugins,omitempty" export:"true"` KubernetesGateway bool `description:"Allow the Kubernetes gateway api provider usage." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" export:"true"` - Hub bool `description:"Enable the Traefik Hub provider." json:"hub,omitempty" toml:"hub,omitempty" yaml:"hub,omitempty" export:"true"` } diff --git a/pkg/config/static/hub.go b/pkg/config/static/hub.go index 5cf97ae32..2a87b342a 100644 --- a/pkg/config/static/hub.go +++ b/pkg/config/static/hub.go @@ -4,16 +4,11 @@ import ( "errors" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/provider/hub" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider/hub" ) func (c *Configuration) initHubProvider() error { - // Hub provider is an experimental feature. It requires the experimental flag to be enabled before continuing. - if c.Experimental == nil || !c.Experimental.Hub { - return errors.New("the experimental flag for Hub is not set") - } - if _, ok := c.EntryPoints[hub.TunnelEntrypoint]; !ok { var ep EntryPoint ep.SetDefaults() diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index da32b76f9..05051ff54 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -9,35 +9,33 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/ping" - acmeprovider "github.com/traefik/traefik/v2/pkg/provider/acme" - "github.com/traefik/traefik/v2/pkg/provider/consulcatalog" - "github.com/traefik/traefik/v2/pkg/provider/docker" - "github.com/traefik/traefik/v2/pkg/provider/ecs" - "github.com/traefik/traefik/v2/pkg/provider/file" - "github.com/traefik/traefik/v2/pkg/provider/http" - "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/gateway" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/ingress" - "github.com/traefik/traefik/v2/pkg/provider/kv/consul" - "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/rancher" - "github.com/traefik/traefik/v2/pkg/provider/rest" - "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/tracing/datadog" - "github.com/traefik/traefik/v2/pkg/tracing/elastic" - "github.com/traefik/traefik/v2/pkg/tracing/haystack" - "github.com/traefik/traefik/v2/pkg/tracing/instana" - "github.com/traefik/traefik/v2/pkg/tracing/jaeger" - "github.com/traefik/traefik/v2/pkg/tracing/opentelemetry" - "github.com/traefik/traefik/v2/pkg/tracing/zipkin" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/ping" + acmeprovider "github.com/traefik/traefik/v3/pkg/provider/acme" + "github.com/traefik/traefik/v3/pkg/provider/consulcatalog" + "github.com/traefik/traefik/v3/pkg/provider/docker" + "github.com/traefik/traefik/v3/pkg/provider/ecs" + "github.com/traefik/traefik/v3/pkg/provider/file" + "github.com/traefik/traefik/v3/pkg/provider/http" + "github.com/traefik/traefik/v3/pkg/provider/hub" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/gateway" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/ingress" + "github.com/traefik/traefik/v3/pkg/provider/kv/consul" + "github.com/traefik/traefik/v3/pkg/provider/kv/etcd" + "github.com/traefik/traefik/v3/pkg/provider/kv/redis" + "github.com/traefik/traefik/v3/pkg/provider/kv/zk" + "github.com/traefik/traefik/v3/pkg/provider/nomad" + "github.com/traefik/traefik/v3/pkg/provider/rest" + "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/tracing/datadog" + "github.com/traefik/traefik/v3/pkg/tracing/elastic" + "github.com/traefik/traefik/v3/pkg/tracing/haystack" + "github.com/traefik/traefik/v3/pkg/tracing/instana" + "github.com/traefik/traefik/v3/pkg/tracing/jaeger" + "github.com/traefik/traefik/v3/pkg/tracing/opentelemetry" + "github.com/traefik/traefik/v3/pkg/tracing/zipkin" + "github.com/traefik/traefik/v3/pkg/types" ) const ( @@ -63,9 +61,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 +117,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"` @@ -193,12 +212,10 @@ 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"` 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"` @@ -243,7 +260,7 @@ func (c *Configuration) SetEffectiveConfiguration() { c.Hub = nil log.Error().Err(err).Msg("Unable to activate the Hub provider") } else { - log.Debug().Msg("Experimental Hub provider has been activated") + log.Debug().Msg("Hub provider has been activated") } } @@ -257,12 +274,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/config/static/static_config_test.go b/pkg/config/static/static_config_test.go index 9680233dd..26b67fbd2 100644 --- a/pkg/config/static/static_config_test.go +++ b/pkg/config/static/static_config_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/provider/hub" + "github.com/traefik/traefik/v3/pkg/provider/hub" ) func TestHasEntrypoint(t *testing.T) { diff --git a/pkg/healthcheck/healthcheck.go b/pkg/healthcheck/healthcheck.go index 7a590d3f1..1452bfa66 100644 --- a/pkg/healthcheck/healthcheck.go +++ b/pkg/healthcheck/healthcheck.go @@ -12,8 +12,8 @@ import ( gokitmetrics "github.com/go-kit/kit/metrics" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" diff --git a/pkg/healthcheck/healthcheck_test.go b/pkg/healthcheck/healthcheck_test.go index 5bc08bb94..c7813fae0 100644 --- a/pkg/healthcheck/healthcheck_test.go +++ b/pkg/healthcheck/healthcheck_test.go @@ -12,9 +12,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/testhelpers" healthpb "google.golang.org/grpc/health/grpc_health_v1" ) diff --git a/pkg/healthcheck/mock_test.go b/pkg/healthcheck/mock_test.go index d2a9b52e1..ba288cc26 100644 --- a/pkg/healthcheck/mock_test.go +++ b/pkg/healthcheck/mock_test.go @@ -12,8 +12,8 @@ import ( gokitmetrics "github.com/go-kit/kit/metrics" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/testhelpers" "google.golang.org/grpc" healthpb "google.golang.org/grpc/health/grpc_health_v1" ) diff --git a/pkg/metrics/datadog.go b/pkg/metrics/datadog.go index fce4c4cc4..b09e3407a 100644 --- a/pkg/metrics/datadog.go +++ b/pkg/metrics/datadog.go @@ -6,9 +6,9 @@ import ( "github.com/go-kit/kit/metrics/dogstatsd" "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" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/types" ) var ( @@ -18,23 +18,21 @@ var ( // Metric names consistent with https://github.com/DataDog/integrations-extras/pull/64 const ( - ddConfigReloadsName = "config.reload.total" - ddConfigReloadsFailureTagName = "failure" - ddLastConfigReloadSuccessName = "config.reload.lastSuccessTimestamp" - ddLastConfigReloadFailureName = "config.reload.lastFailureTimestamp" + ddConfigReloadsName = "config.reload.total" + ddLastConfigReloadSuccessName = "config.reload.lastSuccessTimestamp" + ddOpenConnsName = "open.connections" + ddTLSCertsNotAfterTimestampName = "tls.certs.notAfterTimestamp" ddEntryPointReqsName = "entrypoint.request.total" ddEntryPointReqsTLSName = "entrypoint.request.tls.total" ddEntryPointReqDurationName = "entrypoint.request.duration" - ddEntryPointOpenConnsName = "entrypoint.connections.open" ddEntryPointReqsBytesName = "entrypoint.requests.bytes.total" ddEntryPointRespsBytesName = "entrypoint.responses.bytes.total" ddRouterReqsName = "router.request.total" ddRouterReqsTLSName = "router.request.tls.total" ddRouterReqsDurationName = "router.request.duration" - ddRouterOpenConnsName = "router.connections.open" ddRouterReqsBytesName = "router.requests.bytes.total" ddRouterRespsBytesName = "router.responses.bytes.total" @@ -42,7 +40,6 @@ const ( ddServiceReqsTLSName = "service.request.tls.total" ddServiceReqsDurationName = "service.request.duration" ddServiceRetriesName = "service.retries.total" - ddServiceOpenConnsName = "service.connections.open" ddServiceServerUpName = "service.server.up" ddServiceReqsBytesName = "service.requests.bytes.total" ddServiceRespsBytesName = "service.responses.bytes.total" @@ -64,39 +61,35 @@ func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry { registry := &standardRegistry{ configReloadsCounter: datadogClient.NewCounter(ddConfigReloadsName, 1.0), - configReloadsFailureCounter: datadogClient.NewCounter(ddConfigReloadsName, 1.0).With(ddConfigReloadsFailureTagName, "true"), lastConfigReloadSuccessGauge: datadogClient.NewGauge(ddLastConfigReloadSuccessName), - lastConfigReloadFailureGauge: datadogClient.NewGauge(ddLastConfigReloadFailureName), + openConnectionsGauge: datadogClient.NewGauge(ddOpenConnsName), tlsCertsNotAfterTimestampGauge: datadogClient.NewGauge(ddTLSCertsNotAfterTimestampName), } if config.AddEntryPointsLabels { registry.epEnabled = config.AddEntryPointsLabels - registry.entryPointReqsCounter = datadogClient.NewCounter(ddEntryPointReqsName, 1.0) + registry.entryPointReqsCounter = NewCounterWithNoopHeaders(datadogClient.NewCounter(ddEntryPointReqsName, 1.0)) registry.entryPointReqsTLSCounter = datadogClient.NewCounter(ddEntryPointReqsTLSName, 1.0) registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(datadogClient.NewHistogram(ddEntryPointReqDurationName, 1.0), time.Second) - registry.entryPointOpenConnsGauge = datadogClient.NewGauge(ddEntryPointOpenConnsName) registry.entryPointReqsBytesCounter = datadogClient.NewCounter(ddEntryPointReqsBytesName, 1.0) registry.entryPointRespsBytesCounter = datadogClient.NewCounter(ddEntryPointRespsBytesName, 1.0) } if config.AddRoutersLabels { registry.routerEnabled = config.AddRoutersLabels - registry.routerReqsCounter = datadogClient.NewCounter(ddRouterReqsName, 1.0) + registry.routerReqsCounter = NewCounterWithNoopHeaders(datadogClient.NewCounter(ddRouterReqsName, 1.0)) registry.routerReqsTLSCounter = datadogClient.NewCounter(ddRouterReqsTLSName, 1.0) registry.routerReqDurationHistogram, _ = NewHistogramWithScale(datadogClient.NewHistogram(ddRouterReqsDurationName, 1.0), time.Second) - registry.routerOpenConnsGauge = datadogClient.NewGauge(ddRouterOpenConnsName) registry.routerReqsBytesCounter = datadogClient.NewCounter(ddRouterReqsBytesName, 1.0) registry.routerRespsBytesCounter = datadogClient.NewCounter(ddRouterRespsBytesName, 1.0) } if config.AddServicesLabels { registry.svcEnabled = config.AddServicesLabels - registry.serviceReqsCounter = datadogClient.NewCounter(ddServiceReqsName, 1.0) + registry.serviceReqsCounter = NewCounterWithNoopHeaders(datadogClient.NewCounter(ddServiceReqsName, 1.0)) registry.serviceReqsTLSCounter = datadogClient.NewCounter(ddServiceReqsTLSName, 1.0) registry.serviceReqDurationHistogram, _ = NewHistogramWithScale(datadogClient.NewHistogram(ddServiceReqsDurationName, 1.0), time.Second) registry.serviceRetriesCounter = datadogClient.NewCounter(ddServiceRetriesName, 1.0) - registry.serviceOpenConnsGauge = datadogClient.NewGauge(ddServiceOpenConnsName) registry.serviceServerUpGauge = datadogClient.NewGauge(ddServiceServerUpName) registry.serviceReqsBytesCounter = datadogClient.NewCounter(ddServiceReqsBytesName, 1.0) registry.serviceRespsBytesCounter = datadogClient.NewCounter(ddServiceRespsBytesName, 1.0) diff --git a/pkg/metrics/datadog_test.go b/pkg/metrics/datadog_test.go index 7a36c1d77..68e79ba71 100644 --- a/pkg/metrics/datadog_test.go +++ b/pkg/metrics/datadog_test.go @@ -9,7 +9,7 @@ import ( "github.com/stvp/go-udp-testing" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/types" ) func TestDatadog(t *testing.T) { @@ -45,16 +45,14 @@ func testDatadogRegistry(t *testing.T, metricsPrefix string, datadogRegistry Reg expected := []string{ metricsPrefix + ".config.reload.total:1.000000|c\n", - metricsPrefix + ".config.reload.total:1.000000|c|#failure:true\n", metricsPrefix + ".config.reload.lastSuccessTimestamp:1.000000|g\n", - metricsPrefix + ".config.reload.lastFailureTimestamp:1.000000|g\n", + metricsPrefix + ".open.connections:1.000000|g|#entrypoint:test,protocol:TCP\n", metricsPrefix + ".tls.certs.notAfterTimestamp:1.000000|g|#key:value\n", metricsPrefix + ".entrypoint.request.total:1.000000|c|#entrypoint:test\n", metricsPrefix + ".entrypoint.request.tls.total:1.000000|c|#entrypoint:test,tls_version:foo,tls_cipher:bar\n", metricsPrefix + ".entrypoint.request.duration:10000.000000|h|#entrypoint:test\n", - metricsPrefix + ".entrypoint.connections.open:1.000000|g|#entrypoint:test\n", metricsPrefix + ".entrypoint.requests.bytes.total:1.000000|c|#entrypoint:test\n", metricsPrefix + ".entrypoint.responses.bytes.total:1.000000|c|#entrypoint:test\n", @@ -62,7 +60,6 @@ func testDatadogRegistry(t *testing.T, metricsPrefix string, datadogRegistry Reg metricsPrefix + ".router.request.total:1.000000|c|#router:demo,service:test,code:200,method:GET\n", metricsPrefix + ".router.request.tls.total:1.000000|c|#router:demo,service:test,tls_version:foo,tls_cipher:bar\n", metricsPrefix + ".router.request.duration:10000.000000|h|#router:demo,service:test,code:200\n", - metricsPrefix + ".router.connections.open:1.000000|g|#router:demo,service:test\n", metricsPrefix + ".router.requests.bytes.total:1.000000|c|#router:demo,service:test,code:200,method:GET\n", metricsPrefix + ".router.responses.bytes.total:1.000000|c|#router:demo,service:test,code:200,method:GET\n", @@ -70,7 +67,6 @@ func testDatadogRegistry(t *testing.T, metricsPrefix string, datadogRegistry Reg metricsPrefix + ".service.request.total:1.000000|c|#service:test,code:200,method:GET\n", metricsPrefix + ".service.request.tls.total:1.000000|c|#service:test,tls_version:foo,tls_cipher:bar\n", metricsPrefix + ".service.request.duration:10000.000000|h|#service:test,code:200\n", - metricsPrefix + ".service.connections.open:1.000000|g|#service:test\n", metricsPrefix + ".service.retries.total:2.000000|c|#service:test\n", metricsPrefix + ".service.request.duration:10000.000000|h|#service:test,code:200\n", metricsPrefix + ".service.server.up:1.000000|g|#service:test,url:http://127.0.0.1,one:two\n", @@ -80,32 +76,28 @@ func testDatadogRegistry(t *testing.T, metricsPrefix string, datadogRegistry Reg udp.ShouldReceiveAll(t, expected, func() { datadogRegistry.ConfigReloadsCounter().Add(1) - datadogRegistry.ConfigReloadsFailureCounter().Add(1) datadogRegistry.LastConfigReloadSuccessGauge().Add(1) - datadogRegistry.LastConfigReloadFailureGauge().Add(1) + datadogRegistry.OpenConnectionsGauge().With("entrypoint", "test", "protocol", "TCP").Add(1) datadogRegistry.TLSCertsNotAfterTimestampGauge().With("key", "value").Set(1) - datadogRegistry.EntryPointReqsCounter().With("entrypoint", "test").Add(1) + datadogRegistry.EntryPointReqsCounter().With(nil, "entrypoint", "test").Add(1) datadogRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) datadogRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000) - datadogRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1) datadogRegistry.EntryPointReqsBytesCounter().With("entrypoint", "test").Add(1) datadogRegistry.EntryPointRespsBytesCounter().With("entrypoint", "test").Add(1) - datadogRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - datadogRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) + datadogRegistry.RouterReqsCounter().With(nil, "router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) + datadogRegistry.RouterReqsCounter().With(nil, "router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) datadogRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) datadogRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - datadogRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1) datadogRegistry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) datadogRegistry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - datadogRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - datadogRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) + datadogRegistry.ServiceReqsCounter().With(nil, "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) + datadogRegistry.ServiceReqsCounter().With(nil, "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) datadogRegistry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) datadogRegistry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - datadogRegistry.ServiceOpenConnsGauge().With("service", "test").Set(1) datadogRegistry.ServiceRetriesCounter().With("service", "test").Add(1) datadogRegistry.ServiceRetriesCounter().With("service", "test").Add(1) datadogRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1", "one", "two").Set(1) diff --git a/pkg/metrics/headers.go b/pkg/metrics/headers.go new file mode 100644 index 000000000..65443cd29 --- /dev/null +++ b/pkg/metrics/headers.go @@ -0,0 +1,57 @@ +package metrics + +import ( + "net/http" + + "github.com/go-kit/kit/metrics" +) + +// CounterWithHeaders represents a counter that can use http.Header values as label values. +type CounterWithHeaders interface { + Add(delta float64) + With(headers http.Header, labelValues ...string) CounterWithHeaders +} + +// MultiCounterWithHeaders collects multiple individual CounterWithHeaders and treats them as a unit. +type MultiCounterWithHeaders []CounterWithHeaders + +// NewMultiCounterWithHeaders returns a multi-counter, wrapping the passed CounterWithHeaders. +func NewMultiCounterWithHeaders(c ...CounterWithHeaders) MultiCounterWithHeaders { + return c +} + +// Add adds the given delta value to the counter value. +func (c MultiCounterWithHeaders) Add(delta float64) { + for _, counter := range c { + counter.Add(delta) + } +} + +// With creates a new counter by appending the given label values and http.Header as labels and returns it. +func (c MultiCounterWithHeaders) With(headers http.Header, labelValues ...string) CounterWithHeaders { + next := make(MultiCounterWithHeaders, len(c)) + for i := range c { + next[i] = c[i].With(headers, labelValues...) + } + return next +} + +// NewCounterWithNoopHeaders returns a CounterWithNoopHeaders. +func NewCounterWithNoopHeaders(counter metrics.Counter) CounterWithNoopHeaders { + return CounterWithNoopHeaders{counter: counter} +} + +// CounterWithNoopHeaders is a counter that satisfies CounterWithHeaders but ignores the given http.Header. +type CounterWithNoopHeaders struct { + counter metrics.Counter +} + +// Add adds the given delta value to the counter value. +func (c CounterWithNoopHeaders) Add(delta float64) { + c.counter.Add(delta) +} + +// With creates a new counter by appending the given label values and returns it. +func (c CounterWithNoopHeaders) With(_ http.Header, labelValues ...string) CounterWithHeaders { + return NewCounterWithNoopHeaders(c.counter.With(labelValues...)) +} 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..270ac03a9 100644 --- a/pkg/metrics/influxdb2.go +++ b/pkg/metrics/influxdb2.go @@ -12,9 +12,9 @@ import ( influxdb2log "github.com/influxdata/influxdb-client-go/v2/log" 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" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/types" ) var ( @@ -23,6 +23,34 @@ var ( influxDB2Client influxdb2.Client ) +const ( + influxDBConfigReloadsName = "traefik.config.reload.total" + influxDBLastConfigReloadSuccessName = "traefik.config.reload.lastSuccessTimestamp" + influxDBOpenConnsName = "traefik.open.connections" + + influxDBTLSCertsNotAfterTimestampName = "traefik.tls.certs.notAfterTimestamp" + + influxDBEntryPointReqsName = "traefik.entrypoint.requests.total" + influxDBEntryPointReqsTLSName = "traefik.entrypoint.requests.tls.total" + influxDBEntryPointReqDurationName = "traefik.entrypoint.request.duration" + 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" + 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" + 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) @@ -52,39 +80,35 @@ func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry { registry := &standardRegistry{ configReloadsCounter: influxDB2Store.NewCounter(influxDBConfigReloadsName), - configReloadsFailureCounter: influxDB2Store.NewCounter(influxDBConfigReloadsFailureName), lastConfigReloadSuccessGauge: influxDB2Store.NewGauge(influxDBLastConfigReloadSuccessName), - lastConfigReloadFailureGauge: influxDB2Store.NewGauge(influxDBLastConfigReloadFailureName), + openConnectionsGauge: influxDB2Store.NewGauge(influxDBOpenConnsName), tlsCertsNotAfterTimestampGauge: influxDB2Store.NewGauge(influxDBTLSCertsNotAfterTimestampName), } if config.AddEntryPointsLabels { registry.epEnabled = config.AddEntryPointsLabels - registry.entryPointReqsCounter = influxDB2Store.NewCounter(influxDBEntryPointReqsName) + registry.entryPointReqsCounter = NewCounterWithNoopHeaders(influxDB2Store.NewCounter(influxDBEntryPointReqsName)) registry.entryPointReqsTLSCounter = influxDB2Store.NewCounter(influxDBEntryPointReqsTLSName) registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(influxDB2Store.NewHistogram(influxDBEntryPointReqDurationName), time.Second) - registry.entryPointOpenConnsGauge = influxDB2Store.NewGauge(influxDBEntryPointOpenConnsName) registry.entryPointReqsBytesCounter = influxDB2Store.NewCounter(influxDBEntryPointReqsBytesName) registry.entryPointRespsBytesCounter = influxDB2Store.NewCounter(influxDBEntryPointRespsBytesName) } if config.AddRoutersLabels { registry.routerEnabled = config.AddRoutersLabels - registry.routerReqsCounter = influxDB2Store.NewCounter(influxDBRouterReqsName) + registry.routerReqsCounter = NewCounterWithNoopHeaders(influxDB2Store.NewCounter(influxDBRouterReqsName)) registry.routerReqsTLSCounter = influxDB2Store.NewCounter(influxDBRouterReqsTLSName) registry.routerReqDurationHistogram, _ = NewHistogramWithScale(influxDB2Store.NewHistogram(influxDBRouterReqsDurationName), time.Second) - registry.routerOpenConnsGauge = influxDB2Store.NewGauge(influxDBORouterOpenConnsName) registry.routerReqsBytesCounter = influxDB2Store.NewCounter(influxDBRouterReqsBytesName) registry.routerRespsBytesCounter = influxDB2Store.NewCounter(influxDBRouterRespsBytesName) } if config.AddServicesLabels { registry.svcEnabled = config.AddServicesLabels - registry.serviceReqsCounter = influxDB2Store.NewCounter(influxDBServiceReqsName) + registry.serviceReqsCounter = NewCounterWithNoopHeaders(influxDB2Store.NewCounter(influxDBServiceReqsName)) registry.serviceReqsTLSCounter = influxDB2Store.NewCounter(influxDBServiceReqsTLSName) registry.serviceReqDurationHistogram, _ = NewHistogramWithScale(influxDB2Store.NewHistogram(influxDBServiceReqsDurationName), time.Second) registry.serviceRetriesCounter = influxDB2Store.NewCounter(influxDBServiceRetriesTotalName) - registry.serviceOpenConnsGauge = influxDB2Store.NewGauge(influxDBServiceOpenConnsName) registry.serviceServerUpGauge = influxDB2Store.NewGauge(influxDBServiceServerUpName) registry.serviceReqsBytesCounter = influxDB2Store.NewCounter(influxDBServiceReqsBytesName) registry.serviceRespsBytesCounter = influxDB2Store.NewCounter(influxDBServiceRespsBytesName) diff --git a/pkg/metrics/influxdb2_test.go b/pkg/metrics/influxdb2_test.go index 3fc628d67..89b558075 100644 --- a/pkg/metrics/influxdb2_test.go +++ b/pkg/metrics/influxdb2_test.go @@ -6,13 +6,14 @@ import ( "io" "net/http" "net/http/httptest" + "regexp" "strconv" "testing" "time" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/types" ) func TestInfluxDB2(t *testing.T) { @@ -46,15 +47,13 @@ func TestInfluxDB2(t *testing.T) { 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}`, + `(traefik\.open\.connections,entrypoint=test,protocol=TCP value=1) [\d]{19}`, } influxDB2Registry.ConfigReloadsCounter().Add(1) - influxDB2Registry.ConfigReloadsFailureCounter().Add(1) influxDB2Registry.LastConfigReloadSuccessGauge().Set(1) - influxDB2Registry.LastConfigReloadFailureGauge().Set(1) + influxDB2Registry.OpenConnectionsGauge().With("entrypoint", "test", "protocol", "TCP").Set(1) msgServer := <-c assertMessage(t, *msgServer, expectedServer) @@ -72,15 +71,13 @@ func TestInfluxDB2(t *testing.T) { `(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}`, } - influxDB2Registry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) + influxDB2Registry.EntryPointReqsCounter().With(nil, "entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) influxDB2Registry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) influxDB2Registry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000) - influxDB2Registry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1) influxDB2Registry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) influxDB2Registry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) msgEntrypoint := <-c @@ -92,16 +89,14 @@ func TestInfluxDB2(t *testing.T) { `(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}`, } - influxDB2Registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) - influxDB2Registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) + influxDB2Registry.RouterReqsCounter().With(nil, "router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) + influxDB2Registry.RouterReqsCounter().With(nil, "router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) influxDB2Registry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) influxDB2Registry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - influxDB2Registry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1) influxDB2Registry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) influxDB2Registry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) msgRouter := <-c @@ -118,8 +113,8 @@ func TestInfluxDB2(t *testing.T) { `(traefik\.service\.responses\.bytes\.total,code=200,method=GET,service=test count=1) [\d]{19}`, } - influxDB2Registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - influxDB2Registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) + influxDB2Registry.ServiceReqsCounter().With(nil, "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) + influxDB2Registry.ServiceReqsCounter().With(nil, "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) influxDB2Registry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) influxDB2Registry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) influxDB2Registry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1) @@ -141,17 +136,15 @@ func TestInfluxDB2(t *testing.T) { msgServiceRetries := <-c assertMessage(t, *msgServiceRetries, expectedServiceRetries) - - expectedServiceOpenConns := []string{ - `(traefik\.service\.connections\.open,service=test value=2) [\d]{19}`, - `(traefik\.service\.connections\.open,service=foobar value=1) [\d]{19}`, - } - - influxDB2Registry.ServiceOpenConnsGauge().With("service", "test").Add(1) - influxDB2Registry.ServiceOpenConnsGauge().With("service", "test").Add(1) - influxDB2Registry.ServiceOpenConnsGauge().With("service", "foobar").Add(1) - - msgServiceOpenConns := <-c - - 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/metrics/metrics.go b/pkg/metrics/metrics.go index ac49d389a..e87af0277 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -22,9 +22,8 @@ type Registry interface { // server metrics ConfigReloadsCounter() metrics.Counter - ConfigReloadsFailureCounter() metrics.Counter LastConfigReloadSuccessGauge() metrics.Gauge - LastConfigReloadFailureGauge() metrics.Gauge + OpenConnectionsGauge() metrics.Gauge // TLS @@ -32,28 +31,25 @@ type Registry interface { // entry point metrics - EntryPointReqsCounter() metrics.Counter + EntryPointReqsCounter() CounterWithHeaders EntryPointReqsTLSCounter() metrics.Counter EntryPointReqDurationHistogram() ScalableHistogram - EntryPointOpenConnsGauge() metrics.Gauge EntryPointReqsBytesCounter() metrics.Counter EntryPointRespsBytesCounter() metrics.Counter // router metrics - RouterReqsCounter() metrics.Counter + RouterReqsCounter() CounterWithHeaders RouterReqsTLSCounter() metrics.Counter RouterReqDurationHistogram() ScalableHistogram - RouterOpenConnsGauge() metrics.Gauge RouterReqsBytesCounter() metrics.Counter RouterRespsBytesCounter() metrics.Counter // service metrics - ServiceReqsCounter() metrics.Counter + ServiceReqsCounter() CounterWithHeaders ServiceReqsTLSCounter() metrics.Counter ServiceReqDurationHistogram() ScalableHistogram - ServiceOpenConnsGauge() metrics.Gauge ServiceRetriesCounter() metrics.Counter ServiceServerUpGauge() metrics.Gauge ServiceReqsBytesCounter() metrics.Counter @@ -71,26 +67,22 @@ func NewVoidRegistry() Registry { // This allows for feature disparity between the different metric implementations. func NewMultiRegistry(registries []Registry) Registry { var configReloadsCounter []metrics.Counter - var configReloadsFailureCounter []metrics.Counter var lastConfigReloadSuccessGauge []metrics.Gauge - var lastConfigReloadFailureGauge []metrics.Gauge + var openConnectionsGauge []metrics.Gauge var tlsCertsNotAfterTimestampGauge []metrics.Gauge - var entryPointReqsCounter []metrics.Counter + var entryPointReqsCounter []CounterWithHeaders var entryPointReqsTLSCounter []metrics.Counter var entryPointReqDurationHistogram []ScalableHistogram - var entryPointOpenConnsGauge []metrics.Gauge var entryPointReqsBytesCounter []metrics.Counter var entryPointRespsBytesCounter []metrics.Counter - var routerReqsCounter []metrics.Counter + var routerReqsCounter []CounterWithHeaders var routerReqsTLSCounter []metrics.Counter var routerReqDurationHistogram []ScalableHistogram - var routerOpenConnsGauge []metrics.Gauge var routerReqsBytesCounter []metrics.Counter var routerRespsBytesCounter []metrics.Counter - var serviceReqsCounter []metrics.Counter + var serviceReqsCounter []CounterWithHeaders var serviceReqsTLSCounter []metrics.Counter var serviceReqDurationHistogram []ScalableHistogram - var serviceOpenConnsGauge []metrics.Gauge var serviceRetriesCounter []metrics.Counter var serviceServerUpGauge []metrics.Gauge var serviceReqsBytesCounter []metrics.Counter @@ -100,14 +92,11 @@ func NewMultiRegistry(registries []Registry) Registry { if r.ConfigReloadsCounter() != nil { configReloadsCounter = append(configReloadsCounter, r.ConfigReloadsCounter()) } - if r.ConfigReloadsFailureCounter() != nil { - configReloadsFailureCounter = append(configReloadsFailureCounter, r.ConfigReloadsFailureCounter()) - } if r.LastConfigReloadSuccessGauge() != nil { lastConfigReloadSuccessGauge = append(lastConfigReloadSuccessGauge, r.LastConfigReloadSuccessGauge()) } - if r.LastConfigReloadFailureGauge() != nil { - lastConfigReloadFailureGauge = append(lastConfigReloadFailureGauge, r.LastConfigReloadFailureGauge()) + if r.OpenConnectionsGauge() != nil { + openConnectionsGauge = append(openConnectionsGauge, r.OpenConnectionsGauge()) } if r.TLSCertsNotAfterTimestampGauge() != nil { tlsCertsNotAfterTimestampGauge = append(tlsCertsNotAfterTimestampGauge, r.TLSCertsNotAfterTimestampGauge()) @@ -121,9 +110,6 @@ func NewMultiRegistry(registries []Registry) Registry { if r.EntryPointReqDurationHistogram() != nil { entryPointReqDurationHistogram = append(entryPointReqDurationHistogram, r.EntryPointReqDurationHistogram()) } - if r.EntryPointOpenConnsGauge() != nil { - entryPointOpenConnsGauge = append(entryPointOpenConnsGauge, r.EntryPointOpenConnsGauge()) - } if r.EntryPointReqsBytesCounter() != nil { entryPointReqsBytesCounter = append(entryPointReqsBytesCounter, r.EntryPointReqsBytesCounter()) } @@ -139,9 +125,6 @@ func NewMultiRegistry(registries []Registry) Registry { if r.RouterReqDurationHistogram() != nil { routerReqDurationHistogram = append(routerReqDurationHistogram, r.RouterReqDurationHistogram()) } - if r.RouterOpenConnsGauge() != nil { - routerOpenConnsGauge = append(routerOpenConnsGauge, r.RouterOpenConnsGauge()) - } if r.RouterReqsBytesCounter() != nil { routerReqsBytesCounter = append(routerReqsBytesCounter, r.RouterReqsBytesCounter()) } @@ -157,9 +140,6 @@ func NewMultiRegistry(registries []Registry) Registry { if r.ServiceReqDurationHistogram() != nil { serviceReqDurationHistogram = append(serviceReqDurationHistogram, r.ServiceReqDurationHistogram()) } - if r.ServiceOpenConnsGauge() != nil { - serviceOpenConnsGauge = append(serviceOpenConnsGauge, r.ServiceOpenConnsGauge()) - } if r.ServiceRetriesCounter() != nil { serviceRetriesCounter = append(serviceRetriesCounter, r.ServiceRetriesCounter()) } @@ -175,30 +155,26 @@ func NewMultiRegistry(registries []Registry) Registry { } return &standardRegistry{ - epEnabled: len(entryPointReqsCounter) > 0 || len(entryPointReqDurationHistogram) > 0 || len(entryPointOpenConnsGauge) > 0, - svcEnabled: len(serviceReqsCounter) > 0 || len(serviceReqDurationHistogram) > 0 || len(serviceOpenConnsGauge) > 0 || len(serviceRetriesCounter) > 0 || len(serviceServerUpGauge) > 0, - routerEnabled: len(routerReqsCounter) > 0 || len(routerReqDurationHistogram) > 0 || len(routerOpenConnsGauge) > 0, + epEnabled: len(entryPointReqsCounter) > 0 || len(entryPointReqDurationHistogram) > 0, + svcEnabled: len(serviceReqsCounter) > 0 || len(serviceReqDurationHistogram) > 0 || len(serviceRetriesCounter) > 0 || len(serviceServerUpGauge) > 0, + routerEnabled: len(routerReqsCounter) > 0 || len(routerReqDurationHistogram) > 0, configReloadsCounter: multi.NewCounter(configReloadsCounter...), - configReloadsFailureCounter: multi.NewCounter(configReloadsFailureCounter...), lastConfigReloadSuccessGauge: multi.NewGauge(lastConfigReloadSuccessGauge...), - lastConfigReloadFailureGauge: multi.NewGauge(lastConfigReloadFailureGauge...), + openConnectionsGauge: multi.NewGauge(openConnectionsGauge...), tlsCertsNotAfterTimestampGauge: multi.NewGauge(tlsCertsNotAfterTimestampGauge...), - entryPointReqsCounter: multi.NewCounter(entryPointReqsCounter...), + entryPointReqsCounter: NewMultiCounterWithHeaders(entryPointReqsCounter...), entryPointReqsTLSCounter: multi.NewCounter(entryPointReqsTLSCounter...), entryPointReqDurationHistogram: MultiHistogram(entryPointReqDurationHistogram), - entryPointOpenConnsGauge: multi.NewGauge(entryPointOpenConnsGauge...), entryPointReqsBytesCounter: multi.NewCounter(entryPointReqsBytesCounter...), entryPointRespsBytesCounter: multi.NewCounter(entryPointRespsBytesCounter...), - routerReqsCounter: multi.NewCounter(routerReqsCounter...), + routerReqsCounter: NewMultiCounterWithHeaders(routerReqsCounter...), routerReqsTLSCounter: multi.NewCounter(routerReqsTLSCounter...), routerReqDurationHistogram: MultiHistogram(routerReqDurationHistogram), - routerOpenConnsGauge: multi.NewGauge(routerOpenConnsGauge...), routerReqsBytesCounter: multi.NewCounter(routerReqsBytesCounter...), routerRespsBytesCounter: multi.NewCounter(routerRespsBytesCounter...), - serviceReqsCounter: multi.NewCounter(serviceReqsCounter...), + serviceReqsCounter: NewMultiCounterWithHeaders(serviceReqsCounter...), serviceReqsTLSCounter: multi.NewCounter(serviceReqsTLSCounter...), serviceReqDurationHistogram: MultiHistogram(serviceReqDurationHistogram), - serviceOpenConnsGauge: multi.NewGauge(serviceOpenConnsGauge...), serviceRetriesCounter: multi.NewCounter(serviceRetriesCounter...), serviceServerUpGauge: multi.NewGauge(serviceServerUpGauge...), serviceReqsBytesCounter: multi.NewCounter(serviceReqsBytesCounter...), @@ -211,26 +187,22 @@ type standardRegistry struct { routerEnabled bool svcEnabled bool configReloadsCounter metrics.Counter - configReloadsFailureCounter metrics.Counter lastConfigReloadSuccessGauge metrics.Gauge - lastConfigReloadFailureGauge metrics.Gauge + openConnectionsGauge metrics.Gauge tlsCertsNotAfterTimestampGauge metrics.Gauge - entryPointReqsCounter metrics.Counter + entryPointReqsCounter CounterWithHeaders entryPointReqsTLSCounter metrics.Counter entryPointReqDurationHistogram ScalableHistogram - entryPointOpenConnsGauge metrics.Gauge entryPointReqsBytesCounter metrics.Counter entryPointRespsBytesCounter metrics.Counter - routerReqsCounter metrics.Counter + routerReqsCounter CounterWithHeaders routerReqsTLSCounter metrics.Counter routerReqDurationHistogram ScalableHistogram - routerOpenConnsGauge metrics.Gauge routerReqsBytesCounter metrics.Counter routerRespsBytesCounter metrics.Counter - serviceReqsCounter metrics.Counter + serviceReqsCounter CounterWithHeaders serviceReqsTLSCounter metrics.Counter serviceReqDurationHistogram ScalableHistogram - serviceOpenConnsGauge metrics.Gauge serviceRetriesCounter metrics.Counter serviceServerUpGauge metrics.Gauge serviceReqsBytesCounter metrics.Counter @@ -253,23 +225,19 @@ func (r *standardRegistry) ConfigReloadsCounter() metrics.Counter { return r.configReloadsCounter } -func (r *standardRegistry) ConfigReloadsFailureCounter() metrics.Counter { - return r.configReloadsFailureCounter -} - func (r *standardRegistry) LastConfigReloadSuccessGauge() metrics.Gauge { return r.lastConfigReloadSuccessGauge } -func (r *standardRegistry) LastConfigReloadFailureGauge() metrics.Gauge { - return r.lastConfigReloadFailureGauge +func (r *standardRegistry) OpenConnectionsGauge() metrics.Gauge { + return r.openConnectionsGauge } func (r *standardRegistry) TLSCertsNotAfterTimestampGauge() metrics.Gauge { return r.tlsCertsNotAfterTimestampGauge } -func (r *standardRegistry) EntryPointReqsCounter() metrics.Counter { +func (r *standardRegistry) EntryPointReqsCounter() CounterWithHeaders { return r.entryPointReqsCounter } @@ -281,10 +249,6 @@ func (r *standardRegistry) EntryPointReqDurationHistogram() ScalableHistogram { return r.entryPointReqDurationHistogram } -func (r *standardRegistry) EntryPointOpenConnsGauge() metrics.Gauge { - return r.entryPointOpenConnsGauge -} - func (r *standardRegistry) EntryPointReqsBytesCounter() metrics.Counter { return r.entryPointReqsBytesCounter } @@ -293,7 +257,7 @@ func (r *standardRegistry) EntryPointRespsBytesCounter() metrics.Counter { return r.entryPointRespsBytesCounter } -func (r *standardRegistry) RouterReqsCounter() metrics.Counter { +func (r *standardRegistry) RouterReqsCounter() CounterWithHeaders { return r.routerReqsCounter } @@ -305,10 +269,6 @@ func (r *standardRegistry) RouterReqDurationHistogram() ScalableHistogram { return r.routerReqDurationHistogram } -func (r *standardRegistry) RouterOpenConnsGauge() metrics.Gauge { - return r.routerOpenConnsGauge -} - func (r *standardRegistry) RouterReqsBytesCounter() metrics.Counter { return r.routerReqsBytesCounter } @@ -317,7 +277,7 @@ func (r *standardRegistry) RouterRespsBytesCounter() metrics.Counter { return r.routerRespsBytesCounter } -func (r *standardRegistry) ServiceReqsCounter() metrics.Counter { +func (r *standardRegistry) ServiceReqsCounter() CounterWithHeaders { return r.serviceReqsCounter } @@ -329,10 +289,6 @@ func (r *standardRegistry) ServiceReqDurationHistogram() ScalableHistogram { return r.serviceReqDurationHistogram } -func (r *standardRegistry) ServiceOpenConnsGauge() metrics.Gauge { - return r.serviceOpenConnsGauge -} - func (r *standardRegistry) ServiceRetriesCounter() metrics.Counter { return r.serviceRetriesCounter } diff --git a/pkg/metrics/metrics_test.go b/pkg/metrics/metrics_test.go index 7036335ea..6871aa0a5 100644 --- a/pkg/metrics/metrics_test.go +++ b/pkg/metrics/metrics_test.go @@ -2,6 +2,7 @@ package metrics import ( "bytes" + "net/http" "strings" "testing" "time" @@ -37,12 +38,12 @@ func TestNewMultiRegistry(t *testing.T) { registries := []Registry{newCollectingRetryMetrics(), newCollectingRetryMetrics()} registry := NewMultiRegistry(registries) - registry.ServiceReqsCounter().With("key", "requests").Add(1) + registry.ServiceReqsCounter().With(nil, "key", "requests").Add(1) registry.ServiceReqDurationHistogram().With("key", "durations").Observe(float64(2)) registry.ServiceRetriesCounter().With("key", "retries").Add(3) for _, collectingRegistry := range registries { - cReqsCounter := collectingRegistry.ServiceReqsCounter().(*counterMock) + cReqsCounter := collectingRegistry.ServiceReqsCounter().(*counterWithHeadersMock) cReqDurationHistogram := collectingRegistry.ServiceReqDurationHistogram().(*histogramMock) cRetriesCounter := collectingRegistry.ServiceRetriesCounter().(*counterMock) @@ -67,7 +68,7 @@ func TestNewMultiRegistry(t *testing.T) { func newCollectingRetryMetrics() Registry { return &standardRegistry{ - serviceReqsCounter: &counterMock{}, + serviceReqsCounter: &counterWithHeadersMock{}, serviceReqDurationHistogram: &histogramMock{}, serviceRetriesCounter: &counterMock{}, } @@ -87,6 +88,20 @@ func (c *counterMock) Add(delta float64) { c.counterValue += delta } +type counterWithHeadersMock struct { + counterValue float64 + lastLabelValues []string +} + +func (c *counterWithHeadersMock) With(_ http.Header, labelValues ...string) CounterWithHeaders { + c.lastLabelValues = labelValues + return c +} + +func (c *counterWithHeadersMock) Add(delta float64) { + c.counterValue += delta +} + type histogramMock struct { lastHistogramValue float64 lastLabelValues []string diff --git a/pkg/metrics/opentelemetry.go b/pkg/metrics/opentelemetry.go index 328f6fc54..5dda1d5d0 100644 --- a/pkg/metrics/opentelemetry.go +++ b/pkg/metrics/opentelemetry.go @@ -10,8 +10,8 @@ import ( "github.com/go-kit/kit/metrics" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/types" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/types" + "github.com/traefik/traefik/v3/pkg/version" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" @@ -23,7 +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/metric/view" + "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" ) @@ -56,49 +57,39 @@ func RegisterOpenTelemetry(ctx context.Context, config *types.OpenTelemetry) Reg routerEnabled: config.AddRoutersLabels, svcEnabled: config.AddServicesLabels, configReloadsCounter: newOTLPCounterFrom(meter, configReloadsTotalName, "Config reloads"), - configReloadsFailureCounter: newOTLPCounterFrom(meter, configReloadsFailuresTotalName, "Config reload failures"), lastConfigReloadSuccessGauge: newOTLPGaugeFrom(meter, configLastReloadSuccessName, "Last config reload success", unit.Milliseconds), - lastConfigReloadFailureGauge: newOTLPGaugeFrom(meter, configLastReloadFailureName, "Last config reload failure", unit.Milliseconds), - tlsCertsNotAfterTimestampGauge: newOTLPGaugeFrom(meter, tlsCertsNotAfterTimestamp, "Certificate expiration timestamp", unit.Milliseconds), + openConnectionsGauge: newOTLPGaugeFrom(meter, openConnectionsName, "How many open connections exist, by entryPoint and protocol", unit.Dimensionless), + tlsCertsNotAfterTimestampGauge: newOTLPGaugeFrom(meter, tlsCertsNotAfterTimestampName, "Certificate expiration timestamp", unit.Milliseconds), } if config.AddEntryPointsLabels { - reg.entryPointReqsCounter = newOTLPCounterFrom(meter, entryPointReqsTotalName, - "How many HTTP requests processed on an entrypoint, partitioned by status code, protocol, and method.") + reg.entryPointReqsCounter = NewCounterWithNoopHeaders(newOTLPCounterFrom(meter, entryPointReqsTotalName, + "How many HTTP requests processed on an entrypoint, partitioned by status code, protocol, and method.")) reg.entryPointReqsTLSCounter = newOTLPCounterFrom(meter, entryPointReqsTLSTotalName, "How many HTTP requests with TLS processed on an entrypoint, partitioned by TLS Version and TLS cipher Used.") reg.entryPointReqDurationHistogram, _ = NewHistogramWithScale(newOTLPHistogramFrom(meter, entryPointReqDurationName, "How long it took to process the request on an entrypoint, partitioned by status code, protocol, and method.", unit.Milliseconds), time.Second) - reg.entryPointOpenConnsGauge = newOTLPGaugeFrom(meter, entryPointOpenConnsName, - "How many open connections exist on an entrypoint, partitioned by method and protocol.", - unit.Dimensionless) } if config.AddRoutersLabels { - reg.routerReqsCounter = newOTLPCounterFrom(meter, routerReqsTotalName, - "How many HTTP requests are processed on a router, partitioned by service, status code, protocol, and method.") + reg.routerReqsCounter = NewCounterWithNoopHeaders(newOTLPCounterFrom(meter, routerReqsTotalName, + "How many HTTP requests are processed on a router, partitioned by service, status code, protocol, and method.")) reg.routerReqsTLSCounter = newOTLPCounterFrom(meter, routerReqsTLSTotalName, "How many HTTP requests with TLS are processed on a router, partitioned by service, TLS Version, and TLS cipher Used.") reg.routerReqDurationHistogram, _ = NewHistogramWithScale(newOTLPHistogramFrom(meter, routerReqDurationName, "How long it took to process the request on a router, partitioned by service, status code, protocol, and method.", unit.Milliseconds), time.Second) - reg.routerOpenConnsGauge = newOTLPGaugeFrom(meter, routerOpenConnsName, - "How many open connections exist on a router, partitioned by service, method, and protocol.", - unit.Dimensionless) } if config.AddServicesLabels { - reg.serviceReqsCounter = newOTLPCounterFrom(meter, serviceReqsTotalName, - "How many HTTP requests processed on a service, partitioned by status code, protocol, and method.") + reg.serviceReqsCounter = NewCounterWithNoopHeaders(newOTLPCounterFrom(meter, serviceReqsTotalName, + "How many HTTP requests processed on a service, partitioned by status code, protocol, and method.")) reg.serviceReqsTLSCounter = newOTLPCounterFrom(meter, serviceReqsTLSTotalName, "How many HTTP requests with TLS processed on a service, partitioned by TLS version and TLS cipher.") reg.serviceReqDurationHistogram, _ = NewHistogramWithScale(newOTLPHistogramFrom(meter, serviceReqDurationName, "How long it took to process the request on a service, partitioned by status code, protocol, and method.", unit.Milliseconds), time.Second) - reg.serviceOpenConnsGauge = newOTLPGaugeFrom(meter, serviceOpenConnsName, - "How many open connections exist on a service, partitioned by method and protocol.", - unit.Dimensionless) reg.serviceRetriesCounter = newOTLPCounterFrom(meter, serviceRetriesTotalName, "How many request retries happened on a service.") reg.serviceServerUpGauge = newOTLPGaugeFrom(meter, serviceServerUpName, @@ -140,27 +131,31 @@ 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)), } - // 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.WithResource(res), + 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) diff --git a/pkg/metrics/opentelemetry_test.go b/pkg/metrics/opentelemetry_test.go index 16890b6ba..4f174700c 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" @@ -16,7 +15,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/types" + "github.com/traefik/traefik/v3/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,103 +329,96 @@ func TestOpenTelemetry(t *testing.T) { t.Fatalf("registry should return true for IsEnabled(), IsRouterEnabled() and IsSvcEnabled()") } - // TODO: the len of startUnixNano is no supposed to be 20, it should be 19 - expectedServer := []string{ - `({"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}\]}})`, + 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 + 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_last_reload_success","description":"Last config reload success","unit":"ms","gauge":{"dataPoints":\[{"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":1}\]}})`, + `({"name":"traefik_open_connections","description":"How many open connections exist, by entryPoint and protocol","unit":"1","gauge":{"dataPoints":\[{"attributes":\[{"key":"entrypoint","value":{"stringValue":"test"}},{"key":"protocol","value":{"stringValue":"TCP"}}\],"startTimeUnixNano":"[\d]{20}","timeUnixNano":"[\d]{19}","asDouble":1}\]}})`, + ) registry.ConfigReloadsCounter().Add(1) - registry.ConfigReloadsFailureCounter().Add(1) registry.LastConfigReloadSuccessGauge().Set(1) - registry.LastConfigReloadFailureGauge().Set(1) + registry.OpenConnectionsGauge().With("entrypoint", "test", "protocol", "TCP").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.EntryPointReqsCounter().With(nil, "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) registry.EntryPointReqDurationHistogram().With("entrypoint", "test3").Observe(10000) - 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) + registry.RouterReqsCounter().With(nil, "router", "RouterReqsCounter", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) + registry.RouterReqsCounter().With(nil, "router", "RouterReqsCounter", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) registry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) registry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - 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) + registry.ServiceReqsCounter().With(nil, "service", "ServiceReqsCounter", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) + registry.ServiceReqsCounter().With(nil, "service", "ServiceReqsCounter", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) registry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) registry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) 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) - - expectedServiceOpenConns := []string{ - `({"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) - registry.ServiceOpenConnsGauge().With("service", "test").Add(1) - registry.ServiceOpenConnsGauge().With("service", "foobar").Add(1) - msgServiceOpenConns := <-c - - assertMessage(t, *msgServiceOpenConns, expectedServiceOpenConns) + assertMessage(t, *msgServiceRetries, 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/metrics/prometheus.go b/pkg/metrics/prometheus.go index edad9e6f7..608acf16a 100644 --- a/pkg/metrics/prometheus.go +++ b/pkg/metrics/prometheus.go @@ -12,8 +12,8 @@ import ( "github.com/prometheus/client_golang/prometheus/collectors" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/types" ) const ( @@ -21,22 +21,20 @@ const ( MetricNamePrefix = "traefik_" // server meta information. - metricConfigPrefix = MetricNamePrefix + "config_" - configReloadsTotalName = metricConfigPrefix + "reloads_total" - configReloadsFailuresTotalName = metricConfigPrefix + "reloads_failure_total" - configLastReloadSuccessName = metricConfigPrefix + "last_reload_success" - configLastReloadFailureName = metricConfigPrefix + "last_reload_failure" + metricConfigPrefix = MetricNamePrefix + "config_" + configReloadsTotalName = metricConfigPrefix + "reloads_total" + configLastReloadSuccessName = metricConfigPrefix + "last_reload_success" + openConnectionsName = MetricNamePrefix + "open_connections" // TLS. - metricsTLSPrefix = MetricNamePrefix + "tls_" - tlsCertsNotAfterTimestamp = metricsTLSPrefix + "certs_not_after" + metricsTLSPrefix = MetricNamePrefix + "tls_" + tlsCertsNotAfterTimestampName = metricsTLSPrefix + "certs_not_after" // entry point. metricEntryPointPrefix = MetricNamePrefix + "entrypoint_" entryPointReqsTotalName = metricEntryPointPrefix + "requests_total" entryPointReqsTLSTotalName = metricEntryPointPrefix + "requests_tls_total" entryPointReqDurationName = metricEntryPointPrefix + "request_duration_seconds" - entryPointOpenConnsName = metricEntryPointPrefix + "open_connections" entryPointReqsBytesTotalName = metricEntryPointPrefix + "requests_bytes_total" entryPointRespsBytesTotalName = metricEntryPointPrefix + "responses_bytes_total" @@ -45,7 +43,6 @@ const ( routerReqsTotalName = metricRouterPrefix + "requests_total" routerReqsTLSTotalName = metricRouterPrefix + "requests_tls_total" routerReqDurationName = metricRouterPrefix + "request_duration_seconds" - routerOpenConnsName = metricRouterPrefix + "open_connections" routerReqsBytesTotalName = metricRouterPrefix + "requests_bytes_total" routerRespsBytesTotalName = metricRouterPrefix + "responses_bytes_total" @@ -54,7 +51,6 @@ const ( serviceReqsTotalName = metricServicePrefix + "requests_total" serviceReqsTLSTotalName = metricServicePrefix + "requests_tls_total" serviceReqDurationName = metricServicePrefix + "request_duration_seconds" - serviceOpenConnsName = metricServicePrefix + "open_connections" serviceRetriesTotalName = metricServicePrefix + "retries_total" serviceServerUpName = metricServicePrefix + "server_up" serviceReqsBytesTotalName = metricServicePrefix + "requests_bytes_total" @@ -118,29 +114,24 @@ func initStandardRegistry(config *types.Prometheus) Registry { Name: configReloadsTotalName, Help: "Config reloads", }, []string{}) - configReloadsFailures := newCounterFrom(stdprometheus.CounterOpts{ - Name: configReloadsFailuresTotalName, - Help: "Config failure reloads", - }, []string{}) lastConfigReloadSuccess := newGaugeFrom(stdprometheus.GaugeOpts{ Name: configLastReloadSuccessName, Help: "Last config reload success", }, []string{}) - lastConfigReloadFailure := newGaugeFrom(stdprometheus.GaugeOpts{ - Name: configLastReloadFailureName, - Help: "Last config reload failure", - }, []string{}) tlsCertsNotAfterTimestamp := newGaugeFrom(stdprometheus.GaugeOpts{ - Name: tlsCertsNotAfterTimestamp, + Name: tlsCertsNotAfterTimestampName, Help: "Certificate expiration timestamp", }, []string{"cn", "serial", "sans"}) + openConnections := newGaugeFrom(stdprometheus.GaugeOpts{ + Name: openConnectionsName, + Help: "How many open connections exist, by entryPoint and protocol", + }, []string{"entrypoint", "protocol"}) promState.vectors = []vector{ configReloads.cv, - configReloadsFailures.cv, lastConfigReloadSuccess.gv, - lastConfigReloadFailure.gv, tlsCertsNotAfterTimestamp.gv, + openConnections.gv, } reg := &standardRegistry{ @@ -148,17 +139,16 @@ func initStandardRegistry(config *types.Prometheus) Registry { routerEnabled: config.AddRoutersLabels, svcEnabled: config.AddServicesLabels, configReloadsCounter: configReloads, - configReloadsFailureCounter: configReloadsFailures, lastConfigReloadSuccessGauge: lastConfigReloadSuccess, - lastConfigReloadFailureGauge: lastConfigReloadFailure, tlsCertsNotAfterTimestampGauge: tlsCertsNotAfterTimestamp, + openConnectionsGauge: openConnections, } if config.AddEntryPointsLabels { - entryPointReqs := newCounterFrom(stdprometheus.CounterOpts{ + entryPointReqs := newCounterWithHeadersFrom(stdprometheus.CounterOpts{ Name: entryPointReqsTotalName, Help: "How many HTTP requests processed on an entrypoint, partitioned by status code, protocol, and method.", - }, []string{"code", "method", "protocol", "entrypoint"}) + }, config.HeaderLabels, []string{"code", "method", "protocol", "entrypoint"}) entryPointReqsTLS := newCounterFrom(stdprometheus.CounterOpts{ Name: entryPointReqsTLSTotalName, Help: "How many HTTP requests with TLS processed on an entrypoint, partitioned by TLS Version and TLS cipher Used.", @@ -168,10 +158,6 @@ func initStandardRegistry(config *types.Prometheus) Registry { Help: "How long it took to process the request on an entrypoint, partitioned by status code, protocol, and method.", Buckets: buckets, }, []string{"code", "method", "protocol", "entrypoint"}) - entryPointOpenConns := newGaugeFrom(stdprometheus.GaugeOpts{ - Name: entryPointOpenConnsName, - Help: "How many open connections exist on an entrypoint, partitioned by method and protocol.", - }, []string{"method", "protocol", "entrypoint"}) entryPointReqsBytesTotal := newCounterFrom(stdprometheus.CounterOpts{ Name: entryPointReqsBytesTotalName, Help: "The total size of requests in bytes handled by an entrypoint, partitioned by status code, protocol, and method.", @@ -185,7 +171,6 @@ func initStandardRegistry(config *types.Prometheus) Registry { entryPointReqs.cv, entryPointReqsTLS.cv, entryPointReqDurations.hv, - entryPointOpenConns.gv, entryPointReqsBytesTotal.cv, entryPointRespsBytesTotal.cv, ) @@ -193,16 +178,15 @@ func initStandardRegistry(config *types.Prometheus) Registry { reg.entryPointReqsCounter = entryPointReqs reg.entryPointReqsTLSCounter = entryPointReqsTLS reg.entryPointReqDurationHistogram, _ = NewHistogramWithScale(entryPointReqDurations, time.Second) - reg.entryPointOpenConnsGauge = entryPointOpenConns reg.entryPointReqsBytesCounter = entryPointReqsBytesTotal reg.entryPointRespsBytesCounter = entryPointRespsBytesTotal } if config.AddRoutersLabels { - routerReqs := newCounterFrom(stdprometheus.CounterOpts{ + routerReqs := newCounterWithHeadersFrom(stdprometheus.CounterOpts{ Name: routerReqsTotalName, Help: "How many HTTP requests are processed on a router, partitioned by service, status code, protocol, and method.", - }, []string{"code", "method", "protocol", "router", "service"}) + }, config.HeaderLabels, []string{"code", "method", "protocol", "router", "service"}) routerReqsTLS := newCounterFrom(stdprometheus.CounterOpts{ Name: routerReqsTLSTotalName, Help: "How many HTTP requests with TLS are processed on a router, partitioned by service, TLS Version, and TLS cipher Used.", @@ -212,10 +196,6 @@ func initStandardRegistry(config *types.Prometheus) Registry { Help: "How long it took to process the request on a router, partitioned by service, status code, protocol, and method.", Buckets: buckets, }, []string{"code", "method", "protocol", "router", "service"}) - routerOpenConns := newGaugeFrom(stdprometheus.GaugeOpts{ - Name: routerOpenConnsName, - Help: "How many open connections exist on a router, partitioned by service, method, and protocol.", - }, []string{"method", "protocol", "router", "service"}) routerReqsBytesTotal := newCounterFrom(stdprometheus.CounterOpts{ Name: routerReqsBytesTotalName, Help: "The total size of requests in bytes handled by a router, partitioned by service, status code, protocol, and method.", @@ -229,23 +209,21 @@ func initStandardRegistry(config *types.Prometheus) Registry { routerReqs.cv, routerReqsTLS.cv, routerReqDurations.hv, - routerOpenConns.gv, routerReqsBytesTotal.cv, routerRespsBytesTotal.cv, ) reg.routerReqsCounter = routerReqs reg.routerReqsTLSCounter = routerReqsTLS reg.routerReqDurationHistogram, _ = NewHistogramWithScale(routerReqDurations, time.Second) - reg.routerOpenConnsGauge = routerOpenConns reg.routerReqsBytesCounter = routerReqsBytesTotal reg.routerRespsBytesCounter = routerRespsBytesTotal } if config.AddServicesLabels { - serviceReqs := newCounterFrom(stdprometheus.CounterOpts{ + serviceReqs := newCounterWithHeadersFrom(stdprometheus.CounterOpts{ Name: serviceReqsTotalName, Help: "How many HTTP requests processed on a service, partitioned by status code, protocol, and method.", - }, []string{"code", "method", "protocol", "service"}) + }, config.HeaderLabels, []string{"code", "method", "protocol", "service"}) serviceReqsTLS := newCounterFrom(stdprometheus.CounterOpts{ Name: serviceReqsTLSTotalName, Help: "How many HTTP requests with TLS processed on a service, partitioned by TLS version and TLS cipher.", @@ -255,10 +233,6 @@ func initStandardRegistry(config *types.Prometheus) Registry { Help: "How long it took to process the request on a service, partitioned by status code, protocol, and method.", Buckets: buckets, }, []string{"code", "method", "protocol", "service"}) - serviceOpenConns := newGaugeFrom(stdprometheus.GaugeOpts{ - Name: serviceOpenConnsName, - Help: "How many open connections exist on a service, partitioned by method and protocol.", - }, []string{"method", "protocol", "service"}) serviceRetries := newCounterFrom(stdprometheus.CounterOpts{ Name: serviceRetriesTotalName, Help: "How many request retries happened on a service.", @@ -280,7 +254,6 @@ func initStandardRegistry(config *types.Prometheus) Registry { serviceReqs.cv, serviceReqsTLS.cv, serviceReqDurations.hv, - serviceOpenConns.gv, serviceRetries.cv, serviceServerUp.gv, serviceReqsBytesTotal.cv, @@ -290,7 +263,6 @@ func initStandardRegistry(config *types.Prometheus) Registry { reg.serviceReqsCounter = serviceReqs reg.serviceReqsTLSCounter = serviceReqsTLS reg.serviceReqDurationHistogram, _ = NewHistogramWithScale(serviceReqDurations, time.Second) - reg.serviceOpenConnsGauge = serviceOpenConns reg.serviceRetriesCounter = serviceRetries reg.serviceServerUpGauge = serviceServerUp reg.serviceReqsBytesCounter = serviceReqsBytesTotal @@ -508,6 +480,55 @@ func (d *dynamicConfig) hasServerURL(serviceName, serverURL string) bool { return false } +func newCounterWithHeadersFrom(opts stdprometheus.CounterOpts, headers map[string]string, labelNames []string) *counterWithHeaders { + var headerLabels []string + for k := range headers { + headerLabels = append(headerLabels, k) + } + + cv := stdprometheus.NewCounterVec(opts, append(labelNames, headerLabels...)) + c := &counterWithHeaders{ + name: opts.Name, + headers: headers, + cv: cv, + } + if len(labelNames) == 0 && len(headerLabels) == 0 { + c.collector = cv.WithLabelValues() + c.Add(0) + } + return c +} + +type counterWithHeaders struct { + name string + cv *stdprometheus.CounterVec + labelNamesValues labelNamesValues + headers map[string]string + collector stdprometheus.Counter +} + +func (c *counterWithHeaders) With(headers http.Header, labelValues ...string) CounterWithHeaders { + for headerLabel, headerKey := range c.headers { + labelValues = append(labelValues, headerLabel, headers.Get(headerKey)) + } + lnv := c.labelNamesValues.With(labelValues...) + return &counterWithHeaders{ + name: c.name, + headers: c.headers, + cv: c.cv, + labelNamesValues: lnv, + collector: c.cv.With(lnv.ToLabels()), + } +} + +func (c *counterWithHeaders) Add(delta float64) { + c.collector.Add(delta) +} + +func (c *counterWithHeaders) Describe(ch chan<- *stdprometheus.Desc) { + c.cv.Describe(ch) +} + func newCounterFrom(opts stdprometheus.CounterOpts, labelNames []string) *counter { cv := stdprometheus.NewCounterVec(opts, labelNames) c := &counter{ diff --git a/pkg/metrics/prometheus_test.go b/pkg/metrics/prometheus_test.go index 744a7615d..9a5bfeba7 100644 --- a/pkg/metrics/prometheus_test.go +++ b/pkg/metrics/prometheus_test.go @@ -11,9 +11,9 @@ import ( "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - th "github.com/traefik/traefik/v2/pkg/testhelpers" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + th "github.com/traefik/traefik/v3/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/types" ) func TestRegisterPromState(t *testing.T) { @@ -92,7 +92,12 @@ func TestPrometheus(t *testing.T) { promRegistry = prometheus.NewRegistry() t.Cleanup(promState.reset) - prometheusRegistry := RegisterPrometheus(context.Background(), &types.Prometheus{AddEntryPointsLabels: true, AddRoutersLabels: true, AddServicesLabels: true}) + prometheusRegistry := RegisterPrometheus(context.Background(), &types.Prometheus{ + AddEntryPointsLabels: true, + AddRoutersLabels: true, + AddServicesLabels: true, + HeaderLabels: map[string]string{"useragent": "User-Agent"}, + }) defer promRegistry.Unregister(promState) if !prometheusRegistry.IsEpEnabled() || !prometheusRegistry.IsRouterEnabled() || !prometheusRegistry.IsSvcEnabled() { @@ -100,9 +105,11 @@ func TestPrometheus(t *testing.T) { } prometheusRegistry.ConfigReloadsCounter().Add(1) - prometheusRegistry.ConfigReloadsFailureCounter().Add(1) prometheusRegistry.LastConfigReloadSuccessGauge().Set(float64(time.Now().Unix())) - prometheusRegistry.LastConfigReloadFailureGauge().Set(float64(time.Now().Unix())) + prometheusRegistry. + OpenConnectionsGauge(). + With("entrypoint", "test", "protocol", "TCP"). + Set(1) prometheusRegistry. TLSCertsNotAfterTimestampGauge(). @@ -111,16 +118,12 @@ func TestPrometheus(t *testing.T) { prometheusRegistry. EntryPointReqsCounter(). - With("code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http", "entrypoint", "http"). + With(map[string][]string{"User-Agent": {"foobar"}}, "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http", "entrypoint", "http"). Add(1) prometheusRegistry. EntryPointReqDurationHistogram(). With("code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http", "entrypoint", "http"). Observe(1) - prometheusRegistry. - EntryPointOpenConnsGauge(). - With("method", http.MethodGet, "protocol", "http", "entrypoint", "http"). - Set(1) prometheusRegistry. EntryPointRespsBytesCounter(). With("code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http", "entrypoint", "http"). @@ -132,7 +135,7 @@ func TestPrometheus(t *testing.T) { prometheusRegistry. RouterReqsCounter(). - With("router", "demo", "service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + With(nil, "router", "demo", "service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Add(1) prometheusRegistry. RouterReqsTLSCounter(). @@ -142,10 +145,6 @@ func TestPrometheus(t *testing.T) { RouterReqDurationHistogram(). With("router", "demo", "service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Observe(10000) - prometheusRegistry. - RouterOpenConnsGauge(). - With("router", "demo", "service", "service1", "method", http.MethodGet, "protocol", "http"). - Set(1) prometheusRegistry. RouterRespsBytesCounter(). With("router", "demo", "service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). @@ -157,7 +156,7 @@ func TestPrometheus(t *testing.T) { prometheusRegistry. ServiceReqsCounter(). - With("service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + With(map[string][]string{"User-Agent": {"foobar"}}, "service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Add(1) prometheusRegistry. ServiceReqsTLSCounter(). @@ -167,10 +166,6 @@ func TestPrometheus(t *testing.T) { ServiceReqDurationHistogram(). With("service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Observe(10000) - prometheusRegistry. - ServiceOpenConnsGauge(). - With("service", "service1", "method", http.MethodGet, "protocol", "http"). - Set(1) prometheusRegistry. ServiceRetriesCounter(). With("service", "service1"). @@ -201,26 +196,26 @@ func TestPrometheus(t *testing.T) { name: configReloadsTotalName, assert: buildCounterAssert(t, configReloadsTotalName, 1), }, - { - name: configReloadsFailuresTotalName, - assert: buildCounterAssert(t, configReloadsFailuresTotalName, 1), - }, { name: configLastReloadSuccessName, assert: buildTimestampAssert(t, configLastReloadSuccessName), }, { - name: configLastReloadFailureName, - assert: buildTimestampAssert(t, configLastReloadFailureName), + name: openConnectionsName, + labels: map[string]string{ + "protocol": "TCP", + "entrypoint": "test", + }, + assert: buildGaugeAssert(t, openConnectionsName, 1), }, { - name: tlsCertsNotAfterTimestamp, + name: tlsCertsNotAfterTimestampName, labels: map[string]string{ "cn": "value", "serial": "value", "sans": "value", }, - assert: buildTimestampAssert(t, tlsCertsNotAfterTimestamp), + assert: buildTimestampAssert(t, tlsCertsNotAfterTimestampName), }, { name: entryPointReqsTotalName, @@ -229,6 +224,7 @@ func TestPrometheus(t *testing.T) { "method": http.MethodGet, "protocol": "http", "entrypoint": "http", + "useragent": "foobar", }, assert: buildCounterAssert(t, entryPointReqsTotalName, 1), }, @@ -242,15 +238,6 @@ func TestPrometheus(t *testing.T) { }, assert: buildHistogramAssert(t, entryPointReqDurationName, 1), }, - { - name: entryPointOpenConnsName, - labels: map[string]string{ - "method": http.MethodGet, - "protocol": "http", - "entrypoint": "http", - }, - assert: buildGaugeAssert(t, entryPointOpenConnsName, 1), - }, { name: entryPointReqsBytesTotalName, labels: map[string]string{ @@ -274,11 +261,12 @@ func TestPrometheus(t *testing.T) { { name: routerReqsTotalName, labels: map[string]string{ - "code": "200", - "method": http.MethodGet, - "protocol": "http", - "service": "service1", - "router": "demo", + "code": "200", + "method": http.MethodGet, + "protocol": "http", + "service": "service1", + "router": "demo", + "useragent": "", }, assert: buildCounterAssert(t, routerReqsTotalName, 1), }, @@ -303,16 +291,6 @@ func TestPrometheus(t *testing.T) { }, assert: buildHistogramAssert(t, routerReqDurationName, 1), }, - { - name: routerOpenConnsName, - labels: map[string]string{ - "method": http.MethodGet, - "protocol": "http", - "service": "service1", - "router": "demo", - }, - assert: buildGaugeAssert(t, routerOpenConnsName, 1), - }, { name: routerReqsBytesTotalName, labels: map[string]string{ @@ -338,10 +316,11 @@ func TestPrometheus(t *testing.T) { { name: serviceReqsTotalName, labels: map[string]string{ - "code": "200", - "method": http.MethodGet, - "protocol": "http", - "service": "service1", + "code": "200", + "method": http.MethodGet, + "protocol": "http", + "service": "service1", + "useragent": "foobar", }, assert: buildCounterAssert(t, serviceReqsTotalName, 1), }, @@ -364,15 +343,6 @@ func TestPrometheus(t *testing.T) { }, assert: buildHistogramAssert(t, serviceReqDurationName, 1), }, - { - name: serviceOpenConnsName, - labels: map[string]string{ - "method": http.MethodGet, - "protocol": "http", - "service": "service1", - }, - assert: buildGaugeAssert(t, serviceOpenConnsName, 1), - }, { name: serviceRetriesTotalName, labels: map[string]string{ @@ -476,15 +446,15 @@ func TestPrometheusMetricRemoval(t *testing.T) { // should be removed after that scrape. prometheusRegistry. EntryPointReqsCounter(). - With("entrypoint", "entrypoint2", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + With(nil, "entrypoint", "entrypoint2", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Add(1) prometheusRegistry. RouterReqsCounter(). - With("router", "router2", "service", "bar@providerName", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + With(nil, "router", "router2", "service", "bar@providerName", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Add(1) prometheusRegistry. ServiceReqsCounter(). - With("service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + With(nil, "service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Add(1) prometheusRegistry. ServiceServerUpGauge(). @@ -502,15 +472,15 @@ func TestPrometheusMetricRemoval(t *testing.T) { // here the counter examples. prometheusRegistry. EntryPointReqsCounter(). - With("entrypoint", "entrypoint1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + With(nil, "entrypoint", "entrypoint1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Add(1) prometheusRegistry. RouterReqsCounter(). - With("router", "foo@providerName", "service", "bar", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + With(nil, "router", "foo@providerName", "service", "bar", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Add(1) prometheusRegistry. ServiceReqsCounter(). - With("service", "bar@providerName", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + With(nil, "service", "bar@providerName", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Add(1) prometheusRegistry. ServiceServerUpGauge(). @@ -588,7 +558,7 @@ func TestPrometheusRemovedMetricsReset(t *testing.T) { } prometheusRegistry. ServiceReqsCounter(). - With(labelNamesValues...). + With(nil, labelNamesValues...). Add(3) delayForTrackingCompletion() @@ -602,7 +572,7 @@ func TestPrometheusRemovedMetricsReset(t *testing.T) { prometheusRegistry. ServiceReqsCounter(). - With(labelNamesValues...). + With(nil, labelNamesValues...). Add(1) delayForTrackingCompletion() diff --git a/pkg/metrics/statsd.go b/pkg/metrics/statsd.go index 2a1c80a9c..871300ef6 100644 --- a/pkg/metrics/statsd.go +++ b/pkg/metrics/statsd.go @@ -6,9 +6,9 @@ import ( "github.com/go-kit/kit/metrics/statsd" "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" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/types" ) var ( @@ -18,23 +18,20 @@ var ( const ( statsdConfigReloadsName = "config.reload.total" - statsdConfigReloadsFailureName = statsdConfigReloadsName + ".failure" statsdLastConfigReloadSuccessName = "config.reload.lastSuccessTimestamp" - statsdLastConfigReloadFailureName = "config.reload.lastFailureTimestamp" + statsdOpenConnectionsName = "open.connections" statsdTLSCertsNotAfterTimestampName = "tls.certs.notAfterTimestamp" statsdEntryPointReqsName = "entrypoint.request.total" statsdEntryPointReqsTLSName = "entrypoint.request.tls.total" statsdEntryPointReqDurationName = "entrypoint.request.duration" - statsdEntryPointOpenConnsName = "entrypoint.connections.open" statsdEntryPointReqsBytesName = "entrypoint.requests.bytes.total" statsdEntryPointRespsBytesName = "entrypoint.responses.bytes.total" statsdRouterReqsName = "router.request.total" statsdRouterReqsTLSName = "router.request.tls.total" statsdRouterReqsDurationName = "router.request.duration" - statsdRouterOpenConnsName = "router.connections.open" statsdRouterReqsBytesName = "router.requests.bytes.total" statsdRouterRespsBytesName = "router.responses.bytes.total" @@ -43,7 +40,6 @@ const ( statsdServiceReqsDurationName = "service.request.duration" statsdServiceRetriesTotalName = "service.retries.total" statsdServiceServerUpName = "service.server.up" - statsdServiceOpenConnsName = "service.connections.open" statsdServiceReqsBytesName = "service.requests.bytes.total" statsdServiceRespsBytesName = "service.responses.bytes.total" ) @@ -63,39 +59,35 @@ func RegisterStatsd(ctx context.Context, config *types.Statsd) Registry { registry := &standardRegistry{ configReloadsCounter: statsdClient.NewCounter(statsdConfigReloadsName, 1.0), - configReloadsFailureCounter: statsdClient.NewCounter(statsdConfigReloadsFailureName, 1.0), lastConfigReloadSuccessGauge: statsdClient.NewGauge(statsdLastConfigReloadSuccessName), - lastConfigReloadFailureGauge: statsdClient.NewGauge(statsdLastConfigReloadFailureName), tlsCertsNotAfterTimestampGauge: statsdClient.NewGauge(statsdTLSCertsNotAfterTimestampName), + openConnectionsGauge: statsdClient.NewGauge(statsdOpenConnectionsName), } if config.AddEntryPointsLabels { registry.epEnabled = config.AddEntryPointsLabels - registry.entryPointReqsCounter = statsdClient.NewCounter(statsdEntryPointReqsName, 1.0) + registry.entryPointReqsCounter = NewCounterWithNoopHeaders(statsdClient.NewCounter(statsdEntryPointReqsName, 1.0)) registry.entryPointReqsTLSCounter = statsdClient.NewCounter(statsdEntryPointReqsTLSName, 1.0) registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(statsdClient.NewTiming(statsdEntryPointReqDurationName, 1.0), time.Millisecond) - registry.entryPointOpenConnsGauge = statsdClient.NewGauge(statsdEntryPointOpenConnsName) registry.entryPointReqsBytesCounter = statsdClient.NewCounter(statsdEntryPointReqsBytesName, 1.0) registry.entryPointRespsBytesCounter = statsdClient.NewCounter(statsdEntryPointRespsBytesName, 1.0) } if config.AddRoutersLabels { registry.routerEnabled = config.AddRoutersLabels - registry.routerReqsCounter = statsdClient.NewCounter(statsdRouterReqsName, 1.0) + registry.routerReqsCounter = NewCounterWithNoopHeaders(statsdClient.NewCounter(statsdRouterReqsName, 1.0)) registry.routerReqsTLSCounter = statsdClient.NewCounter(statsdRouterReqsTLSName, 1.0) registry.routerReqDurationHistogram, _ = NewHistogramWithScale(statsdClient.NewTiming(statsdRouterReqsDurationName, 1.0), time.Millisecond) - registry.routerOpenConnsGauge = statsdClient.NewGauge(statsdRouterOpenConnsName) registry.routerReqsBytesCounter = statsdClient.NewCounter(statsdRouterReqsBytesName, 1.0) registry.routerRespsBytesCounter = statsdClient.NewCounter(statsdRouterRespsBytesName, 1.0) } if config.AddServicesLabels { registry.svcEnabled = config.AddServicesLabels - registry.serviceReqsCounter = statsdClient.NewCounter(statsdServiceReqsName, 1.0) + registry.serviceReqsCounter = NewCounterWithNoopHeaders(statsdClient.NewCounter(statsdServiceReqsName, 1.0)) registry.serviceReqsTLSCounter = statsdClient.NewCounter(statsdServiceReqsTLSName, 1.0) registry.serviceReqDurationHistogram, _ = NewHistogramWithScale(statsdClient.NewTiming(statsdServiceReqsDurationName, 1.0), time.Millisecond) registry.serviceRetriesCounter = statsdClient.NewCounter(statsdServiceRetriesTotalName, 1.0) - registry.serviceOpenConnsGauge = statsdClient.NewGauge(statsdServiceOpenConnsName) registry.serviceServerUpGauge = statsdClient.NewGauge(statsdServiceServerUpName) registry.serviceReqsBytesCounter = statsdClient.NewCounter(statsdServiceReqsBytesName, 1.0) registry.serviceRespsBytesCounter = statsdClient.NewCounter(statsdServiceRespsBytesName, 1.0) diff --git a/pkg/metrics/statsd_test.go b/pkg/metrics/statsd_test.go index 3eb8e4705..174081db4 100644 --- a/pkg/metrics/statsd_test.go +++ b/pkg/metrics/statsd_test.go @@ -9,7 +9,7 @@ import ( "github.com/stvp/go-udp-testing" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/types" ) func TestStatsD(t *testing.T) { @@ -49,30 +49,26 @@ func testRegistry(t *testing.T, metricsPrefix string, registry Registry) { expected := []string{ metricsPrefix + ".config.reload.total:1.000000|c\n", - metricsPrefix + ".config.reload.total.failure:1.000000|c\n", metricsPrefix + ".config.reload.lastSuccessTimestamp:1.000000|g\n", - metricsPrefix + ".config.reload.lastFailureTimestamp:1.000000|g\n", + metricsPrefix + ".open.connections:1.000000|g\n", metricsPrefix + ".tls.certs.notAfterTimestamp:1.000000|g\n", metricsPrefix + ".entrypoint.request.total:1.000000|c\n", metricsPrefix + ".entrypoint.request.tls.total:1.000000|c\n", metricsPrefix + ".entrypoint.request.duration:10000.000000|ms", - metricsPrefix + ".entrypoint.connections.open:1.000000|g\n", metricsPrefix + ".entrypoint.requests.bytes.total:1.000000|c\n", metricsPrefix + ".entrypoint.responses.bytes.total:1.000000|c\n", metricsPrefix + ".router.request.total:2.000000|c\n", metricsPrefix + ".router.request.tls.total:1.000000|c\n", metricsPrefix + ".router.request.duration:10000.000000|ms", - metricsPrefix + ".router.connections.open:1.000000|g\n", metricsPrefix + ".router.requests.bytes.total:1.000000|c\n", metricsPrefix + ".router.responses.bytes.total:1.000000|c\n", metricsPrefix + ".service.request.total:2.000000|c\n", metricsPrefix + ".service.request.tls.total:1.000000|c\n", metricsPrefix + ".service.request.duration:10000.000000|ms", - metricsPrefix + ".service.connections.open:1.000000|g\n", metricsPrefix + ".service.retries.total:2.000000|c\n", metricsPrefix + ".service.server.up:1.000000|g\n", metricsPrefix + ".service.requests.bytes.total:1.000000|c\n", @@ -81,32 +77,28 @@ func testRegistry(t *testing.T, metricsPrefix string, registry Registry) { udp.ShouldReceiveAll(t, expected, func() { registry.ConfigReloadsCounter().Add(1) - registry.ConfigReloadsFailureCounter().Add(1) registry.LastConfigReloadSuccessGauge().Set(1) - registry.LastConfigReloadFailureGauge().Set(1) + registry.OpenConnectionsGauge().With("entrypoint", "test", "protocol", "TCP").Set(1) registry.TLSCertsNotAfterTimestampGauge().With("key", "value").Set(1) - registry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) + registry.EntryPointReqsCounter().With(nil, "entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) registry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) registry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000) - registry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1) registry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) registry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) - registry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) + registry.RouterReqsCounter().With(nil, "router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) + registry.RouterReqsCounter().With(nil, "router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) registry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) registry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - registry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1) registry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) registry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) - registry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) + registry.ServiceReqsCounter().With(nil, "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1) + registry.ServiceReqsCounter().With(nil, "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1) registry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1) registry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000) - registry.ServiceOpenConnsGauge().With("service", "test").Set(1) registry.ServiceRetriesCounter().With("service", "test").Add(1) registry.ServiceRetriesCounter().With("service", "test").Add(1) registry.ServiceServerUpGauge().With("service:test", "url", "http://127.0.0.1").Set(1) diff --git a/pkg/middlewares/accesslog/field_middleware.go b/pkg/middlewares/accesslog/field_middleware.go index a7a63f683..81f8cf606 100644 --- a/pkg/middlewares/accesslog/field_middleware.go +++ b/pkg/middlewares/accesslog/field_middleware.go @@ -5,8 +5,8 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/middlewares/capture" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/middlewares/capture" "github.com/vulcand/oxy/v2/utils" ) diff --git a/pkg/middlewares/accesslog/logger.go b/pkg/middlewares/accesslog/logger.go index 5c5b95dad..20ee4659f 100644 --- a/pkg/middlewares/accesslog/logger.go +++ b/pkg/middlewares/accesslog/logger.go @@ -19,10 +19,10 @@ import ( "github.com/rs/zerolog/log" "github.com/sirupsen/logrus" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/middlewares/capture" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/middlewares/capture" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" ) type key string diff --git a/pkg/middlewares/accesslog/logger_test.go b/pkg/middlewares/accesslog/logger_test.go index 967070b7d..0f3c63607 100644 --- a/pkg/middlewares/accesslog/logger_test.go +++ b/pkg/middlewares/accesslog/logger_test.go @@ -22,8 +22,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/middlewares/capture" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/middlewares/capture" + "github.com/traefik/traefik/v3/pkg/types" ) var ( diff --git a/pkg/middlewares/addprefix/add_prefix.go b/pkg/middlewares/addprefix/add_prefix.go index 83c4b0648..4363da9b9 100644 --- a/pkg/middlewares/addprefix/add_prefix.go +++ b/pkg/middlewares/addprefix/add_prefix.go @@ -6,9 +6,9 @@ import ( "net/http" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/addprefix/add_prefix_test.go b/pkg/middlewares/addprefix/add_prefix_test.go index 9ec4df5fa..b7bbeb697 100644 --- a/pkg/middlewares/addprefix/add_prefix_test.go +++ b/pkg/middlewares/addprefix/add_prefix_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestNewAddPrefix(t *testing.T) { diff --git a/pkg/middlewares/auth/basic_auth.go b/pkg/middlewares/auth/basic_auth.go index b67eaf643..70e25d3a1 100644 --- a/pkg/middlewares/auth/basic_auth.go +++ b/pkg/middlewares/auth/basic_auth.go @@ -9,10 +9,10 @@ import ( goauth "github.com/abbot/go-http-auth" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/auth/basic_auth_test.go b/pkg/middlewares/auth/basic_auth_test.go index 9e1b92ad1..4da9edcae 100644 --- a/pkg/middlewares/auth/basic_auth_test.go +++ b/pkg/middlewares/auth/basic_auth_test.go @@ -11,8 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestBasicAuthFail(t *testing.T) { diff --git a/pkg/middlewares/auth/digest_auth.go b/pkg/middlewares/auth/digest_auth.go index 214e968ee..ea772aeb5 100644 --- a/pkg/middlewares/auth/digest_auth.go +++ b/pkg/middlewares/auth/digest_auth.go @@ -9,10 +9,10 @@ import ( goauth "github.com/abbot/go-http-auth" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/auth/digest_auth_test.go b/pkg/middlewares/auth/digest_auth_test.go index 066f80e0f..46c0b7481 100644 --- a/pkg/middlewares/auth/digest_auth_test.go +++ b/pkg/middlewares/auth/digest_auth_test.go @@ -11,8 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestDigestAuthError(t *testing.T) { diff --git a/pkg/middlewares/auth/forward.go b/pkg/middlewares/auth/forward.go index b6adb3cb1..6ad5f628f 100644 --- a/pkg/middlewares/auth/forward.go +++ b/pkg/middlewares/auth/forward.go @@ -12,10 +12,10 @@ import ( "time" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/middlewares/connectionheader" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares/connectionheader" + "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/forward" "github.com/vulcand/oxy/v2/utils" ) diff --git a/pkg/middlewares/auth/forward_test.go b/pkg/middlewares/auth/forward_test.go index 4e17f7ff5..0f300fc71 100644 --- a/pkg/middlewares/auth/forward_test.go +++ b/pkg/middlewares/auth/forward_test.go @@ -12,10 +12,10 @@ import ( "github.com/opentracing/opentracing-go/mocktracer" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - tracingMiddleware "github.com/traefik/traefik/v2/pkg/middlewares/tracing" - "github.com/traefik/traefik/v2/pkg/testhelpers" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + tracingMiddleware "github.com/traefik/traefik/v3/pkg/middlewares/tracing" + "github.com/traefik/traefik/v3/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/forward" ) diff --git a/pkg/middlewares/buffering/buffering.go b/pkg/middlewares/buffering/buffering.go index 300052460..6aa2ed562 100644 --- a/pkg/middlewares/buffering/buffering.go +++ b/pkg/middlewares/buffering/buffering.go @@ -6,10 +6,10 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" oxybuffer "github.com/vulcand/oxy/v2/buffer" ) diff --git a/pkg/middlewares/buffering/buffering_test.go b/pkg/middlewares/buffering/buffering_test.go index 22477785a..3d40aee5f 100644 --- a/pkg/middlewares/buffering/buffering_test.go +++ b/pkg/middlewares/buffering/buffering_test.go @@ -3,20 +3,20 @@ package buffering import ( "bytes" "context" + "crypto/rand" "math" - "math/rand" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestBuffering(t *testing.T) { payload := make([]byte, math.MaxInt8) - rand.Read(payload) + _, _ = rand.Read(payload) testCases := []struct { desc string diff --git a/pkg/middlewares/capture/capture.go b/pkg/middlewares/capture/capture.go index 3608945b8..b7e182117 100644 --- a/pkg/middlewares/capture/capture.go +++ b/pkg/middlewares/capture/capture.go @@ -32,7 +32,7 @@ import ( "net" "net/http" - "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares" ) type key string diff --git a/pkg/middlewares/capture/capture_test.go b/pkg/middlewares/capture/capture_test.go index 7705aa6b6..b3cfff1de 100644 --- a/pkg/middlewares/capture/capture_test.go +++ b/pkg/middlewares/capture/capture_test.go @@ -58,7 +58,7 @@ func TestCapture(t *testing.T) { // $ go test -bench=. ./pkg/middlewares/capture/ // goos: linux // goarch: amd64 -// pkg: github.com/traefik/traefik/v2/pkg/middlewares/capture +// pkg: github.com/traefik/traefik/v3/pkg/middlewares/capture // cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz // BenchmarkCapture/2k-12 280507 4015 ns/op 510.03 MB/s 5072 B/op 14 allocs/op // BenchmarkCapture/20k-12 135726 8301 ns/op 2467.26 MB/s 41936 B/op 14 allocs/op diff --git a/pkg/middlewares/chain/chain.go b/pkg/middlewares/chain/chain.go index e5fd9aa93..d87596b42 100644 --- a/pkg/middlewares/chain/chain.go +++ b/pkg/middlewares/chain/chain.go @@ -5,8 +5,8 @@ import ( "net/http" "github.com/containous/alice" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" ) const ( diff --git a/pkg/middlewares/circuitbreaker/circuit_breaker.go b/pkg/middlewares/circuitbreaker/circuit_breaker.go index 8e3f3339b..8445b45b8 100644 --- a/pkg/middlewares/circuitbreaker/circuit_breaker.go +++ b/pkg/middlewares/circuitbreaker/circuit_breaker.go @@ -8,10 +8,10 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/cbreaker" ) diff --git a/pkg/middlewares/compress/compress.go b/pkg/middlewares/compress/compress.go index 4db054d65..ab9bdc71b 100644 --- a/pkg/middlewares/compress/compress.go +++ b/pkg/middlewares/compress/compress.go @@ -9,10 +9,10 @@ import ( "github.com/klauspost/compress/gzhttp" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/middlewares/compress/brotli" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares/compress/brotli" + "github.com/traefik/traefik/v3/pkg/tracing" ) const typeName = "Compress" diff --git a/pkg/middlewares/compress/compress_test.go b/pkg/middlewares/compress/compress_test.go index b3eb0e03c..fb7f95a69 100644 --- a/pkg/middlewares/compress/compress_test.go +++ b/pkg/middlewares/compress/compress_test.go @@ -12,8 +12,8 @@ import ( "github.com/klauspost/compress/gzhttp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) const ( @@ -173,6 +173,60 @@ func TestShouldCompressWhenNoAcceptEncodingHeader(t *testing.T) { assert.Equal(t, got, fakeBody) } +func TestShouldNotCompressWhenIdentityAcceptEncodingHeader(t *testing.T) { + req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) + req.Header.Set(acceptEncodingHeader, "identity") + + fakeBody := generateBytes(gzhttp.DefaultMinSize) + next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + if r.Header.Get(acceptEncodingHeader) != "identity" { + http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + + _, err := rw.Write(fakeBody) + if err != nil { + http.Error(rw, err.Error(), http.StatusInternalServerError) + } + }) + handler, err := New(context.Background(), next, dynamic.Compress{}, "testing") + require.NoError(t, err) + + rw := httptest.NewRecorder() + handler.ServeHTTP(rw, req) + + assert.Empty(t, rw.Header().Get(contentEncodingHeader)) + assert.Empty(t, rw.Header().Get(varyHeader)) + assert.EqualValues(t, rw.Body.Bytes(), fakeBody) +} + +func TestShouldNotCompressWhenEmptyAcceptEncodingHeader(t *testing.T) { + req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) + req.Header.Set(acceptEncodingHeader, "") + + fakeBody := generateBytes(gzhttp.DefaultMinSize) + next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + if r.Header.Get(acceptEncodingHeader) != "" { + http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + + _, err := rw.Write(fakeBody) + if err != nil { + http.Error(rw, err.Error(), http.StatusInternalServerError) + } + }) + handler, err := New(context.Background(), next, dynamic.Compress{}, "testing") + require.NoError(t, err) + + rw := httptest.NewRecorder() + handler.ServeHTTP(rw, req) + + assert.Empty(t, rw.Header().Get(contentEncodingHeader)) + assert.Empty(t, rw.Header().Get(varyHeader)) + assert.EqualValues(t, rw.Body.Bytes(), fakeBody) +} + func TestShouldNotCompressHeadRequest(t *testing.T) { req := testhelpers.MustNewRequest(http.MethodHead, "http://localhost", nil) req.Header.Add(acceptEncodingHeader, gzipValue) diff --git a/pkg/middlewares/contenttype/content_type.go b/pkg/middlewares/contenttype/content_type.go index bfe5a5c48..763f7587e 100644 --- a/pkg/middlewares/contenttype/content_type.go +++ b/pkg/middlewares/contenttype/content_type.go @@ -4,7 +4,7 @@ import ( "context" "net/http" - "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares" ) const ( diff --git a/pkg/middlewares/contenttype/content_type_test.go b/pkg/middlewares/contenttype/content_type_test.go index f134994c0..24facb0d2 100644 --- a/pkg/middlewares/contenttype/content_type_test.go +++ b/pkg/middlewares/contenttype/content_type_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestAutoDetection(t *testing.T) { diff --git a/pkg/middlewares/customerrors/custom_errors.go b/pkg/middlewares/customerrors/custom_errors.go index 55684f82e..945552456 100644 --- a/pkg/middlewares/customerrors/custom_errors.go +++ b/pkg/middlewares/customerrors/custom_errors.go @@ -11,10 +11,10 @@ import ( "strings" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/types" "github.com/vulcand/oxy/v2/utils" ) @@ -209,6 +209,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() } diff --git a/pkg/middlewares/customerrors/custom_errors_test.go b/pkg/middlewares/customerrors/custom_errors_test.go index c0de064c7..e066be29a 100644 --- a/pkg/middlewares/customerrors/custom_errors_test.go +++ b/pkg/middlewares/customerrors/custom_errors_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestHandler(t *testing.T) { diff --git a/pkg/middlewares/extractor.go b/pkg/middlewares/extractor.go index 6766132c9..9fca2a1ce 100644 --- a/pkg/middlewares/extractor.go +++ b/pkg/middlewares/extractor.go @@ -7,7 +7,7 @@ import ( "net/http" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/vulcand/oxy/v2/utils" ) diff --git a/pkg/middlewares/forwardedheaders/forwarded_header.go b/pkg/middlewares/forwardedheaders/forwarded_header.go index 19881ad74..3f4e32301 100644 --- a/pkg/middlewares/forwardedheaders/forwarded_header.go +++ b/pkg/middlewares/forwardedheaders/forwarded_header.go @@ -6,7 +6,7 @@ import ( "os" "strings" - "github.com/traefik/traefik/v2/pkg/ip" + "github.com/traefik/traefik/v3/pkg/ip" ) const ( diff --git a/pkg/middlewares/grpcweb/grpcweb.go b/pkg/middlewares/grpcweb/grpcweb.go index e0813fed9..896ac7148 100644 --- a/pkg/middlewares/grpcweb/grpcweb.go +++ b/pkg/middlewares/grpcweb/grpcweb.go @@ -5,8 +5,8 @@ import ( "net/http" "github.com/improbable-eng/grpc-web/go/grpcweb" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" ) const typeName = "grpc-web" diff --git a/pkg/middlewares/handler_switcher.go b/pkg/middlewares/handler_switcher.go index 7c8c775fc..d5b465b60 100644 --- a/pkg/middlewares/handler_switcher.go +++ b/pkg/middlewares/handler_switcher.go @@ -3,7 +3,7 @@ package middlewares import ( "net/http" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/safe" ) // HTTPHandlerSwitcher allows hot switching of http.ServeMux. diff --git a/pkg/middlewares/headers/header.go b/pkg/middlewares/headers/header.go index 88d788bf6..a62fc097e 100644 --- a/pkg/middlewares/headers/header.go +++ b/pkg/middlewares/headers/header.go @@ -7,7 +7,7 @@ import ( "strconv" "strings" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) // Header is a middleware that helps setup a few basic security features. diff --git a/pkg/middlewares/headers/header_test.go b/pkg/middlewares/headers/header_test.go index fa21fe311..269756b46 100644 --- a/pkg/middlewares/headers/header_test.go +++ b/pkg/middlewares/headers/header_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestNewHeader_customRequestHeader(t *testing.T) { diff --git a/pkg/middlewares/headers/headers.go b/pkg/middlewares/headers/headers.go index 07ad06224..1210f6711 100644 --- a/pkg/middlewares/headers/headers.go +++ b/pkg/middlewares/headers/headers.go @@ -7,10 +7,10 @@ import ( "net/http" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/middlewares/connectionheader" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares/connectionheader" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/headers/headers_test.go b/pkg/middlewares/headers/headers_test.go index efbcdb0b2..13c6dd377 100644 --- a/pkg/middlewares/headers/headers_test.go +++ b/pkg/middlewares/headers/headers_test.go @@ -10,8 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/tracing" ) func TestNew_withoutOptions(t *testing.T) { diff --git a/pkg/middlewares/headers/secure.go b/pkg/middlewares/headers/secure.go index e5fcd9cd4..99b03a489 100644 --- a/pkg/middlewares/headers/secure.go +++ b/pkg/middlewares/headers/secure.go @@ -3,7 +3,7 @@ package headers import ( "net/http" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/unrolled/secure" ) diff --git a/pkg/middlewares/headers/secure_test.go b/pkg/middlewares/headers/secure_test.go index 6ed22f1e3..24e38564e 100644 --- a/pkg/middlewares/headers/secure_test.go +++ b/pkg/middlewares/headers/secure_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) // Middleware tests based on https://github.com/unrolled/secure diff --git a/pkg/middlewares/inflightreq/inflight_req.go b/pkg/middlewares/inflightreq/inflight_req.go index c34982bef..a6fcdf101 100644 --- a/pkg/middlewares/inflightreq/inflight_req.go +++ b/pkg/middlewares/inflightreq/inflight_req.go @@ -7,10 +7,10 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/connlimit" ) diff --git a/pkg/middlewares/ipallowlist/ip_allowlist.go b/pkg/middlewares/ipallowlist/ip_allowlist.go index b9ddaf94b..e888d5d92 100644 --- a/pkg/middlewares/ipallowlist/ip_allowlist.go +++ b/pkg/middlewares/ipallowlist/ip_allowlist.go @@ -8,10 +8,10 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/ip" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/ip" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/ipallowlist/ip_allowlist_test.go b/pkg/middlewares/ipallowlist/ip_allowlist_test.go index df2e49835..8bd26b3eb 100644 --- a/pkg/middlewares/ipallowlist/ip_allowlist_test.go +++ b/pkg/middlewares/ipallowlist/ip_allowlist_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestNewIPAllowLister(t *testing.T) { diff --git a/pkg/middlewares/metrics/metrics.go b/pkg/middlewares/metrics/metrics.go index b04a49c85..64a09db17 100644 --- a/pkg/middlewares/metrics/metrics.go +++ b/pkg/middlewares/metrics/metrics.go @@ -11,11 +11,11 @@ import ( "github.com/containous/alice" gokitmetrics "github.com/go-kit/kit/metrics" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/middlewares/capture" - "github.com/traefik/traefik/v2/pkg/middlewares/retry" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares/capture" + "github.com/traefik/traefik/v3/pkg/middlewares/retry" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" "google.golang.org/grpc/codes" ) @@ -33,10 +33,9 @@ const ( type metricsMiddleware struct { next http.Handler - reqsCounter gokitmetrics.Counter + reqsCounter metrics.CounterWithHeaders reqsTLSCounter gokitmetrics.Counter reqDurationHistogram metrics.ScalableHistogram - openConnsGauge gokitmetrics.Gauge reqsBytesCounter gokitmetrics.Counter respsBytesCounter gokitmetrics.Counter baseLabels []string @@ -51,7 +50,6 @@ func NewEntryPointMiddleware(ctx context.Context, next http.Handler, registry me reqsCounter: registry.EntryPointReqsCounter(), reqsTLSCounter: registry.EntryPointReqsTLSCounter(), reqDurationHistogram: registry.EntryPointReqDurationHistogram(), - openConnsGauge: registry.EntryPointOpenConnsGauge(), reqsBytesCounter: registry.EntryPointReqsBytesCounter(), respsBytesCounter: registry.EntryPointRespsBytesCounter(), baseLabels: []string{"entrypoint", entryPointName}, @@ -67,7 +65,6 @@ func NewRouterMiddleware(ctx context.Context, next http.Handler, registry metric reqsCounter: registry.RouterReqsCounter(), reqsTLSCounter: registry.RouterReqsTLSCounter(), reqDurationHistogram: registry.RouterReqDurationHistogram(), - openConnsGauge: registry.RouterOpenConnsGauge(), reqsBytesCounter: registry.RouterReqsBytesCounter(), respsBytesCounter: registry.RouterRespsBytesCounter(), baseLabels: []string{"router", routerName, "service", serviceName}, @@ -83,7 +80,6 @@ func NewServiceMiddleware(ctx context.Context, next http.Handler, registry metri reqsCounter: registry.ServiceReqsCounter(), reqsTLSCounter: registry.ServiceReqsTLSCounter(), reqDurationHistogram: registry.ServiceReqDurationHistogram(), - openConnsGauge: registry.ServiceOpenConnsGauge(), reqsBytesCounter: registry.ServiceReqsBytesCounter(), respsBytesCounter: registry.ServiceRespsBytesCounter(), baseLabels: []string{"service", serviceName}, @@ -112,10 +108,6 @@ func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) labels = append(labels, "method", getMethod(req)) labels = append(labels, "protocol", proto) - openConnsGauge := m.openConnsGauge.With(labels...) - openConnsGauge.Add(1) - defer openConnsGauge.Add(-1) - // TLS metrics if req.TLS != nil { var tlsLabels []string @@ -153,7 +145,7 @@ func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) labels = append(labels, "code", strconv.Itoa(code)) m.reqDurationHistogram.With(labels...).ObserveFromStart(start) - m.reqsCounter.With(labels...).Add(1) + m.reqsCounter.With(req.Header, labels...).Add(1) m.respsBytesCounter.With(labels...).Add(float64(capt.ResponseSize())) m.reqsBytesCounter.With(labels...).Add(float64(capt.RequestSize())) } diff --git a/pkg/middlewares/middleware.go b/pkg/middlewares/middleware.go index 32aadf29a..928a9982e 100644 --- a/pkg/middlewares/middleware.go +++ b/pkg/middlewares/middleware.go @@ -5,7 +5,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/logs" ) // GetLogger creates a logger with the middleware fields. diff --git a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go index 3f0f80423..94367ce28 100644 --- a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go +++ b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go @@ -13,9 +13,9 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" ) const typeName = "PassClientTLSCert" diff --git a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert_test.go b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert_test.go index 96c1bdffa..47f6b451f 100644 --- a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert_test.go +++ b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) const ( diff --git a/pkg/middlewares/ratelimiter/rate_limiter.go b/pkg/middlewares/ratelimiter/rate_limiter.go index 303b20e8e..1c3582c4e 100644 --- a/pkg/middlewares/ratelimiter/rate_limiter.go +++ b/pkg/middlewares/ratelimiter/rate_limiter.go @@ -11,9 +11,9 @@ import ( "github.com/mailgun/ttlmap" "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/utils" "golang.org/x/time/rate" ) @@ -81,10 +81,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, @@ -155,10 +157,6 @@ func (rl *rateLimiter) ServeHTTP(rw http.ResponseWriter, req *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(rw, "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..5187d5d63 100644 --- a/pkg/middlewares/ratelimiter/rate_limiter_test.go +++ b/pkg/middlewares/ratelimiter/rate_limiter_test.go @@ -12,9 +12,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/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) + } }) } } diff --git a/pkg/middlewares/recovery/recovery.go b/pkg/middlewares/recovery/recovery.go index 90e0b3659..ebd3edcb5 100644 --- a/pkg/middlewares/recovery/recovery.go +++ b/pkg/middlewares/recovery/recovery.go @@ -5,7 +5,7 @@ import ( "net/http" "runtime" - "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares" ) const ( diff --git a/pkg/middlewares/redirect/redirect.go b/pkg/middlewares/redirect/redirect.go index a48053f8a..d64d8cd70 100644 --- a/pkg/middlewares/redirect/redirect.go +++ b/pkg/middlewares/redirect/redirect.go @@ -6,7 +6,7 @@ import ( "regexp" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/utils" ) diff --git a/pkg/middlewares/redirect/redirect_regex.go b/pkg/middlewares/redirect/redirect_regex.go index 62e5dc986..f68493205 100644 --- a/pkg/middlewares/redirect/redirect_regex.go +++ b/pkg/middlewares/redirect/redirect_regex.go @@ -5,8 +5,8 @@ import ( "net/http" "strings" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" ) const typeRegexName = "RedirectRegex" diff --git a/pkg/middlewares/redirect/redirect_regex_test.go b/pkg/middlewares/redirect/redirect_regex_test.go index d6346cf75..a93c78844 100644 --- a/pkg/middlewares/redirect/redirect_regex_test.go +++ b/pkg/middlewares/redirect/redirect_regex_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestRedirectRegexHandler(t *testing.T) { diff --git a/pkg/middlewares/redirect/redirect_scheme.go b/pkg/middlewares/redirect/redirect_scheme.go index b828ff287..b0d8146c7 100644 --- a/pkg/middlewares/redirect/redirect_scheme.go +++ b/pkg/middlewares/redirect/redirect_scheme.go @@ -7,8 +7,8 @@ import ( "net/http" "strings" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" ) const ( @@ -17,6 +17,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 := middlewares.GetLogger(ctx, name, typeSchemeName) @@ -32,10 +38,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 { @@ -70,12 +85,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 + middlewares.GetLogger(req.Context(), r.name, typeSchemeName).Debug().Msgf("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..7ef53f252 100644 --- a/pkg/middlewares/redirect/redirect_scheme_test.go +++ b/pkg/middlewares/redirect/redirect_scheme_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestRedirectSchemeHandler(t *testing.T) { @@ -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, }, { diff --git a/pkg/middlewares/replacepath/replace_path.go b/pkg/middlewares/replacepath/replace_path.go index e19361056..9f6fea443 100644 --- a/pkg/middlewares/replacepath/replace_path.go +++ b/pkg/middlewares/replacepath/replace_path.go @@ -6,9 +6,9 @@ import ( "net/url" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/replacepath/replace_path_test.go b/pkg/middlewares/replacepath/replace_path_test.go index 782733bc0..5998579d1 100644 --- a/pkg/middlewares/replacepath/replace_path_test.go +++ b/pkg/middlewares/replacepath/replace_path_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestReplacePath(t *testing.T) { diff --git a/pkg/middlewares/replacepathregex/replace_path_regex.go b/pkg/middlewares/replacepathregex/replace_path_regex.go index 2f2621b8c..1fffb6bd4 100644 --- a/pkg/middlewares/replacepathregex/replace_path_regex.go +++ b/pkg/middlewares/replacepathregex/replace_path_regex.go @@ -9,10 +9,10 @@ import ( "strings" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/middlewares/replacepath" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares/replacepath" + "github.com/traefik/traefik/v3/pkg/tracing" ) const typeName = "ReplacePathRegex" diff --git a/pkg/middlewares/replacepathregex/replace_path_regex_test.go b/pkg/middlewares/replacepathregex/replace_path_regex_test.go index 59018d784..7e83f3862 100644 --- a/pkg/middlewares/replacepathregex/replace_path_regex_test.go +++ b/pkg/middlewares/replacepathregex/replace_path_regex_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares/replacepath" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares/replacepath" ) func TestReplacePathRegex(t *testing.T) { diff --git a/pkg/middlewares/requestdecorator/request_decorator.go b/pkg/middlewares/requestdecorator/request_decorator.go index 013cb12c3..e2a82395c 100644 --- a/pkg/middlewares/requestdecorator/request_decorator.go +++ b/pkg/middlewares/requestdecorator/request_decorator.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/containous/alice" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/types" ) const ( diff --git a/pkg/middlewares/requestdecorator/request_decorator_test.go b/pkg/middlewares/requestdecorator/request_decorator_test.go index 03c8f4018..75ccc0139 100644 --- a/pkg/middlewares/requestdecorator/request_decorator_test.go +++ b/pkg/middlewares/requestdecorator/request_decorator_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/testhelpers" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/types" ) func TestRequestHost(t *testing.T) { diff --git a/pkg/middlewares/retry/retry.go b/pkg/middlewares/retry/retry.go index b9f3b6af7..310164bd3 100644 --- a/pkg/middlewares/retry/retry.go +++ b/pkg/middlewares/retry/retry.go @@ -13,9 +13,9 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" ) // Compile time validation that the response writer implements http interfaces correctly. diff --git a/pkg/middlewares/retry/retry_test.go b/pkg/middlewares/retry/retry_test.go index 4622093af..a2d96b3ce 100644 --- a/pkg/middlewares/retry/retry_test.go +++ b/pkg/middlewares/retry/retry_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestRetry(t *testing.T) { diff --git a/pkg/middlewares/snicheck/snicheck.go b/pkg/middlewares/snicheck/snicheck.go index 27f8148d1..89f817fcb 100644 --- a/pkg/middlewares/snicheck/snicheck.go +++ b/pkg/middlewares/snicheck/snicheck.go @@ -6,8 +6,8 @@ import ( "strings" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/middlewares/requestdecorator" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" ) // SNICheck is an HTTP handler that checks whether the TLS configuration for the server name is the same as for the host header. diff --git a/pkg/middlewares/stripprefix/strip_prefix.go b/pkg/middlewares/stripprefix/strip_prefix.go index 8338ee2ed..a017c051f 100644 --- a/pkg/middlewares/stripprefix/strip_prefix.go +++ b/pkg/middlewares/stripprefix/strip_prefix.go @@ -6,9 +6,9 @@ import ( "strings" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/stripprefix/strip_prefix_test.go b/pkg/middlewares/stripprefix/strip_prefix_test.go index 7f2717bd3..612a282f1 100644 --- a/pkg/middlewares/stripprefix/strip_prefix_test.go +++ b/pkg/middlewares/stripprefix/strip_prefix_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestStripPrefix(t *testing.T) { diff --git a/pkg/middlewares/stripprefixregex/strip_prefix_regex.go b/pkg/middlewares/stripprefixregex/strip_prefix_regex.go index debeba16d..383ce1f01 100644 --- a/pkg/middlewares/stripprefixregex/strip_prefix_regex.go +++ b/pkg/middlewares/stripprefixregex/strip_prefix_regex.go @@ -7,10 +7,10 @@ import ( "strings" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/middlewares/stripprefix" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares/stripprefix" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/stripprefixregex/strip_prefix_regex_test.go b/pkg/middlewares/stripprefixregex/strip_prefix_regex_test.go index 763985ba9..64db6b842 100644 --- a/pkg/middlewares/stripprefixregex/strip_prefix_regex_test.go +++ b/pkg/middlewares/stripprefixregex/strip_prefix_regex_test.go @@ -8,9 +8,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares/stripprefix" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares/stripprefix" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestStripPrefixRegex(t *testing.T) { diff --git a/pkg/middlewares/tcp/inflightconn/inflight_conn.go b/pkg/middlewares/tcp/inflightconn/inflight_conn.go index 6213d4e42..b8663efc5 100644 --- a/pkg/middlewares/tcp/inflightconn/inflight_conn.go +++ b/pkg/middlewares/tcp/inflightconn/inflight_conn.go @@ -6,9 +6,9 @@ import ( "net" "sync" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tcp" ) const typeName = "InFlightConnTCP" diff --git a/pkg/middlewares/tcp/inflightconn/inflight_conn_test.go b/pkg/middlewares/tcp/inflightconn/inflight_conn_test.go index 138e92b41..28fca80df 100644 --- a/pkg/middlewares/tcp/inflightconn/inflight_conn_test.go +++ b/pkg/middlewares/tcp/inflightconn/inflight_conn_test.go @@ -7,8 +7,8 @@ import ( "time" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/tcp" ) func TestInFlightConn_ServeTCP(t *testing.T) { diff --git a/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go b/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go index e2a513cf0..0ebe2fab7 100644 --- a/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go +++ b/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/ip" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/ip" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tcp" ) const ( diff --git a/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go b/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go index 4f3b59e15..8da65c1ad 100644 --- a/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go +++ b/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/tcp" ) func TestNewIPAllowLister(t *testing.T) { diff --git a/pkg/middlewares/tracing/entrypoint.go b/pkg/middlewares/tracing/entrypoint.go index d665823a2..b17d8c2ce 100644 --- a/pkg/middlewares/tracing/entrypoint.go +++ b/pkg/middlewares/tracing/entrypoint.go @@ -7,8 +7,8 @@ import ( "github.com/containous/alice" "github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/tracing/entrypoint_test.go b/pkg/middlewares/tracing/entrypoint_test.go index 604c8c012..e8528e048 100644 --- a/pkg/middlewares/tracing/entrypoint_test.go +++ b/pkg/middlewares/tracing/entrypoint_test.go @@ -9,7 +9,7 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/tracing" ) func TestEntryPointMiddleware(t *testing.T) { diff --git a/pkg/middlewares/tracing/forwarder.go b/pkg/middlewares/tracing/forwarder.go index 2ebf5fe77..e2ee76a10 100644 --- a/pkg/middlewares/tracing/forwarder.go +++ b/pkg/middlewares/tracing/forwarder.go @@ -5,9 +5,9 @@ import ( "net/http" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" ) const ( diff --git a/pkg/middlewares/tracing/forwarder_test.go b/pkg/middlewares/tracing/forwarder_test.go index 1253412d3..785e729cb 100644 --- a/pkg/middlewares/tracing/forwarder_test.go +++ b/pkg/middlewares/tracing/forwarder_test.go @@ -9,7 +9,7 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/tracing" ) func TestNewForwarder(t *testing.T) { diff --git a/pkg/middlewares/tracing/wrapper.go b/pkg/middlewares/tracing/wrapper.go index e13209d54..1fa3cfcdd 100644 --- a/pkg/middlewares/tracing/wrapper.go +++ b/pkg/middlewares/tracing/wrapper.go @@ -7,8 +7,8 @@ import ( "github.com/containous/alice" "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/tracing" ) // Traceable embeds tracing information. diff --git a/pkg/muxer/http/matcher.go b/pkg/muxer/http/matcher.go index d30e6df61..9b6861d2f 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" + "github.com/traefik/traefik/v3/pkg/ip" + "github.com/traefik/traefik/v3/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..1b527a392 100644 --- a/pkg/muxer/http/matcher_test.go +++ b/pkg/muxer/http/matcher_test.go @@ -3,11 +3,12 @@ package http import ( "net/http" "net/http/httptest" + "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" + "github.com/traefik/traefik/v3/pkg/middlewares/requestdecorator" ) func TestClientIPMatcher(t *testing.T) { @@ -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..979634aa1 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/traefik/traefik/v2/pkg/rules" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v3/pkg/rules" "github.com/vulcand/predicate" ) // Muxer handles routing with rules. type Muxer struct { - *mux.Router + routes routes parser predicate.Parser } @@ -24,18 +25,36 @@ 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) +} + +// 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 (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 +64,23 @@ func (r *Muxer) AddRoute(rule string, priority int, handler http.Handler) error return fmt.Errorf("error while parsing rule %s", rule) } - if priority == 0 { - priority = len(rule) - } - - route := r.NewRoute().Handler(handler).Priority(priority) - - err = addRuleOnRoute(route, buildTree()) + var matchers matchersTree + err = matchers.addRule(buildTree()) if err != nil { - route.BuildOnly() - return err + return fmt.Errorf("error while adding rule %s: %w", rule, err) } + m.routes = append(m.routes, &route{ + handler: handler, + matchers: matchers, + priority: priority, + }) + + 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 +90,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 +105,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..a31a37881 100644 --- a/pkg/muxer/http/mux_test.go +++ b/pkg/muxer/http/mux_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/middlewares/requestdecorator" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestMuxer(t *testing.T) { @@ -36,6 +36,20 @@ func TestMuxer(t *testing.T) { rule: "Host(example.com)", expectedError: true, }, + { + desc: "Host IPv4", + rule: "Host(`127.0.0.1`)", + expected: map[string]int{ + "http://127.0.0.1/foo": http.StatusOK, + }, + }, + { + desc: "Host IPv6", + rule: "Host(`10::10`)", + expected: map[string]int{ + "http://10::10/foo": http.StatusOK, + }, + }, { desc: "Host and PathPrefix", rule: "Host(`localhost`) && PathPrefix(`/css`)", @@ -376,12 +390,14 @@ 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) } - muxer.SortRoutes() - w := httptest.NewRecorder() req := testhelpers.MustNewRequest(http.MethodGet, test.path, http.NoBody) @@ -519,3 +535,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/matcher.go b/pkg/muxer/tcp/matcher.go index 40694c3ea..0ac0ed23a 100644 --- a/pkg/muxer/tcp/matcher.go +++ b/pkg/muxer/tcp/matcher.go @@ -8,7 +8,7 @@ import ( "github.com/go-acme/lego/v4/challenge/tlsalpn01" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/ip" + "github.com/traefik/traefik/v3/pkg/ip" ) var tcpFuncs = map[string]func(*matchersTree, ...string) error{ @@ -67,7 +67,7 @@ func clientIP(tree *matchersTree, clientIP ...string) error { return nil } -var almostFQDN = regexp.MustCompile(`^[[:alnum:]\.-]+$`) +var hostOrIP = regexp.MustCompile(`^[[:alnum:]\.\-\:]+$`) // hostSNI checks if the SNI Host of the connection match the matcher host. func hostSNI(tree *matchersTree, hosts ...string) error { @@ -80,7 +80,7 @@ func hostSNI(tree *matchersTree, hosts ...string) error { return nil } - if !almostFQDN.MatchString(host) { + if !hostOrIP.MatchString(host) { return fmt.Errorf("invalid value for HostSNI matcher, %q is not a valid hostname", host) } diff --git a/pkg/muxer/tcp/matcher_test.go b/pkg/muxer/tcp/matcher_test.go index 06b45e186..3ba833d49 100644 --- a/pkg/muxer/tcp/matcher_test.go +++ b/pkg/muxer/tcp/matcher_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/tcp" ) func Test_HostSNICatchAll(t *testing.T) { diff --git a/pkg/muxer/tcp/mux.go b/pkg/muxer/tcp/mux.go index 3c5abffaf..f23ce629d 100644 --- a/pkg/muxer/tcp/mux.go +++ b/pkg/muxer/tcp/mux.go @@ -7,38 +7,12 @@ import ( "strings" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/rules" - "github.com/traefik/traefik/v2/pkg/tcp" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/rules" + "github.com/traefik/traefik/v3/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/types" "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 } @@ -98,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 { @@ -114,9 +120,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 @@ -124,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, @@ -144,41 +138,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 +148,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 +201,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 +236,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/muxer/tcp/mux_test.go b/pkg/muxer/tcp/mux_test.go index 95e84a245..08258b99e 100644 --- a/pkg/muxer/tcp/mux_test.go +++ b/pkg/muxer/tcp/mux_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/tcp" ) func Test_addTCPRoute(t *testing.T) { @@ -250,6 +250,16 @@ func Test_addTCPRoute(t *testing.T) { serverName: "example.com", matchErr: true, }, + { + desc: "Matching IPv4", + rule: "HostSNI(`127.0.0.1`)", + serverName: "127.0.0.1", + }, + { + desc: "Matching IPv6", + rule: "HostSNI(`10::10`)", + serverName: "10::10", + }, } for _, test := range testCases { @@ -332,6 +342,16 @@ func TestParseHostSNI(t *testing.T) { expression: "hostsni(`example.com`)", domain: []string{"example.com"}, }, + { + desc: "HostSNI IPv4", + expression: "HostSNI(`127.0.0.1`)", + domain: []string{"127.0.0.1"}, + }, + { + desc: "HostSNI IPv6", + expression: "HostSNI(`10::10`)", + domain: []string{"10::10"}, + }, { desc: "No hostSNI rule", expression: "ClientIP(`10.1`)", @@ -444,6 +464,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/plugins/builder.go b/pkg/plugins/builder.go index aa3d4c982..c2012427b 100644 --- a/pkg/plugins/builder.go +++ b/pkg/plugins/builder.go @@ -8,7 +8,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/logs" "github.com/traefik/yaegi/interp" "github.com/traefik/yaegi/stdlib" ) diff --git a/pkg/plugins/client.go b/pkg/plugins/client.go index 9e7ba8538..476d3f302 100644 --- a/pkg/plugins/client.go +++ b/pkg/plugins/client.go @@ -18,7 +18,7 @@ import ( "github.com/hashicorp/go-retryablehttp" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/logs" "golang.org/x/mod/module" "golang.org/x/mod/zip" "gopkg.in/yaml.v3" diff --git a/pkg/plugins/providers.go b/pkg/plugins/providers.go index ea024c836..5fdaf03ac 100644 --- a/pkg/plugins/providers.go +++ b/pkg/plugins/providers.go @@ -10,10 +10,10 @@ import ( "github.com/mitchellh/mapstructure" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "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/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" "github.com/traefik/yaegi/interp" ) @@ -45,7 +45,7 @@ func (p _PP) Stop() error { func ppSymbols() map[string]map[string]reflect.Value { return map[string]map[string]reflect.Value{ - "github.com/traefik/traefik/v2/pkg/plugins/plugins": { + "github.com/traefik/traefik/v3/pkg/plugins/plugins": { "PP": reflect.ValueOf((*PP)(nil)), "_PP": reflect.ValueOf((*_PP)(nil)), }, @@ -115,7 +115,7 @@ import ( "context" ` + basePkg + ` "` + builder.Import + `" - "github.com/traefik/traefik/v2/pkg/plugins" + "github.com/traefik/traefik/v3/pkg/plugins" ) func NewWrapper(ctx context.Context, config *` + basePkg + `.Config, name string) (plugins.PP, error) { diff --git a/pkg/provider/acme/account.go b/pkg/provider/acme/account.go index 6bac6c186..c0a7458b3 100644 --- a/pkg/provider/acme/account.go +++ b/pkg/provider/acme/account.go @@ -10,7 +10,7 @@ import ( "github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/registration" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/logs" ) // Account is used to store lets encrypt registration info. diff --git a/pkg/provider/acme/challenge_http.go b/pkg/provider/acme/challenge_http.go index 80d6a6c67..155356505 100644 --- a/pkg/provider/acme/challenge_http.go +++ b/pkg/provider/acme/challenge_http.go @@ -14,8 +14,8 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/go-acme/lego/v4/challenge/http01" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/safe" ) // ChallengeHTTP HTTP challenge provider implements challenge.Provider. diff --git a/pkg/provider/acme/challenge_tls.go b/pkg/provider/acme/challenge_tls.go index a53f83f2b..b4ce624d5 100644 --- a/pkg/provider/acme/challenge_tls.go +++ b/pkg/provider/acme/challenge_tls.go @@ -7,11 +7,11 @@ import ( "github.com/go-acme/lego/v4/challenge/tlsalpn01" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/safe" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/safe" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" ) const providerNameALPN = "tlsalpn.acme" diff --git a/pkg/provider/acme/local_store.go b/pkg/provider/acme/local_store.go index 57a26207b..c7677e047 100644 --- a/pkg/provider/acme/local_store.go +++ b/pkg/provider/acme/local_store.go @@ -7,8 +7,8 @@ import ( "sync" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/safe" ) var _ Store = (*LocalStore)(nil) diff --git a/pkg/provider/acme/provider.go b/pkg/provider/acme/provider.go index e57c84d5b..c9c7a70e7 100644 --- a/pkg/provider/acme/provider.go +++ b/pkg/provider/acme/provider.go @@ -21,14 +21,14 @@ import ( "github.com/go-acme/lego/v4/registration" "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/logs" - httpmuxer "github.com/traefik/traefik/v2/pkg/muxer/http" - tcpmuxer "github.com/traefik/traefik/v2/pkg/muxer/tcp" - "github.com/traefik/traefik/v2/pkg/safe" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + httpmuxer "github.com/traefik/traefik/v3/pkg/muxer/http" + tcpmuxer "github.com/traefik/traefik/v3/pkg/muxer/tcp" + "github.com/traefik/traefik/v3/pkg/safe" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" + "github.com/traefik/traefik/v3/pkg/version" ) // ocspMustStaple enables OCSP stapling as from https://github.com/go-acme/lego/issues/270. diff --git a/pkg/provider/acme/provider_test.go b/pkg/provider/acme/provider_test.go index 3268b1c92..d41f19c45 100644 --- a/pkg/provider/acme/provider_test.go +++ b/pkg/provider/acme/provider_test.go @@ -8,8 +8,8 @@ import ( "github.com/go-acme/lego/v4/certcrypto" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/types" ) func TestGetUncheckedCertificates(t *testing.T) { diff --git a/pkg/provider/aggregator/aggregator.go b/pkg/provider/aggregator/aggregator.go index 8001711fc..009aa9c93 100644 --- a/pkg/provider/aggregator/aggregator.go +++ b/pkg/provider/aggregator/aggregator.go @@ -5,13 +5,13 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/file" - "github.com/traefik/traefik/v2/pkg/provider/traefik" - "github.com/traefik/traefik/v2/pkg/redactor" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/file" + "github.com/traefik/traefik/v3/pkg/provider/traefik" + "github.com/traefik/traefik/v3/pkg/redactor" + "github.com/traefik/traefik/v3/pkg/safe" ) // throttled defines what kind of config refresh throttling the aggregator should @@ -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) } @@ -100,10 +96,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/aggregator/aggregator_test.go b/pkg/provider/aggregator/aggregator_test.go index 4bcf2bd79..4683a2480 100644 --- a/pkg/provider/aggregator/aggregator_test.go +++ b/pkg/provider/aggregator/aggregator_test.go @@ -6,9 +6,9 @@ import ( "time" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" ) func TestProviderAggregator_Provide(t *testing.T) { diff --git a/pkg/provider/aggregator/ring_channel.go b/pkg/provider/aggregator/ring_channel.go index e69328da1..454a43a58 100644 --- a/pkg/provider/aggregator/ring_channel.go +++ b/pkg/provider/aggregator/ring_channel.go @@ -1,7 +1,7 @@ package aggregator import ( - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) // RingChannel implements a channel in a way that never blocks the writer. diff --git a/pkg/provider/configuration.go b/pkg/provider/configuration.go index c0119c885..ebe57b92e 100644 --- a/pkg/provider/configuration.go +++ b/pkg/provider/configuration.go @@ -11,8 +11,8 @@ import ( "github.com/Masterminds/sprig/v3" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" ) // Merge Merges multiple configurations. @@ -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/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/consulcatalog/config.go b/pkg/provider/consulcatalog/config.go index af8e7830c..14c4fcc87 100644 --- a/pkg/provider/consulcatalog/config.go +++ b/pkg/provider/consulcatalog/config.go @@ -11,11 +11,11 @@ import ( "github.com/hashicorp/consul/api" "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/logs" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/constraints" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/label" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/constraints" ) func (p *Provider) buildConfiguration(ctx context.Context, items []itemData, certInfo *connectCert) *dynamic.Configuration { @@ -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..d1a606554 100644 --- a/pkg/provider/consulcatalog/config_test.go +++ b/pkg/provider/consulcatalog/config_test.go @@ -10,8 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/tls" ) func Int(v int) *int { return &v } @@ -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..904131283 100644 --- a/pkg/provider/consulcatalog/connect_tls.go +++ b/pkg/provider/consulcatalog/connect_tls.go @@ -4,8 +4,8 @@ import ( "fmt" "github.com/hashicorp/consul/agent/connect" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" ) // connectCert holds our certificates as a client of the Consul Connect protocol. @@ -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/consulcatalog/consul_catalog.go b/pkg/provider/consulcatalog/consul_catalog.go index af8c7e2f7..696214e0c 100644 --- a/pkg/provider/consulcatalog/consul_catalog.go +++ b/pkg/provider/consulcatalog/consul_catalog.go @@ -14,13 +14,13 @@ import ( "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/provider/constraints" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/job" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/constraints" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/types" ) // defaultTemplateRule is the default template for the default rule. diff --git a/pkg/provider/consulcatalog/label.go b/pkg/provider/consulcatalog/label.go index 65178750c..dd71e9347 100644 --- a/pkg/provider/consulcatalog/label.go +++ b/pkg/provider/consulcatalog/label.go @@ -1,7 +1,7 @@ package consulcatalog import ( - "github.com/traefik/traefik/v2/pkg/config/label" + "github.com/traefik/traefik/v3/pkg/config/label" ) // configuration contains information from the labels that are globals (not related to the dynamic configuration) or specific to the provider. diff --git a/pkg/provider/docker/config.go b/pkg/provider/docker/config.go index e23575caf..53ff07fe1 100644 --- a/pkg/provider/docker/config.go +++ b/pkg/provider/docker/config.go @@ -10,11 +10,11 @@ import ( dockertypes "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" "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/logs" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/constraints" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/label" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/constraints" ) func (p *Provider) buildConfiguration(ctx context.Context, containersInspected []dockerData) *dynamic.Configuration { @@ -75,11 +75,13 @@ func (p *Provider) buildConfiguration(ctx context.Context, containersInspected [ serviceName := getServiceName(container) model := struct { - Name string - Labels map[string]string + Name string + ContainerName string + Labels map[string]string }{ - Name: serviceName, - Labels: container.Labels, + Name: serviceName, + ContainerName: strings.TrimPrefix(container.Name, "/"), + Labels: container.Labels, } provider.BuildRouterConfiguration(ctx, confFromLabel.HTTP, serviceName, p.defaultRuleTpl, model) @@ -94,11 +96,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..5f0048b2a 100644 --- a/pkg/provider/docker/config_test.go +++ b/pkg/provider/docker/config_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestDefaultRule(t *testing.T) { @@ -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/docker/docker.go b/pkg/provider/docker/docker.go index 2e902cf8a..ec48f714c 100644 --- a/pkg/provider/docker/docker.go +++ b/pkg/provider/docker/docker.go @@ -25,13 +25,13 @@ import ( "github.com/docker/go-connections/sockets" "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" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/job" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/types" + "github.com/traefik/traefik/v3/pkg/version" ) const ( diff --git a/pkg/provider/docker/label.go b/pkg/provider/docker/label.go index f86de2166..b968eedf1 100644 --- a/pkg/provider/docker/label.go +++ b/pkg/provider/docker/label.go @@ -3,7 +3,7 @@ package docker import ( "fmt" - "github.com/traefik/traefik/v2/pkg/config/label" + "github.com/traefik/traefik/v3/pkg/config/label" ) const ( diff --git a/pkg/provider/ecs/config.go b/pkg/provider/ecs/config.go index 8dbdf1550..e53c7480e 100644 --- a/pkg/provider/ecs/config.go +++ b/pkg/provider/ecs/config.go @@ -11,10 +11,10 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/docker/go-connections/nat" "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" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/label" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/constraints" ) func (p *Provider) buildConfiguration(ctx context.Context, instances []ecsInstance) *dynamic.Configuration { @@ -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..aac4d9cfd 100644 --- a/pkg/provider/ecs/config_test.go +++ b/pkg/provider/ecs/config_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func Int(v int) *int { return &v } @@ -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/ecs/ecs.go b/pkg/provider/ecs/ecs.go index 22e3e5695..93337c766 100644 --- a/pkg/provider/ecs/ecs.go +++ b/pkg/provider/ecs/ecs.go @@ -19,11 +19,11 @@ import ( "github.com/patrickmn/go-cache" "github.com/rs/zerolog" "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" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/job" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" ) // Provider holds configurations of the provider. @@ -320,6 +320,11 @@ func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsI var mach *machine if len(task.Attachments) != 0 { + if len(container.NetworkInterfaces) == 0 { + logger.Error().Msgf("Skip container %s: no network interfaces", aws.StringValue(container.Name)) + continue + } + var ports []portMapping for _, mapping := range containerDefinition.PortMappings { if mapping != nil { diff --git a/pkg/provider/ecs/label.go b/pkg/provider/ecs/label.go index 0f3b2a8b3..7a01a93ff 100644 --- a/pkg/provider/ecs/label.go +++ b/pkg/provider/ecs/label.go @@ -1,7 +1,7 @@ package ecs import ( - "github.com/traefik/traefik/v2/pkg/config/label" + "github.com/traefik/traefik/v3/pkg/config/label" ) // configuration Contains information from the labels that are globals (not related to the dynamic configuration) or specific to the provider. diff --git a/pkg/provider/file/file.go b/pkg/provider/file/file.go index 839986cf8..938252664 100644 --- a/pkg/provider/file/file.go +++ b/pkg/provider/file/file.go @@ -13,11 +13,11 @@ import ( "github.com/Masterminds/sprig/v3" "github.com/rs/zerolog/log" "github.com/traefik/paerser/file" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "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/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/tls" "gopkg.in/fsnotify.v1" ) @@ -47,11 +47,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 @@ -69,6 +64,19 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } } + configuration, err := p.BuildConfiguration() + if err != nil { + if p.Watch { + log.Debug(). + Str(logs.ProviderName, providerName). + Err(err). + Msg("Error while building configuration (for the first time)") + + return nil + } + return err + } + sendConfigToChannel(configurationChan, configuration) return nil } @@ -215,7 +223,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 +262,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 +345,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 +443,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 +565,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..571280306 100644 --- a/pkg/provider/file/file_test.go +++ b/pkg/provider/file/file_test.go @@ -11,8 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/safe" ) type ProvideTestCase struct { @@ -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..c354e5f8b 100644 --- a/pkg/provider/http/http.go +++ b/pkg/provider/http/http.go @@ -12,13 +12,13 @@ import ( "github.com/rs/zerolog/log" "github.com/traefik/paerser/file" 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/tls" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/job" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" ) var _ provider.Provider = (*Provider)(nil) @@ -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..d805dd3c4 100644 --- a/pkg/provider/http/http_test.go +++ b/pkg/provider/http/http_test.go @@ -11,9 +11,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/tls" ) func TestProvider_Init(t *testing.T) { @@ -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/handler.go b/pkg/provider/hub/handler.go index 23cc47b1e..86014cb7c 100644 --- a/pkg/provider/hub/handler.go +++ b/pkg/provider/hub/handler.go @@ -10,7 +10,7 @@ import ( "sync/atomic" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) type handler struct { diff --git a/pkg/provider/hub/handler_test.go b/pkg/provider/hub/handler_test.go index b69fc8b6d..bc13f90c0 100644 --- a/pkg/provider/hub/handler_test.go +++ b/pkg/provider/hub/handler_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/tls/generate" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/tls/generate" ) func TestHandleConfig(t *testing.T) { diff --git a/pkg/provider/hub/hub.go b/pkg/provider/hub/hub.go index c44cb7e97..f1120cc80 100644 --- a/pkg/provider/hub/hub.go +++ b/pkg/provider/hub/hub.go @@ -9,11 +9,11 @@ import ( "net/http" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/safe" - ttls "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" + ttls "github.com/traefik/traefik/v3/pkg/tls" ) var _ provider.Provider = (*Provider)(nil) @@ -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..44e0cb29c 100644 --- a/pkg/provider/kubernetes/crd/client.go +++ b/pkg/provider/kubernetes/crd/client.go @@ -9,11 +9,11 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/informers/externalversions" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" + "github.com/traefik/traefik/v3/pkg/version" corev1 "k8s.io/api/core/v1" kubeerror "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -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) @@ -300,11 +302,11 @@ func (c *clientWrapper) GetTraefikServices() []*v1alpha1.TraefikService { var result []*v1alpha1.TraefikService for ns, factory := range c.factoriesCrd { - ings, err := factory.Traefik().V1alpha1().TraefikServices().Lister().List(labels.Everything()) + traefikServices, err := factory.Traefik().V1alpha1().TraefikServices().Lister().List(labels.Everything()) if err != nil { log.Error().Err(err).Msgf("Failed to list Traefik services in namespace %s", ns) } - result = append(result, ings...) + result = append(result, traefikServices...) } return result @@ -317,7 +319,22 @@ func (c *clientWrapper) GetServersTransports() []*v1alpha1.ServersTransport { for ns, factory := range c.factoriesCrd { serversTransports, err := factory.Traefik().V1alpha1().ServersTransports().Lister().List(labels.Everything()) if err != nil { - log.Error().Err(err).Msgf("Failed to list servers transport in namespace %s", ns) + log.Error().Err(err).Str("namespace", ns).Msg("Failed to list servers transport in namespace") + } + result = append(result, serversTransports...) + } + + 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...) } @@ -401,15 +418,6 @@ func (c *clientWrapper) lookupNamespace(ns string) string { return ns } -// translateNotFoundError will translate a "not found" error to a boolean return -// value which indicates if the resource exists and a nil error. -func translateNotFoundError(err error) (bool, error) { - if kubeerror.IsNotFound(err) { - return false, nil - } - return err == nil, err -} - // isWatchedNamespace checks to ensure that the namespace is being watched before we request // it to ensure we don't panic by requesting an out-of-watch object. func (c *clientWrapper) isWatchedNamespace(ns string) bool { @@ -423,3 +431,12 @@ func (c *clientWrapper) isWatchedNamespace(ns string) bool { } return false } + +// translateNotFoundError will translate a "not found" error to a boolean return +// value which indicates if the resource exists and a nil error. +func translateNotFoundError(err error) (bool, error) { + if kubeerror.IsNotFound(err) { + return false, nil + } + return err == nil, err +} diff --git a/pkg/provider/kubernetes/crd/client_mock_test.go b/pkg/provider/kubernetes/crd/client_mock_test.go index 5e018ca6d..7509fc2ef 100644 --- a/pkg/provider/kubernetes/crd/client_mock_test.go +++ b/pkg/provider/kubernetes/crd/client_mock_test.go @@ -5,8 +5,8 @@ import ( "os" "path/filepath" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes/scheme" ) @@ -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/client_test.go b/pkg/provider/kubernetes/crd/client_test.go index 42aa574ee..5d64d08f7 100644 --- a/pkg/provider/kubernetes/crd/client_test.go +++ b/pkg/provider/kubernetes/crd/client_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - crdfake "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake" + crdfake "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubefake "k8s.io/client-go/kubernetes/fake" diff --git a/pkg/provider/kubernetes/crd/fixtures/services.yml b/pkg/provider/kubernetes/crd/fixtures/services.yml index 8de8ff369..818a5bd3d 100644 --- a/pkg/provider/kubernetes/crd/fixtures/services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/services.yml @@ -252,3 +252,17 @@ apiVersion: v1 metadata: name: whoami-without-endpoints-subsets namespace: default + +--- +apiVersion: v1 +kind: Service +metadata: + name: native-svc + namespace: default + +spec: + ports: + - name: web + port: 80 + type: ClusterIP + clusterIP: 10.10.0.1 diff --git a/pkg/provider/kubernetes/crd/fixtures/simple.yml b/pkg/provider/kubernetes/crd/fixtures/simple.yml index 15e20535c..36d431338 100644 --- a/pkg/provider/kubernetes/crd/fixtures/simple.yml +++ b/pkg/provider/kubernetes/crd/fixtures/simple.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/services.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/services.yml index 9b5cfd973..8c18ffdc8 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/services.yml @@ -261,3 +261,17 @@ apiVersion: v1 metadata: name: whoamitcp-without-endpoints-subsets namespace: default + +--- +apiVersion: v1 +kind: Service +metadata: + name: native-svc + namespace: default + +spec: + ports: + - name: myapp + port: 8000 + type: ClusterIP + clusterIP: 10.10.0.1 diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/simple.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/simple.yml index 141cf6cb4..170b05a09 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/simple.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/simple.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_bad_tls_options.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_bad_tls_options.yml index 5bb19f259..8b44aecb3 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_bad_tls_options.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_bad_tls_options.yml @@ -18,7 +18,7 @@ data: tls.ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -49,7 +49,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_cross_namespace.yml index c7ba22f19..da7dcb4f4 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_cross_namespace.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_different_services_ns.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_different_services_ns.yml index 02af98254..9d129badb 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_different_services_ns.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_different_services_ns.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_empty_services.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_empty_services.yml index cf5853736..55202d867 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_empty_services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_empty_services.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname.yml index 43226be28..34a105c34 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname_with_port.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname_with_port.yml index 3645601c5..f31764a3e 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname_with_port.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname_with_port.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname_without_ports.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname_without_ports.yml index 376d82469..1065d1380 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname_without_ports.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_externalname_without_ports.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_ipv6.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_ipv6.yml index 777915c18..dd6f23bea 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_ipv6.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_ipv6.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware.yml index 19f83bd76..8c54dc2ef 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: ipallowlist @@ -9,7 +9,7 @@ spec: - 127.0.0.1/32 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: ipallowlist @@ -19,7 +19,7 @@ spec: sourceRange: - 127.0.0.1/32 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_crossprovider.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_crossprovider.yml index 731d8aaba..375cf7c40 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_crossprovider.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_crossprovider.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: ipallowlist @@ -9,7 +9,7 @@ spec: - 127.0.0.1/32 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: ipallowlist @@ -19,7 +19,7 @@ spec: sourceRange: - 127.0.0.1/32 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_multiple_hyphens.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_multiple_hyphens.yml index ba7aed1c0..3523c780b 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_multiple_hyphens.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_multiple_hyphens.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: multiple---hyphens @@ -9,7 +9,7 @@ spec: - 127.0.0.1/32 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_with_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_with_cross_namespace.yml index 8b631fc98..c504d8f24 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_with_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_with_cross_namespace.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: ipallowlist @@ -9,7 +9,7 @@ spec: - 127.0.0.1/32 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: MiddlewareTCP metadata: name: ipallowlist @@ -19,7 +19,7 @@ spec: sourceRange: - 127.0.0.1/32 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb.yml new file mode 100644 index 000000000..f95202ec0 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_native_service_lb.yml @@ -0,0 +1,16 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRouteTCP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: HostSNI(`foo.com`) + services: + - name: native-svc + port: 8000 + nativeLB: true diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_no_rule_value.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_no_rule_value.yml index e78a0bfec..2c3d57803 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_no_rule_value.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_no_rule_value.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_proxyprotocol.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_proxyprotocol.yml index 843f13a71..af9c53b9f 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_proxyprotocol.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_proxyprotocol.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route 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..f0fb21f5d --- /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.io/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.io/v1alpha1 +kind: ServersTransportTCP +metadata: + name: test + namespace: default + +spec: + tls: + serverName: "test" + +--- +apiVersion: traefik.io/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..2f64f0e2b --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_servers_transport_cross_namespace.yml @@ -0,0 +1,27 @@ +apiVersion: traefik.io/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.io/v1alpha1 +kind: ServersTransportTCP +metadata: + name: st-cross-ns + namespace: cross-ns + +spec: + dialKeepAlive: 0 diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_termination_delay.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_termination_delay.yml index 1d942ab6a..7b0076dfe 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_termination_delay.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_termination_delay.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls.yml index 17548e2b3..4bb90073a 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls.yml @@ -9,7 +9,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_acme.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_acme.yml index f7e334513..8d22a46e4 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_acme.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_acme.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options.yml index 1b45d9953..123abc113 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options.yml @@ -18,7 +18,7 @@ data: tls.ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -47,7 +47,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_and_specific_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_and_specific_namespace.yml index 27e34fcaf..0861644d0 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_and_specific_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_and_specific_namespace.yml @@ -18,7 +18,7 @@ data: tls.ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -48,7 +48,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_cross_namespace.yml index 13958f95d..2d6687e5c 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_cross_namespace.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route @@ -20,7 +20,7 @@ spec: namespace: cross-ns --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: tls-options-cn diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_passthrough.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_passthrough.yml index 5cfac32f5..4f84b0280 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_passthrough.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_passthrough.yml @@ -9,7 +9,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_store.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_store.yml index 24894e300..16918e314 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_store.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_store.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSStore metadata: name: default @@ -20,7 +20,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_identical_rules.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_identical_rules.yml index b6e6108cd..99aabf28b 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_identical_rules.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_identical_rules.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_rules.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_rules.yml index dd068d0c3..3b148ec31 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_rules.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_rules.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_services.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_services.yml index 73f60f037..d45527039 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_two_services.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_unknown_tls_options.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_unknown_tls_options.yml index 5798a0719..3df4fdae3 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_unknown_tls_options.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_unknown_tls_options.yml @@ -1,5 +1,5 @@ --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -9,7 +9,7 @@ spec: minVersion: VersionTLS12 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_unknown_tls_options_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_unknown_tls_options_namespace.yml index ed34abdf6..6a9eb2ecd 100644 --- a/pkg/provider/kubernetes/crd/fixtures/tcp/with_unknown_tls_options_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_unknown_tls_options_namespace.yml @@ -1,5 +1,5 @@ --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -9,7 +9,7 @@ spec: minVersion: VersionTLS12 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/services.yml b/pkg/provider/kubernetes/crd/fixtures/udp/services.yml index d58973c82..adaa7272e 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/services.yml @@ -220,3 +220,17 @@ apiVersion: v1 metadata: name: whoamiudp-without-endpoints-subsets namespace: default + +--- +apiVersion: v1 +kind: Service +metadata: + name: native-svc + namespace: default + +spec: + ports: + - name: myapp + port: 8000 + type: ClusterIP + clusterIP: 10.10.0.1 diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/simple.yml b/pkg/provider/kubernetes/crd/fixtures/udp/simple.yml index f514d78a5..60da5fa88 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/simple.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/simple.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_cross_namespace.yml index 8df091d70..5b54397d7 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_cross_namespace.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_different_services_ns.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_different_services_ns.yml index d5c6cc728..c6518c62c 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_different_services_ns.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_different_services_ns.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_empty_services.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_empty_services.yml index 98aeb2bd6..dc588d5e9 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_empty_services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_empty_services.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname.yml index 14c3ab658..dbd919422 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_service.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_service.yml index 962178ed5..302332c0c 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_service.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_service.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_with_port.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_with_port.yml index 962178ed5..302332c0c 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_with_port.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_with_port.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_without_ports.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_without_ports.yml index 6478e6aa4..2a30279bb 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_without_ports.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_externalname_without_ports.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_ipv6.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_ipv6.yml index 2acc8bdc7..dfdbe512f 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_ipv6.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_ipv6.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_native_service_lb.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_native_service_lb.yml new file mode 100644 index 000000000..6942f106b --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_native_service_lb.yml @@ -0,0 +1,15 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRouteUDP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - services: + - name: native-svc + port: 8000 + nativeLB: true diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_two_routes.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_two_routes.yml index 9abffc0d8..762a17178 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_two_routes.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_two_routes.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/udp/with_two_services.yml b/pkg/provider/kubernetes/crd/fixtures/udp/with_two_services.yml index 46bae5d8c..0cee38f9e 100644 --- a/pkg/provider/kubernetes/crd/fixtures/udp/with_two_services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/udp/with_two_services.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRouteUDP metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_auth.yml b/pkg/provider/kubernetes/crd/fixtures/with_auth.yml index b03b82b64..6da695b12 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_auth.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_auth.yml @@ -30,7 +30,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: basicauth @@ -41,7 +41,7 @@ spec: secret: authsecret --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: digestauth @@ -51,7 +51,7 @@ spec: digestAuth: secret: authsecret --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: forwardauth diff --git a/pkg/provider/kubernetes/crd/fixtures/with_bad_tls_options.yml b/pkg/provider/kubernetes/crd/fixtures/with_bad_tls_options.yml index 2df4c3a67..2dd766bfe 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_bad_tls_options.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_bad_tls_options.yml @@ -18,7 +18,7 @@ data: tls.ca: --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -38,7 +38,7 @@ spec: clientAuthType: VerifyClientCertIfGiven --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_cross_namespace.yml index 543c5696c..e66307a71 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_cross_namespace.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: cross-ns-route @@ -36,7 +36,7 @@ spec: serversTransport: foo-test@kubernetescrd --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: tr-svc-wrr1 @@ -51,7 +51,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: tr-svc-wrr2 @@ -65,7 +65,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: tr-svc-mirror1 @@ -82,7 +82,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: tr-svc-mirror2 @@ -99,7 +99,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: test diff --git a/pkg/provider/kubernetes/crd/fixtures/with_default_tls_options.yml b/pkg/provider/kubernetes/crd/fixtures/with_default_tls_options.yml index 3646d9522..494fb2369 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_default_tls_options.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_default_tls_options.yml @@ -18,7 +18,7 @@ data: tls.ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default @@ -37,7 +37,7 @@ spec: clientAuthType: VerifyClientCertIfGiven --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_default_tls_options_default_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_default_tls_options_default_namespace.yml index 49e128983..ec84b589d 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_default_tls_options_default_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_default_tls_options_default_namespace.yml @@ -18,7 +18,7 @@ data: tls.ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: default @@ -37,7 +37,7 @@ spec: clientAuthType: VerifyClientCertIfGiven --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_default_tls_store.yml b/pkg/provider/kubernetes/crd/fixtures/with_default_tls_store.yml index 07f1f982c..36de8bd50 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_default_tls_store.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_default_tls_store.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSStore metadata: name: default @@ -20,7 +20,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_empty_services.yml b/pkg/provider/kubernetes/crd/fixtures/with_empty_services.yml index f6ebb84c0..b3ff215d1 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_empty_services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_empty_services.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_empty_services_ts.yml b/pkg/provider/kubernetes/crd/fixtures/with_empty_services_ts.yml index 92500f3fd..bc4f9626c 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_empty_services_ts.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_empty_services_ts.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route @@ -21,7 +21,7 @@ spec: - name: test-errorpage --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: test-weighted @@ -35,7 +35,7 @@ spec: port: 80 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: test-mirror @@ -52,7 +52,7 @@ spec: kind: TraefikService --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-errorpage diff --git a/pkg/provider/kubernetes/crd/fixtures/with_error_page.yml b/pkg/provider/kubernetes/crd/fixtures/with_error_page.yml index 3eea37acd..e352d596b 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_error_page.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_error_page.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: errorpage diff --git a/pkg/provider/kubernetes/crd/fixtures/with_externalname.yml b/pkg/provider/kubernetes/crd/fixtures/with_externalname.yml index b70ec012e..8a1426211 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_externalname.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_externalname.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_externalname_with_http.yml b/pkg/provider/kubernetes/crd/fixtures/with_externalname_with_http.yml index 1f3e3a3f7..af1c37d38 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_externalname_with_http.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_externalname_with_http.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_externalname_with_https.yml b/pkg/provider/kubernetes/crd/fixtures/with_externalname_with_https.yml index 21c39a1c3..51a7bb3e2 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_externalname_with_https.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_externalname_with_https.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_externalname_without_ports.yml b/pkg/provider/kubernetes/crd/fixtures/with_externalname_without_ports.yml index 25f230574..15b45c3df 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_externalname_without_ports.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_externalname_without_ports.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_https_default.yml b/pkg/provider/kubernetes/crd/fixtures/with_https_default.yml index c022a6cde..2df7e0079 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_https_default.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_https_default.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_https_scheme.yml b/pkg/provider/kubernetes/crd/fixtures/with_https_scheme.yml index 4a9bb8b46..1a0ff7d77 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_https_scheme.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_https_scheme.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_ipv6.yml b/pkg/provider/kubernetes/crd/fixtures/with_ipv6.yml index 23af879ac..27a67bc4a 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_ipv6.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_ipv6.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_middleware.yml b/pkg/provider/kubernetes/crd/fixtures/with_middleware.yml index 45b2dcd49..3837a507b 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_middleware.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_middleware.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: stripprefix @@ -10,7 +10,7 @@ spec: - /tobestripped --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: ratelimit @@ -28,7 +28,7 @@ spec: - 192.168.1.7 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: addprefix @@ -39,7 +39,7 @@ spec: prefix: /tobeadded --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test2.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_middleware_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_middleware_cross_namespace.yml index 25a2ac448..3c1e89956 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_middleware_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_middleware_cross_namespace.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test-crossnamespace.route @@ -39,7 +39,7 @@ spec: - name: cross-ns-stripprefix@kubernetescrd --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: stripprefix @@ -51,7 +51,7 @@ spec: - /stripit --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-errorpage diff --git a/pkg/provider/kubernetes/crd/fixtures/with_middleware_crossprovider.yml b/pkg/provider/kubernetes/crd/fixtures/with_middleware_crossprovider.yml index 915000329..0607ea066 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_middleware_crossprovider.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_middleware_crossprovider.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: stripprefix @@ -10,7 +10,7 @@ spec: - /tobestripped --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: addprefix @@ -21,7 +21,7 @@ spec: prefix: /tobeadded --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test2.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_middleware_multiple_hyphens.yml b/pkg/provider/kubernetes/crd/fixtures/with_middleware_multiple_hyphens.yml index cee835136..648137c6e 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_middleware_multiple_hyphens.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_middleware_multiple_hyphens.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: multiple---hyphens @@ -10,7 +10,7 @@ spec: - /tobestripped --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test2.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_mirroring.yml b/pkg/provider/kubernetes/crd/fixtures/with_mirroring.yml index 7a9fb49c9..a1ead36d8 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_mirroring.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_mirroring.yml @@ -59,7 +59,7 @@ spec: task: whoami5 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror1 @@ -77,7 +77,7 @@ spec: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_mirroring2.yml b/pkg/provider/kubernetes/crd/fixtures/with_mirroring2.yml index b43b33c1c..5f498a296 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_mirroring2.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_mirroring2.yml @@ -59,7 +59,7 @@ spec: task: whoami5 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr2 @@ -73,7 +73,7 @@ spec: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -87,7 +87,7 @@ spec: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror1 @@ -103,7 +103,7 @@ spec: percent: 30 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_namespaces.yml b/pkg/provider/kubernetes/crd/fixtures/with_namespaces.yml index 9bdf1a004..d8d4867e9 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_namespaces.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_namespaces.yml @@ -89,7 +89,7 @@ spec: task: whoami4 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror1 @@ -111,7 +111,7 @@ spec: namespace: bar --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr2 @@ -126,7 +126,7 @@ spec: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror2 @@ -150,7 +150,7 @@ spec: namespace: foo --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror3 @@ -176,7 +176,7 @@ spec: --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror4 @@ -200,7 +200,7 @@ spec: namespace: foo --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirrored @@ -218,7 +218,7 @@ spec: namespace: foo --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -239,7 +239,7 @@ spec: namespace: bar --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_native_service_lb.yml b/pkg/provider/kubernetes/crd/fixtures/with_native_service_lb.yml new file mode 100644 index 000000000..259ea216c --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/with_native_service_lb.yml @@ -0,0 +1,17 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: Host(`foo.com`) + kind: Rule + services: + - name: native-svc + port: 80 + nativeLB: true diff --git a/pkg/provider/kubernetes/crd/fixtures/with_no_rule_value.yml b/pkg/provider/kubernetes/crd/fixtures/with_no_rule_value.yml index 35a2df6d3..a1f3ed335 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_no_rule_value.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_no_rule_value.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_options.yml b/pkg/provider/kubernetes/crd/fixtures/with_options.yml index 1c945829d..281975a71 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_options.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_options.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_plugin_deep_read_secret.yml b/pkg/provider/kubernetes/crd/fixtures/with_plugin_deep_read_secret.yml index f99bde07c..fcd10d6bd 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_plugin_deep_read_secret.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_plugin_deep_read_secret.yml @@ -8,7 +8,7 @@ data: key: dGhpc19pc190aGVfdmVyeV9kZWVwX3NlY3JldA== --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-secret diff --git a/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_array_of_map_contain_secret.yml b/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_array_of_map_contain_secret.yml index 36042fe57..c45873cbf 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_array_of_map_contain_secret.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_array_of_map_contain_secret.yml @@ -9,7 +9,7 @@ data: key2: dXNlcl9wYXNzd29yZA== --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-secret diff --git a/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_array_of_secret.yml b/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_array_of_secret.yml index 7b88c1c42..7544b2e6d 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_array_of_secret.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_array_of_secret.yml @@ -9,7 +9,7 @@ data: key2: c2VjcmV0X2RhdGEy --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-secret diff --git a/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_not_exist_secret.yml b/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_not_exist_secret.yml index c9923d1d8..8430ca600 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_not_exist_secret.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_not_exist_secret.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-secret diff --git a/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_secret.yml b/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_secret.yml index bcd368619..e7f9a70dd 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_secret.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_plugin_read_secret.yml @@ -8,7 +8,7 @@ data: key: dGhpc19pc190aGVfc2VjcmV0 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-secret diff --git a/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml index fdbf7b930..8515039f4 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml @@ -83,7 +83,7 @@ data: tls.key: VEVTVEtFWTM= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: test @@ -119,7 +119,7 @@ spec: trustDomain: spiffe://lol --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: test @@ -129,7 +129,7 @@ spec: serverName: "test" --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_servers_transport_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport_cross_namespace.yml index 7b9ab8891..7aa2e6fb3 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_servers_transport_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport_cross_namespace.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route @@ -18,7 +18,7 @@ spec: serversTransport: cross-ns-st-cross-ns@kubernetescrd --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: st-cross-ns diff --git a/pkg/provider/kubernetes/crd/fixtures/with_services_lb0.yml b/pkg/provider/kubernetes/crd/fixtures/with_services_lb0.yml index 7a1456498..d4f7b7d94 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_services_lb0.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_services_lb0.yml @@ -29,7 +29,7 @@ spec: task: whoami5 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -44,7 +44,7 @@ spec: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_services_lb1.yml b/pkg/provider/kubernetes/crd/fixtures/with_services_lb1.yml index 078b261dc..d863c3f1f 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_services_lb1.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_services_lb1.yml @@ -119,7 +119,7 @@ spec: task: whoami7 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -136,7 +136,7 @@ spec: weight: 1 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr2 @@ -153,7 +153,7 @@ spec: weight: 1 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_services_lb2.yml b/pkg/provider/kubernetes/crd/fixtures/with_services_lb2.yml index 4d99705e9..c1732c18b 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_services_lb2.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_services_lb2.yml @@ -14,7 +14,7 @@ subsets: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr2 @@ -43,7 +43,7 @@ spec: task: whoami5 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -60,7 +60,7 @@ spec: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_services_lb3.yml b/pkg/provider/kubernetes/crd/fixtures/with_services_lb3.yml index 939cf7c7b..8b15d9fd9 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_services_lb3.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_services_lb3.yml @@ -59,7 +59,7 @@ spec: task: whoami4 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr2 @@ -73,7 +73,7 @@ spec: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: mirror1 @@ -89,7 +89,7 @@ spec: port: 8080 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 @@ -109,7 +109,7 @@ spec: weight: 1 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_services_only.yml b/pkg/provider/kubernetes/crd/fixtures/with_services_only.yml index 9dabe6147..c98462ee9 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_services_only.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_services_only.yml @@ -29,7 +29,7 @@ spec: task: whoami5 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TraefikService metadata: name: wrr1 diff --git a/pkg/provider/kubernetes/crd/fixtures/with_tls.yml b/pkg/provider/kubernetes/crd/fixtures/with_tls.yml index 8f78a318d..224164d36 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_tls.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_tls.yml @@ -9,7 +9,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_tls_acme.yml b/pkg/provider/kubernetes/crd/fixtures/with_tls_acme.yml index 170c7a94d..22ef09000 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_tls_acme.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_tls_acme.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_tls_options.yml b/pkg/provider/kubernetes/crd/fixtures/with_tls_options.yml index f49aab66e..f4bb0850a 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_tls_options.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_tls_options.yml @@ -18,7 +18,7 @@ data: ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -37,7 +37,7 @@ spec: clientAuthType: VerifyClientCertIfGiven --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_tls_options_and_specific_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_tls_options_and_specific_namespace.yml index eec9d6fd1..976cd8821 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_tls_options_and_specific_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_tls_options_and_specific_namespace.yml @@ -18,7 +18,7 @@ data: tls.ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -37,7 +37,7 @@ spec: clientAuthType: VerifyClientCertIfGiven --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_tls_options_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_tls_options_cross_namespace.yml index 57228278b..ac8a90297 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_tls_options_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_tls_options_cross_namespace.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route @@ -21,7 +21,7 @@ spec: namespace: cross-ns --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: tls-options-cn diff --git a/pkg/provider/kubernetes/crd/fixtures/with_tls_store.yml b/pkg/provider/kubernetes/crd/fixtures/with_tls_store.yml index ba1acc4cd..84a892fee 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_tls_store.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_tls_store.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSStore metadata: name: default @@ -20,7 +20,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_tls_store_certificates.yml b/pkg/provider/kubernetes/crd/fixtures/with_tls_store_certificates.yml index 2691ac79b..01127dcd1 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_tls_store_certificates.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_tls_store_certificates.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSStore metadata: name: default @@ -20,7 +20,7 @@ data: tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_two_rules.yml b/pkg/provider/kubernetes/crd/fixtures/with_two_rules.yml index f307b797d..a3ea7a5d1 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_two_rules.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_two_rules.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_two_services.yml b/pkg/provider/kubernetes/crd/fixtures/with_two_services.yml index 8a6a17e24..4a971280a 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_two_services.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_two_services.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_two_services_weight.yml b/pkg/provider/kubernetes/crd/fixtures/with_two_services_weight.yml index 76a5c7c3e..e9bb74c21 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_two_services_weight.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_two_services_weight.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_unknown_tls_options.yml b/pkg/provider/kubernetes/crd/fixtures/with_unknown_tls_options.yml index 543851e37..8f4a0d0c8 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_unknown_tls_options.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_unknown_tls_options.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -8,7 +8,7 @@ spec: minVersion: VersionTLS12 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_unknown_tls_options_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_unknown_tls_options_namespace.yml index 133561482..2ebfc2e62 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_unknown_tls_options_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_unknown_tls_options_namespace.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: TLSOption metadata: name: foo @@ -8,7 +8,7 @@ spec: minVersion: VersionTLS12 --- -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/fixtures/with_wrong_rule_kind.yml b/pkg/provider/kubernetes/crd/fixtures/with_wrong_rule_kind.yml index 6c649295a..1cb62e1a9 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_wrong_rule_kind.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_wrong_rule_kind.yml @@ -1,4 +1,4 @@ -apiVersion: traefik.containo.us/v1alpha1 +apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: test.route diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go index 334f5de4c..ec71200a7 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 @@ -29,7 +29,7 @@ package versioned import ( "fmt" - traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1" + traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" 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..55b5edcb2 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 @@ -27,9 +27,9 @@ THE SOFTWARE. package fake import ( - clientset "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned" - traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1" - faketraefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake" + clientset "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1" + faketraefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/discovery" 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..c25b16318 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 @@ -27,7 +27,7 @@ THE SOFTWARE. package fake import ( - traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" 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..cb048b154 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 @@ -27,7 +27,7 @@ THE SOFTWARE. package scheme import ( - traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/doc.go similarity index 94% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/doc.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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/traefikio/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/traefikio/v1alpha1/fake/doc.go similarity index 94% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/doc.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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/traefikio/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/traefikio/v1alpha1/fake/fake_ingressroute.go similarity index 95% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroute.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroute.go index 76aa065c4..b01905713 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/traefikio/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 @@ -29,7 +29,7 @@ package fake import ( "context" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,9 +44,9 @@ type FakeIngressRoutes struct { ns string } -var ingressroutesResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "ingressroutes"} +var ingressroutesResource = schema.GroupVersionResource{Group: "traefik.io", Version: "v1alpha1", Resource: "ingressroutes"} -var ingressroutesKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "IngressRoute"} +var ingressroutesKind = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "IngressRoute"} // Get takes name of the ingressRoute, and returns the corresponding ingressRoute object, and an error if there is any. func (c *FakeIngressRoutes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.IngressRoute, err error) { 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/traefikio/v1alpha1/fake/fake_ingressroutetcp.go similarity index 95% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressroutetcp.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroutetcp.go index c98c593a6..394b1ff55 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/traefikio/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 @@ -29,7 +29,7 @@ package fake import ( "context" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,9 +44,9 @@ type FakeIngressRouteTCPs struct { ns string } -var ingressroutetcpsResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "ingressroutetcps"} +var ingressroutetcpsResource = schema.GroupVersionResource{Group: "traefik.io", Version: "v1alpha1", Resource: "ingressroutetcps"} -var ingressroutetcpsKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "IngressRouteTCP"} +var ingressroutetcpsKind = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "IngressRouteTCP"} // Get takes name of the ingressRouteTCP, and returns the corresponding ingressRouteTCP object, and an error if there is any. func (c *FakeIngressRouteTCPs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.IngressRouteTCP, err error) { 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/traefikio/v1alpha1/fake/fake_ingressrouteudp.go similarity index 95% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_ingressrouteudp.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressrouteudp.go index e81872b0d..f67d889de 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/traefikio/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 @@ -29,7 +29,7 @@ package fake import ( "context" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,9 +44,9 @@ type FakeIngressRouteUDPs struct { ns string } -var ingressrouteudpsResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "ingressrouteudps"} +var ingressrouteudpsResource = schema.GroupVersionResource{Group: "traefik.io", Version: "v1alpha1", Resource: "ingressrouteudps"} -var ingressrouteudpsKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "IngressRouteUDP"} +var ingressrouteudpsKind = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "IngressRouteUDP"} // Get takes name of the ingressRouteUDP, and returns the corresponding ingressRouteUDP object, and an error if there is any. func (c *FakeIngressRouteUDPs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.IngressRouteUDP, err error) { 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/traefikio/v1alpha1/fake/fake_middleware.go similarity index 93% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middleware.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middleware.go index e1bcc7603..efef604fd 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/traefikio/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 @@ -29,7 +29,7 @@ package fake import ( "context" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,9 +44,9 @@ type FakeMiddlewares struct { ns string } -var middlewaresResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "middlewares"} +var middlewaresResource = schema.GroupVersionResource{Group: "traefik.io", Version: "v1alpha1", Resource: "middlewares"} -var middlewaresKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "Middleware"} +var middlewaresKind = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "Middleware"} // Get takes name of the middleware, and returns the corresponding middleware object, and an error if there is any. func (c *FakeMiddlewares) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.Middleware, err error) { 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/traefikio/v1alpha1/fake/fake_middlewaretcp.go similarity index 95% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middlewaretcp.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middlewaretcp.go index cb9adaae8..767405b0e 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/traefikio/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 @@ -29,7 +29,7 @@ package fake import ( "context" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,9 +44,9 @@ type FakeMiddlewareTCPs struct { ns string } -var middlewaretcpsResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "middlewaretcps"} +var middlewaretcpsResource = schema.GroupVersionResource{Group: "traefik.io", Version: "v1alpha1", Resource: "middlewaretcps"} -var middlewaretcpsKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "MiddlewareTCP"} +var middlewaretcpsKind = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "MiddlewareTCP"} // Get takes name of the middlewareTCP, and returns the corresponding middlewareTCP object, and an error if there is any. func (c *FakeMiddlewareTCPs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.MiddlewareTCP, err error) { 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/traefikio/v1alpha1/fake/fake_serverstransport.go similarity index 95% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_serverstransport.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_serverstransport.go index b144f0c65..3666bb4a5 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/traefikio/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 @@ -29,7 +29,7 @@ package fake import ( "context" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,9 +44,9 @@ type FakeServersTransports struct { ns string } -var serverstransportsResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "serverstransports"} +var serverstransportsResource = schema.GroupVersionResource{Group: "traefik.io", Version: "v1alpha1", Resource: "serverstransports"} -var serverstransportsKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "ServersTransport"} +var serverstransportsKind = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "ServersTransport"} // Get takes name of the serversTransport, and returns the corresponding serversTransport object, and an error if there is any. func (c *FakeServersTransports) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ServersTransport, err error) { diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_serverstransporttcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_serverstransporttcp.go new file mode 100644 index 000000000..e18ae4db1 --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_serverstransporttcp.go @@ -0,0 +1,138 @@ +/* +The MIT License (MIT) + +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 +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/v3/pkg/provider/kubernetes/crd/traefikio/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.io", Version: "v1alpha1", Resource: "serverstransporttcps"} + +var serverstransporttcpsKind = schema.GroupVersionKind{Group: "traefik.io", 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_tlsoption.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsoption.go similarity index 93% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsoption.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsoption.go index bfcab1e9e..182812ff9 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/traefikio/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 @@ -29,7 +29,7 @@ package fake import ( "context" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,9 +44,9 @@ type FakeTLSOptions struct { ns string } -var tlsoptionsResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "tlsoptions"} +var tlsoptionsResource = schema.GroupVersionResource{Group: "traefik.io", Version: "v1alpha1", Resource: "tlsoptions"} -var tlsoptionsKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "TLSOption"} +var tlsoptionsKind = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "TLSOption"} // Get takes name of the tLSOption, and returns the corresponding tLSOption object, and an error if there is any. func (c *FakeTLSOptions) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.TLSOption, err error) { 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/traefikio/v1alpha1/fake/fake_tlsstore.go similarity index 93% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_tlsstore.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsstore.go index 8fe3e1fb0..09bd1f827 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/traefikio/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 @@ -29,7 +29,7 @@ package fake import ( "context" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,9 +44,9 @@ type FakeTLSStores struct { ns string } -var tlsstoresResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "tlsstores"} +var tlsstoresResource = schema.GroupVersionResource{Group: "traefik.io", Version: "v1alpha1", Resource: "tlsstores"} -var tlsstoresKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "TLSStore"} +var tlsstoresKind = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "TLSStore"} // Get takes name of the tLSStore, and returns the corresponding tLSStore object, and an error if there is any. func (c *FakeTLSStores) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.TLSStore, err error) { 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/traefikio/v1alpha1/fake/fake_traefikio_client.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikio_client.go index c593b1ccd..6e6ca7d86 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/traefikio/v1alpha1/fake/fake_traefikio_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 @@ -27,7 +27,7 @@ THE SOFTWARE. package fake import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1" rest "k8s.io/client-go/rest" testing "k8s.io/client-go/testing" ) @@ -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/fake/fake_traefikservice.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikservice.go similarity index 95% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefikservice.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikservice.go index d30335386..ef3cf30f3 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/traefikio/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 @@ -29,7 +29,7 @@ package fake import ( "context" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,9 +44,9 @@ type FakeTraefikServices struct { ns string } -var traefikservicesResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "traefikservices"} +var traefikservicesResource = schema.GroupVersionResource{Group: "traefik.io", Version: "v1alpha1", Resource: "traefikservices"} -var traefikservicesKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "TraefikService"} +var traefikservicesKind = schema.GroupVersionKind{Group: "traefik.io", Version: "v1alpha1", Kind: "TraefikService"} // Get takes name of the traefikService, and returns the corresponding traefikService object, and an error if there is any. func (c *FakeTraefikServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.TraefikService, err error) { 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/traefikio/v1alpha1/generated_expansion.go similarity index 93% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/generated_expansion.go index a252692a7..0fbf0a82f 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -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/ingressroute.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroute.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroute.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroute.go index 32021452e..6ec921760 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -30,8 +30,8 @@ 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" + scheme "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroutetcp.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroutetcp.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroutetcp.go index e32f1622a..93caa16aa 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -30,8 +30,8 @@ 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" + scheme "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressrouteudp.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressrouteudp.go index 9c2db2a10..74dab24ac 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -30,8 +30,8 @@ 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" + scheme "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middleware.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middleware.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middleware.go index b6b895ed1..615f8d200 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -30,8 +30,8 @@ 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" + scheme "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middlewaretcp.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middlewaretcp.go index 563b2c6da..ca4c596f9 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -30,8 +30,8 @@ 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" + scheme "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/serverstransport.go similarity index 97% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransport.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/serverstransport.go index 89f015e9a..cc1b467fa 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -30,8 +30,8 @@ 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" + scheme "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/serverstransporttcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/serverstransporttcp.go new file mode 100644 index 000000000..ba1c1bd07 --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/serverstransporttcp.go @@ -0,0 +1,186 @@ +/* +The MIT License (MIT) + +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 +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/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/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/tlsoption.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsoption.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsoption.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsoption.go index bc9556934..24ba147f1 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -30,8 +30,8 @@ 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" + scheme "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsstore.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsstore.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsstore.go index e90d79e45..1f66fb482 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -30,8 +30,8 @@ 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" + scheme "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" 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/traefikio/v1alpha1/traefikio_client.go similarity index 90% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikio_client.go index 2682dbad5..6de07c33c 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikio_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 @@ -27,8 +27,8 @@ THE SOFTWARE. package v1alpha1 import ( - "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" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" rest "k8s.io/client-go/rest" ) @@ -40,12 +40,13 @@ type TraefikV1alpha1Interface interface { MiddlewaresGetter MiddlewareTCPsGetter ServersTransportsGetter + ServersTransportTCPsGetter TLSOptionsGetter TLSStoresGetter TraefikServicesGetter } -// TraefikV1alpha1Client is used to interact with features provided by the traefik.containo.us group. +// TraefikV1alpha1Client is used to interact with features provided by the traefik.io group. type TraefikV1alpha1Client struct { restClient rest.Interface } @@ -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/clientset/versioned/typed/traefik/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikservice.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefikservice.go rename to pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikservice.go index ad5f093f4..e83889472 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/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 @@ -30,8 +30,8 @@ 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" + scheme "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go index d198621df..75b79d658 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 @@ -31,9 +31,9 @@ import ( sync "sync" 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" - traefik "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + traefikio "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -180,9 +180,9 @@ type SharedInformerFactory interface { ForResource(resource schema.GroupVersionResource) (GenericInformer, error) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool - Traefik() traefik.Interface + Traefik() traefikio.Interface } -func (f *sharedInformerFactory) Traefik() traefik.Interface { - return traefik.New(f, f.namespace, f.tweakListOptions) +func (f *sharedInformerFactory) Traefik() traefikio.Interface { + return traefikio.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go index a062e290d..93ba25251 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 @@ -29,7 +29,7 @@ package externalversions import ( "fmt" - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" ) @@ -60,7 +60,7 @@ func (f *genericInformer) Lister() cache.GenericLister { // TODO extend this to unknown resources with a client pool func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { - // Group=traefik.containo.us, Version=v1alpha1 + // Group=traefik.io, Version=v1alpha1 case v1alpha1.SchemeGroupVersion.WithResource("ingressroutes"): return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().IngressRoutes().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("ingressroutetcps"): @@ -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/internalinterfaces/factory_interfaces.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces/factory_interfaces.go index 0809220e6..6af7a12d8 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 @@ -29,7 +29,7 @@ package internalinterfaces import ( time "time" - versioned "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" cache "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/interface.go similarity index 87% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/interface.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/interface.go index 8bc5dfcd2..22009c56e 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -24,11 +24,11 @@ THE SOFTWARE. // Code generated by informer-gen. DO NOT EDIT. -package traefik +package traefikio import ( - 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/informers/externalversions/traefik/v1alpha1" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1" ) // Interface provides access to each of this group's versions. diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroute.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroute.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroute.go index 49c8df238..c2293518f 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -30,10 +30,10 @@ 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" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" @@ -79,7 +79,7 @@ func NewFilteredIngressRouteInformer(client versioned.Interface, namespace strin return client.TraefikV1alpha1().IngressRoutes(namespace).Watch(context.TODO(), options) }, }, - &traefikv1alpha1.IngressRoute{}, + &traefikiov1alpha1.IngressRoute{}, resyncPeriod, indexers, ) @@ -90,7 +90,7 @@ func (f *ingressRouteInformer) defaultInformer(client versioned.Interface, resyn } func (f *ingressRouteInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&traefikv1alpha1.IngressRoute{}, f.defaultInformer) + return f.factory.InformerFor(&traefikiov1alpha1.IngressRoute{}, f.defaultInformer) } func (f *ingressRouteInformer) Lister() v1alpha1.IngressRouteLister { diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroutetcp.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroutetcp.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroutetcp.go index 4fecc2bdd..0ed00501a 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -30,10 +30,10 @@ 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" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" @@ -79,7 +79,7 @@ func NewFilteredIngressRouteTCPInformer(client versioned.Interface, namespace st return client.TraefikV1alpha1().IngressRouteTCPs(namespace).Watch(context.TODO(), options) }, }, - &traefikv1alpha1.IngressRouteTCP{}, + &traefikiov1alpha1.IngressRouteTCP{}, resyncPeriod, indexers, ) @@ -90,7 +90,7 @@ func (f *ingressRouteTCPInformer) defaultInformer(client versioned.Interface, re } func (f *ingressRouteTCPInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&traefikv1alpha1.IngressRouteTCP{}, f.defaultInformer) + return f.factory.InformerFor(&traefikiov1alpha1.IngressRouteTCP{}, f.defaultInformer) } func (f *ingressRouteTCPInformer) Lister() v1alpha1.IngressRouteTCPLister { diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressrouteudp.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressrouteudp.go index 4b4b00743..68787c969 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -30,10 +30,10 @@ 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" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" @@ -79,7 +79,7 @@ func NewFilteredIngressRouteUDPInformer(client versioned.Interface, namespace st return client.TraefikV1alpha1().IngressRouteUDPs(namespace).Watch(context.TODO(), options) }, }, - &traefikv1alpha1.IngressRouteUDP{}, + &traefikiov1alpha1.IngressRouteUDP{}, resyncPeriod, indexers, ) @@ -90,7 +90,7 @@ func (f *ingressRouteUDPInformer) defaultInformer(client versioned.Interface, re } func (f *ingressRouteUDPInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&traefikv1alpha1.IngressRouteUDP{}, f.defaultInformer) + return f.factory.InformerFor(&traefikiov1alpha1.IngressRouteUDP{}, f.defaultInformer) } func (f *ingressRouteUDPInformer) Lister() v1alpha1.IngressRouteUDPLister { diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/interface.go similarity index 90% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/interface.go index 563e81956..a611e3c78 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - internalinterfaces "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" ) // Interface provides access to all the informers in this group version. @@ -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/middleware.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middleware.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middleware.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middleware.go index 80e2679ba..9a00c146b 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -30,10 +30,10 @@ 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" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" @@ -79,7 +79,7 @@ func NewFilteredMiddlewareInformer(client versioned.Interface, namespace string, return client.TraefikV1alpha1().Middlewares(namespace).Watch(context.TODO(), options) }, }, - &traefikv1alpha1.Middleware{}, + &traefikiov1alpha1.Middleware{}, resyncPeriod, indexers, ) @@ -90,7 +90,7 @@ func (f *middlewareInformer) defaultInformer(client versioned.Interface, resyncP } func (f *middlewareInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&traefikv1alpha1.Middleware{}, f.defaultInformer) + return f.factory.InformerFor(&traefikiov1alpha1.Middleware{}, f.defaultInformer) } func (f *middlewareInformer) Lister() v1alpha1.MiddlewareLister { diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middlewaretcp.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middlewaretcp.go index 2285d4a4b..8b547fc45 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -30,10 +30,10 @@ 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" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" @@ -79,7 +79,7 @@ func NewFilteredMiddlewareTCPInformer(client versioned.Interface, namespace stri return client.TraefikV1alpha1().MiddlewareTCPs(namespace).Watch(context.TODO(), options) }, }, - &traefikv1alpha1.MiddlewareTCP{}, + &traefikiov1alpha1.MiddlewareTCP{}, resyncPeriod, indexers, ) @@ -90,7 +90,7 @@ func (f *middlewareTCPInformer) defaultInformer(client versioned.Interface, resy } func (f *middlewareTCPInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&traefikv1alpha1.MiddlewareTCP{}, f.defaultInformer) + return f.factory.InformerFor(&traefikiov1alpha1.MiddlewareTCP{}, f.defaultInformer) } func (f *middlewareTCPInformer) Lister() v1alpha1.MiddlewareTCPLister { diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/serverstransport.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransport.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/serverstransport.go index dfd10f485..cd76b4457 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -30,10 +30,10 @@ 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" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" @@ -79,7 +79,7 @@ func NewFilteredServersTransportInformer(client versioned.Interface, namespace s return client.TraefikV1alpha1().ServersTransports(namespace).Watch(context.TODO(), options) }, }, - &traefikv1alpha1.ServersTransport{}, + &traefikiov1alpha1.ServersTransport{}, resyncPeriod, indexers, ) @@ -90,7 +90,7 @@ func (f *serversTransportInformer) defaultInformer(client versioned.Interface, r } func (f *serversTransportInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&traefikv1alpha1.ServersTransport{}, f.defaultInformer) + return f.factory.InformerFor(&traefikiov1alpha1.ServersTransport{}, f.defaultInformer) } func (f *serversTransportInformer) Lister() v1alpha1.ServersTransportLister { diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/serverstransporttcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/serverstransporttcp.go new file mode 100644 index 000000000..467e2fad1 --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/serverstransporttcp.go @@ -0,0 +1,98 @@ +/* +The MIT License (MIT) + +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 +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/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/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) + }, + }, + &traefikiov1alpha1.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(&traefikiov1alpha1.ServersTransportTCP{}, f.defaultInformer) +} + +func (f *serversTransportTCPInformer) Lister() v1alpha1.ServersTransportTCPLister { + return v1alpha1.NewServersTransportTCPLister(f.Informer().GetIndexer()) +} diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsoption.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsoption.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsoption.go index 7e1f3ad68..34336133b 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -30,10 +30,10 @@ 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" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" @@ -79,7 +79,7 @@ func NewFilteredTLSOptionInformer(client versioned.Interface, namespace string, return client.TraefikV1alpha1().TLSOptions(namespace).Watch(context.TODO(), options) }, }, - &traefikv1alpha1.TLSOption{}, + &traefikiov1alpha1.TLSOption{}, resyncPeriod, indexers, ) @@ -90,7 +90,7 @@ func (f *tLSOptionInformer) defaultInformer(client versioned.Interface, resyncPe } func (f *tLSOptionInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&traefikv1alpha1.TLSOption{}, f.defaultInformer) + return f.factory.InformerFor(&traefikiov1alpha1.TLSOption{}, f.defaultInformer) } func (f *tLSOptionInformer) Lister() v1alpha1.TLSOptionLister { diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsstore.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsstore.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsstore.go index c017915f3..56314fa20 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -30,10 +30,10 @@ 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" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" @@ -79,7 +79,7 @@ func NewFilteredTLSStoreInformer(client versioned.Interface, namespace string, r return client.TraefikV1alpha1().TLSStores(namespace).Watch(context.TODO(), options) }, }, - &traefikv1alpha1.TLSStore{}, + &traefikiov1alpha1.TLSStore{}, resyncPeriod, indexers, ) @@ -90,7 +90,7 @@ func (f *tLSStoreInformer) defaultInformer(client versioned.Interface, resyncPer } func (f *tLSStoreInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&traefikv1alpha1.TLSStore{}, f.defaultInformer) + return f.factory.InformerFor(&traefikiov1alpha1.TLSStore{}, f.defaultInformer) } func (f *tLSStoreInformer) Lister() v1alpha1.TLSStoreLister { diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/traefikservice.go similarity index 88% rename from pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/traefikservice.go rename to pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/traefikservice.go index 8a3dce49c..59dd21c71 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/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 @@ -30,10 +30,10 @@ 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" + versioned "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1" + traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" @@ -79,7 +79,7 @@ func NewFilteredTraefikServiceInformer(client versioned.Interface, namespace str return client.TraefikV1alpha1().TraefikServices(namespace).Watch(context.TODO(), options) }, }, - &traefikv1alpha1.TraefikService{}, + &traefikiov1alpha1.TraefikService{}, resyncPeriod, indexers, ) @@ -90,7 +90,7 @@ func (f *traefikServiceInformer) defaultInformer(client versioned.Interface, res } func (f *traefikServiceInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&traefikv1alpha1.TraefikService{}, f.defaultInformer) + return f.factory.InformerFor(&traefikiov1alpha1.TraefikService{}, f.defaultInformer) } func (f *traefikServiceInformer) Lister() v1alpha1.TraefikServiceLister { diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/expansion_generated.go similarity index 90% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/expansion_generated.go index c338fb976..a8df13373 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -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/ingressroute.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroute.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroute.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroute.go index 532620c79..dbbcd28fe 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroutetcp.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroutetcp.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroutetcp.go index 8bdd6c94c..63ffc06b1 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressrouteudp.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressrouteudp.go index 4c8166d94..7156f8bf9 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middleware.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middleware.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middleware.go index 89ec6190f..c69ef6bea 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middlewaretcp.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middlewaretcp.go index 597cbcd97..388537233 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/serverstransport.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransport.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/serverstransport.go index 1d18bf9fc..2532091fa 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/serverstransporttcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/serverstransporttcp.go new file mode 100644 index 000000000..2b2354e1a --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/serverstransporttcp.go @@ -0,0 +1,107 @@ +/* +The MIT License (MIT) + +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 +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/v3/pkg/provider/kubernetes/crd/traefikio/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/generated/listers/traefik/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsoption.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsoption.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsoption.go index 1d6fc9049..520c95da1 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsstore.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsstore.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsstore.go index 8c79402c1..9687ba492 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/traefikservice.go similarity index 96% rename from pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/traefikservice.go rename to pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/traefikservice.go index 89e8f4d85..cb4331c10 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/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 @@ -27,7 +27,7 @@ THE SOFTWARE. package v1alpha1 import ( - v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index f2054d09e..c0180b639 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -10,8 +10,10 @@ import ( "encoding/json" "errors" "fmt" + "net" "os" "sort" + "strconv" "strings" "time" @@ -19,14 +21,14 @@ import ( "github.com/mitchellh/hashstructure" "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/provider/kubernetes/crd/traefik/v1alpha1" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/job" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" corev1 "k8s.io/api/core/v1" apiextensionv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/labels" @@ -102,6 +104,8 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. logger := log.With().Str(logs.ProviderName, providerName).Logger() ctxLog := logger.WithContext(context.Background()) + logger.Warn().Msg("CRDs API Version \"traefik.io/v1alpha1\" will not be supported in Traefik v3 itself. However, an automatic migration path to the next version will be available.") + k8sClient, err := p.newK8sClient(ctxLog) if err != nil { return err @@ -393,9 +397,84 @@ 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 } +// getServicePort always returns a valid port, an error otherwise. func getServicePort(svc *corev1.Service, port intstr.IntOrString) (*corev1.ServicePort, error) { if svc == nil { return nil, errors.New("service is not defined") @@ -428,6 +507,18 @@ func getServicePort(svc *corev1.Service, port intstr.IntOrString) (*corev1.Servi return &corev1.ServicePort{Port: port.IntVal}, nil } +func getNativeServiceAddress(service corev1.Service, svcPort corev1.ServicePort) (string, error) { + if service.Spec.ClusterIP == "None" { + return "", fmt.Errorf("no clusterIP on headless service: %s/%s", service.Namespace, service.Name) + } + + if service.Spec.ClusterIP == "" { + return "", fmt.Errorf("no clusterIP found for service: %s/%s", service.Namespace, service.Name) + } + + return net.JoinHostPort(service.Spec.ClusterIP, strconv.Itoa(int(svcPort.Port))), nil +} + func createPluginMiddleware(k8sClient Client, ns string, plugins map[string]apiextensionv1.JSON) (map[string]dynamic.PluginConf, error) { if plugins == nil { return nil, nil diff --git a/pkg/provider/kubernetes/crd/kubernetes_http.go b/pkg/provider/kubernetes/crd/kubernetes_http.go index fa8bed11d..66eb87dcd 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_http.go +++ b/pkg/provider/kubernetes/crd/kubernetes_http.go @@ -9,11 +9,11 @@ import ( "strings" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" + "github.com/traefik/traefik/v3/pkg/tls" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" ) @@ -374,6 +374,20 @@ func (c configBuilder) loadServers(parentNamespace string, svc v1alpha1.LoadBala return nil, err } + if svc.NativeLB { + address, err := getNativeServiceAddress(*service, *svcPort) + if err != nil { + return nil, fmt.Errorf("getting native Kubernetes Service address: %w", err) + } + + protocol, err := parseServiceProtocol(svc.Scheme, svcPort.Name, svcPort.Port) + if err != nil { + return nil, err + } + + return []dynamic.Server{{URL: fmt.Sprintf("%s://%s", protocol, address)}}, nil + } + var servers []dynamic.Server if service.Spec.Type == corev1.ServiceTypeExternalName { if !c.allowExternalNameServices { diff --git a/pkg/provider/kubernetes/crd/kubernetes_tcp.go b/pkg/provider/kubernetes/crd/kubernetes_tcp.go index bdb11ee33..374a2a7ab 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_tcp.go +++ b/pkg/provider/kubernetes/crd/kubernetes_tcp.go @@ -9,19 +9,20 @@ import ( "strings" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" + "github.com/traefik/traefik/v3/pkg/tls" corev1 "k8s.io/api/core/v1" ) 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 @@ -228,6 +232,15 @@ func (p *Provider) loadTCPServers(client Client, namespace string, svc v1alpha1. return nil, err } + if svc.NativeLB { + address, err := getNativeServiceAddress(*service, *svcPort) + if err != nil { + return nil, fmt.Errorf("getting native Kubernetes Service address: %w", err) + } + + return []dynamic.TCPServer{{Address: address}}, nil + } + var servers []dynamic.TCPServer if service.Spec.Type == corev1.ServiceTypeExternalName { servers = append(servers, dynamic.TCPServer{ @@ -271,6 +284,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..d09989ed7 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_test.go +++ b/pkg/provider/kubernetes/crd/kubernetes_test.go @@ -12,13 +12,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/provider" - crdfake "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" - "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/provider" + crdfake "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" + "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" @@ -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{}, @@ -6442,6 +6749,219 @@ func TestExternalNameService(t *testing.T) { } } +func TestNativeLB(t *testing.T) { + testCases := []struct { + desc string + ingressClass string + paths []string + expected *dynamic.Configuration + }{ + { + desc: "Empty", + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "HTTP with native Service LB", + paths: []string{"services.yml", "with_native_service_lb.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{ + "default-test-route-6f97418635c7e18853da": { + EntryPoints: []string{"foo"}, + Service: "default-test-route-6f97418635c7e18853da", + Rule: "Host(`foo.com`)", + Priority: 0, + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "default-test-route-6f97418635c7e18853da": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval}, + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:80", + }, + }, + PassHostHeader: Bool(true), + }, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "TCP with native Service LB", + paths: []string{"tcp/services.yml", "tcp/with_native_service_lb.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TCP: &dynamic.TCPConfiguration{ + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + 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": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + Port: "", + }, + }, + }, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "UDP with native Service LB", + paths: []string{"udp/services.yml", "udp/with_native_service_lb.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{ + "default-test.route-0": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-0", + }, + }, + Services: map[string]*dynamic.UDPService{ + "default-test.route-0": { + LoadBalancer: &dynamic.UDPServersLoadBalancer{ + Servers: []dynamic.UDPServer{ + { + Address: "10.10.0.1:8000", + Port: "", + }, + }, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TCP: &dynamic.TCPConfiguration{ + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + } + + for _, test := range testCases { + test := test + + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + var k8sObjects []runtime.Object + var crdObjects []runtime.Object + for _, path := range test.paths { + yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path)) + if err != nil { + panic(err) + } + + objects := k8s.MustParseYaml(yamlContent) + for _, obj := range objects { + switch o := obj.(type) { + case *corev1.Service, *corev1.Endpoints, *corev1.Secret: + k8sObjects = append(k8sObjects, o) + case *v1alpha1.IngressRoute: + crdObjects = append(crdObjects, o) + case *v1alpha1.IngressRouteTCP: + crdObjects = append(crdObjects, o) + case *v1alpha1.IngressRouteUDP: + crdObjects = append(crdObjects, o) + case *v1alpha1.Middleware: + crdObjects = append(crdObjects, o) + case *v1alpha1.TraefikService: + crdObjects = append(crdObjects, o) + case *v1alpha1.TLSOption: + crdObjects = append(crdObjects, o) + case *v1alpha1.TLSStore: + crdObjects = append(crdObjects, o) + default: + } + } + } + + kubeClient := kubefake.NewSimpleClientset(k8sObjects...) + crdClient := crdfake.NewSimpleClientset(crdObjects...) + + client := newClientImpl(kubeClient, crdClient) + + stopCh := make(chan struct{}) + + eventCh, err := client.WatchAll([]string{"default", "cross-ns"}, stopCh) + require.NoError(t, err) + + if k8sObjects != nil || crdObjects != nil { + // just wait for the first event + <-eventCh + } + + p := Provider{} + + conf := p.loadConfigurationFromCRD(context.Background(), client) + assert.Equal(t, test.expected, conf) + }) + } +} + func TestCreateBasicAuthCredentials(t *testing.T) { var k8sObjects []runtime.Object var crdObjects []runtime.Object diff --git a/pkg/provider/kubernetes/crd/kubernetes_udp.go b/pkg/provider/kubernetes/crd/kubernetes_udp.go index 2589ebb0f..5d0d02bb9 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_udp.go +++ b/pkg/provider/kubernetes/crd/kubernetes_udp.go @@ -8,8 +8,8 @@ import ( "strconv" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" corev1 "k8s.io/api/core/v1" ) @@ -121,6 +121,15 @@ func (p *Provider) loadUDPServers(client Client, namespace string, svc v1alpha1. return nil, err } + if svc.NativeLB { + address, err := getNativeServiceAddress(*service, *svcPort) + if err != nil { + return nil, fmt.Errorf("getting native Kubernetes Service address: %w", err) + } + + return []dynamic.UDPServer{{Address: address}}, nil + } + var servers []dynamic.UDPServer if service.Spec.Type == corev1.ServiceTypeExternalName { servers = append(servers, dynamic.UDPServer{ diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/doc.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/doc.go similarity index 67% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/doc.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/doc.go index 71b5219b4..7004a1712 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/doc.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/doc.go @@ -1,5 +1,6 @@ // +k8s:deepcopy-gen=package // Package v1alpha1 is the v1alpha1 version of the API. -// +groupName=traefik.containo.us +// +groupName=traefik.io +// +groupGoName=Traefik package v1alpha1 diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go similarity index 95% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroute.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go index 93f57998c..6471381ae 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go @@ -1,8 +1,8 @@ package v1alpha1 import ( - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/types" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" ) @@ -115,10 +115,14 @@ type LoadBalancerSpec struct { // It allows to configure the transport between Traefik and your servers. // Can only be used on a Kubernetes Service. ServersTransport string `json:"serversTransport,omitempty"` - // Weight defines the weight and should only be specified when Name references a TraefikService object // (and to be precise, one that embeds a Weighted Round Robin). Weight *int `json:"weight,omitempty"` + // NativeLB controls, when creating the load-balancer, + // whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + // The Kubernetes Service itself does load-balance to the pods. + // By default, NativeLB is false. + NativeLB bool `json:"nativeLB,omitempty"` } type ResponseForwarding struct { diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroutetcp.go similarity index 85% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroutetcp.go index 4d89c7fdb..5669e8f4f 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroutetcp.go @@ -1,8 +1,8 @@ package v1alpha1 import ( - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/types" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" ) @@ -69,15 +69,20 @@ 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"` + // NativeLB controls, when creating the load-balancer, + // whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + // The Kubernetes Service itself does load-balance to the pods. + // By default, NativeLB is false. + NativeLB bool `json:"nativeLB,omitempty"` } // +genclient diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressrouteudp.go similarity index 87% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressrouteudp.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressrouteudp.go index 374461346..18773f437 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressrouteudp.go @@ -33,6 +33,11 @@ type ServiceUDP struct { Port intstr.IntOrString `json:"port"` // Weight defines the weight used when balancing requests between multiple Kubernetes Service. Weight *int `json:"weight,omitempty"` + // NativeLB controls, when creating the load-balancer, + // whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. + // The Kubernetes Service itself does load-balance to the pods. + // By default, NativeLB is false. + NativeLB bool `json:"nativeLB,omitempty"` } // +genclient diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go similarity index 99% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go index c0d55d28f..51078f856 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go @@ -1,7 +1,7 @@ package v1alpha1 import ( - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" apiextensionv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go similarity index 96% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/middlewaretcp.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go index 655bf0e26..10799f295 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ package v1alpha1 import ( - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/objectreference.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/objectreference.go similarity index 100% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/objectreference.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/objectreference.go diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/register.go similarity index 94% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/register.go index e87a2ff65..e4c0d2c75 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/register.go @@ -7,7 +7,7 @@ import ( ) // GroupName is the group name for Traefik. -const GroupName = "traefik.containo.us" +const GroupName = "traefik.io" var ( // SchemeBuilder collects the scheme builder functions. @@ -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/serverstransport.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go similarity index 98% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/serverstransport.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go index 68a3438d2..d8ae851de 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ package v1alpha1 import ( - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" ) diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransporttcp.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransporttcp.go new file mode 100644 index 000000000..202dd39d9 --- /dev/null +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransporttcp.go @@ -0,0 +1,68 @@ +package v1alpha1 + +import ( + "github.com/traefik/traefik/v3/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/v3.0/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/service.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/service.go similarity index 98% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/service.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/service.go index 09fafb11b..2e93ced5d 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/service.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/service.go @@ -1,7 +1,7 @@ package v1alpha1 import ( - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go similarity index 100% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/tlsoption.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsstore.go similarity index 98% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/tlsstore.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsstore.go index 2af463df1..2f7bff622 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ package v1alpha1 import ( - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/tls" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go similarity index 92% rename from pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go rename to pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go index eaa5d450c..e8f75cda6 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefikio/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 @@ -30,9 +30,9 @@ THE SOFTWARE. package v1alpha1 import ( - dynamic "github.com/traefik/traefik/v2/pkg/config/dynamic" - tls "github.com/traefik/traefik/v2/pkg/tls" - types "github.com/traefik/traefik/v2/pkg/types" + dynamic "github.com/traefik/traefik/v3/pkg/config/dynamic" + tls "github.com/traefik/traefik/v3/pkg/tls" + types "github.com/traefik/traefik/v3/pkg/types" v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" intstr "k8s.io/apimachinery/pkg/util/intstr" @@ -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/client_mock_test.go b/pkg/provider/kubernetes/gateway/client_mock_test.go index 010ce6635..1003a777c 100644 --- a/pkg/provider/kubernetes/gateway/client_mock_test.go +++ b/pkg/provider/kubernetes/gateway/client_mock_test.go @@ -5,7 +5,7 @@ import ( "os" "path/filepath" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" 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/fixtures/httproute/simple_cross_provider.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml index 3010f3a59..ff90c82d0 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml @@ -42,7 +42,7 @@ spec: value: /bar backendRefs: - weight: 1 - group: traefik.containo.us + group: traefik.io kind: TraefikService name: service@file port: 80 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml index 6fe6d48b6..6426736f6 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml @@ -42,7 +42,7 @@ spec: value: /bar backendRefs: - weight: 1 - group: traefik.containo.us + group: traefik.io kind: TraefikService name: api@internal port: 80 diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml index a712ca739..be491cf79 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml @@ -39,7 +39,7 @@ spec: rules: - backendRefs: - weight: 1 - group: traefik.containo.us + group: traefik.io kind: TraefikService name: service@file port: 9000 diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml index d530c3d0e..4d687b5de 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml @@ -55,7 +55,7 @@ spec: rules: - backendRefs: - weight: 1 - group: traefik.containo.us + group: traefik.io kind: TraefikService name: service@file port: 9000 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 3f62e98a2..170540394 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" @@ -18,13 +19,13 @@ import ( "github.com/mitchellh/hashstructure" "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" - traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/job" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/tls" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -183,19 +184,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 +274,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{}, } @@ -750,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 } @@ -833,7 +860,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}, } @@ -964,8 +991,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 } @@ -1201,7 +1236,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 { @@ -1213,25 +1248,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) { @@ -1426,7 +1464,7 @@ func loadServices(client Client, namespace string, backendRefs []v1alpha2.HTTPBa weight := int(pointer.Int32Deref(backendRef.Weight, 1)) - if *backendRef.Group == traefikv1alpha1.GroupName && *backendRef.Kind == kindTraefikService { + if isTraefikService(backendRef.BackendRef) { wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.WRRService{Name: string(backendRef.Name), Weight: &weight}) continue } @@ -1549,7 +1587,7 @@ func loadTCPServices(client Client, namespace string, backendRefs []v1alpha2.Bac weight := int(pointer.Int32Deref(backendRef.Weight, 1)) - if *backendRef.Group == traefikv1alpha1.GroupName && *backendRef.Kind == kindTraefikService { + if isTraefikService(backendRef) { wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.TCPWRRService{Name: string(backendRef.Name), Weight: &weight}) continue } @@ -1646,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") { @@ -1685,14 +1802,16 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s return eventsChanBuffered } -func isInternalService(ref v1alpha2.BackendRef) bool { +func isTraefikService(ref v1alpha2.BackendRef) bool { if ref.Kind == nil || ref.Group == nil { return false } - return *ref.Kind == kindTraefikService && - *ref.Group == traefikv1alpha1.GroupName && - strings.HasSuffix(string(ref.Name), "@internal") + return *ref.Group == traefikv1alpha1.GroupName && *ref.Kind == kindTraefikService +} + +func isInternalService(ref v1alpha2.BackendRef) bool { + return isTraefikService(ref) && strings.HasSuffix(string(ref.Name), "@internal") } // makeListenerKey joins protocol, hostname, and port of a listener into a string key. diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index 44b3ce249..f7e2acafe 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -8,9 +8,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/tls" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/pointer" "sigs.k8s.io/gateway-api/apis/v1alpha2" @@ -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{ @@ -1521,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 { @@ -1555,9 +1724,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 +1750,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 +1776,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 +1802,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 +1828,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 +1854,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 +1880,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 +1938,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1845,6 +2022,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1937,6 +2115,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1995,6 +2174,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2048,6 +2228,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2111,6 +2292,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2192,6 +2374,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2246,6 +2429,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2290,9 +2474,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 +2500,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 +2526,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 +2552,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 +2578,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 +2604,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 +2638,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 +2664,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 +2723,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2597,6 +2790,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2654,6 +2848,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2740,6 +2935,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2808,6 +3004,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2874,6 +3071,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2931,6 +3129,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2988,6 +3187,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3011,10 +3211,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, }, @@ -3022,7 +3222,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{ { @@ -3045,6 +3245,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3102,6 +3303,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3189,6 +3391,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3246,6 +3449,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3339,6 +3543,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -3383,9 +3588,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 +3614,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 +3640,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 +3666,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 +3762,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3635,9 +3845,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 +3941,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -3923,6 +4135,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -4120,6 +4333,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -4251,6 +4465,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -4700,6 +4915,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.*"}, @@ -4708,7 +4928,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", @@ -4718,12 +4938,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`)", }, } diff --git a/pkg/provider/kubernetes/ingress/annotations.go b/pkg/provider/kubernetes/ingress/annotations.go index 25807cdd2..134b2eda2 100644 --- a/pkg/provider/kubernetes/ingress/annotations.go +++ b/pkg/provider/kubernetes/ingress/annotations.go @@ -4,8 +4,8 @@ import ( "regexp" "strings" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/label" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/label" ) const ( @@ -45,6 +45,7 @@ type ServiceIng struct { ServersTransport string `json:"serversTransport,omitempty"` PassHostHeader *bool `json:"passHostHeader"` Sticky *dynamic.Sticky `json:"sticky,omitempty" label:"allowEmpty"` + NativeLB bool `json:"nativeLB,omitempty"` } // SetDefaults sets the default values. diff --git a/pkg/provider/kubernetes/ingress/annotations_test.go b/pkg/provider/kubernetes/ingress/annotations_test.go index 075e76f90..ee77647f3 100644 --- a/pkg/provider/kubernetes/ingress/annotations_test.go +++ b/pkg/provider/kubernetes/ingress/annotations_test.go @@ -5,8 +5,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/types" ) func Test_parseRouterConfig(t *testing.T) { @@ -106,6 +106,7 @@ func Test_parseServiceConfig(t *testing.T) { "traefik.ingress.kubernetes.io/service.serversscheme": "protocol", "traefik.ingress.kubernetes.io/service.serverstransport": "foobar@file", "traefik.ingress.kubernetes.io/service.passhostheader": "true", + "traefik.ingress.kubernetes.io/service.nativelb": "true", "traefik.ingress.kubernetes.io/service.sticky.cookie": "true", "traefik.ingress.kubernetes.io/service.sticky.cookie.httponly": "true", "traefik.ingress.kubernetes.io/service.sticky.cookie.name": "foobar", @@ -125,6 +126,7 @@ func Test_parseServiceConfig(t *testing.T) { ServersScheme: "protocol", ServersTransport: "foobar@file", PassHostHeader: Bool(true), + NativeLB: true, }, }, }, diff --git a/pkg/provider/kubernetes/ingress/client.go b/pkg/provider/kubernetes/ingress/client.go index eccd39657..11854c12b 100644 --- a/pkg/provider/kubernetes/ingress/client.go +++ b/pkg/provider/kubernetes/ingress/client.go @@ -11,8 +11,8 @@ import ( "github.com/hashicorp/go-version" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" - traefikversion "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" + traefikversion "github.com/traefik/traefik/v3/pkg/version" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" networkingv1beta1 "k8s.io/api/networking/v1beta1" @@ -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/client_mock_test.go b/pkg/provider/kubernetes/ingress/client_mock_test.go index 6cc6ef138..6d91c37c8 100644 --- a/pkg/provider/kubernetes/ingress/client_mock_test.go +++ b/pkg/provider/kubernetes/ingress/client_mock_test.go @@ -5,7 +5,7 @@ import ( "os" "github.com/hashicorp/go-version" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" networkingv1beta1 "k8s.io/api/networking/v1beta1" diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-service-lb_ingress.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-service-lb_ingress.yml new file mode 100644 index 000000000..f9645ad09 --- /dev/null +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-service-lb_ingress.yml @@ -0,0 +1,15 @@ +kind: Ingress +apiVersion: networking.k8s.io/v1beta1 +metadata: + name: "" + namespace: testing + +spec: + rules: + - host: traefik.tchouk + http: + paths: + - path: /bar + backend: + serviceName: service1 + servicePort: 8080 diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-service-lb_service.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-service-lb_service.yml new file mode 100644 index 000000000..e394301fc --- /dev/null +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-native-service-lb_service.yml @@ -0,0 +1,15 @@ +kind: Service +apiVersion: v1 +metadata: + name: service1 + namespace: testing + annotations: + traefik.ingress.kubernetes.io/service.nativelb: "true" + +spec: + ports: + - port: 8080 + clusterIP: 10.0.0.1 + type: ClusterIP + externalName: traefik.wtf + diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index 95a71c12d..9bab326a2 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -18,12 +18,12 @@ import ( "github.com/mitchellh/hashstructure" "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/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/job" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/tls" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/labels" @@ -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") @@ -543,6 +545,21 @@ func (p *Provider) loadService(client Client, namespace string, backend networki if svcConfig.Service.ServersTransport != "" { svc.LoadBalancer.ServersTransport = svcConfig.Service.ServersTransport } + + if svcConfig.Service.NativeLB { + address, err := getNativeServiceAddress(*service, portSpec) + if err != nil { + return nil, fmt.Errorf("getting native Kubernetes Service address: %w", err) + } + + protocol := getProtocol(portSpec, portSpec.Name, svcConfig) + + svc.LoadBalancer.Servers = []dynamic.Server{ + {URL: fmt.Sprintf("%s://%s", protocol, address)}, + } + + return svc, nil + } } if service.Spec.Type == corev1.ServiceTypeExternalName { @@ -592,6 +609,18 @@ func (p *Provider) loadService(client Client, namespace string, backend networki return svc, nil } +func getNativeServiceAddress(service corev1.Service, svcPort corev1.ServicePort) (string, error) { + if service.Spec.ClusterIP == "None" { + return "", fmt.Errorf("no clusterIP on headless service: %s/%s", service.Namespace, service.Name) + } + + if service.Spec.ClusterIP == "" { + return "", fmt.Errorf("no clusterIP found for service: %s/%s", service.Namespace, service.Name) + } + + return net.JoinHostPort(service.Spec.ClusterIP, strconv.Itoa(int(svcPort.Port))), nil +} + func getProtocol(portSpec corev1.ServicePort, portName string, svcConfig *ServiceConfig) string { if svcConfig != nil && svcConfig.Service != nil && svcConfig.Service.ServersScheme != "" { return svcConfig.Service.ServersScheme diff --git a/pkg/provider/kubernetes/ingress/kubernetes_test.go b/pkg/provider/kubernetes/ingress/kubernetes_test.go index 3b032f996..9a3e4e05f 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes_test.go +++ b/pkg/provider/kubernetes/ingress/kubernetes_test.go @@ -5,16 +5,17 @@ import ( "errors" "math" "os" + "path/filepath" "strings" "testing" "time" "github.com/stretchr/testify/assert" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -26,11 +27,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 +1394,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 +1460,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 +1662,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 +1726,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 +1883,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) @@ -1948,8 +2052,88 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) { } } +func TestLoadConfigurationFromIngressesWithNativeLB(t *testing.T) { + testCases := []struct { + desc string + ingressClass string + serverVersion string + expected *dynamic.Configuration + }{ + { + desc: "Ingress with native service lb", + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{}, + HTTP: &dynamic.HTTPConfiguration{ + Middlewares: map[string]*dynamic.Middleware{}, + Routers: map[string]*dynamic.Router{ + "testing-traefik-tchouk-bar": { + Rule: "Host(`traefik.tchouk`) && PathPrefix(`/bar`)", + Service: "testing-service1-8080", + }, + }, + Services: map[string]*dynamic.Service{ + "testing-service1-8080": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval}, + PassHostHeader: Bool(true), + Servers: []dynamic.Server{ + { + URL: "http://10.0.0.1:8080", + }, + }, + }, + }, + }, + }, + }, + }, + } + + for _, test := range testCases { + test := test + + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + var paths []string + _, err := os.Stat(generateTestFilename("_ingress", test.desc)) + if err == nil { + paths = append(paths, generateTestFilename("_ingress", test.desc)) + } + _, err = os.Stat(generateTestFilename("_endpoint", test.desc)) + if err == nil { + paths = append(paths, generateTestFilename("_endpoint", test.desc)) + } + _, err = os.Stat(generateTestFilename("_service", test.desc)) + if err == nil { + paths = append(paths, generateTestFilename("_service", test.desc)) + } + _, err = os.Stat(generateTestFilename("_secret", test.desc)) + if err == nil { + paths = append(paths, generateTestFilename("_secret", test.desc)) + } + _, err = os.Stat(generateTestFilename("_ingressclass", test.desc)) + if err == nil { + paths = append(paths, generateTestFilename("_ingressclass", test.desc)) + } + + serverVersion := test.serverVersion + if serverVersion == "" { + serverVersion = "v1.17" + } + + clientMock := newClientMock(serverVersion, paths...) + + p := Provider{IngressClass: test.ingressClass} + conf := p.loadConfigurationFromIngresses(context.Background(), clientMock) + + assert.Equal(t, test.expected, conf) + }) + } +} + func generateTestFilename(suffix, desc string) string { - return "./fixtures/" + strings.ReplaceAll(desc, " ", "-") + suffix + ".yml" + return filepath.Join("fixtures", strings.ReplaceAll(desc, " ", "-")+suffix+".yml") } func TestGetCertificates(t *testing.T) { 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/consul/consul.go b/pkg/provider/kv/consul/consul.go index 4a537c78f..2a5fdfd49 100644 --- a/pkg/provider/kv/consul/consul.go +++ b/pkg/provider/kv/consul/consul.go @@ -7,9 +7,9 @@ import ( "time" "github.com/kvtools/consul" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/kv" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/kv" + "github.com/traefik/traefik/v3/pkg/types" ) // providerName is the Consul provider name. diff --git a/pkg/provider/kv/etcd/etcd.go b/pkg/provider/kv/etcd/etcd.go index 7cf027fed..9da061076 100644 --- a/pkg/provider/kv/etcd/etcd.go +++ b/pkg/provider/kv/etcd/etcd.go @@ -6,9 +6,9 @@ import ( "time" "github.com/kvtools/etcdv3" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/kv" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/kv" + "github.com/traefik/traefik/v3/pkg/types" ) var _ provider.Provider = (*Provider)(nil) diff --git a/pkg/provider/kv/kv.go b/pkg/provider/kv/kv.go index f6697b821..fd2671306 100644 --- a/pkg/provider/kv/kv.go +++ b/pkg/provider/kv/kv.go @@ -11,11 +11,11 @@ import ( "github.com/kvtools/valkeyrie" "github.com/kvtools/valkeyrie/store" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/kv" - "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/kv" + "github.com/traefik/traefik/v3/pkg/job" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/safe" ) // Provider holds configurations of the provider. diff --git a/pkg/provider/kv/kv_test.go b/pkg/provider/kv/kv_test.go index f577da7e3..8ba2cde99 100644 --- a/pkg/provider/kv/kv_test.go +++ b/pkg/provider/kv/kv_test.go @@ -10,9 +10,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" ) func Test_buildConfiguration(t *testing.T) { @@ -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/kv/redis/redis.go b/pkg/provider/kv/redis/redis.go index 23f432bb1..ddd7178cb 100644 --- a/pkg/provider/kv/redis/redis.go +++ b/pkg/provider/kv/redis/redis.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/kvtools/redis" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/kv" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/kv" + "github.com/traefik/traefik/v3/pkg/types" ) var _ provider.Provider = (*Provider)(nil) diff --git a/pkg/provider/kv/zk/zk.go b/pkg/provider/kv/zk/zk.go index 28b7fee12..9d66cee34 100644 --- a/pkg/provider/kv/zk/zk.go +++ b/pkg/provider/kv/zk/zk.go @@ -4,8 +4,8 @@ import ( "time" "github.com/kvtools/zookeeper" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/kv" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/kv" ) var _ provider.Provider = (*Provider)(nil) 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 939505351..000000000 --- a/pkg/provider/marathon/config.go +++ /dev/null @@ -1,474 +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 = make(map[string]*dynamic.TCPService) - lb := &dynamic.TCPServersLoadBalancer{} - lb.SetDefaults() - conf.Services[appName] = &dynamic.TCPService{ - LoadBalancer: lb, - } - } - - 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 4e5b4d563..000000000 --- a/pkg/provider/marathon/config_test.go +++ /dev/null @@ -1,2413 +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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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{}, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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{}, - }, - 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, 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"), - withLabel("traefik.tcp.services.foo.loadbalancer.terminationdelay", "200"), - )), - 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", - }, - }, - TerminationDelay: Int(200), - }, - }, - }, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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{}, - }, - 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/provider/nomad/config.go b/pkg/provider/nomad/config.go index a31b8ee21..b6caa8cf1 100644 --- a/pkg/provider/nomad/config.go +++ b/pkg/provider/nomad/config.go @@ -11,11 +11,11 @@ import ( "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/logs" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/constraints" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/label" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/constraints" ) func (p *Provider) buildConfig(ctx context.Context, items []item) *dynamic.Configuration { @@ -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..db7bb3855 100644 --- a/pkg/provider/nomad/config_test.go +++ b/pkg/provider/nomad/config_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func Test_defaultRule(t *testing.T) { @@ -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/nomad/nomad.go b/pkg/provider/nomad/nomad.go index 8f12086f6..b836707eb 100644 --- a/pkg/provider/nomad/nomad.go +++ b/pkg/provider/nomad/nomad.go @@ -12,13 +12,13 @@ import ( "github.com/hashicorp/nomad/api" "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/provider/constraints" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/job" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/provider/constraints" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/types" ) const ( @@ -48,6 +48,13 @@ type item struct { ExtraConf configuration // global options } +// configuration contains information from the service's tags that are globals +// (not specific to the dynamic configuration). +type configuration struct { + Enable bool // .enable is the corresponding label. + Canary bool // .nomad.canary is the corresponding label. +} + // ProviderBuilder is responsible for constructing namespaced instances of the Nomad provider. type ProviderBuilder struct { Configuration `yaml:",inline" export:"true"` @@ -89,13 +96,39 @@ type Configuration struct { // SetDefaults sets the default values for the Nomad Traefik Provider Configuration. func (c *Configuration) SetDefaults() { - c.Endpoint = &EndpointConfig{} + defConfig := api.DefaultConfig() + c.Endpoint = &EndpointConfig{ + Address: defConfig.Address, + Region: defConfig.Region, + Token: defConfig.SecretID, + } + + if defConfig.TLSConfig != nil && (defConfig.TLSConfig.Insecure || defConfig.TLSConfig.CACert != "" || defConfig.TLSConfig.ClientCert != "" || defConfig.TLSConfig.ClientKey != "") { + c.Endpoint.TLS = &types.ClientTLS{ + CA: defConfig.TLSConfig.CACert, + Cert: defConfig.TLSConfig.ClientCert, + Key: defConfig.TLSConfig.ClientKey, + InsecureSkipVerify: defConfig.TLSConfig.Insecure, + } + } + c.Prefix = defaultPrefix c.ExposedByDefault = true c.RefreshInterval = ptypes.Duration(15 * time.Second) c.DefaultRule = defaultTemplateRule } +type EndpointConfig struct { + // Address is the Nomad endpoint address, if empty it defaults to NOMAD_ADDR or "http://127.0.0.1:4646". + Address string `description:"The address of the Nomad server, including scheme and port." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` + // Region is the Nomad region, if empty it defaults to NOMAD_REGION. + Region string `description:"Nomad region to use. If not provided, the local agent region is used." json:"region,omitempty" toml:"region,omitempty" yaml:"region,omitempty"` + // Token is the ACL token to connect with Nomad, if empty it defaults to NOMAD_TOKEN. + Token string `description:"Token is used to provide a per-request ACL token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"` + TLS *types.ClientTLS `description:"Configure TLS." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` + EndpointWaitTime ptypes.Duration `description:"WaitTime limits how long a Watch will block. If not provided, the agent default values will be used" json:"endpointWaitTime,omitempty" toml:"endpointWaitTime,omitempty" yaml:"endpointWaitTime,omitempty" export:"true"` +} + // Provider holds configuration along with the namespace it will discover services in. type Provider struct { Configuration @@ -106,15 +139,9 @@ type Provider struct { defaultRuleTpl *template.Template // default routing rule } -type EndpointConfig struct { - // Address is the Nomad endpoint address, if empty it defaults to NOMAD_ADDR or "http://localhost:4646". - Address string `description:"The address of the Nomad server, including scheme and port." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` - // Region is the Nomad region, if empty it defaults to NOMAD_REGION or "global". - Region string `description:"Nomad region to use. If not provided, the local agent region is used." json:"region,omitempty" toml:"region,omitempty" yaml:"region,omitempty"` - // Token is the ACL token to connect with Nomad, if empty it defaults to NOMAD_TOKEN. - Token string `description:"Token is used to provide a per-request ACL token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"` - TLS *types.ClientTLS `description:"Configure TLS." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` - EndpointWaitTime ptypes.Duration `description:"WaitTime limits how long a Watch will block. If not provided, the agent default values will be used" json:"endpointWaitTime,omitempty" toml:"endpointWaitTime,omitempty" yaml:"endpointWaitTime,omitempty" export:"true"` +// SetDefaults sets the default values for the Nomad Traefik Provider. +func (p *Provider) SetDefaults() { + p.Configuration.SetDefaults() } // Init the Nomad Traefik Provider. @@ -207,51 +234,6 @@ func (p *Provider) loadConfiguration(ctx context.Context, configurationC chan<- return nil } -func createClient(namespace string, endpoint *EndpointConfig) (*api.Client, error) { - config := api.Config{ - Address: endpoint.Address, - Namespace: namespace, - Region: endpoint.Region, - SecretID: endpoint.Token, - WaitTime: time.Duration(endpoint.EndpointWaitTime), - } - - if endpoint.TLS != nil { - config.TLSConfig = &api.TLSConfig{ - CACert: endpoint.TLS.CA, - ClientCert: endpoint.TLS.Cert, - ClientKey: endpoint.TLS.Key, - Insecure: endpoint.TLS.InsecureSkipVerify, - } - } - - return api.NewClient(&config) -} - -// configuration contains information from the service's tags that are globals -// (not specific to the dynamic configuration). -type configuration struct { - Enable bool // .enable is the corresponding label. - Canary bool // .nomad.canary is the corresponding label. -} - -// getExtraConf returns a configuration with settings which are not part of the dynamic configuration (e.g. ".enable"). -func (p *Provider) getExtraConf(tags []string) configuration { - labels := tagsToLabels(tags, p.Prefix) - - enabled := p.ExposedByDefault - if v, exists := labels["traefik.enable"]; exists { - enabled = strings.EqualFold(v, "true") - } - - var canary bool - if v, exists := labels["traefik.nomad.canary"]; exists { - canary = strings.EqualFold(v, "true") - } - - return configuration{Enable: enabled, Canary: canary} -} - func (p *Provider) getNomadServiceData(ctx context.Context) ([]item, error) { // first, get list of service stubs opts := &api.QueryOptions{AllowStale: p.Stale} @@ -309,6 +291,23 @@ func (p *Provider) getNomadServiceData(ctx context.Context) ([]item, error) { return items, nil } +// getExtraConf returns a configuration with settings which are not part of the dynamic configuration (e.g. ".enable"). +func (p *Provider) getExtraConf(tags []string) configuration { + labels := tagsToLabels(tags, p.Prefix) + + enabled := p.ExposedByDefault + if v, exists := labels["traefik.enable"]; exists { + enabled = strings.EqualFold(v, "true") + } + + var canary bool + if v, exists := labels["traefik.nomad.canary"]; exists { + canary = strings.EqualFold(v, "true") + } + + return configuration{Enable: enabled, Canary: canary} +} + // fetchService queries Nomad API for services matching name, // that also have the .enable=true set in its tags. func (p *Provider) fetchService(ctx context.Context, name string) ([]*api.ServiceRegistration, error) { @@ -329,3 +328,24 @@ func (p *Provider) fetchService(ctx context.Context, name string) ([]*api.Servic } return services, nil } + +func createClient(namespace string, endpoint *EndpointConfig) (*api.Client, error) { + config := api.Config{ + Address: endpoint.Address, + Namespace: namespace, + Region: endpoint.Region, + SecretID: endpoint.Token, + WaitTime: time.Duration(endpoint.EndpointWaitTime), + } + + if endpoint.TLS != nil { + config.TLSConfig = &api.TLSConfig{ + CACert: endpoint.TLS.CA, + ClientCert: endpoint.TLS.Cert, + ClientKey: endpoint.TLS.Key, + Insecure: endpoint.TLS.InsecureSkipVerify, + } + } + + return api.NewClient(&config) +} diff --git a/pkg/provider/nomad/nomad_test.go b/pkg/provider/nomad/nomad_test.go index b9d2bfa39..b83c7727c 100644 --- a/pkg/provider/nomad/nomad_test.go +++ b/pkg/provider/nomad/nomad_test.go @@ -7,7 +7,9 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v3/pkg/types" ) func Test_globalConfig(t *testing.T) { @@ -76,6 +78,60 @@ func Test_globalConfig(t *testing.T) { } } +func TestProvider_SetDefaults_Endpoint(t *testing.T) { + testCases := []struct { + desc string + envs map[string]string + expected *EndpointConfig + }{ + { + desc: "without env vars", + envs: map[string]string{}, + expected: &EndpointConfig{ + Address: "http://127.0.0.1:4646", + }, + }, + { + desc: "with env vars", + envs: map[string]string{ + "NOMAD_ADDR": "https://nomad.example.com", + "NOMAD_REGION": "us-west", + "NOMAD_TOKEN": "almighty_token", + "NOMAD_CACERT": "/etc/ssl/private/nomad-agent-ca.pem", + "NOMAD_CLIENT_CERT": "/etc/ssl/private/global-client-nomad.pem", + "NOMAD_CLIENT_KEY": "/etc/ssl/private/global-client-nomad-key.pem", + "NOMAD_SKIP_VERIFY": "true", + }, + expected: &EndpointConfig{ + Address: "https://nomad.example.com", + Region: "us-west", + Token: "almighty_token", + TLS: &types.ClientTLS{ + CA: "/etc/ssl/private/nomad-agent-ca.pem", + Cert: "/etc/ssl/private/global-client-nomad.pem", + Key: "/etc/ssl/private/global-client-nomad-key.pem", + InsecureSkipVerify: true, + }, + EndpointWaitTime: 0, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + for k, v := range test.envs { + t.Setenv(k, v) + } + + p := &Provider{} + p.SetDefaults() + + assert.Equal(t, test.expected, p.Endpoint) + }) + } +} + func Test_getNomadServiceData(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch { diff --git a/pkg/provider/provider.go b/pkg/provider/provider.go index 70b053055..2597a05e6 100644 --- a/pkg/provider/provider.go +++ b/pkg/provider/provider.go @@ -1,8 +1,8 @@ package provider import ( - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/safe" ) // Provider defines methods of a provider. diff --git a/pkg/provider/rancher/config.go b/pkg/provider/rancher/config.go deleted file mode 100644 index 1b0d5339d..000000000 --- a/pkg/provider/rancher/config.go +++ /dev/null @@ -1,300 +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 = make(map[string]*dynamic.TCPService) - lb := &dynamic.TCPServersLoadBalancer{} - lb.SetDefaults() - configuration.Services[serviceName] = &dynamic.TCPService{ - LoadBalancer: lb, - } - } - - 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 f1b080ecb..000000000 --- a/pkg/provider/rancher/config_test.go +++ /dev/null @@ -1,1188 +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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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{}, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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{}, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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{}, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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{}, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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{}, - }, - 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", - }, - }, - TerminationDelay: Int(100), - }, - }, - }, - }, - 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{}, - }, - 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 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", - }, - 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", - }, - }, - TerminationDelay: Int(200), - }, - }, - }, - }, - 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/provider/rest/rest.go b/pkg/provider/rest/rest.go index f375bd1db..e0a03bb4b 100644 --- a/pkg/provider/rest/rest.go +++ b/pkg/provider/rest/rest.go @@ -7,9 +7,9 @@ import ( "github.com/gorilla/mux" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" "github.com/unrolled/render" ) diff --git a/pkg/provider/tailscale/provider.go b/pkg/provider/tailscale/provider.go index a807dfdcf..b0b439b86 100644 --- a/pkg/provider/tailscale/provider.go +++ b/pkg/provider/tailscale/provider.go @@ -11,12 +11,12 @@ import ( "github.com/rs/zerolog/log" "github.com/tailscale/tscert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/muxer/http" - "github.com/traefik/traefik/v2/pkg/muxer/tcp" - "github.com/traefik/traefik/v2/pkg/safe" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/muxer/http" + "github.com/traefik/traefik/v3/pkg/muxer/tcp" + "github.com/traefik/traefik/v3/pkg/safe" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" ) // Provider is the Tailscale certificates provider implementation. It receives diff --git a/pkg/provider/tailscale/provider_test.go b/pkg/provider/tailscale/provider_test.go index 6a7ae0d6f..614b42ed3 100644 --- a/pkg/provider/tailscale/provider_test.go +++ b/pkg/provider/tailscale/provider_test.go @@ -5,9 +5,9 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" ) func TestProvider_findDomains(t *testing.T) { diff --git a/pkg/provider/traefik/internal.go b/pkg/provider/traefik/internal.go index 1e1c23bec..71a6c321a 100644 --- a/pkg/provider/traefik/internal.go +++ b/pkg/provider/traefik/internal.go @@ -9,12 +9,12 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/static" - "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/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/tls" ) const defaultInternalEntryPointName = "traefik" @@ -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/provider/traefik/internal_test.go b/pkg/provider/traefik/internal_test.go index 1e7d5b282..915bbf6b6 100644 --- a/pkg/provider/traefik/internal_test.go +++ b/pkg/provider/traefik/internal_test.go @@ -10,10 +10,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/ping" - "github.com/traefik/traefik/v2/pkg/provider/rest" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/ping" + "github.com/traefik/traefik/v3/pkg/provider/rest" + "github.com/traefik/traefik/v3/pkg/types" ) var updateExpected = flag.Bool("update_expected", false, "Update expected files in fixtures") diff --git a/pkg/redactor/redactor.go b/pkg/redactor/redactor.go index c122e307c..fc8a9dd14 100644 --- a/pkg/redactor/redactor.go +++ b/pkg/redactor/redactor.go @@ -7,8 +7,8 @@ import ( "regexp" "github.com/mitchellh/copystructure" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/tls" "mvdan.cc/xurls/v2" ) diff --git a/pkg/redactor/redactor_config_test.go b/pkg/redactor/redactor_config_test.go index beb7ed5b1..c8836d2d0 100644 --- a/pkg/redactor/redactor_config_test.go +++ b/pkg/redactor/redactor_config_test.go @@ -10,38 +10,36 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/ping" - "github.com/traefik/traefik/v2/pkg/plugins" - "github.com/traefik/traefik/v2/pkg/provider/acme" - "github.com/traefik/traefik/v2/pkg/provider/consulcatalog" - "github.com/traefik/traefik/v2/pkg/provider/docker" - "github.com/traefik/traefik/v2/pkg/provider/ecs" - "github.com/traefik/traefik/v2/pkg/provider/file" - "github.com/traefik/traefik/v2/pkg/provider/http" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/gateway" - "github.com/traefik/traefik/v2/pkg/provider/kubernetes/ingress" - "github.com/traefik/traefik/v2/pkg/provider/kv" - "github.com/traefik/traefik/v2/pkg/provider/kv/consul" - "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/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" - "github.com/traefik/traefik/v2/pkg/tracing/elastic" - "github.com/traefik/traefik/v2/pkg/tracing/haystack" - "github.com/traefik/traefik/v2/pkg/tracing/instana" - "github.com/traefik/traefik/v2/pkg/tracing/jaeger" - "github.com/traefik/traefik/v2/pkg/tracing/zipkin" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/ping" + "github.com/traefik/traefik/v3/pkg/plugins" + "github.com/traefik/traefik/v3/pkg/provider/acme" + "github.com/traefik/traefik/v3/pkg/provider/consulcatalog" + "github.com/traefik/traefik/v3/pkg/provider/docker" + "github.com/traefik/traefik/v3/pkg/provider/ecs" + "github.com/traefik/traefik/v3/pkg/provider/file" + "github.com/traefik/traefik/v3/pkg/provider/http" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/gateway" + "github.com/traefik/traefik/v3/pkg/provider/kubernetes/ingress" + "github.com/traefik/traefik/v3/pkg/provider/kv" + "github.com/traefik/traefik/v3/pkg/provider/kv/consul" + "github.com/traefik/traefik/v3/pkg/provider/kv/etcd" + "github.com/traefik/traefik/v3/pkg/provider/kv/redis" + "github.com/traefik/traefik/v3/pkg/provider/kv/zk" + "github.com/traefik/traefik/v3/pkg/provider/rest" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/tracing/datadog" + "github.com/traefik/traefik/v3/pkg/tracing/elastic" + "github.com/traefik/traefik/v3/pkg/tracing/haystack" + "github.com/traefik/traefik/v3/pkg/tracing/instana" + "github.com/traefik/traefik/v3/pkg/tracing/jaeger" + "github.com/traefik/traefik/v3/pkg/tracing/zipkin" + "github.com/traefik/traefik/v3/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 +368,6 @@ func init() { Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ - TerminationDelay: intPtr(42), ProxyProtocol: &dynamic.ProxyProtocol{ Version: 42, }, @@ -379,6 +376,7 @@ func init() { Address: "127.0.0.1:8080", }, }, + ServersTransport: "foo", }, }, "bar": { @@ -392,6 +390,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 +516,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 +574,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, @@ -595,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", @@ -659,17 +647,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")`, @@ -807,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{ @@ -885,6 +851,7 @@ func TestDo_staticConfiguration(t *testing.T) { }, Datadog: &datadog.Config{ LocalAgentHostPort: "foobar", + LocalAgentSocket: "foobar", GlobalTags: map[string]string{"foobar": "foobar"}, Debug: true, PrioritySampling: 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..0097aa2c2 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", @@ -100,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", @@ -168,16 +155,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": { @@ -307,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": { @@ -385,6 +351,7 @@ }, "datadog": { "localAgentHostPort": "xxxx", + "localAgentSocket": "xxxx", "globalTags": { "foobar": "foobar" }, diff --git a/pkg/redactor/testdata/example.json b/pkg/redactor/testdata/example.json index 0d12d63d9..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,10 +72,8 @@ "Boltdb": null, "KubernetesIngress": null, "KubernetesCRD": null, - "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..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,10 +72,8 @@ "Boltdb": null, "KubernetesIngress": null, "KubernetesCRD": null, - "Mesos": null, "Eureka": null, "ECS": null, - "Rancher": null, "DynamoDB": null, "ConfigFile": "/etc/traefik/traefik.toml" } 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..bd4fda0f5 100644 --- a/pkg/server/aggregator.go +++ b/pkg/server/aggregator.go @@ -3,10 +3,10 @@ package server import ( "github.com/go-acme/lego/v4/challenge/tlsalpn01" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/server/provider" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/tls" ) func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoints []string) dynamic.Configuration { @@ -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..ea1fb639f 100644 --- a/pkg/server/aggregator_test.go +++ b/pkg/server/aggregator_test.go @@ -5,8 +5,8 @@ import ( "github.com/go-acme/lego/v4/challenge/tlsalpn01" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/tls" ) func Test_mergeConfiguration(t *testing.T) { @@ -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..da2d66f17 100644 --- a/pkg/server/configurationwatcher.go +++ b/pkg/server/configurationwatcher.go @@ -7,11 +7,11 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "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/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/provider" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/tls" ) // ConfigurationWatcher watches configuration changes. @@ -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..d22cb9538 100644 --- a/pkg/server/configurationwatcher_test.go +++ b/pkg/server/configurationwatcher_test.go @@ -9,11 +9,11 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/provider/aggregator" - "github.com/traefik/traefik/v2/pkg/safe" - th "github.com/traefik/traefik/v2/pkg/testhelpers" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/provider/aggregator" + "github.com/traefik/traefik/v3/pkg/safe" + th "github.com/traefik/traefik/v3/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/tls" ) type mockProvider struct { @@ -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/middleware/chainbuilder.go b/pkg/server/middleware/chainbuilder.go index 57d8385c5..864e7e68b 100644 --- a/pkg/server/middleware/chainbuilder.go +++ b/pkg/server/middleware/chainbuilder.go @@ -5,12 +5,12 @@ import ( "github.com/containous/alice" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - "github.com/traefik/traefik/v2/pkg/middlewares/capture" - metricsmiddleware "github.com/traefik/traefik/v2/pkg/middlewares/metrics" - mTracing "github.com/traefik/traefik/v2/pkg/middlewares/tracing" - "github.com/traefik/traefik/v2/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" + "github.com/traefik/traefik/v3/pkg/middlewares/capture" + metricsmiddleware "github.com/traefik/traefik/v3/pkg/middlewares/metrics" + mTracing "github.com/traefik/traefik/v3/pkg/middlewares/tracing" + "github.com/traefik/traefik/v3/pkg/tracing" ) // ChainBuilder Creates a middleware chain by entry point. It is used for middlewares that are created almost systematically and that need to be created before all others. diff --git a/pkg/server/middleware/middlewares.go b/pkg/server/middleware/middlewares.go index 6d1790838..0d1bfcfa8 100644 --- a/pkg/server/middleware/middlewares.go +++ b/pkg/server/middleware/middlewares.go @@ -9,29 +9,29 @@ import ( "strings" "github.com/containous/alice" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/middlewares/addprefix" - "github.com/traefik/traefik/v2/pkg/middlewares/auth" - "github.com/traefik/traefik/v2/pkg/middlewares/buffering" - "github.com/traefik/traefik/v2/pkg/middlewares/chain" - "github.com/traefik/traefik/v2/pkg/middlewares/circuitbreaker" - "github.com/traefik/traefik/v2/pkg/middlewares/compress" - "github.com/traefik/traefik/v2/pkg/middlewares/contenttype" - "github.com/traefik/traefik/v2/pkg/middlewares/customerrors" - "github.com/traefik/traefik/v2/pkg/middlewares/grpcweb" - "github.com/traefik/traefik/v2/pkg/middlewares/headers" - "github.com/traefik/traefik/v2/pkg/middlewares/inflightreq" - "github.com/traefik/traefik/v2/pkg/middlewares/ipallowlist" - "github.com/traefik/traefik/v2/pkg/middlewares/passtlsclientcert" - "github.com/traefik/traefik/v2/pkg/middlewares/ratelimiter" - "github.com/traefik/traefik/v2/pkg/middlewares/redirect" - "github.com/traefik/traefik/v2/pkg/middlewares/replacepath" - "github.com/traefik/traefik/v2/pkg/middlewares/replacepathregex" - "github.com/traefik/traefik/v2/pkg/middlewares/retry" - "github.com/traefik/traefik/v2/pkg/middlewares/stripprefix" - "github.com/traefik/traefik/v2/pkg/middlewares/stripprefixregex" - "github.com/traefik/traefik/v2/pkg/middlewares/tracing" - "github.com/traefik/traefik/v2/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/middlewares/addprefix" + "github.com/traefik/traefik/v3/pkg/middlewares/auth" + "github.com/traefik/traefik/v3/pkg/middlewares/buffering" + "github.com/traefik/traefik/v3/pkg/middlewares/chain" + "github.com/traefik/traefik/v3/pkg/middlewares/circuitbreaker" + "github.com/traefik/traefik/v3/pkg/middlewares/compress" + "github.com/traefik/traefik/v3/pkg/middlewares/contenttype" + "github.com/traefik/traefik/v3/pkg/middlewares/customerrors" + "github.com/traefik/traefik/v3/pkg/middlewares/grpcweb" + "github.com/traefik/traefik/v3/pkg/middlewares/headers" + "github.com/traefik/traefik/v3/pkg/middlewares/inflightreq" + "github.com/traefik/traefik/v3/pkg/middlewares/ipallowlist" + "github.com/traefik/traefik/v3/pkg/middlewares/passtlsclientcert" + "github.com/traefik/traefik/v3/pkg/middlewares/ratelimiter" + "github.com/traefik/traefik/v3/pkg/middlewares/redirect" + "github.com/traefik/traefik/v3/pkg/middlewares/replacepath" + "github.com/traefik/traefik/v3/pkg/middlewares/replacepathregex" + "github.com/traefik/traefik/v3/pkg/middlewares/retry" + "github.com/traefik/traefik/v3/pkg/middlewares/stripprefix" + "github.com/traefik/traefik/v3/pkg/middlewares/stripprefixregex" + "github.com/traefik/traefik/v3/pkg/middlewares/tracing" + "github.com/traefik/traefik/v3/pkg/server/provider" ) type middlewareStackType int diff --git a/pkg/server/middleware/middlewares_test.go b/pkg/server/middleware/middlewares_test.go index 5d8db1aa8..a0b97d1b9 100644 --- a/pkg/server/middleware/middlewares_test.go +++ b/pkg/server/middleware/middlewares_test.go @@ -9,9 +9,9 @@ import ( "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" - "github.com/traefik/traefik/v2/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/server/provider" ) func TestBuilder_BuildChainNilConfig(t *testing.T) { diff --git a/pkg/server/middleware/plugins.go b/pkg/server/middleware/plugins.go index 3a092f140..13b8b1959 100644 --- a/pkg/server/middleware/plugins.go +++ b/pkg/server/middleware/plugins.go @@ -3,8 +3,8 @@ package middleware import ( "errors" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/plugins" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/plugins" ) // PluginsBuilder the plugin's builder interface. diff --git a/pkg/server/middleware/tcp/middlewares.go b/pkg/server/middleware/tcp/middlewares.go index ad6320a46..e03a4fb84 100644 --- a/pkg/server/middleware/tcp/middlewares.go +++ b/pkg/server/middleware/tcp/middlewares.go @@ -5,11 +5,11 @@ import ( "fmt" "strings" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/middlewares/tcp/inflightconn" - "github.com/traefik/traefik/v2/pkg/middlewares/tcp/ipallowlist" - "github.com/traefik/traefik/v2/pkg/server/provider" - "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/middlewares/tcp/inflightconn" + "github.com/traefik/traefik/v3/pkg/middlewares/tcp/ipallowlist" + "github.com/traefik/traefik/v3/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/tcp" ) type middlewareStackType int diff --git a/pkg/server/router/router.go b/pkg/server/router/router.go index 388e792d3..97f7f98b6 100644 --- a/pkg/server/router/router.go +++ b/pkg/server/router/router.go @@ -8,17 +8,17 @@ import ( "github.com/containous/alice" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - metricsMiddle "github.com/traefik/traefik/v2/pkg/middlewares/metrics" - "github.com/traefik/traefik/v2/pkg/middlewares/recovery" - "github.com/traefik/traefik/v2/pkg/middlewares/tracing" - httpmuxer "github.com/traefik/traefik/v2/pkg/muxer/http" - "github.com/traefik/traefik/v2/pkg/server/middleware" - "github.com/traefik/traefik/v2/pkg/server/provider" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" + metricsMiddle "github.com/traefik/traefik/v3/pkg/middlewares/metrics" + "github.com/traefik/traefik/v3/pkg/middlewares/recovery" + "github.com/traefik/traefik/v3/pkg/middlewares/tracing" + httpmuxer "github.com/traefik/traefik/v3/pkg/muxer/http" + "github.com/traefik/traefik/v3/pkg/server/middleware" + "github.com/traefik/traefik/v3/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/tls" ) type middlewareBuilder interface { @@ -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,16 +130,13 @@ 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 } } - muxer.SortRoutes() - chain := alice.New() chain = chain.Append(func(next http.Handler) (http.Handler, error) { return recovery.New(ctx, next) diff --git a/pkg/server/router/router_test.go b/pkg/server/router/router_test.go index 7f867633e..21e0de141 100644 --- a/pkg/server/router/router_test.go +++ b/pkg/server/router/router_test.go @@ -13,17 +13,17 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - "github.com/traefik/traefik/v2/pkg/middlewares/capture" - "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" - "github.com/traefik/traefik/v2/pkg/server/middleware" - "github.com/traefik/traefik/v2/pkg/server/service" - "github.com/traefik/traefik/v2/pkg/testhelpers" - "github.com/traefik/traefik/v2/pkg/tls" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" + "github.com/traefik/traefik/v3/pkg/middlewares/capture" + "github.com/traefik/traefik/v3/pkg/middlewares/requestdecorator" + "github.com/traefik/traefik/v3/pkg/server/middleware" + "github.com/traefik/traefik/v3/pkg/server/service" + "github.com/traefik/traefik/v3/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/types" ) func TestRouterManager_Get(t *testing.T) { diff --git a/pkg/server/router/tcp/manager.go b/pkg/server/router/tcp/manager.go index 9bbadbc20..df24ed704 100644 --- a/pkg/server/router/tcp/manager.go +++ b/pkg/server/router/tcp/manager.go @@ -8,15 +8,15 @@ import ( "net/http" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/middlewares/snicheck" - httpmuxer "github.com/traefik/traefik/v2/pkg/muxer/http" - tcpmuxer "github.com/traefik/traefik/v2/pkg/muxer/tcp" - "github.com/traefik/traefik/v2/pkg/server/provider" - tcpservice "github.com/traefik/traefik/v2/pkg/server/service/tcp" - "github.com/traefik/traefik/v2/pkg/tcp" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/middlewares/snicheck" + httpmuxer "github.com/traefik/traefik/v3/pkg/muxer/http" + tcpmuxer "github.com/traefik/traefik/v3/pkg/muxer/tcp" + "github.com/traefik/traefik/v3/pkg/server/provider" + tcpservice "github.com/traefik/traefik/v3/pkg/server/service/tcp" + "github.com/traefik/traefik/v3/pkg/tcp" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" ) type middlewareBuilder interface { @@ -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/manager_test.go b/pkg/server/router/tcp/manager_test.go index dd31ce3b3..29af7783c 100644 --- a/pkg/server/router/tcp/manager_test.go +++ b/pkg/server/router/tcp/manager_test.go @@ -9,11 +9,12 @@ import ( "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" - tcpmiddleware "github.com/traefik/traefik/v2/pkg/server/middleware/tcp" - "github.com/traefik/traefik/v2/pkg/server/service/tcp" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + tcpmiddleware "github.com/traefik/traefik/v3/pkg/server/middleware/tcp" + "github.com/traefik/traefik/v3/pkg/server/service/tcp" + tcp2 "github.com/traefik/traefik/v3/pkg/tcp" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" ) func TestRuntimeConfiguration(t *testing.T) { @@ -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/postgres.go b/pkg/server/router/tcp/postgres.go index b79c3762f..e82ba7eb3 100644 --- a/pkg/server/router/tcp/postgres.go +++ b/pkg/server/router/tcp/postgres.go @@ -4,11 +4,13 @@ import ( "bufio" "bytes" "errors" + "io" + "net" "sync" "github.com/rs/zerolog/log" - tcpmuxer "github.com/traefik/traefik/v2/pkg/muxer/tcp" - "github.com/traefik/traefik/v2/pkg/tcp" + tcpmuxer "github.com/traefik/traefik/v3/pkg/muxer/tcp" + "github.com/traefik/traefik/v3/pkg/tcp" ) var ( @@ -25,7 +27,10 @@ func isPostgres(br *bufio.Reader) (bool, error) { for i := 1; i < len(PostgresStartTLSMsg)+1; i++ { peeked, err := br.Peek(i) if err != nil { - log.Error().Err(err).Msg("Error while Peeking first bytes") + var opErr *net.OpError + if !errors.Is(err, io.EOF) && (!errors.As(err, &opErr) || opErr.Timeout()) { + log.Error().Err(err).Msg("Error while Peeking first byte") + } return false, err } diff --git a/pkg/server/router/tcp/router.go b/pkg/server/router/tcp/router.go index b3f34ee0d..8c2e8939b 100644 --- a/pkg/server/router/tcp/router.go +++ b/pkg/server/router/tcp/router.go @@ -11,8 +11,8 @@ import ( "time" "github.com/rs/zerolog/log" - tcpmuxer "github.com/traefik/traefik/v2/pkg/muxer/tcp" - "github.com/traefik/traefik/v2/pkg/tcp" + tcpmuxer "github.com/traefik/traefik/v3/pkg/muxer/tcp" + "github.com/traefik/traefik/v3/pkg/tcp" ) const defaultBufSize = 4096 @@ -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/pkg/server/router/tcp/router_test.go b/pkg/server/router/tcp/router_test.go index f6fc4f4ab..3701ca67e 100644 --- a/pkg/server/router/tcp/router_test.go +++ b/pkg/server/router/tcp/router_test.go @@ -16,12 +16,12 @@ import ( "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" - 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" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + tcpmiddleware "github.com/traefik/traefik/v3/pkg/server/middleware/tcp" + "github.com/traefik/traefik/v3/pkg/server/service/tcp" + tcp2 "github.com/traefik/traefik/v3/pkg/tcp" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" ) type applyRouter func(conf *runtime.Configuration) @@ -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/router/udp/router.go b/pkg/server/router/udp/router.go index 0a5303eff..091d77ed5 100644 --- a/pkg/server/router/udp/router.go +++ b/pkg/server/router/udp/router.go @@ -6,11 +6,11 @@ import ( "sort" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/server/provider" - udpservice "github.com/traefik/traefik/v2/pkg/server/service/udp" - "github.com/traefik/traefik/v2/pkg/udp" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/server/provider" + udpservice "github.com/traefik/traefik/v3/pkg/server/service/udp" + "github.com/traefik/traefik/v3/pkg/udp" ) // NewManager Creates a new Manager. diff --git a/pkg/server/router/udp/router_test.go b/pkg/server/router/udp/router_test.go index d29d7d2d6..d6be07491 100644 --- a/pkg/server/router/udp/router_test.go +++ b/pkg/server/router/udp/router_test.go @@ -5,9 +5,9 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/server/service/udp" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/server/service/udp" ) func TestRuntimeConfiguration(t *testing.T) { diff --git a/pkg/server/routerfactory.go b/pkg/server/routerfactory.go index 1b28a0dfd..d7a1bf68c 100644 --- a/pkg/server/routerfactory.go +++ b/pkg/server/routerfactory.go @@ -4,19 +4,20 @@ import ( "context" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/server/middleware" - tcpmiddleware "github.com/traefik/traefik/v2/pkg/server/middleware/tcp" - "github.com/traefik/traefik/v2/pkg/server/router" - 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" - "github.com/traefik/traefik/v2/pkg/tls" - udptypes "github.com/traefik/traefik/v2/pkg/udp" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/server/middleware" + tcpmiddleware "github.com/traefik/traefik/v3/pkg/server/middleware/tcp" + "github.com/traefik/traefik/v3/pkg/server/router" + tcprouter "github.com/traefik/traefik/v3/pkg/server/router/tcp" + udprouter "github.com/traefik/traefik/v3/pkg/server/router/udp" + "github.com/traefik/traefik/v3/pkg/server/service" + tcpsvc "github.com/traefik/traefik/v3/pkg/server/service/tcp" + udpsvc "github.com/traefik/traefik/v3/pkg/server/service/udp" + "github.com/traefik/traefik/v3/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/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..b935df89e 100644 --- a/pkg/server/routerfactory_test.go +++ b/pkg/server/routerfactory_test.go @@ -6,14 +6,15 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/server/middleware" - "github.com/traefik/traefik/v2/pkg/server/service" - th "github.com/traefik/traefik/v2/pkg/testhelpers" - "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/server/middleware" + "github.com/traefik/traefik/v3/pkg/server/service" + "github.com/traefik/traefik/v3/pkg/tcp" + th "github.com/traefik/traefik/v3/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/tls" ) func TestReuseService(t *testing.T) { @@ -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/server.go b/pkg/server/server.go index 421437a38..c17464621 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -8,10 +8,10 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/server/middleware" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/server/middleware" ) // Server is the reverse-proxy/load-balancer engine. @@ -111,7 +111,6 @@ func (s *Server) Close() { func stopMetricsClients() { metrics.StopDatadog() metrics.StopStatsd() - metrics.StopInfluxDB() metrics.StopInfluxDB2() metrics.StopOpenTelemetry() } diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index 87c0a77ef..6f8bfba02 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -15,21 +15,23 @@ import ( "time" "github.com/containous/alice" + gokitmetrics "github.com/go-kit/kit/metrics" "github.com/pires/go-proxyproto" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/ip" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/middlewares" - "github.com/traefik/traefik/v2/pkg/middlewares/contenttype" - "github.com/traefik/traefik/v2/pkg/middlewares/forwardedheaders" - "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/server/router" - tcprouter "github.com/traefik/traefik/v2/pkg/server/router/tcp" - "github.com/traefik/traefik/v2/pkg/tcp" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/ip" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/middlewares/contenttype" + "github.com/traefik/traefik/v3/pkg/middlewares/forwardedheaders" + "github.com/traefik/traefik/v3/pkg/middlewares/requestdecorator" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/server/router" + tcprouter "github.com/traefik/traefik/v3/pkg/server/router/tcp" + "github.com/traefik/traefik/v3/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/types" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) @@ -67,7 +69,7 @@ func (h *httpForwarder) Accept() (net.Conn, error) { type TCPEntryPoints map[string]*TCPEntryPoint // NewTCPEntryPoints creates a new TCPEntryPoints. -func NewTCPEntryPoints(entryPointsConfig static.EntryPoints, hostResolverConfig *types.HostResolverConfig) (TCPEntryPoints, error) { +func NewTCPEntryPoints(entryPointsConfig static.EntryPoints, hostResolverConfig *types.HostResolverConfig, metricsRegistry metrics.Registry) (TCPEntryPoints, error) { serverEntryPointsTCP := make(TCPEntryPoints) for entryPointName, config := range entryPointsConfig { protocol, err := config.GetProtocol() @@ -81,7 +83,11 @@ func NewTCPEntryPoints(entryPointsConfig static.EntryPoints, hostResolverConfig ctx := log.With().Str(logs.EntryPointName, entryPointName).Logger().WithContext(context.Background()) - serverEntryPointsTCP[entryPointName], err = NewTCPEntryPoint(ctx, config, hostResolverConfig) + openConnectionsGauge := metricsRegistry. + OpenConnectionsGauge(). + With("entrypoint", entryPointName, "protocol", "TCP") + + serverEntryPointsTCP[entryPointName], err = NewTCPEntryPoint(ctx, config, hostResolverConfig, openConnectionsGauge) if err != nil { return nil, fmt.Errorf("error while building entryPoint %s: %w", entryPointName, err) } @@ -137,8 +143,8 @@ type TCPEntryPoint struct { } // NewTCPEntryPoint creates a new TCPEntryPoint. -func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint, hostResolverConfig *types.HostResolverConfig) (*TCPEntryPoint, error) { - tracker := newConnectionTracker() +func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint, hostResolverConfig *types.HostResolverConfig, openConnectionsGauge gokitmetrics.Gauge) (*TCPEntryPoint, error) { + tracker := newConnectionTracker(openConnectionsGauge) listener, err := buildListener(ctx, configuration) if err != nil { @@ -440,34 +446,45 @@ func buildListener(ctx context.Context, entryPoint *static.EntryPoint) (net.List return listener, nil } -func newConnectionTracker() *connectionTracker { +func newConnectionTracker(openConnectionsGauge gokitmetrics.Gauge) *connectionTracker { return &connectionTracker{ - conns: make(map[net.Conn]struct{}), + conns: make(map[net.Conn]struct{}), + openConnectionsGauge: openConnectionsGauge, } } type connectionTracker struct { - conns map[net.Conn]struct{} - lock sync.RWMutex + connsMu sync.RWMutex + conns map[net.Conn]struct{} + + openConnectionsGauge gokitmetrics.Gauge } // AddConnection add a connection in the tracked connections list. func (c *connectionTracker) AddConnection(conn net.Conn) { - c.lock.Lock() - defer c.lock.Unlock() + c.connsMu.Lock() c.conns[conn] = struct{}{} + c.connsMu.Unlock() + + if c.openConnectionsGauge != nil { + c.openConnectionsGauge.Add(1) + } } // RemoveConnection remove a connection from the tracked connections list. func (c *connectionTracker) RemoveConnection(conn net.Conn) { - c.lock.Lock() - defer c.lock.Unlock() + c.connsMu.Lock() delete(c.conns, conn) + c.connsMu.Unlock() + + if c.openConnectionsGauge != nil { + c.openConnectionsGauge.Add(-1) + } } func (c *connectionTracker) isEmpty() bool { - c.lock.RLock() - defer c.lock.RUnlock() + c.connsMu.RLock() + defer c.connsMu.RUnlock() return len(c.conns) == 0 } @@ -489,8 +506,8 @@ func (c *connectionTracker) Shutdown(ctx context.Context) error { // Close close all the connections in the tracked connections list. func (c *connectionTracker) Close() { - c.lock.Lock() - defer c.lock.Unlock() + c.connsMu.Lock() + defer c.connsMu.Unlock() for conn := range c.conns { if err := conn.Close(); err != nil { log.Error().Err(err).Msg("Error while closing connection") diff --git a/pkg/server/server_entrypoint_tcp_http3.go b/pkg/server/server_entrypoint_tcp_http3.go index 99755d6d7..188be8026 100644 --- a/pkg/server/server_entrypoint_tcp_http3.go +++ b/pkg/server/server_entrypoint_tcp_http3.go @@ -9,10 +9,10 @@ import ( "net/http" "sync" - "github.com/lucas-clemente/quic-go/http3" + "github.com/quic-go/quic-go/http3" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/static" - tcprouter "github.com/traefik/traefik/v2/pkg/server/router/tcp" + "github.com/traefik/traefik/v3/pkg/config/static" + tcprouter "github.com/traefik/traefik/v3/pkg/server/router/tcp" ) type http3server struct { diff --git a/pkg/server/server_entrypoint_tcp_http3_test.go b/pkg/server/server_entrypoint_tcp_http3_test.go index 6544dd2e0..9b440be4b 100644 --- a/pkg/server/server_entrypoint_tcp_http3_test.go +++ b/pkg/server/server_entrypoint_tcp_http3_test.go @@ -6,12 +6,13 @@ import ( "crypto/tls" "net/http" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/static" - tcprouter "github.com/traefik/traefik/v2/pkg/server/router/tcp" - traefiktls "github.com/traefik/traefik/v2/pkg/tls" + "github.com/traefik/traefik/v3/pkg/config/static" + tcprouter "github.com/traefik/traefik/v3/pkg/server/router/tcp" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" ) // LocalhostCert is a PEM-encoded TLS cert with SAN IPs @@ -92,7 +93,7 @@ func TestHTTP3AdvertisedPort(t *testing.T) { HTTP3: &static.HTTP3Config{ AdvertisedPort: 8080, }, - }, nil) + }, nil, nil) require.NoError(t, err) router, err := tcprouter.NewRouter() @@ -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) diff --git a/pkg/server/server_entrypoint_tcp_test.go b/pkg/server/server_entrypoint_tcp_test.go index 342d7d9fa..3567ca47f 100644 --- a/pkg/server/server_entrypoint_tcp_test.go +++ b/pkg/server/server_entrypoint_tcp_test.go @@ -14,9 +14,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/static" - tcprouter "github.com/traefik/traefik/v2/pkg/server/router/tcp" - "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/config/static" + tcprouter "github.com/traefik/traefik/v3/pkg/server/router/tcp" + "github.com/traefik/traefik/v3/pkg/tcp" ) func TestShutdownHijacked(t *testing.T) { @@ -79,7 +79,7 @@ func testShutdown(t *testing.T, router *tcprouter.Router) { Transport: epConfig, ForwardedHeaders: &static.ForwardedHeaders{}, HTTP2: &static.HTTP2Config{}, - }, nil) + }, nil, nil) require.NoError(t, err) conn, err := startEntrypoint(entryPoint, router) @@ -164,7 +164,7 @@ func TestReadTimeoutWithoutFirstByte(t *testing.T) { Transport: epConfig, ForwardedHeaders: &static.ForwardedHeaders{}, HTTP2: &static.HTTP2Config{}, - }, nil) + }, nil, nil) require.NoError(t, err) router := &tcprouter.Router{} @@ -201,7 +201,7 @@ func TestReadTimeoutWithFirstByte(t *testing.T) { Transport: epConfig, ForwardedHeaders: &static.ForwardedHeaders{}, HTTP2: &static.HTTP2Config{}, - }, nil) + }, nil, nil) require.NoError(t, err) router := &tcprouter.Router{} diff --git a/pkg/server/server_entrypoint_udp.go b/pkg/server/server_entrypoint_udp.go index 1aa4c38c3..347b169db 100644 --- a/pkg/server/server_entrypoint_udp.go +++ b/pkg/server/server_entrypoint_udp.go @@ -8,9 +8,9 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/udp" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/udp" ) // UDPEntryPoints maps UDP entry points by their names. diff --git a/pkg/server/server_entrypoint_udp_test.go b/pkg/server/server_entrypoint_udp_test.go index 0396f434f..e5ac55086 100644 --- a/pkg/server/server_entrypoint_udp_test.go +++ b/pkg/server/server_entrypoint_udp_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/udp" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/udp" ) func TestShutdownUDPConn(t *testing.T) { diff --git a/pkg/server/service/loadbalancer/failover/failover.go b/pkg/server/service/loadbalancer/failover/failover.go index 972d38672..07cf51968 100644 --- a/pkg/server/service/loadbalancer/failover/failover.go +++ b/pkg/server/service/loadbalancer/failover/failover.go @@ -7,7 +7,7 @@ import ( "sync" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) // Failover is an http.Handler that can forward requests to the fallback handler diff --git a/pkg/server/service/loadbalancer/failover/failover_test.go b/pkg/server/service/loadbalancer/failover/failover_test.go index 9f8d38215..a2f7f89f0 100644 --- a/pkg/server/service/loadbalancer/failover/failover_test.go +++ b/pkg/server/service/loadbalancer/failover/failover_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) type responseRecorder struct { diff --git a/pkg/server/service/loadbalancer/mirror/mirror.go b/pkg/server/service/loadbalancer/mirror/mirror.go index cb77b7280..201dade9a 100644 --- a/pkg/server/service/loadbalancer/mirror/mirror.go +++ b/pkg/server/service/loadbalancer/mirror/mirror.go @@ -12,10 +12,10 @@ import ( "sync" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/healthcheck" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/healthcheck" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" + "github.com/traefik/traefik/v3/pkg/safe" ) // Mirroring is an http.Handler that can mirror requests. diff --git a/pkg/server/service/loadbalancer/mirror/mirror_test.go b/pkg/server/service/loadbalancer/mirror/mirror_test.go index eda49a960..57d815f0f 100644 --- a/pkg/server/service/loadbalancer/mirror/mirror_test.go +++ b/pkg/server/service/loadbalancer/mirror/mirror_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/safe" ) const defaultMaxBodySize int64 = -1 diff --git a/pkg/server/service/loadbalancer/wrr/wrr.go b/pkg/server/service/loadbalancer/wrr/wrr.go index ed89dfb31..7442fa3a1 100644 --- a/pkg/server/service/loadbalancer/wrr/wrr.go +++ b/pkg/server/service/loadbalancer/wrr/wrr.go @@ -8,7 +8,7 @@ import ( "sync" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) type namedHandler struct { diff --git a/pkg/server/service/loadbalancer/wrr/wrr_test.go b/pkg/server/service/loadbalancer/wrr/wrr_test.go index 7d6d6acad..e0ca68c04 100644 --- a/pkg/server/service/loadbalancer/wrr/wrr_test.go +++ b/pkg/server/service/loadbalancer/wrr/wrr_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func TestBalancer(t *testing.T) { diff --git a/pkg/server/service/managerfactory.go b/pkg/server/service/managerfactory.go index 5db06ef40..524ae01d9 100644 --- a/pkg/server/service/managerfactory.go +++ b/pkg/server/service/managerfactory.go @@ -4,12 +4,12 @@ import ( "net/http" "github.com/gorilla/mux" - "github.com/traefik/traefik/v2/pkg/api" - "github.com/traefik/traefik/v2/pkg/api/dashboard" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/api" + "github.com/traefik/traefik/v3/pkg/api/dashboard" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/safe" ) // ManagerFactory a factory of service manager. diff --git a/pkg/server/service/proxy.go b/pkg/server/service/proxy.go index 58f5e7081..b34cc0500 100644 --- a/pkg/server/service/proxy.go +++ b/pkg/server/service/proxy.go @@ -53,11 +53,7 @@ func directorBuilder(target *url.URL, passHostHeader bool) func(req *http.Reques outReq.ProtoMajor = 1 outReq.ProtoMinor = 1 - if _, ok := outReq.Header["User-Agent"]; !ok { - outReq.Header.Set("User-Agent", "") - } - - // Do not pass client Host header unless PassHostHeader is set. + // Do not pass client Host header unless optsetter PassHostHeader is set. if !passHostHeader { outReq.Host = outReq.URL.Host } diff --git a/pkg/server/service/proxy_test.go b/pkg/server/service/proxy_test.go index 8abc51cd2..8bea51829 100644 --- a/pkg/server/service/proxy_test.go +++ b/pkg/server/service/proxy_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) type staticTransport struct { diff --git a/pkg/server/service/roundtripper.go b/pkg/server/service/roundtripper.go index a4c01ef06..d7ab54c7a 100644 --- a/pkg/server/service/roundtripper.go +++ b/pkg/server/service/roundtripper.go @@ -16,8 +16,8 @@ import ( "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" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" "golang.org/x/net/http2" ) diff --git a/pkg/server/service/roundtripper_test.go b/pkg/server/service/roundtripper_test.go index d11e2f693..971604d92 100644 --- a/pkg/server/service/roundtripper_test.go +++ b/pkg/server/service/roundtripper_test.go @@ -21,8 +21,8 @@ import ( "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" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + traefiktls "github.com/traefik/traefik/v3/pkg/tls" ) func Int32(i int32) *int32 { diff --git a/pkg/server/service/service.go b/pkg/server/service/service.go index d4295b9c6..9883d79a2 100644 --- a/pkg/server/service/service.go +++ b/pkg/server/service/service.go @@ -14,19 +14,19 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/healthcheck" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/metrics" - "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" - metricsMiddle "github.com/traefik/traefik/v2/pkg/middlewares/metrics" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/server/cookie" - "github.com/traefik/traefik/v2/pkg/server/provider" - "github.com/traefik/traefik/v2/pkg/server/service/loadbalancer/failover" - "github.com/traefik/traefik/v2/pkg/server/service/loadbalancer/mirror" - "github.com/traefik/traefik/v2/pkg/server/service/loadbalancer/wrr" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/healthcheck" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/metrics" + "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" + metricsMiddle "github.com/traefik/traefik/v3/pkg/middlewares/metrics" + "github.com/traefik/traefik/v3/pkg/safe" + "github.com/traefik/traefik/v3/pkg/server/cookie" + "github.com/traefik/traefik/v3/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/failover" + "github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/mirror" + "github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/wrr" ) const defaultMaxBodySize int64 = -1 diff --git a/pkg/server/service/service_test.go b/pkg/server/service/service_test.go index 36501cace..8b5ff946b 100644 --- a/pkg/server/service/service_test.go +++ b/pkg/server/service/service_test.go @@ -2,17 +2,20 @@ package service import ( "context" + "io" "net/http" "net/http/httptest" + "net/http/httptrace" + "net/textproto" "strings" "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" - "github.com/traefik/traefik/v2/pkg/server/provider" - "github.com/traefik/traefik/v2/pkg/testhelpers" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/testhelpers" ) func TestGetLoadBalancer(t *testing.T) { @@ -86,24 +89,34 @@ func TestGetLoadBalancerServiceHandler(t *testing.T) { server1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-From", "first") })) - defer server1.Close() + t.Cleanup(server1.Close) server2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-From", "second") })) - defer server2.Close() + t.Cleanup(server2.Close) serverPassHost := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-From", "passhost") assert.Equal(t, "callme", r.Host) })) - defer serverPassHost.Close() + t.Cleanup(serverPassHost.Close) serverPassHostFalse := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-From", "passhostfalse") assert.NotEqual(t, "callme", r.Host) })) - defer serverPassHostFalse.Close() + t.Cleanup(serverPassHostFalse.Close) + + hasNoUserAgent := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Empty(t, r.Header.Get("User-Agent")) + })) + t.Cleanup(hasNoUserAgent.Close) + + hasUserAgent := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "foobar", r.Header.Get("User-Agent")) + })) + t.Cleanup(hasUserAgent.Close) type ExpectedResult struct { StatusCode int @@ -119,6 +132,7 @@ func TestGetLoadBalancerServiceHandler(t *testing.T) { service *dynamic.ServersLoadBalancer responseModifier func(*http.Response) error cookieRawValue string + userAgent string expected []ExpectedResult }{ @@ -256,6 +270,39 @@ func TestGetLoadBalancerServiceHandler(t *testing.T) { }, }, }, + { + desc: "No user-agent", + serviceName: "test", + service: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: hasNoUserAgent.URL, + }, + }, + }, + expected: []ExpectedResult{ + { + StatusCode: http.StatusOK, + }, + }, + }, + { + desc: "Custom user-agent", + serviceName: "test", + userAgent: "foobar", + service: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: hasUserAgent.URL, + }, + }, + }, + expected: []ExpectedResult{ + { + StatusCode: http.StatusOK, + }, + }, + }, } for _, test := range testCases { @@ -268,6 +315,12 @@ func TestGetLoadBalancerServiceHandler(t *testing.T) { assert.NotNil(t, handler) req := testhelpers.MustNewRequest(http.MethodGet, "http://callme", nil) + assert.Equal(t, "", req.Header.Get("User-Agent")) + + if test.userAgent != "" { + req.Header.Set("User-Agent", test.userAgent) + } + if test.cookieRawValue != "" { req.Header.Set("Cookie", test.cookieRawValue) } @@ -306,6 +359,101 @@ func TestGetLoadBalancerServiceHandler(t *testing.T) { } } +// This test is an adapted version of net/http/httputil.Test1xxResponses test. +func Test1xxResponses(t *testing.T) { + sm := NewManager(nil, nil, nil, &RoundTripperManager{ + roundTrippers: map[string]http.RoundTripper{ + "default@internal": http.DefaultTransport, + }, + }) + + backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + h := w.Header() + h.Add("Link", "; rel=preload; as=style") + h.Add("Link", "; rel=preload; as=script") + w.WriteHeader(http.StatusEarlyHints) + + h.Add("Link", "; rel=preload; as=script") + w.WriteHeader(http.StatusProcessing) + + _, _ = w.Write([]byte("Hello")) + })) + t.Cleanup(backend.Close) + + info := &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: backend.URL, + }, + }, + }, + }, + } + + handler, err := sm.getLoadBalancerServiceHandler(context.Background(), "foobar", info) + assert.Nil(t, err) + + frontend := httptest.NewServer(handler) + t.Cleanup(frontend.Close) + frontendClient := frontend.Client() + + checkLinkHeaders := func(t *testing.T, expected, got []string) { + t.Helper() + + if len(expected) != len(got) { + t.Errorf("Expected %d link headers; got %d", len(expected), len(got)) + } + + for i := range expected { + if i >= len(got) { + t.Errorf("Expected %q link header; got nothing", expected[i]) + + continue + } + + if expected[i] != got[i] { + t.Errorf("Expected %q link header; got %q", expected[i], got[i]) + } + } + } + + var respCounter uint8 + trace := &httptrace.ClientTrace{ + Got1xxResponse: func(code int, header textproto.MIMEHeader) error { + switch code { + case http.StatusEarlyHints: + checkLinkHeaders(t, []string{"; rel=preload; as=style", "; rel=preload; as=script"}, header["Link"]) + case http.StatusProcessing: + checkLinkHeaders(t, []string{"; rel=preload; as=style", "; rel=preload; as=script", "; rel=preload; as=script"}, header["Link"]) + default: + t.Error("Unexpected 1xx response") + } + + respCounter++ + + return nil + }, + } + req, _ := http.NewRequestWithContext(httptrace.WithClientTrace(context.Background(), trace), http.MethodGet, frontend.URL, nil) + + res, err := frontendClient.Do(req) + assert.Nil(t, err) + + defer res.Body.Close() + + if respCounter != 2 { + t.Errorf("Expected 2 1xx responses; got %d", respCounter) + } + checkLinkHeaders(t, []string{"; rel=preload; as=style", "; rel=preload; as=script", "; rel=preload; as=script"}, res.Header["Link"]) + + body, _ := io.ReadAll(res.Body) + if string(body) != "Hello" { + t.Errorf("Read body %q; want Hello", body) + } +} + func TestManager_Build(t *testing.T) { testCases := []struct { desc string diff --git a/pkg/server/service/smart_roundtripper.go b/pkg/server/service/smart_roundtripper.go index 5643e60ed..3b88b499a 100644 --- a/pkg/server/service/smart_roundtripper.go +++ b/pkg/server/service/smart_roundtripper.go @@ -6,7 +6,7 @@ import ( "net/http" "time" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" "golang.org/x/net/http/httpguts" "golang.org/x/net/http2" ) diff --git a/pkg/server/service/tcp/service.go b/pkg/server/service/tcp/service.go index d099af501..bbc19b8cd 100644 --- a/pkg/server/service/tcp/service.go +++ b/pkg/server/service/tcp/service.go @@ -9,23 +9,25 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/server/provider" - "github.com/traefik/traefik/v2/pkg/tcp" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/tcp" ) // 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..cb94becb4 100644 --- a/pkg/server/service/tcp/service_test.go +++ b/pkg/server/service/tcp/service_test.go @@ -6,9 +6,10 @@ import ( "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" - "github.com/traefik/traefik/v2/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/server/provider" + "github.com/traefik/traefik/v3/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/server/service/udp/service.go b/pkg/server/service/udp/service.go index 7d15c19ff..1772c1954 100644 --- a/pkg/server/service/udp/service.go +++ b/pkg/server/service/udp/service.go @@ -9,10 +9,10 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/server/provider" - "github.com/traefik/traefik/v2/pkg/udp" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/udp" ) // Manager handles UDP services creation. diff --git a/pkg/server/service/udp/service_test.go b/pkg/server/service/udp/service_test.go index 335a13a24..6517c66a1 100644 --- a/pkg/server/service/udp/service_test.go +++ b/pkg/server/service/udp/service_test.go @@ -6,9 +6,9 @@ import ( "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" - "github.com/traefik/traefik/v2/pkg/server/provider" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/runtime" + "github.com/traefik/traefik/v3/pkg/server/provider" ) func TestManager_BuildUDP(t *testing.T) { diff --git a/pkg/tcp/dialer.go b/pkg/tcp/dialer.go new file mode 100644 index 000000000..267d1b05b --- /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/v3/pkg/config/dynamic" + traefiktls "github.com/traefik/traefik/v3/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..603f012b5 --- /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/v3/pkg/config/dynamic" + traefiktls "github.com/traefik/traefik/v3/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..8f7e05745 100644 --- a/pkg/tcp/proxy.go +++ b/pkg/tcp/proxy.go @@ -10,52 +10,42 @@ import ( "github.com/pires/go-proxyproto" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) // 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 TCP connection") // needed because of e.g. server.trackedConnection defer conn.Close() connBackend, err := p.dialBackend() if err != nil { - log.Error().Err(err).Msg("Error while connecting to backend") + log.Error().Err(err).Msg("Error while dialing backend") return } @@ -66,7 +56,7 @@ func (p *Proxy) ServeTCP(conn WriteCloser) { if p.proxyProtocol != nil && p.proxyProtocol.Version > 0 && p.proxyProtocol.Version < 3 { header := proxyproto.HeaderProxyFromAddrs(byte(p.proxyProtocol.Version), conn.RemoteAddr(), conn.LocalAddr()) if _, err := header.WriteTo(connBackend); err != nil { - log.Error().Err(err).Msg("Error while writing proxy protocol headers to backend connection") + log.Error().Err(err).Msg("Error while writing TCP proxy protocol headers to backend connection") return } } @@ -80,30 +70,22 @@ func (p *Proxy) ServeTCP(conn WriteCloser) { // This allows to not report an RST packet sent by the peer as an error, // as it is an abrupt but possible end for the TCP session if isReadConnResetError(err) { - log.Debug().Err(err).Msg("Error during connection") + log.Debug().Err(err).Msg("Error while handling TCP connection") } else { - log.Error().Err(err).Msg("Error during connection") + log.Error().Err(err).Msg("Error while handling TCP connection") } } <-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) { @@ -119,16 +101,16 @@ func (p Proxy) connCopy(dst, src WriteCloser, errCh chan error) { // In that case, logging the error is superfluous, // as in the first place we should not have needed to call CloseWrite. if !isSocketNotConnectedError(errClose) { - log.Debug().Err(errClose).Msg("Error while terminating connection") + log.Debug().Err(errClose).Msg("Error while terminating TCP connection") } 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") + log.Debug().Err(err).Msg("Error while setting TCP connection deadline") } } } diff --git a/pkg/tcp/proxy_test.go b/pkg/tcp/proxy_test.go index fb8cad1dd..21176300c 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" @@ -12,7 +11,7 @@ import ( "github.com/pires/go-proxyproto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func fakeRedis(t *testing.T, listener net.Listener) { @@ -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/pkg/tcp/switcher.go b/pkg/tcp/switcher.go index 557f663a1..0b62bab8c 100644 --- a/pkg/tcp/switcher.go +++ b/pkg/tcp/switcher.go @@ -1,7 +1,7 @@ package tcp import ( - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/safe" ) // HandlerSwitcher is a TCP handler switcher. diff --git a/pkg/testhelpers/config.go b/pkg/testhelpers/config.go index ab810e4f0..3f379f6bd 100644 --- a/pkg/testhelpers/config.go +++ b/pkg/testhelpers/config.go @@ -1,7 +1,7 @@ package testhelpers import ( - "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) // BuildConfiguration is a helper to create a configuration. diff --git a/pkg/tls/certificate_store.go b/pkg/tls/certificate_store.go index 353efc95c..20bdb317d 100644 --- a/pkg/tls/certificate_store.go +++ b/pkg/tls/certificate_store.go @@ -10,7 +10,7 @@ import ( "github.com/patrickmn/go-cache" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/safe" ) // CertificateStore store for dynamic certificates. diff --git a/pkg/tls/certificate_store_test.go b/pkg/tls/certificate_store_test.go index a80516142..cd08af2c5 100644 --- a/pkg/tls/certificate_store_test.go +++ b/pkg/tls/certificate_store_test.go @@ -10,7 +10,7 @@ import ( "github.com/patrickmn/go-cache" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/safe" ) func TestGetBestCertificate(t *testing.T) { diff --git a/pkg/tls/tls.go b/pkg/tls/tls.go index fc97e265d..93a9cab36 100644 --- a/pkg/tls/tls.go +++ b/pkg/tls/tls.go @@ -1,6 +1,6 @@ package tls -import "github.com/traefik/traefik/v2/pkg/types" +import "github.com/traefik/traefik/v3/pkg/types" const certificateHeader = "-----BEGIN CERTIFICATE-----\n" diff --git a/pkg/tls/tlsmanager.go b/pkg/tls/tlsmanager.go index 2fd249a87..790745d98 100644 --- a/pkg/tls/tlsmanager.go +++ b/pkg/tls/tlsmanager.go @@ -12,9 +12,9 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/challenge/tlsalpn01" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/tls/generate" - "github.com/traefik/traefik/v2/pkg/types" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/tls/generate" + "github.com/traefik/traefik/v3/pkg/types" ) const ( @@ -224,24 +224,43 @@ func (m *Manager) Get(storeName, configName string) (*tls.Config, error) { return tlsConfig, err } -// GetCertificates returns all stored certificates. -func (m *Manager) GetCertificates() []*x509.Certificate { +// GetServerCertificates returns all certificates from the default store, +// as well as the user-defined default certificate (if it exists). +func (m *Manager) GetServerCertificates() []*x509.Certificate { var certificates []*x509.Certificate - // We iterate over all the certificates. - for _, store := range m.stores { - if store.DynamicCerts != nil && store.DynamicCerts.Get() != nil { - for _, cert := range store.DynamicCerts.Get().(map[string]*tls.Certificate) { - x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) - if err != nil { - continue - } + // The default store is the only relevant, because it is the only one configurable. + defaultStore, ok := m.stores[DefaultTLSStoreName] + if !ok || defaultStore == nil { + return certificates + } - certificates = append(certificates, x509Cert) + // We iterate over all the certificates. + if defaultStore.DynamicCerts != nil && defaultStore.DynamicCerts.Get() != nil { + for _, cert := range defaultStore.DynamicCerts.Get().(map[string]*tls.Certificate) { + x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + continue } + + certificates = append(certificates, x509Cert) } } + if defaultStore.DefaultCertificate != nil { + x509Cert, err := x509.ParseCertificate(defaultStore.DefaultCertificate.Certificate[0]) + if err != nil { + return certificates + } + + // Excluding the generated Traefik default certificate. + if x509Cert.Subject.CommonName == generate.DefaultDomain { + return certificates + } + + certificates = append(certificates, x509Cert) + } + return certificates } diff --git a/pkg/tls/zz_generated.deepcopy.go b/pkg/tls/zz_generated.deepcopy.go index c85405a37..6523c97b1 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 @@ -30,7 +30,7 @@ THE SOFTWARE. package tls import ( - types "github.com/traefik/traefik/v2/pkg/types" + types "github.com/traefik/traefik/v3/pkg/types" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. diff --git a/pkg/tracing/datadog/datadog.go b/pkg/tracing/datadog/datadog.go index 1e9969e37..f1a334f22 100644 --- a/pkg/tracing/datadog/datadog.go +++ b/pkg/tracing/datadog/datadog.go @@ -7,7 +7,7 @@ import ( "github.com/opentracing/opentracing-go" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/logs" ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer" datadog "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" ) @@ -18,6 +18,7 @@ const Name = "datadog" // Config provides configuration settings for a datadog tracer. type Config struct { LocalAgentHostPort string `description:"Sets the Datadog Agent host:port." json:"localAgentHostPort,omitempty" toml:"localAgentHostPort,omitempty" yaml:"localAgentHostPort,omitempty"` + LocalAgentSocket string `description:"Sets the socket for the Datadog Agent." json:"localAgentSocket,omitempty" toml:"localAgentSocket,omitempty" yaml:"localAgentSocket,omitempty"` GlobalTags map[string]string `description:"Sets a list of key:value tags on all spans." json:"globalTags,omitempty" toml:"globalTags,omitempty" yaml:"globalTags,omitempty" export:"true"` Debug bool `description:"Enables Datadog debug." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"` PrioritySampling bool `description:"Enables priority sampling. When using distributed tracing, this option must be enabled in order to get all the parts of a distributed trace sampled." json:"prioritySampling,omitempty" toml:"prioritySampling,omitempty" yaml:"prioritySampling,omitempty" export:"true"` @@ -47,7 +48,6 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error logger := log.With().Str(logs.TracingProviderName, Name).Logger() opts := []datadog.StartOption{ - datadog.WithAgentAddr(c.LocalAgentHostPort), datadog.WithServiceName(serviceName), datadog.WithDebugMode(c.Debug), datadog.WithPropagator(datadog.NewPropagator(&datadog.PropagatorConfig{ @@ -59,6 +59,12 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error datadog.WithLogger(logs.NewDatadogLogger(logger)), } + if c.LocalAgentSocket != "" { + opts = append(opts, datadog.WithUDS(c.LocalAgentSocket)) + } else { + opts = append(opts, datadog.WithAgentAddr(c.LocalAgentHostPort)) + } + for k, v := range c.GlobalTags { opts = append(opts, datadog.WithGlobalTag(k, v)) } diff --git a/pkg/tracing/elastic/elastic.go b/pkg/tracing/elastic/elastic.go index 967f5fcb0..383cca2bd 100644 --- a/pkg/tracing/elastic/elastic.go +++ b/pkg/tracing/elastic/elastic.go @@ -6,8 +6,8 @@ import ( "github.com/opentracing/opentracing-go" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/version" "go.elastic.co/apm" "go.elastic.co/apm/module/apmot" "go.elastic.co/apm/transport" diff --git a/pkg/tracing/haystack/haystack.go b/pkg/tracing/haystack/haystack.go index 9c64dd36b..6e460dcfb 100644 --- a/pkg/tracing/haystack/haystack.go +++ b/pkg/tracing/haystack/haystack.go @@ -8,7 +8,7 @@ import ( "github.com/ExpediaDotCom/haystack-client-go" "github.com/opentracing/opentracing-go" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/logs" ) // Name sets the name of this tracer. diff --git a/pkg/tracing/instana/instana.go b/pkg/tracing/instana/instana.go index 39c664468..edb2ee14e 100644 --- a/pkg/tracing/instana/instana.go +++ b/pkg/tracing/instana/instana.go @@ -6,7 +6,7 @@ import ( instana "github.com/instana/go-sensor" "github.com/opentracing/opentracing-go" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/logs" ) // Name sets the name of this tracer. diff --git a/pkg/tracing/jaeger/jaeger.go b/pkg/tracing/jaeger/jaeger.go index 206c206de..64eeb8e18 100644 --- a/pkg/tracing/jaeger/jaeger.go +++ b/pkg/tracing/jaeger/jaeger.go @@ -6,7 +6,7 @@ import ( "github.com/opentracing/opentracing-go" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/logs" + "github.com/traefik/traefik/v3/pkg/logs" jaegercli "github.com/uber/jaeger-client-go" jaegercfg "github.com/uber/jaeger-client-go/config" "github.com/uber/jaeger-client-go/zipkin" diff --git a/pkg/tracing/opentelemetry/opentelemetry.go b/pkg/tracing/opentelemetry/opentelemetry.go index d42770ae3..af12c67a3 100644 --- a/pkg/tracing/opentelemetry/opentelemetry.go +++ b/pkg/tracing/opentelemetry/opentelemetry.go @@ -8,15 +8,17 @@ import ( "github.com/opentracing/opentracing-go" "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/types" - "github.com/traefik/traefik/v2/pkg/version" + "github.com/traefik/traefik/v3/pkg/types" + "github.com/traefik/traefik/v3/pkg/version" "go.opentelemetry.io/otel" oteltracer "go.opentelemetry.io/otel/bridge/opentracing" "go.opentelemetry.io/otel/exporters/otlp/otlptrace" "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..40fcca159 100644 --- a/pkg/tracing/opentelemetry/opentelemetry_test.go +++ b/pkg/tracing/opentelemetry/opentelemetry_test.go @@ -9,18 +9,48 @@ import ( "net/http/httptest" "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - mtracing "github.com/traefik/traefik/v2/pkg/middlewares/tracing" - "github.com/traefik/traefik/v2/pkg/tracing" + mtracing "github.com/traefik/traefik/v3/pkg/middlewares/tracing" + "github.com/traefik/traefik/v3/pkg/tracing" "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) + } + }) + } } diff --git a/pkg/types/metrics.go b/pkg/types/metrics.go index ddcf71d96..2d8b4114d 100644 --- a/pkg/types/metrics.go +++ b/pkg/types/metrics.go @@ -13,19 +13,19 @@ 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"` } // Prometheus can contain specific configuration used by the Prometheus Metrics exporter. type Prometheus struct { - Buckets []float64 `description:"Buckets for latency metrics." json:"buckets,omitempty" toml:"buckets,omitempty" yaml:"buckets,omitempty" export:"true"` - 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"` - EntryPoint string `description:"EntryPoint" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty" export:"true"` - ManualRouting bool `description:"Manual routing" json:"manualRouting,omitempty" toml:"manualRouting,omitempty" yaml:"manualRouting,omitempty" export:"true"` + Buckets []float64 `description:"Buckets for latency metrics." json:"buckets,omitempty" toml:"buckets,omitempty" yaml:"buckets,omitempty" export:"true"` + 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"` + EntryPoint string `description:"EntryPoint" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty" export:"true"` + ManualRouting bool `description:"Manual routing" json:"manualRouting,omitempty" toml:"manualRouting,omitempty" yaml:"manualRouting,omitempty" export:"true"` + HeaderLabels map[string]string `description:"Defines the extra labels for the requests_total metrics, and for each of them, the request header containing the value for this label." json:"headerLabels,omitempty" toml:"headerLabels,omitempty" yaml:"headerLabels,omitempty" export:"true"` } // SetDefaults sets the default values. @@ -83,30 +83,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"` 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 diff --git a/pkg/udp/proxy.go b/pkg/udp/proxy.go index 31f64a5ce..bb3644a63 100644 --- a/pkg/udp/proxy.go +++ b/pkg/udp/proxy.go @@ -20,14 +20,14 @@ func NewProxy(address string) (*Proxy, error) { // ServeUDP implements the Handler interface. func (p *Proxy) ServeUDP(conn *Conn) { - log.Debug().Msgf("Handling connection from %s to %s", conn.rAddr, p.target) + log.Debug().Msgf("Handling UDP stream from %s to %s", conn.rAddr, p.target) // needed because of e.g. server.trackedConnection defer conn.Close() connBackend, err := net.Dial("udp", p.target) if err != nil { - log.Error().Err(err).Msg("Error while connecting to backend") + log.Error().Err(err).Msg("Error while dialing backend") return } @@ -40,7 +40,7 @@ func (p *Proxy) ServeUDP(conn *Conn) { err = <-errChan if err != nil { - log.Error().Err(err).Msg("Error while serving UDP") + log.Error().Err(err).Msg("Error while handling UDP stream") } <-errChan @@ -55,6 +55,6 @@ func connCopy(dst io.WriteCloser, src io.Reader, errCh chan error) { errCh <- err if err := dst.Close(); err != nil { - log.Debug().Err(err).Msg("Error while terminating connection") + log.Debug().Err(err).Msg("Error while terminating UDP stream") } } diff --git a/pkg/udp/switcher.go b/pkg/udp/switcher.go index d198a3587..bb596be04 100644 --- a/pkg/udp/switcher.go +++ b/pkg/udp/switcher.go @@ -1,7 +1,7 @@ package udp import ( - "github.com/traefik/traefik/v2/pkg/safe" + "github.com/traefik/traefik/v3/pkg/safe" ) // HandlerSwitcher is a switcher implementation of the Handler interface. diff --git a/script/binary b/script/binary index 3a3e94b61..c1de7c9bb 100755 --- a/script/binary +++ b/script/binary @@ -24,7 +24,7 @@ fi # shellcheck disable=SC2086 # shellcheck disable=SC2048 CGO_ENABLED=0 GOGC=off go build ${FLAGS[*]} -ldflags "-s -w \ - -X github.com/traefik/traefik/v2/pkg/version.Version=$VERSION \ - -X github.com/traefik/traefik/v2/pkg/version.Codename=$CODENAME \ - -X github.com/traefik/traefik/v2/pkg/version.BuildDate=$DATE" \ + -X github.com/traefik/traefik/v3/pkg/version.Version=$VERSION \ + -X github.com/traefik/traefik/v3/pkg/version.Codename=$CODENAME \ + -X github.com/traefik/traefik/v3/pkg/version.BuildDate=$DATE" \ -installsuffix nocgo -o dist/traefik ./cmd/traefik diff --git a/script/code-gen.sh b/script/code-gen.sh index de705c814..905ac67cb 100755 --- a/script/code-gen.sh +++ b/script/code-gen.sh @@ -4,7 +4,7 @@ set -e -o pipefail PROJECT_MODULE="github.com/traefik/traefik" -MODULE_VERSION="v2" +MODULE_VERSION="v3" IMAGE_NAME="kubernetes-codegen:latest" CURRENT_DIR="$(pwd)" @@ -18,28 +18,40 @@ docker build --build-arg KUBE_VERSION=v0.20.2 \ "." echo "Generating Traefik clientSet code ..." -cmd="/go/src/k8s.io/code-generator/generate-groups.sh all ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/provider/kubernetes/crd/generated ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/provider/kubernetes/crd traefik:v1alpha1 --go-header-file=/go/src/${PROJECT_MODULE}/script/boilerplate.go.tmpl" docker run --rm \ -v "${CURRENT_DIR}:/go/src/${PROJECT_MODULE}" \ -w "/go/src/${PROJECT_MODULE}" \ - "${IMAGE_NAME}" ${cmd} + "${IMAGE_NAME}" \ + /go/src/k8s.io/code-generator/generate-groups.sh all \ + ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/provider/kubernetes/crd/generated \ + ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/provider/kubernetes/crd \ + "traefikio:v1alpha1" \ + --go-header-file=/go/src/${PROJECT_MODULE}/script/boilerplate.go.tmpl echo "Generating DeepCopy code ..." -cmd="deepcopy-gen --input-dirs ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/config/dynamic --input-dirs ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/tls --input-dirs ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/types --output-package ${PROJECT_MODULE}/${MODULE_VERSION} -O zz_generated.deepcopy --go-header-file=/go/src/${PROJECT_MODULE}/script/boilerplate.go.tmpl" + docker run --rm \ -v "${CURRENT_DIR}:/go/src/${PROJECT_MODULE}" \ -w "/go/src/${PROJECT_MODULE}" \ - "${IMAGE_NAME}" ${cmd} + "${IMAGE_NAME}" \ + deepcopy-gen \ + --input-dirs ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/config/dynamic \ + --input-dirs ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/tls \ + --input-dirs ${PROJECT_MODULE}/${MODULE_VERSION}/pkg/types \ + --output-package ${PROJECT_MODULE}/${MODULE_VERSION} -O zz_generated.deepcopy \ + --go-header-file=/go/src/${PROJECT_MODULE}/script/boilerplate.go.tmpl echo "Generating the CRD definitions for the documentation ..." -cmd="controller-gen crd:crdVersions=v1 paths=./pkg/provider/kubernetes/crd/traefik/v1alpha1/... output:dir=./docs/content/reference/dynamic-configuration/" docker run --rm \ -v "${CURRENT_DIR}:/go/src/${PROJECT_MODULE}" \ -w "/go/src/${PROJECT_MODULE}" \ - "${IMAGE_NAME}" ${cmd} + "${IMAGE_NAME}" \ + controller-gen crd:crdVersions=v1 \ + paths={./pkg/provider/kubernetes/crd/traefikio/v1alpha1/...} \ + output:dir=./docs/content/reference/dynamic-configuration/ echo "Concatenate the CRD definitions for publication and integration tests ..." -cat "${CURRENT_DIR}"/docs/content/reference/dynamic-configuration/traefik.containo.us_*.yaml > "${CURRENT_DIR}"/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +cat "${CURRENT_DIR}"/docs/content/reference/dynamic-configuration/traefik.io_*.yaml > "${CURRENT_DIR}"/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml cp -f "${CURRENT_DIR}"/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml "${CURRENT_DIR}"/integration/fixtures/k8s/01-traefik-crd.yml cp -r "${CURRENT_DIR}/${MODULE_VERSION}"/* "${CURRENT_DIR}" diff --git a/script/codegen.Dockerfile b/script/codegen.Dockerfile index ac2815fb5..d946b2e16 100644 --- a/script/codegen.Dockerfile +++ b/script/codegen.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19 +FROM golang:1.20 ARG USER=$USER ARG UID=$UID diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index 9db9d689c..189f8c451 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v2.9.6 +# example new bugfix v2.9.9 CurrentRef = "v2.9" -PreviousRef = "v2.9.5" +PreviousRef = "v2.9.8" BaseBranch = "v2.9" -FutureCurrentRefName = "v2.9.6" +FutureCurrentRefName = "v2.9.9" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/webui/package.json b/webui/package.json index 1f88c6a52..23e2be3d4 100644 --- a/webui/package.json +++ b/webui/package.json @@ -3,7 +3,7 @@ "version": "2.0.0", "description": "Traefik UI", "productName": "Traefik", - "cordovaId": "us.containo.traefik", + "cordovaId": "io.traefik.traefik", "private": true, "scripts": { "transfer": "node dev/scripts/transfer.js", 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)" > -