From 72e67bf4e9e4991937e7b8ac378bb77ddfdd1e46 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 28 Aug 2019 14:52:05 +0200 Subject: [PATCH 01/37] Rest provider icon in the webui --- webui/src/statics/providers/{rest-api.svg => rest.svg} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename webui/src/statics/providers/{rest-api.svg => rest.svg} (100%) diff --git a/webui/src/statics/providers/rest-api.svg b/webui/src/statics/providers/rest.svg similarity index 100% rename from webui/src/statics/providers/rest-api.svg rename to webui/src/statics/providers/rest.svg From b113972bcf6ab323b64f1de892c31d571291a906 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 29 Aug 2019 09:56:04 +0200 Subject: [PATCH 02/37] Fix trailing slash with check new version --- go.mod | 2 +- go.sum | 4 ++-- pkg/version/version.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index d3304053d..faffae895 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( github.com/go-check/check v0.0.0-00010101000000-000000000000 github.com/go-kit/kit v0.9.0 github.com/golang/protobuf v1.3.2 - github.com/google/go-github/v27 v27.0.4 + github.com/google/go-github/v28 v28.0.0 github.com/googleapis/gnostic v0.1.0 // indirect github.com/gorilla/mux v1.6.2 github.com/gorilla/websocket v1.4.0 diff --git a/go.sum b/go.sum index cbaba2ca0..8932bc8e5 100644 --- a/go.sum +++ b/go.sum @@ -218,8 +218,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-github/v27 v27.0.4 h1:N/EEqsvJLgqTbepTiMBz+12KhwLovv6YvwpRezd+4Fg= -github.com/google/go-github/v27 v27.0.4/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= +github.com/google/go-github/v28 v28.0.0 h1:+UjHI4+1W/vsXR4jJBWt0ZA74XHbvt5yBAvsf1M3bgM= +github.com/google/go-github/v28 v28.0.0/go.mod h1:+5GboIspo7F0NG2qsvfYh7en6F3EK37uyqv+c35AR3s= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= diff --git a/pkg/version/version.go b/pkg/version/version.go index 478c4f132..c208f650e 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -6,7 +6,7 @@ import ( "net/url" "github.com/containous/traefik/v2/pkg/log" - "github.com/google/go-github/v27/github" + "github.com/google/go-github/v28/github" "github.com/gorilla/mux" goversion "github.com/hashicorp/go-version" "github.com/unrolled/render" @@ -54,7 +54,7 @@ func CheckNewVersion() { return } client := github.NewClient(nil) - updateURL, err := url.Parse("https://update.traefik.io") + updateURL, err := url.Parse("https://update.traefik.io/") if err != nil { log.Warnf("Error checking new version: %s", err) return From 38508f9a9cc072dbbac2298f5ede9a3f8aa7d9b7 Mon Sep 17 00:00:00 2001 From: Julien Salleyron Date: Thu, 29 Aug 2019 10:28:05 +0200 Subject: [PATCH 03/37] Fix recovered panic when websocket is mirrored --- .../service/loadbalancer/mirror/mirror.go | 13 +++-- .../loadbalancer/mirror/mirror_test.go | 54 +++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/pkg/server/service/loadbalancer/mirror/mirror.go b/pkg/server/service/loadbalancer/mirror/mirror.go index 593f20858..feba0d343 100644 --- a/pkg/server/service/loadbalancer/mirror/mirror.go +++ b/pkg/server/service/loadbalancer/mirror/mirror.go @@ -1,8 +1,10 @@ package mirror import ( + "bufio" "context" "errors" + "net" "net/http" "sync" @@ -75,7 +77,7 @@ func (m *Mirroring) ServeHTTP(rw http.ResponseWriter, req *http.Request) { // AddMirror adds an httpHandler to mirror to. func (m *Mirroring) AddMirror(handler http.Handler, percent int) error { - if percent < 0 || percent >= 100 { + if percent < 0 || percent > 100 { return errors.New("percent must be between 0 and 100") } m.mirrorHandlers = append(m.mirrorHandlers, &mirrorHandler{Handler: handler, percent: percent}) @@ -84,6 +86,12 @@ func (m *Mirroring) AddMirror(handler http.Handler, percent int) error { type blackholeResponseWriter struct{} +func (b blackholeResponseWriter) Flush() {} + +func (b blackholeResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + return nil, nil, errors.New("you can hijack connection on blackholeResponseWriter") +} + func (b blackholeResponseWriter) Header() http.Header { return http.Header{} } @@ -92,8 +100,7 @@ func (b blackholeResponseWriter) Write(bytes []byte) (int, error) { return len(bytes), nil } -func (b blackholeResponseWriter) WriteHeader(statusCode int) { -} +func (b blackholeResponseWriter) WriteHeader(statusCode int) {} type contextStopPropagation struct { context.Context diff --git a/pkg/server/service/loadbalancer/mirror/mirror_test.go b/pkg/server/service/loadbalancer/mirror/mirror_test.go index fb2c516c5..f223d72fd 100644 --- a/pkg/server/service/loadbalancer/mirror/mirror_test.go +++ b/pkg/server/service/loadbalancer/mirror/mirror_test.go @@ -76,4 +76,58 @@ func TestInvalidPercent(t *testing.T) { err = mirror.AddMirror(nil, 101) assert.Error(t, err) + + err = mirror.AddMirror(nil, 100) + assert.NoError(t, err) + + err = mirror.AddMirror(nil, 0) + assert.NoError(t, err) +} + +func TestHijack(t *testing.T) { + handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.WriteHeader(http.StatusOK) + }) + pool := safe.NewPool(context.Background()) + mirror := New(handler, pool) + + var mirrorRequest bool + err := mirror.AddMirror(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + hijacker, ok := rw.(http.Hijacker) + assert.Equal(t, true, ok) + + _, _, err := hijacker.Hijack() + assert.Error(t, err) + mirrorRequest = true + }), 100) + assert.NoError(t, err) + + mirror.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest(http.MethodGet, "/", nil)) + + pool.Stop() + assert.Equal(t, true, mirrorRequest) +} + +func TestFlush(t *testing.T) { + handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.WriteHeader(http.StatusOK) + }) + pool := safe.NewPool(context.Background()) + mirror := New(handler, pool) + + var mirrorRequest bool + err := mirror.AddMirror(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + hijacker, ok := rw.(http.Flusher) + assert.Equal(t, true, ok) + + hijacker.Flush() + + mirrorRequest = true + }), 100) + assert.NoError(t, err) + + mirror.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest(http.MethodGet, "/", nil)) + + pool.Stop() + assert.Equal(t, true, mirrorRequest) } From df0dd2f5e6b8f3ede8943828f494c353e30be82e Mon Sep 17 00:00:00 2001 From: Julien Salleyron Date: Thu, 29 Aug 2019 12:38:04 +0200 Subject: [PATCH 04/37] Add errors about unknown entryPoint in runtime api --- integration/fixtures/router_errors.toml | 5 +++++ integration/simple_test.go | 4 ++++ pkg/config/runtime/runtime_http.go | 12 +++++++++++- pkg/config/runtime/runtime_http_test.go | 3 ++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/integration/fixtures/router_errors.toml b/integration/fixtures/router_errors.toml index 335339e2b..3e9a75f29 100644 --- a/integration/fixtures/router_errors.toml +++ b/integration/fixtures/router_errors.toml @@ -17,6 +17,11 @@ ## dynamic configuration ## [http.routers] + [http.routers.router3] + entrypoints=["unknown-entrypoint"] + service = "service1" + rule = "Host(`mydomain.com`)" + [http.routers.router4] service = "service1" rule = "Host(`snitest.net`)" diff --git a/integration/simple_test.go b/integration/simple_test.go index 9b40b8b7c..b95151295 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -546,6 +546,10 @@ func (s *SimpleSuite) TestRouterConfigErrors(c *check.C) { err = try.GetRequest("http://127.0.0.1:8080/api/http/routers", 1000*time.Millisecond, try.BodyContains(`["middleware \"unknown@file\" does not exist","found different TLS options for routers on the same host snitest.net, so using the default TLS options instead"]`)) c.Assert(err, checker.IsNil) + // router3 has an error because it uses an unknown entrypoint + err = try.GetRequest("http://127.0.0.1:8080/api/http/routers/router3@file", 1000*time.Millisecond, try.BodyContains(`entryPoint \"unknown-entrypoint\" doesn't exist`, "no valid entryPoint for this router")) + c.Assert(err, checker.IsNil) + // router4 is enabled, but in warning state because its tls options conf was messed up err = try.GetRequest("http://127.0.0.1:8080/api/http/routers/router4@file", 1000*time.Millisecond, try.BodyContains(`"status":"warning"`)) c.Assert(err, checker.IsNil) diff --git a/pkg/config/runtime/runtime_http.go b/pkg/config/runtime/runtime_http.go index 1c6b9e4aa..e604ac32c 100644 --- a/pkg/config/runtime/runtime_http.go +++ b/pkg/config/runtime/runtime_http.go @@ -2,6 +2,7 @@ package runtime import ( "context" + "fmt" "sync" "github.com/containous/traefik/v2/pkg/config/dynamic" @@ -17,23 +18,32 @@ func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints continue } + logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName))) eps := rt.EntryPoints if len(eps) == 0 { + logger.Debugf("No entrypoint defined for this router, using the default one(s) instead: %+v", entryPoints) eps = entryPoints } + entryPointsCount := 0 for _, entryPointName := range eps { if !contains(entryPoints, entryPointName) { - log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))). + rt.AddError(fmt.Errorf("entryPoint %q doesn't exist", entryPointName), false) + logger.WithField(log.EntryPointName, entryPointName). Errorf("entryPoint %q doesn't exist", entryPointName) continue } + entryPointsCount++ if _, ok := entryPointsRouters[entryPointName]; !ok { entryPointsRouters[entryPointName] = make(map[string]*RouterInfo) } entryPointsRouters[entryPointName][rtName] = rt } + if entryPointsCount == 0 { + rt.AddError(fmt.Errorf("no valid entryPoint for this router"), true) + logger.Error("no valid entryPoint for this router") + } } return entryPointsRouters diff --git a/pkg/config/runtime/runtime_http_test.go b/pkg/config/runtime/runtime_http_test.go index 38102c61d..d95c6e780 100644 --- a/pkg/config/runtime/runtime_http_test.go +++ b/pkg/config/runtime/runtime_http_test.go @@ -111,7 +111,8 @@ func TestGetRoutersByEntryPoints(t *testing.T) { Service: "foobar-service@myprovider", Rule: "Host(`bar.foobar`)", }, - Status: "enabled", + Status: "warning", + Err: []string{`entryPoint "webs" doesn't exist`}, }, }, }, From 0d9cf697fa47be20197a430f6dc2accddedfc1ca Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Doumenjou Date: Sat, 31 Aug 2019 09:28:04 +0200 Subject: [PATCH 05/37] Base of the migration guide Co-authored-by: Mathieu Lonjaret --- docs/content/migration/v1-to-v2.md | 344 +++++++++++++++++++++++++++++ docs/mkdocs.yml | 2 + 2 files changed, 346 insertions(+) create mode 100644 docs/content/migration/v1-to-v2.md diff --git a/docs/content/migration/v1-to-v2.md b/docs/content/migration/v1-to-v2.md new file mode 100644 index 000000000..a1564a9fc --- /dev/null +++ b/docs/content/migration/v1-to-v2.md @@ -0,0 +1,344 @@ +# Migration Guide: From v1 to v2 + +How to Migrate from Traefik v1 to Traefik v2. +{: .subtitle } + +The version 2 of Traefik introduces a number of breaking changes, +which require one to update their configuration when they migrate from v1 to v2. +The goal of this page is to recapitulate all of these changes, and in particular to give examples, +feature by feature, of how the configuration looked like in v1, and how it now looks like in v2. + +## Frontends and Backends Are Dead...
... Long Live Routers, Middlewares, and Services + +During the transition from v1 to v2, a number of internal pieces and components of Traefik were rewritten and reorganized. +As such, the combination of core notions such as frontends and backends has been replaced with the combination of routers, services, and middlewares. + +Typically, a router replaces a frontend, and a service assumes the role of a backend, with each router referring to a service. +However, even though a backend was in charge of applying any desired modification on the fly to the incoming request, +the router defers that responsibility to another component. +Instead, a dedicated middleware is now defined for each kind of such modification. +Then any router can refer to an instance of the wanted middleware. + +!!! example "One frontend with basic auth and one backend, become one router, one service, and one basic auth middleware." + + ### v1 + + ```yaml tab="Docker" + labels: + - "traefik.frontend.rule=Host:test.localhost;PathPrefix:/test" + - "traefik.frontend.auth.basic.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" + ``` + + ```yaml tab="K8s Ingress" + apiVersion: extensions/v1beta1 + kind: Ingress + metadata: + name: traefik + namespace: kube-system + annotations: + kubernetes.io/ingress.class: traefik + traefik.ingress.kubernetes.io/rule-type: PathPrefix + spec: + rules: + - host: test.locahost + http: + paths: + - path: /test + backend: + serviceName: server0 + servicePort: 80 + - path: /test + backend: + serviceName: server1 + servicePort: 80 + ``` + + ```toml tab="File (TOML)" + [frontends] + [frontends.frontend1] + entryPoints = ["http"] + backend = "backend1" + + [frontends.frontend1.routes] + [frontends.frontend1.routes.route0] + rule = "Host:test.localhost" + [frontends.frontend1.routes.route0] + rule = "PathPrefix:/test" + + [frontends.frontend1.auth] + [frontends.frontend1.auth.basic] + users = [ + "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", + "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + ] + + [backends] + [backends.backend1] + [backends.backend1.servers.server0] + url = "http://10.10.10.1:80" + [backends.backend1.servers.server1] + url = "http://10.10.10.2:80" + + [backends.backend1.loadBalancer] + method = "wrr" + ``` + + ### v2 + + ```yaml tab="Docker" + labels: + - "traefik.http.routers.router0.rule=Host(`bar.com`) && PathPrefix(`/test`)" + - "traefik.http.routers.router0.middlewares=auth" + - "traefik.http.middlewares.auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" + ``` + + ```yaml tab="K8s IngressRoute" + # The definitions below require the definitions for the Middleware and IngressRoute kinds. + # https://docs.traefik.io/v2.0/providers/kubernetes-crd/#traefik-ingressroute-definition + apiVersion: traefik.containo.us/v1alpha1 + kind: Middleware + metadata: + name: basicauth + namespace: foo + + spec: + basicAuth: + users: + - test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/ + - test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 + + --- + apiVersion: traefik.containo.us/v1alpha1 + kind: IngressRoute + metadata: + name: ingressroutebar + + spec: + entryPoints: + - http + routes: + - match: Host(`test.localhost`) && PathPrefix(`/test`) + kind: Rule + services: + - name: server0 + port: 80 + - name: server1 + port: 80 + middlewares: + - name: basicauth + namespace: foo + ``` + + ```toml tab="File (TOML)" + [http.routers] + [http.routers.router0] + rule = "Host(`test.localhost`) && PathPrefix(`/test`)" + middlewares = ["auth"] + service = "my-service" + + [http.services] + [[http.services.my-service.loadBalancer.servers]] + url = "http://10.10.10.1:80" + [[http.services.my-service.loadBalancer.servers]] + url = "http://10.10.10.2:80" + + [http.middlewares] + [http.middlewares.auth.basicAuth] + users = [ + "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", + "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + ] + ``` + + ```yaml tab="File (YAML)" + http: + routers: + router0: + rule: "Host(`test.localhost`) && PathPrefix(`/test`)" + service: my-service + middlewares: + - auth + + services: + my-service: + loadBalancer: + servers: + - url: http://10.10.10.1:80 + - url: http://10.10.10.2:80 + + middlewares: + auth: + basicAuth: + users: + - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" + - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" + ``` + +## TLS configuration is now dynamic, per router. + +TLS parameters used to be specified in the static configuration, as an entryPoint field. +With Traefik v2, a new dynamic TLS section at the root contains all the desired TLS configurations. +Then, a router's TLS field can refer to one of the TLS configurations defined at the root, hence defining the TLS configuration for that router. + +!!! example "TLS on web-secure entryPoint becomes TLS option on Router-1" + + ### v1 + + ```toml tab="File (TOML)" + # static configuration + [entryPoints] + [entryPoints.web-secure] + address = ":443" + + [entryPoints.web-secure.tls] + minVersion = "VersionTLS12" + cipherSuites = [ + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384" + ] + [[entryPoints.web-secure.tls.certificates]] + certFile = "path/to/my.cert" + keyFile = "path/to/my.key" + ``` + + ```bash tab="CLI" + --entryPoints='Name:web-secure Address::443 TLS:path/to/my.cert,path/to/my.key TLS.MinVersion:VersionTLS12 TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384' + ``` + + ### v2 + + ```toml tab="File (TOML)" + # dynamic configuration + [http.routers] + [http.routers.Router-1] + rule = "Host(`bar.com`)" + service = "service-id" + # will terminate the TLS request + [http.routers.Router-1.tls] + options = "myTLSOptions" + + [[tls.certificates]] + certFile = "/path/to/domain.cert" + keyFile = "/path/to/domain.key" + + [tls.options] + [tls.options.default] + minVersion = "VersionTLS12" + + [tls.options.myTLSOptions] + minVersion = "VersionTLS13" + cipherSuites = [ + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384" + ] + ``` + + ```yaml tab="File (YAML)" + http: + routers: + Router-1: + rule: "Host(`bar.com`)" + service: service-id + # will terminate the TLS request + tls: + options: myTLSOptions + + tls: + certificates: + - certFile: /path/to/domain.cert + keyFile: /path/to/domain.key + options: + myTLSOptions: + minVersion: VersionTLS13 + cipherSuites: + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_RSA_WITH_AES_256_GCM_SHA384 + ``` + + ```yaml tab="K8s IngressRoute" + # The definitions below require the definitions for the TLSOption and IngressRoute kinds. + # https://docs.traefik.io/v2.0/providers/kubernetes-crd/#traefik-ingressroute-definition + apiVersion: traefik.containo.us/v1alpha1 + kind: TLSOption + metadata: + name: mytlsoption + namespace: default + + spec: + minVersion: VersionTLS13 + cipherSuites: + - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + - TLS_RSA_WITH_AES_256_GCM_SHA384 + + --- + apiVersion: traefik.containo.us/v1alpha1 + kind: IngressRoute + metadata: + name: ingressroutebar + + spec: + entryPoints: + - web + routes: + - match: Host(`bar.com`) + kind: Rule + services: + - name: whoami + port: 80 + tls: + options: + name: mytlsoption + namespace: default + ``` + + ```yaml tab="Docker" + labels: + # myTLSOptions must be defined by another provider, in this instance in the File Provider. + # see the cross provider section + - "traefik.http.routers.router0.tls.options=myTLSOptions@file" + ``` + +## HTTP -> HTTPS Redirection + + TODO + +## ACME (let's encrypt) + + TODO + +## Traefik Logs + + TODO + +## Tracing + + TODO + +## Metrics + + TODO + +## No more root level key/values + + TODO + +## Providers + +Supported providers, for now: + +- [ ] Azure Service Fabric +- [ ] BoltDB +- [ ] Consul +- [ ] Consul Catalog +- [x] Docker +- [ ] DynamoDB +- [ ] ECS +- [ ] Etcd +- [ ] Eureka +- [x] File +- [x] Kubernetes Ingress (without annotations) +- [x] Kubernetes IngressRoute +- [x] Marathon +- [ ] Mesos +- [x] Rest +- [ ] Zookeeper diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 46cba835d..533ffc2f7 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -143,6 +143,8 @@ nav: - 'TLS Challenge': 'user-guides/docker-compose/acme-tls/index.md' - 'HTTP Challenge': 'user-guides/docker-compose/acme-http/index.md' - 'DNS Challenge': 'user-guides/docker-compose/acme-dns/index.md' + - 'Migration': + - 'Traefik v1 to v2': 'migration/v1-to-v2.md' - 'Contributing': - 'Thank You!': 'contributing/thank-you.md' - 'Submitting Issues': 'contributing/submitting-issues.md' From 17554202f64272bfce4c2f60e13435c0a4987176 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 2 Sep 2019 10:52:04 +0200 Subject: [PATCH 06/37] fix: stripPrefixRegex documentation. --- docs/content/middlewares/stripprefixregex.md | 8 +- .../dynamic-configuration/docker-labels.yml | 39 +++++---- .../reference/dynamic-configuration/file.toml | 57 ++++++++----- .../reference/dynamic-configuration/file.yaml | 80 +++++++++++-------- .../marathon-labels.json | 52 ++++++------ 5 files changed, 138 insertions(+), 98 deletions(-) diff --git a/docs/content/middlewares/stripprefixregex.md b/docs/content/middlewares/stripprefixregex.md index f6a6451aa..84e55d979 100644 --- a/docs/content/middlewares/stripprefixregex.md +++ b/docs/content/middlewares/stripprefixregex.md @@ -23,7 +23,8 @@ metadata: name: test-stripprefixregex spec: stripPrefixRegex: - regex: "^/foo/(.*)" + regex: + - "^/foo/(.*)" ``` ```json tab="Marathon" @@ -42,7 +43,7 @@ labels: # Replace the path by /foo [http.middlewares] [http.middlewares.test-stripprefixregex.stripPrefixRegex] - regex = "^/foo/(.*)" + regex = ["^/foo/(.*)"] ``` ```yaml tab="File (YAML)" @@ -51,7 +52,8 @@ http: middlewares: test-stripprefixregex: stripPrefixRegex: - regex: "^/foo/(.*)" + regex: + - "^/foo/(.*)" ``` ## Configuration Options diff --git a/docs/content/reference/dynamic-configuration/docker-labels.yml b/docs/content/reference/dynamic-configuration/docker-labels.yml index c01640149..757e525cf 100644 --- a/docs/content/reference/dynamic-configuration/docker-labels.yml +++ b/docs/content/reference/dynamic-configuration/docker-labels.yml @@ -45,13 +45,13 @@ - "traefik.http.middlewares.middleware09.headers.customrequestheaders.name1=foobar" - "traefik.http.middlewares.middleware09.headers.customresponseheaders.name0=foobar" - "traefik.http.middlewares.middleware09.headers.customresponseheaders.name1=foobar" +- "traefik.http.middlewares.middleware09.headers.featurepolicy=foobar" - "traefik.http.middlewares.middleware09.headers.forcestsheader=true" - "traefik.http.middlewares.middleware09.headers.framedeny=true" - "traefik.http.middlewares.middleware09.headers.hostsproxyheaders=foobar, foobar" - "traefik.http.middlewares.middleware09.headers.isdevelopment=true" - "traefik.http.middlewares.middleware09.headers.publickey=foobar" - "traefik.http.middlewares.middleware09.headers.referrerpolicy=foobar" -- "traefik.http.middlewares.middleware09.headers.featurepolicy=foobar" - "traefik.http.middlewares.middleware09.headers.sslforcehost=true" - "traefik.http.middlewares.middleware09.headers.sslhost=foobar" - "traefik.http.middlewares.middleware09.headers.sslproxyheaders.name0=foobar" @@ -65,10 +65,9 @@ - "traefik.http.middlewares.middleware10.ipwhitelist.ipstrategy.excludedips=foobar, foobar" - "traefik.http.middlewares.middleware10.ipwhitelist.sourcerange=foobar, foobar" - "traefik.http.middlewares.middleware11.inflightreq.amount=42" -- "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requestheadername=foobar" -- "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requesthost=true" - "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.ipstrategy.depth=42" - "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.ipstrategy.excludedips=foobar, foobar" +- "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requestheadername=foobar" - "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requesthost=true" - "traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.commonname=true" - "traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.country=true" @@ -88,18 +87,24 @@ - "traefik.http.middlewares.middleware12.passtlsclientcert.info.subject.province=true" - "traefik.http.middlewares.middleware12.passtlsclientcert.info.subject.serialnumber=true" - "traefik.http.middlewares.middleware12.passtlsclientcert.pem=true" -- "traefik.http.middlewares.middleware13.redirectregex.permanent=true" -- "traefik.http.middlewares.middleware13.redirectregex.regex=foobar" -- "traefik.http.middlewares.middleware13.redirectregex.replacement=foobar" -- "traefik.http.middlewares.middleware14.redirectscheme.permanent=true" -- "traefik.http.middlewares.middleware14.redirectscheme.port=foobar" -- "traefik.http.middlewares.middleware14.redirectscheme.scheme=foobar" -- "traefik.http.middlewares.middleware15.replacepath.path=foobar" -- "traefik.http.middlewares.middleware16.replacepathregex.regex=foobar" -- "traefik.http.middlewares.middleware16.replacepathregex.replacement=foobar" -- "traefik.http.middlewares.middleware17.retry.attempts=42" -- "traefik.http.middlewares.middleware18.stripprefix.prefixes=foobar, foobar" -- "traefik.http.middlewares.middleware19.stripprefixregex.regex=foobar, foobar" +- "traefik.http.middlewares.middleware13.ratelimit.average=42" +- "traefik.http.middlewares.middleware13.ratelimit.burst=42" +- "traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.ipstrategy.depth=42" +- "traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.ipstrategy.excludedips=foobar, foobar" +- "traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.requestheadername=foobar" +- "traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.requesthost=true" +- "traefik.http.middlewares.middleware14.redirectregex.permanent=true" +- "traefik.http.middlewares.middleware14.redirectregex.regex=foobar" +- "traefik.http.middlewares.middleware14.redirectregex.replacement=foobar" +- "traefik.http.middlewares.middleware15.redirectscheme.permanent=true" +- "traefik.http.middlewares.middleware15.redirectscheme.port=foobar" +- "traefik.http.middlewares.middleware15.redirectscheme.scheme=foobar" +- "traefik.http.middlewares.middleware16.replacepath.path=foobar" +- "traefik.http.middlewares.middleware17.replacepathregex.regex=foobar" +- "traefik.http.middlewares.middleware17.replacepathregex.replacement=foobar" +- "traefik.http.middlewares.middleware18.retry.attempts=42" +- "traefik.http.middlewares.middleware19.stripprefix.prefixes=foobar, foobar" +- "traefik.http.middlewares.middleware20.stripprefixregex.regex=foobar, foobar" - "traefik.http.routers.router0.entrypoints=foobar, foobar" - "traefik.http.routers.router0.middlewares=foobar, foobar" - "traefik.http.routers.router0.priority=42" @@ -135,8 +140,8 @@ - "traefik.http.services.service0.loadbalancer.passhostheader=true" - "traefik.http.services.service0.loadbalancer.responseforwarding.flushinterval=foobar" - "traefik.http.services.service0.loadbalancer.sticky=true" -- "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.name=foobar" - "traefik.http.services.service0.loadbalancer.sticky.cookie.secure=true" - "traefik.http.services.service0.loadbalancer.server.port=foobar" - "traefik.http.services.service0.loadbalancer.server.scheme=foobar" @@ -151,8 +156,8 @@ - "traefik.http.services.service1.loadbalancer.passhostheader=true" - "traefik.http.services.service1.loadbalancer.responseforwarding.flushinterval=foobar" - "traefik.http.services.service1.loadbalancer.sticky=true" -- "traefik.http.services.service1.loadbalancer.sticky.cookie.name=foobar" - "traefik.http.services.service1.loadbalancer.sticky.cookie.httponly=true" +- "traefik.http.services.service1.loadbalancer.sticky.cookie.name=foobar" - "traefik.http.services.service1.loadbalancer.sticky.cookie.secure=true" - "traefik.http.services.service1.loadbalancer.server.port=foobar" - "traefik.http.services.service1.loadbalancer.server.scheme=foobar" diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 71ad8d891..88fc62144 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -62,17 +62,28 @@ [http.services.Service01.loadBalancer.responseForwarding] flushInterval = "foobar" [http.services.Service02] - [http.services.Service02.weighted] + [http.services.Service02.mirroring] + service = "foobar" - [[http.services.Service02.weighted.services]] + [[http.services.Service02.mirroring.mirrors]] + name = "foobar" + percent = 42 + + [[http.services.Service02.mirroring.mirrors]] + name = "foobar" + percent = 42 + [http.services.Service03] + [http.services.Service03.weighted] + + [[http.services.Service03.weighted.services]] name = "foobar" weight = 42 - [[http.services.Service02.weighted.services]] + [[http.services.Service03.weighted.services]] name = "foobar" weight = 42 - [http.services.Service02.weighted.sticky] - [http.services.Service02.weighted.sticky.cookie] + [http.services.Service03.weighted.sticky] + [http.services.Service03.weighted.sticky.cookie] name = "foobar" secure = true httpOnly = true @@ -202,30 +213,40 @@ serialNumber = true domainComponent = true [http.middlewares.Middleware13] - [http.middlewares.Middleware13.redirectRegex] + [http.middlewares.Middleware13.rateLimit] + average = 42 + burst = 42 + [http.middlewares.Middleware13.rateLimit.sourceCriterion] + requestHeaderName = "foobar" + requestHost = true + [http.middlewares.Middleware13.rateLimit.sourceCriterion.ipStrategy] + depth = 42 + excludedIPs = ["foobar", "foobar"] + [http.middlewares.Middleware14] + [http.middlewares.Middleware14.redirectRegex] regex = "foobar" replacement = "foobar" permanent = true - [http.middlewares.Middleware14] - [http.middlewares.Middleware14.redirectScheme] + [http.middlewares.Middleware15] + [http.middlewares.Middleware15.redirectScheme] scheme = "foobar" port = "foobar" permanent = true - [http.middlewares.Middleware15] - [http.middlewares.Middleware15.replacePath] - path = "foobar" [http.middlewares.Middleware16] - [http.middlewares.Middleware16.replacePathRegex] + [http.middlewares.Middleware16.replacePath] + path = "foobar" + [http.middlewares.Middleware17] + [http.middlewares.Middleware17.replacePathRegex] regex = "foobar" replacement = "foobar" - [http.middlewares.Middleware17] - [http.middlewares.Middleware17.retry] - attempts = 42 [http.middlewares.Middleware18] - [http.middlewares.Middleware18.stripPrefix] - prefixes = ["foobar", "foobar"] + [http.middlewares.Middleware18.retry] + attempts = 42 [http.middlewares.Middleware19] - [http.middlewares.Middleware19.stripPrefixRegex] + [http.middlewares.Middleware19.stripPrefix] + prefixes = ["foobar", "foobar"] + [http.middlewares.Middleware20] + [http.middlewares.Middleware20.stripPrefixRegex] regex = ["foobar", "foobar"] [tcp] diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index 89753c2a5..46a54373f 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -69,6 +69,14 @@ http: responseForwarding: flushInterval: foobar Service02: + mirroring: + service: foobar + mirrors: + - name: foobar + percent: 42 + - name: foobar + percent: 42 + Service03: weighted: services: - name: foobar @@ -201,9 +209,11 @@ http: inFlightReq: amount: 42 sourceCriterion: - ipStrategy: + ipstrategy: depth: 42 - excludedIPs: [ foobar, foobar ] + excludedIPs: + - foobar + - foobar requestHeaderName: foobar requestHost: true Middleware12: @@ -230,45 +240,47 @@ http: serialNumber: true domainComponent: true Middleware13: - redirectRegex: - regex: foobar - replacement: foobar - permanent: true - Middleware14: - redirectScheme: - scheme: foobar - port: foobar - permanent: true - Middleware15: - replacePath: - path: foobar - Middleware16: - replacePathRegex: - regex: foobar - replacement: foobar - Middleware17: - retry: - attempts: 42 - Middleware18: - stripPrefix: - prefixes: - - foobar - - foobar - Middleware19: - stripPrefixRegex: - regex: - - foobar - - foobar - Middleware20: rateLimit: average: 42 burst: 42 sourceCriterion: - ipStrategy: + ipstrategy: depth: 42 - excludedIPs: [ foobar, foobar ] + excludedIPs: + - foobar + - foobar requestHeaderName: foobar requestHost: true + Middleware14: + redirectRegex: + regex: foobar + replacement: foobar + permanent: true + Middleware15: + redirectScheme: + scheme: foobar + port: foobar + permanent: true + Middleware16: + replacePath: + path: foobar + Middleware17: + replacePathRegex: + regex: foobar + replacement: foobar + Middleware18: + retry: + attempts: 42 + Middleware19: + stripPrefix: + prefixes: + - foobar + - foobar + Middleware20: + stripPrefixRegex: + regex: + - foobar + - foobar tcp: routers: TCPRouter0: diff --git a/docs/content/reference/dynamic-configuration/marathon-labels.json b/docs/content/reference/dynamic-configuration/marathon-labels.json index 163924b4a..5b1360841 100644 --- a/docs/content/reference/dynamic-configuration/marathon-labels.json +++ b/docs/content/reference/dynamic-configuration/marathon-labels.json @@ -45,13 +45,13 @@ "traefik.http.middlewares.middleware09.headers.customrequestheaders.name1": "foobar", "traefik.http.middlewares.middleware09.headers.customresponseheaders.name0": "foobar", "traefik.http.middlewares.middleware09.headers.customresponseheaders.name1": "foobar", +"traefik.http.middlewares.middleware09.headers.featurepolicy": "foobar", "traefik.http.middlewares.middleware09.headers.forcestsheader": "true", "traefik.http.middlewares.middleware09.headers.framedeny": "true", "traefik.http.middlewares.middleware09.headers.hostsproxyheaders": "foobar, foobar", "traefik.http.middlewares.middleware09.headers.isdevelopment": "true", "traefik.http.middlewares.middleware09.headers.publickey": "foobar", "traefik.http.middlewares.middleware09.headers.referrerpolicy": "foobar", -"traefik.http.middlewares.middleware09.headers.featurepolicy": "foobar", "traefik.http.middlewares.middleware09.headers.sslforcehost": "true", "traefik.http.middlewares.middleware09.headers.sslhost": "foobar", "traefik.http.middlewares.middleware09.headers.sslproxyheaders.name0": "foobar", @@ -64,11 +64,11 @@ "traefik.http.middlewares.middleware10.ipwhitelist.ipstrategy.depth": "42", "traefik.http.middlewares.middleware10.ipwhitelist.ipstrategy.excludedips": "foobar, foobar", "traefik.http.middlewares.middleware10.ipwhitelist.sourcerange": "foobar, foobar", -"traefik.http.middlewares.Middleware11.inflightreq.amount": "42", -"traefik.http.middlewares.Middleware11.inflightreq.sourcecriterion.ipstrategy.depth": "42", -"traefik.http.middlewares.Middleware11.inflightreq.sourcecriterion.ipstrategy.excludedips": "foobar, fiibar", -"traefik.http.middlewares.Middleware11.inflightreq.sourcecriterion.requestheadername": "foobar", -"traefik.http.middlewares.Middleware11.inflightreq.sourcecriterion.requesthost": "true", +"traefik.http.middlewares.middleware11.inflightreq.amount": "42", +"traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.ipstrategy.depth": "42", +"traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.ipstrategy.excludedips": "foobar, foobar", +"traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requestheadername": "foobar", +"traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requesthost": "true", "traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.commonname": "true", "traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.country": "true", "traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.domaincomponent": "true", @@ -87,24 +87,24 @@ "traefik.http.middlewares.middleware12.passtlsclientcert.info.subject.province": "true", "traefik.http.middlewares.middleware12.passtlsclientcert.info.subject.serialnumber": "true", "traefik.http.middlewares.middleware12.passtlsclientcert.pem": "true", -"traefik.http.middlewares.middleware13.redirectregex.permanent": "true", -"traefik.http.middlewares.middleware13.redirectregex.regex": "foobar", -"traefik.http.middlewares.middleware13.redirectregex.replacement": "foobar", -"traefik.http.middlewares.middleware14.redirectscheme.permanent": "true", -"traefik.http.middlewares.middleware14.redirectscheme.port": "foobar", -"traefik.http.middlewares.middleware14.redirectscheme.scheme": "foobar", -"traefik.http.middlewares.middleware15.replacepath.path": "foobar", -"traefik.http.middlewares.middleware16.replacepathregex.regex": "foobar", -"traefik.http.middlewares.middleware16.replacepathregex.replacement": "foobar", -"traefik.http.middlewares.middleware17.retry.attempts": "42", -"traefik.http.middlewares.middleware18.stripprefix.prefixes": "foobar, foobar", -"traefik.http.middlewares.middleware19.stripprefixregex.regex": "foobar, foobar", -"traefik.http.middlewares.Middleware20.ratelimit.average": "42", -"traefik.http.middlewares.Middleware20.ratelimit.burst": "42", -"traefik.http.middlewares.Middleware20.ratelimit.sourcecriterion.requestheadername": "foobar", -"traefik.http.middlewares.Middleware20.ratelimit.sourcecriterion.requesthost": "true", -"traefik.http.middlewares.Middleware20.ratelimit.sourcecriterion.ipstrategy.depth": "42", -"traefik.http.middlewares.Middleware20.ratelimit.sourcecriterion.ipstrategy.excludedips": "foobar, foobar", +"traefik.http.middlewares.middleware13.ratelimit.average": "42", +"traefik.http.middlewares.middleware13.ratelimit.burst": "42", +"traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.ipstrategy.depth": "42", +"traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.ipstrategy.excludedips": "foobar, foobar", +"traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.requestheadername": "foobar", +"traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.requesthost": "true", +"traefik.http.middlewares.middleware14.redirectregex.permanent": "true", +"traefik.http.middlewares.middleware14.redirectregex.regex": "foobar", +"traefik.http.middlewares.middleware14.redirectregex.replacement": "foobar", +"traefik.http.middlewares.middleware15.redirectscheme.permanent": "true", +"traefik.http.middlewares.middleware15.redirectscheme.port": "foobar", +"traefik.http.middlewares.middleware15.redirectscheme.scheme": "foobar", +"traefik.http.middlewares.middleware16.replacepath.path": "foobar", +"traefik.http.middlewares.middleware17.replacepathregex.regex": "foobar", +"traefik.http.middlewares.middleware17.replacepathregex.replacement": "foobar", +"traefik.http.middlewares.middleware18.retry.attempts": "42", +"traefik.http.middlewares.middleware19.stripprefix.prefixes": "foobar, foobar", +"traefik.http.middlewares.middleware20.stripprefixregex.regex": "foobar, foobar", "traefik.http.routers.router0.entrypoints": "foobar, foobar", "traefik.http.routers.router0.middlewares": "foobar, foobar", "traefik.http.routers.router0.priority": "42", @@ -140,8 +140,8 @@ "traefik.http.services.service0.loadbalancer.passhostheader": "true", "traefik.http.services.service0.loadbalancer.responseforwarding.flushinterval": "foobar", "traefik.http.services.service0.loadbalancer.sticky": "true", -"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.name": "foobar", "traefik.http.services.service0.loadbalancer.sticky.cookie.secure": "true", "traefik.http.services.service0.loadbalancer.server.port": "foobar", "traefik.http.services.service0.loadbalancer.server.scheme": "foobar", @@ -156,9 +156,9 @@ "traefik.http.services.service1.loadbalancer.passhostheader": "true", "traefik.http.services.service1.loadbalancer.responseforwarding.flushinterval": "foobar", "traefik.http.services.service1.loadbalancer.sticky": "true", +"traefik.http.services.service1.loadbalancer.sticky.cookie.httponly": "true", "traefik.http.services.service1.loadbalancer.sticky.cookie.name": "foobar", "traefik.http.services.service1.loadbalancer.sticky.cookie.secure": "true", -"traefik.http.services.service1.loadbalancer.sticky.cookie.httponly": "true", "traefik.http.services.service1.loadbalancer.server.port": "foobar", "traefik.http.services.service1.loadbalancer.server.scheme": "foobar", "traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar", From af9762cf329d50c3f5ec91faa96b553aa376cb65 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 2 Sep 2019 11:38:04 +0200 Subject: [PATCH 07/37] Improve API for the web UI --- integration/testdata/rawdata-crd.json | 35 ++- integration/testdata/rawdata-ingress.json | 26 +- pkg/api/criterion.go | 102 +++++++ pkg/api/handler.go | 81 ++--- pkg/api/handler_entrypoint.go | 16 +- pkg/api/handler_http.go | 150 ++++++---- pkg/api/handler_http_test.go | 278 ++++++++++++++++++ pkg/api/handler_overview.go | 2 +- pkg/api/handler_tcp.go | 98 +++--- pkg/api/handler_tcp_test.go | 189 ++++++++++++ pkg/api/testdata/middleware-auth.json | 1 + .../testdata/middlewares-filtered-search.json | 26 ++ .../testdata/middlewares-filtered-status.json | 29 ++ pkg/api/testdata/middlewares-page2.json | 1 + pkg/api/testdata/middlewares.json | 3 + pkg/api/testdata/router-bar.json | 5 +- pkg/api/testdata/routers-filtered-search.json | 19 ++ pkg/api/testdata/routers-filtered-status.json | 19 ++ pkg/api/testdata/routers-many-lastpage.json | 25 +- pkg/api/testdata/routers-page2.json | 5 +- pkg/api/testdata/routers.json | 10 +- pkg/api/testdata/service-bar.json | 1 + .../testdata/services-filtered-search.json | 22 ++ .../testdata/services-filtered-status.json | 23 ++ pkg/api/testdata/services-page2.json | 1 + pkg/api/testdata/services.json | 46 +++ pkg/api/testdata/tcprouter-bar.json | 6 +- .../testdata/tcprouters-filtered-search.json | 15 + .../testdata/tcprouters-filtered-status.json | 18 ++ pkg/api/testdata/tcprouters-page2.json | 6 +- pkg/api/testdata/tcprouters.json | 15 +- pkg/api/testdata/tcpservice-bar.json | 2 + .../testdata/tcpservices-filtered-search.json | 18 ++ .../testdata/tcpservices-filtered-status.json | 19 ++ pkg/api/testdata/tcpservices-page2.json | 2 + pkg/api/testdata/tcpservices.json | 3 + pkg/config/runtime/runtime_http.go | 41 ++- pkg/config/runtime/runtime_http_test.go | 6 + pkg/config/runtime/runtime_tcp.go | 25 +- pkg/config/runtime/runtime_tcp_test.go | 9 +- .../kubernetes/crd/kubernetes_http.go | 1 - 41 files changed, 1200 insertions(+), 199 deletions(-) create mode 100644 pkg/api/criterion.go create mode 100644 pkg/api/testdata/middlewares-filtered-search.json create mode 100644 pkg/api/testdata/middlewares-filtered-status.json create mode 100644 pkg/api/testdata/routers-filtered-search.json create mode 100644 pkg/api/testdata/routers-filtered-status.json create mode 100644 pkg/api/testdata/services-filtered-search.json create mode 100644 pkg/api/testdata/services-filtered-status.json create mode 100644 pkg/api/testdata/tcprouters-filtered-search.json create mode 100644 pkg/api/testdata/tcprouters-filtered-status.json create mode 100644 pkg/api/testdata/tcpservices-filtered-search.json create mode 100644 pkg/api/testdata/tcpservices-filtered-status.json diff --git a/integration/testdata/rawdata-crd.json b/integration/testdata/rawdata-crd.json index c26803e36..696e34dd2 100644 --- a/integration/testdata/rawdata-crd.json +++ b/integration/testdata/rawdata-crd.json @@ -10,7 +10,10 @@ "tls": { "options": "default/mytlsoption" }, - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] }, "default/test2.route-23c7f4c450289ee29016@kubernetescrd": { "entryPoints": [ @@ -21,7 +24,10 @@ ], "service": "default/test2.route-23c7f4c450289ee29016", "rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/tobestripped`)", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] } }, "middlewares": { @@ -42,10 +48,10 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.4:80" + "url": "http://10.42.0.2:80" }, { - "url": "http://10.42.0.5:80" + "url": "http://10.42.0.6:80" } ], "passHostHeader": true @@ -55,18 +61,18 @@ "default/test.route-6b204d94623b3df4370c@kubernetescrd" ], "serverStatus": { - "http://10.42.0.4:80": "UP", - "http://10.42.0.5:80": "UP" + "http://10.42.0.2:80": "UP", + "http://10.42.0.6:80": "UP" } }, "default/test2.route-23c7f4c450289ee29016@kubernetescrd": { "loadBalancer": { "servers": [ { - "url": "http://10.42.0.4:80" + "url": "http://10.42.0.2:80" }, { - "url": "http://10.42.0.5:80" + "url": "http://10.42.0.6:80" } ], "passHostHeader": true @@ -76,8 +82,8 @@ "default/test2.route-23c7f4c450289ee29016@kubernetescrd" ], "serverStatus": { - "http://10.42.0.4:80": "UP", - "http://10.42.0.5:80": "UP" + "http://10.42.0.2:80": "UP", + "http://10.42.0.6:80": "UP" } } }, @@ -92,7 +98,10 @@ "passthrough": false, "options": "default/mytlsoption" }, - "status": "enabled" + "status": "enabled", + "using": [ + "footcp" + ] } }, "tcpServices": { @@ -100,10 +109,10 @@ "loadBalancer": { "servers": [ { - "address": "10.42.0.3:8080" + "address": "10.42.0.4:8080" }, { - "address": "10.42.0.6:8080" + "address": "10.42.0.5:8080" } ] }, diff --git a/integration/testdata/rawdata-ingress.json b/integration/testdata/rawdata-ingress.json index 9a9e1b9d7..4908d6388 100644 --- a/integration/testdata/rawdata-ingress.json +++ b/integration/testdata/rawdata-ingress.json @@ -4,17 +4,29 @@ "service": "default/whoami/http", "rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)", "tls": {}, - "status": "enabled" + "status": "enabled", + "using": [ + "traefik", + "web" + ] }, "whoami-test-https/whoami@kubernetes": { "service": "default/whoami/http", "rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)", - "status": "enabled" + "status": "enabled", + "using": [ + "traefik", + "web" + ] }, "whoami-test/whoami@kubernetes": { "service": "default/whoami/http", "rule": "Host(`whoami.test`) \u0026\u0026 PathPrefix(`/whoami`)", - "status": "enabled" + "status": "enabled", + "using": [ + "traefik", + "web" + ] } }, "services": { @@ -22,10 +34,10 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.4:80" + "url": "http://10.42.0.2:80" }, { - "url": "http://10.42.0.5:80" + "url": "http://10.42.0.4:80" } ], "passHostHeader": true @@ -37,8 +49,8 @@ "whoami-test/whoami@kubernetes" ], "serverStatus": { - "http://10.42.0.4:80": "UP", - "http://10.42.0.5:80": "UP" + "http://10.42.0.2:80": "UP", + "http://10.42.0.4:80": "UP" } } } diff --git a/pkg/api/criterion.go b/pkg/api/criterion.go new file mode 100644 index 000000000..d81a9f717 --- /dev/null +++ b/pkg/api/criterion.go @@ -0,0 +1,102 @@ +package api + +import ( + "fmt" + "net/http" + "net/url" + "strconv" + "strings" +) + +const ( + defaultPerPage = 100 + defaultPage = 1 +) + +const nextPageHeader = "X-Next-Page" + +type pageInfo struct { + startIndex int + endIndex int + nextPage int +} + +type searchCriterion struct { + Search string `url:"search"` + Status string `url:"status"` +} + +func newSearchCriterion(query url.Values) *searchCriterion { + if len(query) == 0 { + return nil + } + + search := query.Get("search") + status := query.Get("status") + + if status == "" && search == "" { + return nil + } + + return &searchCriterion{Search: search, Status: status} +} + +func (c *searchCriterion) withStatus(name string) bool { + return c.Status == "" || strings.EqualFold(name, c.Status) +} + +func (c *searchCriterion) searchIn(values ...string) bool { + if c.Search == "" { + return true + } + + for _, v := range values { + if strings.Contains(strings.ToLower(v), strings.ToLower(c.Search)) { + return true + } + } + + return false +} + +func pagination(request *http.Request, max int) (pageInfo, error) { + perPage, err := getIntParam(request, "per_page", defaultPerPage) + if err != nil { + return pageInfo{}, err + } + + page, err := getIntParam(request, "page", defaultPage) + if err != nil { + return pageInfo{}, err + } + + startIndex := (page - 1) * perPage + if startIndex != 0 && startIndex >= max { + return pageInfo{}, fmt.Errorf("invalid request: page: %d, per_page: %d", page, perPage) + } + + endIndex := startIndex + perPage + if endIndex >= max { + endIndex = max + } + + nextPage := 1 + if page*perPage < max { + nextPage = page + 1 + } + + return pageInfo{startIndex: startIndex, endIndex: endIndex, nextPage: nextPage}, nil +} + +func getIntParam(request *http.Request, key string, defaultValue int) (int, error) { + raw := request.URL.Query().Get(key) + if raw == "" { + return defaultValue, nil + } + + value, err := strconv.Atoi(raw) + if err != nil || value <= 0 { + return 0, fmt.Errorf("invalid request: %s: %d", key, value) + } + return value, nil +} diff --git a/pkg/api/handler.go b/pkg/api/handler.go index 7ee900c75..4b707c568 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -2,9 +2,8 @@ package api import ( "encoding/json" - "fmt" "net/http" - "strconv" + "reflect" "strings" "github.com/containous/traefik/v2/pkg/config/runtime" @@ -15,12 +14,19 @@ import ( "github.com/gorilla/mux" ) -const ( - defaultPerPage = 100 - defaultPage = 1 -) +type apiError struct { + Message string `json:"message"` +} -const nextPageHeader = "X-Next-Page" +func writeError(rw http.ResponseWriter, msg string, code int) { + data, err := json.Marshal(apiError{Message: msg}) + if err != nil { + http.Error(rw, msg, code) + return + } + + http.Error(rw, string(data), code) +} type serviceInfoRepresentation struct { *runtime.ServiceInfo @@ -36,12 +42,6 @@ type RunTimeRepresentation struct { TCPServices map[string]*runtime.TCPServiceInfo `json:"tcpServices,omitempty"` } -type pageInfo struct { - startIndex int - endIndex int - nextPage int -} - // Handler serves the configuration and status of Traefik on API endpoints. type Handler struct { dashboard bool @@ -136,48 +136,19 @@ func (h Handler) getRuntimeConfiguration(rw http.ResponseWriter, request *http.R } } -func pagination(request *http.Request, max int) (pageInfo, error) { - perPage, err := getIntParam(request, "per_page", defaultPerPage) - if err != nil { - return pageInfo{}, err - } - - page, err := getIntParam(request, "page", defaultPage) - if err != nil { - return pageInfo{}, err - } - - startIndex := (page - 1) * perPage - if startIndex != 0 && startIndex >= max { - return pageInfo{}, fmt.Errorf("invalid request: page: %d, per_page: %d", page, perPage) - } - - endIndex := startIndex + perPage - if endIndex >= max { - endIndex = max - } - - nextPage := 1 - if page*perPage < max { - nextPage = page + 1 - } - - return pageInfo{startIndex: startIndex, endIndex: endIndex, nextPage: nextPage}, nil -} - -func getIntParam(request *http.Request, key string, defaultValue int) (int, error) { - raw := request.URL.Query().Get(key) - if raw == "" { - return defaultValue, nil - } - - value, err := strconv.Atoi(raw) - if err != nil || value <= 0 { - return 0, fmt.Errorf("invalid request: %s: %d", key, value) - } - return value, nil -} - func getProviderName(id string) string { return strings.SplitN(id, "@", 2)[1] } + +func extractType(element interface{}) string { + v := reflect.ValueOf(element).Elem() + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + if field.Kind() == reflect.Ptr && field.Elem().Kind() == reflect.Struct { + if !field.IsNil() { + return v.Type().Field(i).Name + } + } + } + return "" +} diff --git a/pkg/api/handler_entrypoint.go b/pkg/api/handler_entrypoint.go index b4cc3f4e5..808b7e536 100644 --- a/pkg/api/handler_entrypoint.go +++ b/pkg/api/handler_entrypoint.go @@ -2,6 +2,7 @@ package api import ( "encoding/json" + "fmt" "net/http" "sort" "strconv" @@ -30,28 +31,31 @@ func (h Handler) getEntryPoints(rw http.ResponseWriter, request *http.Request) { return results[i].Name < results[j].Name }) + rw.Header().Set("Content-Type", "application/json") + pageInfo, err := pagination(request, len(results)) if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) + writeError(rw, err.Error(), http.StatusBadRequest) return } - rw.Header().Set("Content-Type", "application/json") rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } func (h Handler) getEntryPoint(rw http.ResponseWriter, request *http.Request) { entryPointID := mux.Vars(request)["entryPointID"] + rw.Header().Set("Content-Type", "application/json") + ep, ok := h.staticConfig.EntryPoints[entryPointID] if !ok { - http.NotFound(rw, request) + writeError(rw, fmt.Sprintf("entry point not found: %s", entryPointID), http.StatusNotFound) return } @@ -60,11 +64,9 @@ func (h Handler) getEntryPoint(rw http.ResponseWriter, request *http.Request) { Name: entryPointID, } - rw.Header().Set("Content-Type", "application/json") - err := json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } diff --git a/pkg/api/handler_http.go b/pkg/api/handler_http.go index 39bc3fd3f..fe43c215f 100644 --- a/pkg/api/handler_http.go +++ b/pkg/api/handler_http.go @@ -2,9 +2,11 @@ package api import ( "encoding/json" + "fmt" "net/http" "sort" "strconv" + "strings" "github.com/containous/traefik/v2/pkg/config/runtime" "github.com/containous/traefik/v2/pkg/log" @@ -17,182 +19,224 @@ type routerRepresentation struct { Provider string `json:"provider,omitempty"` } +func newRouterRepresentation(name string, rt *runtime.RouterInfo) routerRepresentation { + return routerRepresentation{ + RouterInfo: rt, + Name: name, + Provider: getProviderName(name), + } +} + type serviceRepresentation struct { *runtime.ServiceInfo ServerStatus map[string]string `json:"serverStatus,omitempty"` Name string `json:"name,omitempty"` Provider string `json:"provider,omitempty"` + Type string `json:"type,omitempty"` +} + +func newServiceRepresentation(name string, si *runtime.ServiceInfo) serviceRepresentation { + return serviceRepresentation{ + ServiceInfo: si, + Name: name, + Provider: getProviderName(name), + ServerStatus: si.GetAllStatus(), + Type: strings.ToLower(extractType(si.Service)), + } } type middlewareRepresentation struct { *runtime.MiddlewareInfo Name string `json:"name,omitempty"` Provider string `json:"provider,omitempty"` + Type string `json:"type,omitempty"` +} + +func newMiddlewareRepresentation(name string, mi *runtime.MiddlewareInfo) middlewareRepresentation { + return middlewareRepresentation{ + MiddlewareInfo: mi, + Name: name, + Provider: getProviderName(name), + Type: strings.ToLower(extractType(mi.Middleware)), + } } func (h Handler) getRouters(rw http.ResponseWriter, request *http.Request) { results := make([]routerRepresentation, 0, len(h.runtimeConfiguration.Routers)) + criterion := newSearchCriterion(request.URL.Query()) + for name, rt := range h.runtimeConfiguration.Routers { - results = append(results, routerRepresentation{ - RouterInfo: rt, - Name: name, - Provider: getProviderName(name), - }) + if keepRouter(name, rt, criterion) { + results = append(results, newRouterRepresentation(name, rt)) + } } sort.Slice(results, func(i, j int) bool { return results[i].Name < results[j].Name }) + rw.Header().Set("Content-Type", "application/json") + pageInfo, err := pagination(request, len(results)) if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) + writeError(rw, err.Error(), http.StatusBadRequest) return } - rw.Header().Set("Content-Type", "application/json") rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } func (h Handler) getRouter(rw http.ResponseWriter, request *http.Request) { routerID := mux.Vars(request)["routerID"] + rw.Header().Set("Content-Type", "application/json") + router, ok := h.runtimeConfiguration.Routers[routerID] if !ok { - http.NotFound(rw, request) + writeError(rw, fmt.Sprintf("router not found: %s", routerID), http.StatusNotFound) return } - result := routerRepresentation{ - RouterInfo: router, - Name: routerID, - Provider: getProviderName(routerID), - } - - rw.Header().Set("Content-Type", "application/json") + result := newRouterRepresentation(routerID, router) err := json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } func (h Handler) getServices(rw http.ResponseWriter, request *http.Request) { results := make([]serviceRepresentation, 0, len(h.runtimeConfiguration.Services)) + criterion := newSearchCriterion(request.URL.Query()) + for name, si := range h.runtimeConfiguration.Services { - results = append(results, serviceRepresentation{ - ServiceInfo: si, - Name: name, - Provider: getProviderName(name), - ServerStatus: si.GetAllStatus(), - }) + if keepService(name, si, criterion) { + results = append(results, newServiceRepresentation(name, si)) + } } sort.Slice(results, func(i, j int) bool { return results[i].Name < results[j].Name }) + rw.Header().Set("Content-Type", "application/json") + pageInfo, err := pagination(request, len(results)) if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) + writeError(rw, err.Error(), http.StatusBadRequest) return } - rw.Header().Set("Content-Type", "application/json") rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } func (h Handler) getService(rw http.ResponseWriter, request *http.Request) { serviceID := mux.Vars(request)["serviceID"] + rw.Header().Add("Content-Type", "application/json") + service, ok := h.runtimeConfiguration.Services[serviceID] if !ok { - http.NotFound(rw, request) + writeError(rw, fmt.Sprintf("service not found: %s", serviceID), http.StatusNotFound) return } - result := serviceRepresentation{ - ServiceInfo: service, - Name: serviceID, - Provider: getProviderName(serviceID), - ServerStatus: service.GetAllStatus(), - } - - rw.Header().Add("Content-Type", "application/json") + result := newServiceRepresentation(serviceID, service) err := json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } func (h Handler) getMiddlewares(rw http.ResponseWriter, request *http.Request) { results := make([]middlewareRepresentation, 0, len(h.runtimeConfiguration.Middlewares)) + criterion := newSearchCriterion(request.URL.Query()) + for name, mi := range h.runtimeConfiguration.Middlewares { - results = append(results, middlewareRepresentation{ - MiddlewareInfo: mi, - Name: name, - Provider: getProviderName(name), - }) + if keepMiddleware(name, mi, criterion) { + results = append(results, newMiddlewareRepresentation(name, mi)) + } } sort.Slice(results, func(i, j int) bool { return results[i].Name < results[j].Name }) + rw.Header().Set("Content-Type", "application/json") + pageInfo, err := pagination(request, len(results)) if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) + writeError(rw, err.Error(), http.StatusBadRequest) return } - rw.Header().Set("Content-Type", "application/json") rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } func (h Handler) getMiddleware(rw http.ResponseWriter, request *http.Request) { middlewareID := mux.Vars(request)["middlewareID"] + rw.Header().Set("Content-Type", "application/json") + middleware, ok := h.runtimeConfiguration.Middlewares[middlewareID] if !ok { - http.NotFound(rw, request) + writeError(rw, fmt.Sprintf("middleware not found: %s", middlewareID), http.StatusNotFound) return } - result := middlewareRepresentation{ - MiddlewareInfo: middleware, - Name: middlewareID, - Provider: getProviderName(middlewareID), - } - - rw.Header().Set("Content-Type", "application/json") + result := newMiddlewareRepresentation(middlewareID, middleware) err := json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } + +func keepRouter(name string, item *runtime.RouterInfo, criterion *searchCriterion) bool { + if criterion == nil { + return true + } + + return criterion.withStatus(item.Status) && criterion.searchIn(item.Rule, name) +} + +func keepService(name string, item *runtime.ServiceInfo, criterion *searchCriterion) bool { + if criterion == nil { + return true + } + + return criterion.withStatus(item.Status) && criterion.searchIn(name) +} + +func keepMiddleware(name string, item *runtime.MiddlewareInfo, criterion *searchCriterion) bool { + if criterion == nil { + return true + } + + return criterion.withStatus(item.Status) && criterion.searchIn(name) +} diff --git a/pkg/api/handler_http_test.go b/pkg/api/handler_http_test.go index 57524e675..38286151f 100644 --- a/pkg/api/handler_http_test.go +++ b/pkg/api/handler_http_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" "io/ioutil" @@ -137,6 +138,68 @@ func TestHandler_HTTP(t *testing.T) { statusCode: http.StatusBadRequest, }, }, + { + desc: "routers filtered by status", + path: "/api/http/routers?status=enabled", + conf: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ + "test@myprovider": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar.other`)", + Middlewares: []string{"addPrefixTest", "auth"}, + }, + 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-status.json", + }, + }, + { + desc: "routers filtered by search", + path: "/api/http/routers?search=fii", + 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, + }, + "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-search.json", + }, + }, { desc: "one router by id", path: "/api/http/routers/bar@myprovider", @@ -232,6 +295,45 @@ func TestHandler_HTTP(t *testing.T) { si.UpdateServerStatus("http://127.0.0.2", "UP") return si }(), + "canary@myprovider": { + Service: &dynamic.Service{ + Weighted: &dynamic.WeightedRoundRobin{ + Services: nil, + Sticky: &dynamic.Sticky{ + Cookie: &dynamic.Cookie{ + Name: "chocolat", + Secure: true, + HTTPOnly: true, + }, + }, + }, + }, + Status: runtime.StatusEnabled, + UsedBy: []string{"foo@myprovider"}, + }, + "mirror@myprovider": { + Service: &dynamic.Service{ + Mirroring: &dynamic.Mirroring{ + Service: "one@myprovider", + Mirrors: []dynamic.MirrorService{ + { + Name: "two@myprovider", + Percent: 10, + }, + { + Name: "three@myprovider", + Percent: 15, + }, + { + Name: "four@myprovider", + Percent: 80, + }, + }, + }, + }, + Status: runtime.StatusEnabled, + UsedBy: []string{"foo@myprovider"}, + }, }, }, expected: expected{ @@ -301,6 +403,100 @@ func TestHandler_HTTP(t *testing.T) { jsonFile: "testdata/services-page2.json", }, }, + { + desc: "services filtered by status", + path: "/api/http/services?status=enabled", + conf: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ + "bar@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://127.0.0.1", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider", "test@myprovider"}, + Status: runtime.StatusEnabled, + } + si.UpdateServerStatus("http://127.0.0.1", "UP") + return si + }(), + "baz@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://127.0.0.2", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider"}, + Status: runtime.StatusDisabled, + } + si.UpdateServerStatus("http://127.0.0.2", "UP") + return si + }(), + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/services-filtered-status.json", + }, + }, + { + desc: "services filtered by search", + path: "/api/http/services?search=baz", + conf: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ + "bar@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://127.0.0.1", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider", "test@myprovider"}, + Status: runtime.StatusEnabled, + } + si.UpdateServerStatus("http://127.0.0.1", "UP") + return si + }(), + "baz@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ + Service: &dynamic.Service{ + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://127.0.0.2", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider"}, + Status: runtime.StatusDisabled, + } + si.UpdateServerStatus("http://127.0.0.2", "UP") + return si + }(), + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/services-filtered-search.json", + }, + }, { desc: "one service by id", path: "/api/http/services/bar@myprovider", @@ -411,6 +607,86 @@ func TestHandler_HTTP(t *testing.T) { jsonFile: "testdata/middlewares.json", }, }, + { + desc: "middlewares filtered by status", + path: "/api/http/middlewares?status=enabled", + conf: runtime.Configuration{ + Middlewares: map[string]*runtime.MiddlewareInfo{ + "auth@myprovider": { + Middleware: &dynamic.Middleware{ + BasicAuth: &dynamic.BasicAuth{ + Users: []string{"admin:admin"}, + }, + }, + UsedBy: []string{"bar@myprovider", "test@myprovider"}, + Status: runtime.StatusEnabled, + }, + "addPrefixTest@myprovider": { + Middleware: &dynamic.Middleware{ + AddPrefix: &dynamic.AddPrefix{ + Prefix: "/titi", + }, + }, + UsedBy: []string{"test@myprovider"}, + Status: runtime.StatusDisabled, + }, + "addPrefixTest@anotherprovider": { + Middleware: &dynamic.Middleware{ + AddPrefix: &dynamic.AddPrefix{ + Prefix: "/toto", + }, + }, + UsedBy: []string{"bar@myprovider"}, + Status: runtime.StatusEnabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/middlewares-filtered-status.json", + }, + }, + { + desc: "middlewares filtered by search", + path: "/api/http/middlewares?search=addprefixtest", + conf: runtime.Configuration{ + Middlewares: map[string]*runtime.MiddlewareInfo{ + "auth@myprovider": { + Middleware: &dynamic.Middleware{ + BasicAuth: &dynamic.BasicAuth{ + Users: []string{"admin:admin"}, + }, + }, + UsedBy: []string{"bar@myprovider", "test@myprovider"}, + Status: runtime.StatusEnabled, + }, + "addPrefixTest@myprovider": { + Middleware: &dynamic.Middleware{ + AddPrefix: &dynamic.AddPrefix{ + Prefix: "/titi", + }, + }, + UsedBy: []string{"test@myprovider"}, + Status: runtime.StatusDisabled, + }, + "addPrefixTest@anotherprovider": { + Middleware: &dynamic.Middleware{ + AddPrefix: &dynamic.AddPrefix{ + Prefix: "/toto", + }, + }, + UsedBy: []string{"bar@myprovider"}, + Status: runtime.StatusEnabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/middlewares-filtered-search.json", + }, + }, { desc: "all middlewares, 1 res per page, want page 2", path: "/api/http/middlewares?page=2&per_page=1", @@ -521,6 +797,8 @@ func TestHandler_HTTP(t *testing.T) { rtConf := &test.conf // To lazily initialize the Statuses. rtConf.PopulateUsedBy() + rtConf.GetRoutersByEntryPoints(context.Background(), []string{"web"}, false) + handler := New(static.Configuration{API: &static.API{}, Global: &static.Global{}}, rtConf) router := mux.NewRouter() handler.Append(router) diff --git a/pkg/api/handler_overview.go b/pkg/api/handler_overview.go index f08d80351..21f1921e1 100644 --- a/pkg/api/handler_overview.go +++ b/pkg/api/handler_overview.go @@ -56,7 +56,7 @@ func (h Handler) getOverview(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } diff --git a/pkg/api/handler_tcp.go b/pkg/api/handler_tcp.go index 3f91f0386..823af5178 100644 --- a/pkg/api/handler_tcp.go +++ b/pkg/api/handler_tcp.go @@ -2,9 +2,11 @@ package api import ( "encoding/json" + "fmt" "net/http" "sort" "strconv" + "strings" "github.com/containous/traefik/v2/pkg/config/runtime" "github.com/containous/traefik/v2/pkg/log" @@ -17,118 +19,146 @@ type tcpRouterRepresentation struct { Provider string `json:"provider,omitempty"` } +func newTCPRouterRepresentation(name string, rt *runtime.TCPRouterInfo) tcpRouterRepresentation { + return tcpRouterRepresentation{ + TCPRouterInfo: rt, + Name: name, + Provider: getProviderName(name), + } +} + type tcpServiceRepresentation struct { *runtime.TCPServiceInfo Name string `json:"name,omitempty"` Provider string `json:"provider,omitempty"` + Type string `json:"type,omitempty"` +} + +func newTCPServiceRepresentation(name string, si *runtime.TCPServiceInfo) tcpServiceRepresentation { + return tcpServiceRepresentation{ + TCPServiceInfo: si, + Name: name, + Provider: getProviderName(name), + Type: strings.ToLower(extractType(si.TCPService)), + } } func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) { results := make([]tcpRouterRepresentation, 0, len(h.runtimeConfiguration.TCPRouters)) + criterion := newSearchCriterion(request.URL.Query()) + for name, rt := range h.runtimeConfiguration.TCPRouters { - results = append(results, tcpRouterRepresentation{ - TCPRouterInfo: rt, - Name: name, - Provider: getProviderName(name), - }) + if keepTCPRouter(name, rt, criterion) { + results = append(results, newTCPRouterRepresentation(name, rt)) + } } sort.Slice(results, func(i, j int) bool { return results[i].Name < results[j].Name }) + rw.Header().Set("Content-Type", "application/json") + pageInfo, err := pagination(request, len(results)) if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) + writeError(rw, err.Error(), http.StatusBadRequest) return } - rw.Header().Set("Content-Type", "application/json") rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } func (h Handler) getTCPRouter(rw http.ResponseWriter, request *http.Request) { routerID := mux.Vars(request)["routerID"] + rw.Header().Set("Content-Type", "application/json") + router, ok := h.runtimeConfiguration.TCPRouters[routerID] if !ok { - http.NotFound(rw, request) + writeError(rw, fmt.Sprintf("router not found: %s", routerID), http.StatusNotFound) return } - result := tcpRouterRepresentation{ - TCPRouterInfo: router, - Name: routerID, - Provider: getProviderName(routerID), - } - - rw.Header().Set("Content-Type", "application/json") + result := newTCPRouterRepresentation(routerID, router) err := json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } func (h Handler) getTCPServices(rw http.ResponseWriter, request *http.Request) { results := make([]tcpServiceRepresentation, 0, len(h.runtimeConfiguration.TCPServices)) + criterion := newSearchCriterion(request.URL.Query()) + for name, si := range h.runtimeConfiguration.TCPServices { - results = append(results, tcpServiceRepresentation{ - TCPServiceInfo: si, - Name: name, - Provider: getProviderName(name), - }) + if keepTCPService(name, si, criterion) { + results = append(results, newTCPServiceRepresentation(name, si)) + } } sort.Slice(results, func(i, j int) bool { return results[i].Name < results[j].Name }) + rw.Header().Set("Content-Type", "application/json") + pageInfo, err := pagination(request, len(results)) if err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) + writeError(rw, err.Error(), http.StatusBadRequest) return } - rw.Header().Set("Content-Type", "application/json") rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } func (h Handler) getTCPService(rw http.ResponseWriter, request *http.Request) { serviceID := mux.Vars(request)["serviceID"] + rw.Header().Set("Content-Type", "application/json") + service, ok := h.runtimeConfiguration.TCPServices[serviceID] if !ok { - http.NotFound(rw, request) + writeError(rw, fmt.Sprintf("service not found: %s", serviceID), http.StatusNotFound) return } - result := tcpServiceRepresentation{ - TCPServiceInfo: service, - Name: serviceID, - Provider: getProviderName(serviceID), - } - - rw.Header().Set("Content-Type", "application/json") + result := newTCPServiceRepresentation(serviceID, service) err := json.NewEncoder(rw).Encode(result) if err != nil { log.FromContext(request.Context()).Error(err) - http.Error(rw, err.Error(), http.StatusInternalServerError) + writeError(rw, err.Error(), http.StatusInternalServerError) } } + +func keepTCPRouter(name string, item *runtime.TCPRouterInfo, criterion *searchCriterion) bool { + if criterion == nil { + return true + } + + return criterion.withStatus(item.Status) && criterion.searchIn(item.Rule, name) +} + +func keepTCPService(name string, item *runtime.TCPServiceInfo, criterion *searchCriterion) bool { + if criterion == nil { + return true + } + + return criterion.withStatus(item.Status) && criterion.searchIn(name) +} diff --git a/pkg/api/handler_tcp_test.go b/pkg/api/handler_tcp_test.go index 28c833f8b..798876de4 100644 --- a/pkg/api/handler_tcp_test.go +++ b/pkg/api/handler_tcp_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "io/ioutil" "net/http" @@ -112,6 +113,86 @@ func TestHandler_TCP(t *testing.T) { jsonFile: "testdata/tcprouters-page2.json", }, }, + { + desc: "TCP routers filtered by status", + path: "/api/tcp/routers?status=enabled", + 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@myprovider", + Rule: "Host(`foo.bar`)", + }, + Status: runtime.StatusWarning, + }, + "foo@myprovider": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar`)", + }, + Status: runtime.StatusDisabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/tcprouters-filtered-status.json", + }, + }, + { + desc: "TCP routers filtered by search", + path: "/api/tcp/routers?search=bar@my", + 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@myprovider", + Rule: "Host(`foo.bar`)", + }, + Status: runtime.StatusWarning, + }, + "foo@myprovider": { + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar`)", + }, + Status: runtime.StatusDisabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/tcprouters-filtered-search.json", + }, + }, { desc: "one TCP router by id", path: "/api/tcp/routers/bar@myprovider", @@ -219,6 +300,110 @@ func TestHandler_TCP(t *testing.T) { jsonFile: "testdata/tcpservices.json", }, }, + { + desc: "tcp services filtered by status", + path: "/api/tcp/services?status=enabled", + conf: runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ + "bar@myprovider": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPLoadBalancerService{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.1:2345", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider", "test@myprovider"}, + Status: runtime.StatusEnabled, + }, + "baz@myprovider": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPLoadBalancerService{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.2:2345", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider"}, + Status: runtime.StatusWarning, + }, + "foz@myprovider": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPLoadBalancerService{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.2:2345", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider"}, + Status: runtime.StatusDisabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/tcpservices-filtered-status.json", + }, + }, + { + desc: "tcp services filtered by search", + path: "/api/tcp/services?search=baz@my", + conf: runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ + "bar@myprovider": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPLoadBalancerService{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.1:2345", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider", "test@myprovider"}, + Status: runtime.StatusEnabled, + }, + "baz@myprovider": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPLoadBalancerService{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.2:2345", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider"}, + Status: runtime.StatusWarning, + }, + "foz@myprovider": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPLoadBalancerService{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.2:2345", + }, + }, + }, + }, + UsedBy: []string{"foo@myprovider"}, + Status: runtime.StatusDisabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/tcpservices-filtered-search.json", + }, + }, { desc: "all tcp services, 1 res per page, want page 2", path: "/api/tcp/services?page=2&per_page=1", @@ -330,6 +515,10 @@ func TestHandler_TCP(t *testing.T) { t.Parallel() rtConf := &test.conf + // To lazily initialize the Statuses. + rtConf.PopulateUsedBy() + rtConf.GetTCPRoutersByEntryPoints(context.Background(), []string{"web"}) + handler := New(static.Configuration{API: &static.API{}, Global: &static.Global{}}, rtConf) router := mux.NewRouter() handler.Append(router) diff --git a/pkg/api/testdata/middleware-auth.json b/pkg/api/testdata/middleware-auth.json index 0ed588873..3c7ff53fa 100644 --- a/pkg/api/testdata/middleware-auth.json +++ b/pkg/api/testdata/middleware-auth.json @@ -7,6 +7,7 @@ "name": "auth@myprovider", "provider": "myprovider", "status": "enabled", + "type": "basicauth", "usedBy": [ "bar@myprovider", "test@myprovider" diff --git a/pkg/api/testdata/middlewares-filtered-search.json b/pkg/api/testdata/middlewares-filtered-search.json new file mode 100644 index 000000000..ba1382268 --- /dev/null +++ b/pkg/api/testdata/middlewares-filtered-search.json @@ -0,0 +1,26 @@ +[ + { + "addPrefix": { + "prefix": "/toto" + }, + "name": "addPrefixTest@anotherprovider", + "provider": "anotherprovider", + "status": "enabled", + "type": "addprefix", + "usedBy": [ + "bar@myprovider" + ] + }, + { + "addPrefix": { + "prefix": "/titi" + }, + "name": "addPrefixTest@myprovider", + "provider": "myprovider", + "status": "disabled", + "type": "addprefix", + "usedBy": [ + "test@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/middlewares-filtered-status.json b/pkg/api/testdata/middlewares-filtered-status.json new file mode 100644 index 000000000..eab60c6a4 --- /dev/null +++ b/pkg/api/testdata/middlewares-filtered-status.json @@ -0,0 +1,29 @@ +[ + { + "addPrefix": { + "prefix": "/toto" + }, + "name": "addPrefixTest@anotherprovider", + "provider": "anotherprovider", + "status": "enabled", + "type": "addprefix", + "usedBy": [ + "bar@myprovider" + ] + }, + { + "basicAuth": { + "users": [ + "admin:admin" + ] + }, + "name": "auth@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "basicauth", + "usedBy": [ + "bar@myprovider", + "test@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/middlewares-page2.json b/pkg/api/testdata/middlewares-page2.json index 25ebc13f5..ecaf5978a 100644 --- a/pkg/api/testdata/middlewares-page2.json +++ b/pkg/api/testdata/middlewares-page2.json @@ -6,6 +6,7 @@ "name": "addPrefixTest@myprovider", "provider": "myprovider", "status": "enabled", + "type": "addprefix", "usedBy": [ "test@myprovider" ] diff --git a/pkg/api/testdata/middlewares.json b/pkg/api/testdata/middlewares.json index c27533ee1..f48f52efb 100644 --- a/pkg/api/testdata/middlewares.json +++ b/pkg/api/testdata/middlewares.json @@ -6,6 +6,7 @@ "name": "addPrefixTest@anotherprovider", "provider": "anotherprovider", "status": "enabled", + "type": "addprefix", "usedBy": [ "bar@myprovider" ] @@ -17,6 +18,7 @@ "name": "addPrefixTest@myprovider", "provider": "myprovider", "status": "enabled", + "type": "addprefix", "usedBy": [ "test@myprovider" ] @@ -30,6 +32,7 @@ "name": "auth@myprovider", "provider": "myprovider", "status": "enabled", + "type": "basicauth", "usedBy": [ "bar@myprovider", "test@myprovider" diff --git a/pkg/api/testdata/router-bar.json b/pkg/api/testdata/router-bar.json index 267a9628b..098ea0b1a 100644 --- a/pkg/api/testdata/router-bar.json +++ b/pkg/api/testdata/router-bar.json @@ -10,5 +10,8 @@ "provider": "myprovider", "rule": "Host(`foo.bar`)", "service": "foo-service@myprovider", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] } \ No newline at end of file diff --git a/pkg/api/testdata/routers-filtered-search.json b/pkg/api/testdata/routers-filtered-search.json new file mode 100644 index 000000000..4e251f5da --- /dev/null +++ b/pkg/api/testdata/routers-filtered-search.json @@ -0,0 +1,19 @@ +[ + { + "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-status.json b/pkg/api/testdata/routers-filtered-status.json new file mode 100644 index 000000000..1c96e3802 --- /dev/null +++ b/pkg/api/testdata/routers-filtered-status.json @@ -0,0 +1,19 @@ +[ + { + "entryPoints": [ + "web" + ], + "middlewares": [ + "addPrefixTest", + "auth" + ], + "name": "test@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar.other`)", + "service": "foo-service@myprovider", + "status": "enabled", + "using": [ + "web" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/routers-many-lastpage.json b/pkg/api/testdata/routers-many-lastpage.json index 290672375..df1ee7929 100644 --- a/pkg/api/testdata/routers-many-lastpage.json +++ b/pkg/api/testdata/routers-many-lastpage.json @@ -7,7 +7,10 @@ "provider": "myprovider", "rule": "Host(`foo.bar14`)", "service": "foo-service@myprovider", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] }, { "entryPoints": [ @@ -17,7 +20,10 @@ "provider": "myprovider", "rule": "Host(`foo.bar15`)", "service": "foo-service@myprovider", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] }, { "entryPoints": [ @@ -27,7 +33,10 @@ "provider": "myprovider", "rule": "Host(`foo.bar16`)", "service": "foo-service@myprovider", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] }, { "entryPoints": [ @@ -37,7 +46,10 @@ "provider": "myprovider", "rule": "Host(`foo.bar17`)", "service": "foo-service@myprovider", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] }, { "entryPoints": [ @@ -47,6 +59,9 @@ "provider": "myprovider", "rule": "Host(`foo.bar18`)", "service": "foo-service@myprovider", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] } ] \ No newline at end of file diff --git a/pkg/api/testdata/routers-page2.json b/pkg/api/testdata/routers-page2.json index 8c7f65d1b..579e2a04f 100644 --- a/pkg/api/testdata/routers-page2.json +++ b/pkg/api/testdata/routers-page2.json @@ -7,6 +7,9 @@ "provider": "myprovider", "rule": "Host(`toto.bar`)", "service": "foo-service@myprovider", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] } ] \ No newline at end of file diff --git a/pkg/api/testdata/routers.json b/pkg/api/testdata/routers.json index 664aedc51..ed0d10e28 100644 --- a/pkg/api/testdata/routers.json +++ b/pkg/api/testdata/routers.json @@ -11,7 +11,10 @@ "provider": "myprovider", "rule": "Host(`foo.bar`)", "service": "foo-service@myprovider", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] }, { "entryPoints": [ @@ -25,6 +28,9 @@ "provider": "myprovider", "rule": "Host(`foo.bar.other`)", "service": "foo-service@myprovider", - "status": "enabled" + "status": "enabled", + "using": [ + "web" + ] } ] \ No newline at end of file diff --git a/pkg/api/testdata/service-bar.json b/pkg/api/testdata/service-bar.json index e26b65a72..11e832136 100644 --- a/pkg/api/testdata/service-bar.json +++ b/pkg/api/testdata/service-bar.json @@ -13,6 +13,7 @@ "http://127.0.0.1": "UP" }, "status": "enabled", + "type": "loadbalancer", "usedBy": [ "foo@myprovider", "test@myprovider" diff --git a/pkg/api/testdata/services-filtered-search.json b/pkg/api/testdata/services-filtered-search.json new file mode 100644 index 000000000..fd854ed72 --- /dev/null +++ b/pkg/api/testdata/services-filtered-search.json @@ -0,0 +1,22 @@ +[ + { + "loadBalancer": { + "passHostHeader": false, + "servers": [ + { + "url": "http://127.0.0.2" + } + ] + }, + "name": "baz@myprovider", + "provider": "myprovider", + "serverStatus": { + "http://127.0.0.2": "UP" + }, + "status": "disabled", + "type": "loadbalancer", + "usedBy": [ + "foo@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/services-filtered-status.json b/pkg/api/testdata/services-filtered-status.json new file mode 100644 index 000000000..df1a52dcb --- /dev/null +++ b/pkg/api/testdata/services-filtered-status.json @@ -0,0 +1,23 @@ +[ + { + "loadBalancer": { + "passHostHeader": false, + "servers": [ + { + "url": "http://127.0.0.1" + } + ] + }, + "name": "bar@myprovider", + "provider": "myprovider", + "serverStatus": { + "http://127.0.0.1": "UP" + }, + "status": "enabled", + "type": "loadbalancer", + "usedBy": [ + "foo@myprovider", + "test@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/services-page2.json b/pkg/api/testdata/services-page2.json index 66b8390d1..9b8b5ce72 100644 --- a/pkg/api/testdata/services-page2.json +++ b/pkg/api/testdata/services-page2.json @@ -14,6 +14,7 @@ "http://127.0.0.2": "UP" }, "status": "enabled", + "type": "loadbalancer", "usedBy": [ "foo@myprovider" ] diff --git a/pkg/api/testdata/services.json b/pkg/api/testdata/services.json index bd54b536c..e96abc23b 100644 --- a/pkg/api/testdata/services.json +++ b/pkg/api/testdata/services.json @@ -14,6 +14,7 @@ "http://127.0.0.1": "UP" }, "status": "enabled", + "type": "loadbalancer", "usedBy": [ "foo@myprovider", "test@myprovider" @@ -34,6 +35,51 @@ "http://127.0.0.2": "UP" }, "status": "enabled", + "type": "loadbalancer", + "usedBy": [ + "foo@myprovider" + ] + }, + { + "name": "canary@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "weighted", + "usedBy": [ + "foo@myprovider" + ], + "weighted": { + "sticky": { + "cookie": { + "httpOnly": true, + "name": "chocolat", + "secure": true + } + } + } + }, + { + "mirroring": { + "mirrors": [ + { + "name": "two@myprovider", + "percent": 10 + }, + { + "name": "three@myprovider", + "percent": 15 + }, + { + "name": "four@myprovider", + "percent": 80 + } + ], + "service": "one@myprovider" + }, + "name": "mirror@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "mirroring", "usedBy": [ "foo@myprovider" ] diff --git a/pkg/api/testdata/tcprouter-bar.json b/pkg/api/testdata/tcprouter-bar.json index b6b244199..70d06a3ea 100644 --- a/pkg/api/testdata/tcprouter-bar.json +++ b/pkg/api/testdata/tcprouter-bar.json @@ -5,5 +5,9 @@ "name": "bar@myprovider", "provider": "myprovider", "rule": "Host(`foo.bar`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled", + "using": [ + "web" + ] } \ No newline at end of file diff --git a/pkg/api/testdata/tcprouters-filtered-search.json b/pkg/api/testdata/tcprouters-filtered-search.json new file mode 100644 index 000000000..4593f1b03 --- /dev/null +++ b/pkg/api/testdata/tcprouters-filtered-search.json @@ -0,0 +1,15 @@ +[ + { + "entryPoints": [ + "web" + ], + "name": "bar@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar`)", + "service": "foo-service@myprovider", + "status": "warning", + "using": [ + "web" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/tcprouters-filtered-status.json b/pkg/api/testdata/tcprouters-filtered-status.json new file mode 100644 index 000000000..64d232ebc --- /dev/null +++ b/pkg/api/testdata/tcprouters-filtered-status.json @@ -0,0 +1,18 @@ +[ + { + "entryPoints": [ + "web" + ], + "name": "test@myprovider", + "provider": "myprovider", + "rule": "Host(`foo.bar.other`)", + "service": "foo-service@myprovider", + "status": "enabled", + "tls": { + "passthrough": false + }, + "using": [ + "web" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/tcprouters-page2.json b/pkg/api/testdata/tcprouters-page2.json index 73d97c6d6..579e2a04f 100644 --- a/pkg/api/testdata/tcprouters-page2.json +++ b/pkg/api/testdata/tcprouters-page2.json @@ -6,6 +6,10 @@ "name": "baz@myprovider", "provider": "myprovider", "rule": "Host(`toto.bar`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled", + "using": [ + "web" + ] } ] \ No newline at end of file diff --git a/pkg/api/testdata/tcprouters.json b/pkg/api/testdata/tcprouters.json index a2bf3c401..bf6bffc17 100644 --- a/pkg/api/testdata/tcprouters.json +++ b/pkg/api/testdata/tcprouters.json @@ -7,7 +7,10 @@ "provider": "myprovider", "rule": "Host(`foo.bar`)", "service": "foo-service@myprovider", - "status": "warning" + "status": "warning", + "using": [ + "web" + ] }, { "entryPoints": [ @@ -17,7 +20,10 @@ "provider": "myprovider", "rule": "Host(`foo.bar`)", "service": "foo-service@myprovider", - "status": "disabled" + "status": "disabled", + "using": [ + "web" + ] }, { "entryPoints": [ @@ -30,6 +36,9 @@ "status": "enabled", "tls": { "passthrough": false - } + }, + "using": [ + "web" + ] } ] \ No newline at end of file diff --git a/pkg/api/testdata/tcpservice-bar.json b/pkg/api/testdata/tcpservice-bar.json index 114f0b74b..ade480a92 100644 --- a/pkg/api/testdata/tcpservice-bar.json +++ b/pkg/api/testdata/tcpservice-bar.json @@ -8,6 +8,8 @@ }, "name": "bar@myprovider", "provider": "myprovider", + "status": "enabled", + "type": "loadbalancer", "usedBy": [ "foo@myprovider", "test@myprovider" diff --git a/pkg/api/testdata/tcpservices-filtered-search.json b/pkg/api/testdata/tcpservices-filtered-search.json new file mode 100644 index 000000000..130d5eace --- /dev/null +++ b/pkg/api/testdata/tcpservices-filtered-search.json @@ -0,0 +1,18 @@ +[ + { + "loadBalancer": { + "servers": [ + { + "address": "127.0.0.2:2345" + } + ] + }, + "name": "baz@myprovider", + "provider": "myprovider", + "status": "warning", + "type": "loadbalancer", + "usedBy": [ + "foo@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/tcpservices-filtered-status.json b/pkg/api/testdata/tcpservices-filtered-status.json new file mode 100644 index 000000000..03ec085a0 --- /dev/null +++ b/pkg/api/testdata/tcpservices-filtered-status.json @@ -0,0 +1,19 @@ +[ + { + "loadBalancer": { + "servers": [ + { + "address": "127.0.0.1:2345" + } + ] + }, + "name": "bar@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "loadbalancer", + "usedBy": [ + "foo@myprovider", + "test@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/tcpservices-page2.json b/pkg/api/testdata/tcpservices-page2.json index 345151040..414e0f37d 100644 --- a/pkg/api/testdata/tcpservices-page2.json +++ b/pkg/api/testdata/tcpservices-page2.json @@ -9,6 +9,8 @@ }, "name": "baz@myprovider", "provider": "myprovider", + "status": "enabled", + "type": "loadbalancer", "usedBy": [ "foo@myprovider" ] diff --git a/pkg/api/testdata/tcpservices.json b/pkg/api/testdata/tcpservices.json index 24320d948..c3f9f7ea6 100644 --- a/pkg/api/testdata/tcpservices.json +++ b/pkg/api/testdata/tcpservices.json @@ -10,6 +10,7 @@ "name": "bar@myprovider", "provider": "myprovider", "status": "enabled", + "type": "loadbalancer", "usedBy": [ "foo@myprovider", "test@myprovider" @@ -26,6 +27,7 @@ "name": "baz@myprovider", "provider": "myprovider", "status": "warning", + "type": "loadbalancer", "usedBy": [ "foo@myprovider" ] @@ -41,6 +43,7 @@ "name": "foz@myprovider", "provider": "myprovider", "status": "disabled", + "type": "loadbalancer", "usedBy": [ "foo@myprovider" ] diff --git a/pkg/config/runtime/runtime_http.go b/pkg/config/runtime/runtime_http.go index e604ac32c..af5062fd9 100644 --- a/pkg/config/runtime/runtime_http.go +++ b/pkg/config/runtime/runtime_http.go @@ -3,13 +3,14 @@ package runtime import ( "context" "fmt" + "sort" "sync" "github.com/containous/traefik/v2/pkg/config/dynamic" "github.com/containous/traefik/v2/pkg/log" ) -// GetRoutersByEntryPoints returns all the http routers by entry points name and routers name +// GetRoutersByEntryPoints returns all the http routers by entry points name and routers name. func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*RouterInfo { entryPointsRouters := make(map[string]map[string]*RouterInfo) @@ -19,11 +20,13 @@ func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints } logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName))) + eps := rt.EntryPoints if len(eps) == 0 { - logger.Debugf("No entrypoint defined for this router, using the default one(s) instead: %+v", entryPoints) + logger.Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints) eps = entryPoints } + entryPointsCount := 0 for _, entryPointName := range eps { if !contains(entryPoints, entryPointName) { @@ -33,23 +36,44 @@ func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints continue } - entryPointsCount++ if _, ok := entryPointsRouters[entryPointName]; !ok { entryPointsRouters[entryPointName] = make(map[string]*RouterInfo) } + entryPointsCount++ + rt.Using = append(rt.Using, entryPointName) + entryPointsRouters[entryPointName][rtName] = rt } + if entryPointsCount == 0 { rt.AddError(fmt.Errorf("no valid entryPoint for this router"), true) logger.Error("no valid entryPoint for this router") } + + rt.Using = unique(rt.Using) } return entryPointsRouters } -// RouterInfo holds information about a currently running HTTP router +func unique(src []string) []string { + var uniq []string + + set := make(map[string]struct{}) + for _, v := range src { + if _, exist := set[v]; !exist { + set[v] = struct{}{} + uniq = append(uniq, v) + } + } + + sort.Strings(uniq) + + return uniq +} + +// RouterInfo holds information about a currently running HTTP router. type RouterInfo struct { *dynamic.Router // dynamic configuration // Err contains all the errors that occurred during router's creation. @@ -57,7 +81,8 @@ type RouterInfo struct { // Status reports whether the router is disabled, in a warning state, or all good (enabled). // If not in "enabled" state, the reason for it should be in the list of Err. // It is the caller's responsibility to set the initial status. - Status string `json:"status,omitempty"` + Status string `json:"status,omitempty"` + Using []string `json:"using,omitempty"` // Effective entry points used by that router. } // AddError adds err to r.Err, if it does not already exist. @@ -81,13 +106,13 @@ func (r *RouterInfo) AddError(err error, critical bool) { } } -// MiddlewareInfo holds information about a currently running middleware +// MiddlewareInfo holds information about a currently running middleware. type MiddlewareInfo struct { *dynamic.Middleware // dynamic configuration // Err contains all the errors that occurred during service creation. Err []string `json:"error,omitempty"` Status string `json:"status,omitempty"` - UsedBy []string `json:"usedBy,omitempty"` // list of routers and services using that middleware + UsedBy []string `json:"usedBy,omitempty"` // list of routers and services using that middleware. } // AddError adds err to s.Err, if it does not already exist. @@ -111,7 +136,7 @@ func (m *MiddlewareInfo) AddError(err error, critical bool) { } } -// ServiceInfo holds information about a currently running service +// ServiceInfo holds information about a currently running service. type ServiceInfo struct { *dynamic.Service // dynamic configuration // Err contains all the errors that occurred during service creation. diff --git a/pkg/config/runtime/runtime_http_test.go b/pkg/config/runtime/runtime_http_test.go index d95c6e780..909d664b7 100644 --- a/pkg/config/runtime/runtime_http_test.go +++ b/pkg/config/runtime/runtime_http_test.go @@ -104,6 +104,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) { Rule: "Host(`bar.foo`)", }, Status: "enabled", + Using: []string{"web"}, }, "foobar": { Router: &dynamic.Router{ @@ -113,6 +114,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) { }, Status: "warning", Err: []string{`entryPoint "webs" doesn't exist`}, + Using: []string{"web"}, }, }, }, @@ -169,6 +171,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) { Rule: "Host(`bar.foo`)", }, Status: "enabled", + Using: []string{"web"}, }, "foobar": { Router: &dynamic.Router{ @@ -177,6 +180,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) { Rule: "Host(`bar.foobar`)", }, Status: "enabled", + Using: []string{"web", "webs"}, }, }, "webs": { @@ -188,6 +192,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) { Rule: "Host(`foo.bar`)", }, Status: "enabled", + Using: []string{"webs"}, }, "foobar": { Router: &dynamic.Router{ @@ -196,6 +201,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) { Rule: "Host(`bar.foobar`)", }, Status: "enabled", + Using: []string{"web", "webs"}, }, }, }, diff --git a/pkg/config/runtime/runtime_tcp.go b/pkg/config/runtime/runtime_tcp.go index a99d519f9..427412bdb 100644 --- a/pkg/config/runtime/runtime_tcp.go +++ b/pkg/config/runtime/runtime_tcp.go @@ -2,24 +2,30 @@ package runtime import ( "context" + "fmt" "github.com/containous/traefik/v2/pkg/config/dynamic" "github.com/containous/traefik/v2/pkg/log" ) -// GetTCPRoutersByEntryPoints returns all the tcp routers by entry points name and routers name +// GetTCPRoutersByEntryPoints returns all the tcp routers by entry points name and routers name. func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoints []string) map[string]map[string]*TCPRouterInfo { entryPointsRouters := make(map[string]map[string]*TCPRouterInfo) for rtName, rt := range c.TCPRouters { + logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName))) + eps := rt.EntryPoints if len(eps) == 0 { + logger.Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints) eps = entryPoints } + entryPointsCount := 0 for _, entryPointName := range eps { if !contains(entryPoints, entryPointName) { - log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))). + rt.AddError(fmt.Errorf("entryPoint %q doesn't exist", entryPointName), false) + logger.WithField(log.EntryPointName, entryPointName). Errorf("entryPoint %q doesn't exist", entryPointName) continue } @@ -28,21 +34,30 @@ func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoi entryPointsRouters[entryPointName] = make(map[string]*TCPRouterInfo) } + entryPointsCount++ + rt.Using = append(rt.Using, entryPointName) + entryPointsRouters[entryPointName][rtName] = rt } + + if entryPointsCount == 0 { + rt.AddError(fmt.Errorf("no valid entryPoint for this router"), true) + logger.Error("no valid entryPoint for this router") + } } return entryPointsRouters } -// TCPRouterInfo holds information about a currently running TCP router +// TCPRouterInfo holds information about a currently running TCP router. type TCPRouterInfo struct { *dynamic.TCPRouter // dynamic configuration Err []string `json:"error,omitempty"` // initialization error // Status reports whether the router is disabled, in a warning state, or all good (enabled). // If not in "enabled" state, the reason for it should be in the list of Err. // It is the caller's responsibility to set the initial status. - Status string `json:"status,omitempty"` + Status string `json:"status,omitempty"` + Using []string `json:"using,omitempty"` // Effective entry points used by that router. } // AddError adds err to r.Err, if it does not already exist. @@ -66,7 +81,7 @@ func (r *TCPRouterInfo) AddError(err error, critical bool) { } } -// TCPServiceInfo holds information about a currently running TCP service +// TCPServiceInfo holds information about a currently running TCP service. type TCPServiceInfo struct { *dynamic.TCPService // dynamic configuration Err []string `json:"error,omitempty"` // initialization error diff --git a/pkg/config/runtime/runtime_tcp_test.go b/pkg/config/runtime/runtime_tcp_test.go index 9fb3f137e..8df42fc9b 100644 --- a/pkg/config/runtime/runtime_tcp_test.go +++ b/pkg/config/runtime/runtime_tcp_test.go @@ -104,6 +104,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) { Rule: "HostSNI(`bar.foo`)", }, Status: "enabled", + Using: []string{"web"}, }, "foobar": { TCPRouter: &dynamic.TCPRouter{ @@ -111,7 +112,9 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) { Service: "foobar-service@myprovider", Rule: "HostSNI(`bar.foobar`)", }, - Status: "enabled", + Status: "warning", + Err: []string{`entryPoint "webs" doesn't exist`}, + Using: []string{"web"}, }, }, }, @@ -168,6 +171,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) { Rule: "HostSNI(`bar.foo`)", }, Status: "enabled", + Using: []string{"web"}, }, "foobar": { TCPRouter: &dynamic.TCPRouter{ @@ -176,6 +180,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) { Rule: "HostSNI(`bar.foobar`)", }, Status: "enabled", + Using: []string{"web", "webs"}, }, }, "webs": { @@ -187,6 +192,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) { Rule: "HostSNI(`foo.bar`)", }, Status: "enabled", + Using: []string{"webs"}, }, "foobar": { TCPRouter: &dynamic.TCPRouter{ @@ -195,6 +201,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) { Rule: "HostSNI(`bar.foobar`)", }, Status: "enabled", + Using: []string{"web", "webs"}, }, }, }, diff --git a/pkg/provider/kubernetes/crd/kubernetes_http.go b/pkg/provider/kubernetes/crd/kubernetes_http.go index 52d18dd30..059e41b9c 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_http.go +++ b/pkg/provider/kubernetes/crd/kubernetes_http.go @@ -144,7 +144,6 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli } conf.Routers[serviceName].TLS = tlsConf } - } } From 259c7adc817c1138b9f6ccdd453a92b4e8a4b6b3 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 2 Sep 2019 11:54:04 +0200 Subject: [PATCH 08/37] deep-copy for MirrorService --- pkg/config/dynamic/zz_generated.deepcopy.go | 42 +++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index 84aefd044..fa391b000 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -687,6 +687,43 @@ func (in *Middleware) DeepCopy() *Middleware { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MirrorService) DeepCopyInto(out *MirrorService) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MirrorService. +func (in *MirrorService) DeepCopy() *MirrorService { + if in == nil { + return nil + } + out := new(MirrorService) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Mirroring) DeepCopyInto(out *Mirroring) { + *out = *in + if in.Mirrors != nil { + in, out := &in.Mirrors, &out.Mirrors + *out = make([]MirrorService, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Mirroring. +func (in *Mirroring) DeepCopy() *Mirroring { + if in == nil { + return nil + } + out := new(Mirroring) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PassTLSClientCert) DeepCopyInto(out *PassTLSClientCert) { *out = *in @@ -967,6 +1004,11 @@ func (in *Service) DeepCopyInto(out *Service) { *out = new(WeightedRoundRobin) (*in).DeepCopyInto(*out) } + if in.Mirroring != nil { + in, out := &in.Mirroring, &out.Mirroring + *out = new(Mirroring) + (*in).DeepCopyInto(*out) + } return } From 306e5081d90dd68d9416fc502777c7ddeac9a16c Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 2 Sep 2019 12:18:04 +0200 Subject: [PATCH 09/37] fix: Datadog case. --- CHANGELOG.md | 24 ++++++++--------- docs/content/observability/metrics/datadog.md | 24 ++++++++--------- .../content/observability/metrics/overview.md | 2 +- docs/content/observability/tracing/datadog.md | 26 +++++++++---------- .../content/observability/tracing/overview.md | 2 +- .../reference/static-configuration/cli-ref.md | 10 +++---- .../reference/static-configuration/env-ref.md | 10 +++---- .../reference/static-configuration/file.toml | 4 +-- .../reference/static-configuration/file.yaml | 4 +-- docs/mkdocs.yml | 4 +-- pkg/anonymize/anonymize_config_test.go | 4 +-- pkg/config/dynamic/fixtures/sample.toml | 4 +-- pkg/config/file/file_node_test.go | 8 +++--- pkg/config/file/fixtures/sample.toml | 4 +-- pkg/config/file/fixtures/sample.yml | 4 +-- pkg/config/static/static_config.go | 2 +- pkg/metrics/datadog.go | 4 +-- pkg/metrics/datadog_test.go | 2 +- pkg/server/server.go | 14 +++++----- pkg/tracing/datadog/datadog.go | 4 +-- pkg/tracing/haystack/haystack.go | 2 +- pkg/types/metrics.go | 12 ++++----- 22 files changed, 87 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39faf0a9d..2854b13d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -217,7 +217,7 @@ - **[api,authentication]** Remove authentication hashes from API ([#4918](https://github.com/containous/traefik/pull/4918) by [ldez](https://github.com/ldez)) - **[consul]** Enhance KV logs. ([#4877](https://github.com/containous/traefik/pull/4877) by [ldez](https://github.com/ldez)) - **[k8s]** Fix kubernetes template for backend responseforwarding flushinterval setting ([#4901](https://github.com/containous/traefik/pull/4901) by [ravilr](https://github.com/ravilr)) -- **[metrics]** Upgraded DataDog tracing library to 1.13.0 ([#4878](https://github.com/containous/traefik/pull/4878) by [aantono](https://github.com/aantono)) +- **[metrics]** Upgraded Datadog tracing library to 1.13.0 ([#4878](https://github.com/containous/traefik/pull/4878) by [aantono](https://github.com/aantono)) - **[server]** Add missing callback on close of hijacked connections ([#4900](https://github.com/containous/traefik/pull/4900) by [ravilr](https://github.com/ravilr)) **Documentation:** @@ -419,7 +419,7 @@ - **[k8s/ingress]** Loop through service ports for global backend ([#4486](https://github.com/containous/traefik/pull/4486) by [dtomcej](https://github.com/dtomcej)) - **[k8s]** Add entrypoints prefix in kubernetes frontend/backend id ([#4679](https://github.com/containous/traefik/pull/4679) by [juliens](https://github.com/juliens)) - **[websocket]** Exclude websocket connections from Average Response Time ([#4313](https://github.com/containous/traefik/pull/4313) by [siyu6974](https://github.com/siyu6974)) -- **[middleware]** Added support for configuring trace headers for DataDog tracing ([#4516](https://github.com/containous/traefik/pull/4516) by [aantono](https://github.com/aantono)) +- **[middleware]** Added support for configuring trace headers for Datadog tracing ([#4516](https://github.com/containous/traefik/pull/4516) by [aantono](https://github.com/aantono)) **Documentation:** - **[acme]** Add _FILE Environment Variable Documentation ([#4643](https://github.com/containous/traefik/pull/4643) by [dargmuesli](https://github.com/dargmuesli)) @@ -670,7 +670,7 @@ - **[metrics]** Metrics: Add support for InfluxDB Database / RetentionPolicy and HTTP client ([#3391](https://github.com/containous/traefik/pull/3391) by [drewkerrigan](https://github.com/drewkerrigan)) - **[middleware,consulcatalog,docker,ecs,kv,marathon,mesos,rancher]** Pass the TLS Cert infos in headers ([#3826](https://github.com/containous/traefik/pull/3826) by [jbdoumenjou](https://github.com/jbdoumenjou)) - **[middleware,server]** Extreme Makeover: server refactoring ([#3461](https://github.com/containous/traefik/pull/3461) by [ldez](https://github.com/ldez)) -- **[middleware,tracing]** Added integration support for DataDog APM Tracing ([#3517](https://github.com/containous/traefik/pull/3517) by [aantono](https://github.com/aantono)) +- **[middleware,tracing]** Added integration support for Datadog APM Tracing ([#3517](https://github.com/containous/traefik/pull/3517) by [aantono](https://github.com/aantono)) - **[middleware,tracing]** Create a custom logger for jaeger ([#3541](https://github.com/containous/traefik/pull/3541) by [mmatur](https://github.com/mmatur)) - **[middleware]** Performance enhancements for the rules matchers. ([#3563](https://github.com/containous/traefik/pull/3563) by [ShaneSaww](https://github.com/ShaneSaww)) - **[middleware]** Extract internal router creation from server ([#3204](https://github.com/containous/traefik/pull/3204) by [Juliens](https://github.com/Juliens)) @@ -731,7 +731,7 @@ - **[oxy]** Handle Te header when http2 ([#3824](https://github.com/containous/traefik/pull/3824) by [Juliens](https://github.com/Juliens)) - **[server]** Avoid goroutine leak in server ([#3851](https://github.com/containous/traefik/pull/3851) by [nmengin](https://github.com/nmengin)) - **[server]** Avoid panic during stop ([#3898](https://github.com/containous/traefik/pull/3898) by [nmengin](https://github.com/nmengin)) -- **[tracing]** Added default configuration for DataDog APM Tracer ([#3655](https://github.com/containous/traefik/pull/3655) by [aantono](https://github.com/aantono)) +- **[tracing]** Added default configuration for Datadog APM Tracer ([#3655](https://github.com/containous/traefik/pull/3655) by [aantono](https://github.com/aantono)) - **[tracing]** Added support for Trace name truncation for traces ([#3689](https://github.com/containous/traefik/pull/3689) by [aantono](https://github.com/aantono)) - **[websocket]** Handle shutdown of Hijacked connections ([#3636](https://github.com/containous/traefik/pull/3636) by [Juliens](https://github.com/Juliens)) - **[webui]** Added Dashboard table item for Rate Limits ([#3893](https://github.com/containous/traefik/pull/3893) by [codecyclist](https://github.com/codecyclist)) @@ -868,7 +868,7 @@ - **[docker]** Uses both binded HostIP and HostPort when useBindPortIP=true ([#3638](https://github.com/containous/traefik/pull/3638) by [geraldcroes](https://github.com/geraldcroes)) - **[k8s]** Fix Rewrite-target regex ([#3699](https://github.com/containous/traefik/pull/3699) by [dtomcej](https://github.com/dtomcej)) - **[middleware]** Correct Entrypoint Redirect with Stripped or Added Path ([#3631](https://github.com/containous/traefik/pull/3631) by [dtomcej](https://github.com/dtomcej)) -- **[tracing]** Added default configuration for DataDog APM Tracer ([#3655](https://github.com/containous/traefik/pull/3655) by [aantono](https://github.com/aantono)) +- **[tracing]** Added default configuration for Datadog APM Tracer ([#3655](https://github.com/containous/traefik/pull/3655) by [aantono](https://github.com/aantono)) - **[tracing]** Added support for Trace name truncation for traces ([#3689](https://github.com/containous/traefik/pull/3689) by [aantono](https://github.com/aantono)) - **[websocket]** Handle shutdown of Hijacked connections ([#3636](https://github.com/containous/traefik/pull/3636) by [Juliens](https://github.com/Juliens)) - H2C: Remove buggy line in init to make verbose switch working ([#3701](https://github.com/containous/traefik/pull/3701) by [dduportal](https://github.com/dduportal)) @@ -964,7 +964,7 @@ - **[mesos]** Segments Labels: Mesos ([#3383](https://github.com/containous/traefik/pull/3383) by [drewkerrigan](https://github.com/drewkerrigan)) - **[metrics]** Metrics: Add support for InfluxDB Database / RetentionPolicy and HTTP client ([#3391](https://github.com/containous/traefik/pull/3391) by [drewkerrigan](https://github.com/drewkerrigan)) - **[middleware,server]** Extreme Makeover: server refactoring ([#3461](https://github.com/containous/traefik/pull/3461) by [ldez](https://github.com/ldez)) -- **[middleware,tracing]** Added integration support for DataDog APM Tracing ([#3517](https://github.com/containous/traefik/pull/3517) by [aantono](https://github.com/aantono)) +- **[middleware,tracing]** Added integration support for Datadog APM Tracing ([#3517](https://github.com/containous/traefik/pull/3517) by [aantono](https://github.com/aantono)) - **[middleware,tracing]** Create a custom logger for jaeger ([#3541](https://github.com/containous/traefik/pull/3541) by [mmatur](https://github.com/mmatur)) - **[middleware]** Performance enhancements for the rules matchers. ([#3563](https://github.com/containous/traefik/pull/3563) by [ShaneSaww](https://github.com/ShaneSaww)) - **[middleware]** Extract internal router creation from server ([#3204](https://github.com/containous/traefik/pull/3204) by [Juliens](https://github.com/Juliens)) @@ -1142,7 +1142,7 @@ - **[metrics]** Added entrypoint metrics to influxdb ([#2992](https://github.com/containous/traefik/pull/2992) by [adityacs](https://github.com/adityacs)) - **[metrics]** Remove unnecessary conversion ([#2850](https://github.com/containous/traefik/pull/2850) by [ferhatelmas](https://github.com/ferhatelmas)) - **[metrics]** Extend metrics and rebuild prometheus exporting logic ([#2567](https://github.com/containous/traefik/pull/2567) by [marco-jantke](https://github.com/marco-jantke)) -- **[metrics]** Added missing metrics to registry for DataDog and StatsD ([#2890](https://github.com/containous/traefik/pull/2890) by [aantono](https://github.com/aantono)) +- **[metrics]** Added missing metrics to registry for Datadog and StatsD ([#2890](https://github.com/containous/traefik/pull/2890) by [aantono](https://github.com/aantono)) - **[middleware,consul,consulcatalog,docker,ecs,k8s,marathon,mesos,rancher]** New option in secure middleware ([#2958](https://github.com/containous/traefik/pull/2958) by [mmatur](https://github.com/mmatur)) - **[middleware,consulcatalog,docker,ecs,k8s,kv,marathon,mesos,rancher]** Ability to use "X-Forwarded-For" as a source of IP for white list. ([#3070](https://github.com/containous/traefik/pull/3070) by [ldez](https://github.com/ldez)) - **[middleware,docker]** Use pointer of error pages ([#2607](https://github.com/containous/traefik/pull/2607) by [ldez](https://github.com/ldez)) @@ -1394,7 +1394,7 @@ - **[mesos]** Add all available labels to Mesos Backend ([#2687](https://github.com/containous/traefik/pull/2687) by [ldez](https://github.com/ldez)) - **[metrics]** Added entrypoint metrics to influxdb ([#2992](https://github.com/containous/traefik/pull/2992) by [adityacs](https://github.com/adityacs)) - **[metrics]** Extend metrics and rebuild prometheus exporting logic ([#2567](https://github.com/containous/traefik/pull/2567) by [marco-jantke](https://github.com/marco-jantke)) -- **[metrics]** Added missing metrics to registry for DataDog and StatsD ([#2890](https://github.com/containous/traefik/pull/2890) by [aantono](https://github.com/aantono)) +- **[metrics]** Added missing metrics to registry for Datadog and StatsD ([#2890](https://github.com/containous/traefik/pull/2890) by [aantono](https://github.com/aantono)) - **[metrics]** Remove unnecessary conversion ([#2850](https://github.com/containous/traefik/pull/2850) by [ferhatelmas](https://github.com/ferhatelmas)) - **[middleware,consul,consulcatalog,docker,ecs,k8s,marathon,mesos,rancher]** New option in secure middleware ([#2958](https://github.com/containous/traefik/pull/2958) by [mmatur](https://github.com/mmatur)) - **[middleware,consulcatalog,docker,ecs,k8s,kv,marathon,mesos,rancher]** Ability to use "X-Forwarded-For" as a source of IP for white list. ([#3070](https://github.com/containous/traefik/pull/3070) by [ldez](https://github.com/ldez)) @@ -2015,12 +2015,12 @@ - **[marathon]** Add support for readiness checks. ([#1883](https://github.com/containous/traefik/pull/1883) by [timoreimann](https://github.com/timoreimann)) - **[marathon]** Move marathon mock ([#1732](https://github.com/containous/traefik/pull/1732) by [ldez](https://github.com/ldez)) - **[marathon]** Use single API call to fetch Marathon resources. ([#1815](https://github.com/containous/traefik/pull/1815) by [timoreimann](https://github.com/timoreimann)) -- **[metrics]** Added RetryMetrics to DataDog and StatsD providers ([#1884](https://github.com/containous/traefik/pull/1884) by [aantono](https://github.com/aantono)) +- **[metrics]** Added RetryMetrics to Datadog and StatsD providers ([#1884](https://github.com/containous/traefik/pull/1884) by [aantono](https://github.com/aantono)) - **[metrics]** Extract metrics to own package and refactor implementations ([#1968](https://github.com/containous/traefik/pull/1968) by [marco-jantke](https://github.com/marco-jantke)) - **[metrics]** Add metrics for backend_retries_total ([#1504](https://github.com/containous/traefik/pull/1504) by [marco-jantke](https://github.com/marco-jantke)) - **[metrics]** Add status code to request duration metric ([#1755](https://github.com/containous/traefik/pull/1755) by [marco-jantke](https://github.com/marco-jantke)) - **[middleware]** Add trusted whitelist proxy protocol ([#2234](https://github.com/containous/traefik/pull/2234) by [emilevauge](https://github.com/emilevauge))) -- **[metrics]** DataDog and StatsD Metrics Support ([#1701](https://github.com/containous/traefik/pull/1701) by [aantono](https://github.com/aantono)) +- **[metrics]** Datadog and StatsD Metrics Support ([#1701](https://github.com/containous/traefik/pull/1701) by [aantono](https://github.com/aantono)) - **[middleware]** Create Header Middleware ([#1236](https://github.com/containous/traefik/pull/1236) by [dtomcej](https://github.com/dtomcej)) - **[middleware]** Add configurable timeouts and curate default timeout settings ([#1873](https://github.com/containous/traefik/pull/1873) by [marco-jantke](https://github.com/marco-jantke)) - **[middleware]** Fix command bug content. ([#2002](https://github.com/containous/traefik/pull/2002) by [ldez](https://github.com/ldez)) @@ -2326,11 +2326,11 @@ - **[marathon]** Move marathon mock ([#1732](https://github.com/containous/traefik/pull/1732) by [ldez](https://github.com/ldez)) - **[marathon]** Support multi-port service routing for containers running on Marathon ([#1742](https://github.com/containous/traefik/pull/1742) by [aantono](https://github.com/aantono)) - **[marathon]** Use test builder. ([#1871](https://github.com/containous/traefik/pull/1871) by [timoreimann](https://github.com/timoreimann)) -- **[metrics]** DataDog and StatsD Metrics Support ([#1701](https://github.com/containous/traefik/pull/1701) by [aantono](https://github.com/aantono)) +- **[metrics]** Datadog and StatsD Metrics Support ([#1701](https://github.com/containous/traefik/pull/1701) by [aantono](https://github.com/aantono)) - **[metrics]** Add status code to request duration metric ([#1755](https://github.com/containous/traefik/pull/1755) by [marco-jantke](https://github.com/marco-jantke)) - **[metrics]** Add metrics for backend_retries_total ([#1504](https://github.com/containous/traefik/pull/1504) by [marco-jantke](https://github.com/marco-jantke)) - **[metrics]** Extract metrics to own package and refactor implementations ([#1968](https://github.com/containous/traefik/pull/1968) by [marco-jantke](https://github.com/marco-jantke)) -- **[metrics]** Added RetryMetrics to DataDog and StatsD providers ([#1884](https://github.com/containous/traefik/pull/1884) by [aantono](https://github.com/aantono)) +- **[metrics]** Added RetryMetrics to Datadog and StatsD providers ([#1884](https://github.com/containous/traefik/pull/1884) by [aantono](https://github.com/aantono)) - **[middleware]** Return 503 on empty backend ([#1748](https://github.com/containous/traefik/pull/1748) by [marco-jantke](https://github.com/marco-jantke)) - **[middleware]** Add configurable timeouts and curate default timeout settings ([#1873](https://github.com/containous/traefik/pull/1873) by [marco-jantke](https://github.com/marco-jantke)) - **[middleware]** Custom Error Pages ([#1675](https://github.com/containous/traefik/pull/1675) by [bparli](https://github.com/bparli)) diff --git a/docs/content/observability/metrics/datadog.md b/docs/content/observability/metrics/datadog.md index 00af98c58..cb412a383 100644 --- a/docs/content/observability/metrics/datadog.md +++ b/docs/content/observability/metrics/datadog.md @@ -1,15 +1,15 @@ -# DataDog +# Datadog -To enable the DataDog: +To enable the Datadog: ```toml tab="File (TOML)" [metrics] - [metrics.dataDog] + [metrics.datadog] ``` ```yaml tab="File (YAML)" metrics: - dataDog: {} + datadog: {} ``` ```bash tab="CLI" @@ -24,13 +24,13 @@ Address instructs exporter to send metrics to datadog-agent at this address. ```toml tab="File (TOML)" [metrics] - [metrics.dataDog] + [metrics.datadog] address = "127.0.0.1:8125" ``` ```yaml tab="File (YAML)" metrics: - dataDog: + datadog: address: 127.0.0.1:8125 ``` @@ -46,13 +46,13 @@ Enable metrics on entry points. ```toml tab="File (TOML)" [metrics] - [metrics.dataDog] + [metrics.datadog] addEntryPointsLabels = true ``` ```yaml tab="File (YAML)" metrics: - dataDog: + datadog: addEntryPointsLabels: true ``` @@ -68,13 +68,13 @@ Enable metrics on services. ```toml tab="File (TOML)" [metrics] - [metrics.dataDog] + [metrics.datadog] addServicesLabels = true ``` ```yaml tab="File (YAML)" metrics: - dataDog: + datadog: addServicesLabels: true ``` @@ -90,13 +90,13 @@ The interval used by the exporter to push metrics to datadog-agent. ```toml tab="File (TOML)" [metrics] - [metrics.dataDog] + [metrics.datadog] pushInterval = 10s ``` ```yaml tab="File (YAML)" metrics: - dataDog: + datadog: pushInterval: 10s ``` diff --git a/docs/content/observability/metrics/overview.md b/docs/content/observability/metrics/overview.md index f7d148fbf..07fbb9667 100644 --- a/docs/content/observability/metrics/overview.md +++ b/docs/content/observability/metrics/overview.md @@ -4,7 +4,7 @@ Metrics system Traefik supports 4 metrics backends: -- [DataDog](./datadog.md) +- [Datadog](./datadog.md) - [InfluxDB](./influxdb.md) - [Prometheus](./prometheus.md) - [StatsD](./statsd.md) diff --git a/docs/content/observability/tracing/datadog.md b/docs/content/observability/tracing/datadog.md index 5f3ed46b5..844f4fc70 100644 --- a/docs/content/observability/tracing/datadog.md +++ b/docs/content/observability/tracing/datadog.md @@ -1,15 +1,15 @@ -# DataDog +# Datadog -To enable the DataDog: +To enable the Datadog: ```toml tab="File (TOML)" [tracing] - [tracing.dataDog] + [tracing.datadog] ``` ```yaml tab="File (YAML)" tracing: - dataDog: {} + datadog: {} ``` ```bash tab="CLI" @@ -24,13 +24,13 @@ Local Agent Host Port instructs reporter to send spans to datadog-tracing-agent ```toml tab="File (TOML)" [tracing] - [tracing.dataDog] + [tracing.datadog] localAgentHostPort = "127.0.0.1:8126" ``` ```yaml tab="File (YAML)" tracing: - dataDog: + datadog: localAgentHostPort: 127.0.0.1:8126 ``` @@ -42,17 +42,17 @@ tracing: _Optional, Default=false_ -Enable DataDog debug. +Enable Datadog debug. ```toml tab="File (TOML)" [tracing] - [tracing.dataDog] + [tracing.datadog] debug = true ``` ```yaml tab="File (YAML)" tracing: - dataDog: + datadog: debug: true ``` @@ -68,13 +68,13 @@ Apply shared tag in a form of Key:Value to all the traces. ```toml tab="File (TOML)" [tracing] - [tracing.dataDog] + [tracing.datadog] globalTag = "sample" ``` ```yaml tab="File (YAML)" tracing: - dataDog: + datadog: globalTag: sample ``` @@ -91,13 +91,13 @@ this option must be enabled in order to get all the parts of a distributed trace ```toml tab="File (TOML)" [tracing] - [tracing.dataDog] + [tracing.datadog] prioritySampling = true ``` ```yaml tab="File (YAML)" tracing: - dataDog: + datadog: prioritySampling: true ``` diff --git a/docs/content/observability/tracing/overview.md b/docs/content/observability/tracing/overview.md index 543f0a354..a6cb8dbd8 100644 --- a/docs/content/observability/tracing/overview.md +++ b/docs/content/observability/tracing/overview.md @@ -11,7 +11,7 @@ Traefik supports five tracing backends: - [Jaeger](./jaeger.md) - [Zipkin](./zipkin.md) -- [DataDog](./datadog.md) +- [Datadog](./datadog.md) - [Instana](./instana.md) - [Haystack](./haystack.md) diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 55ebff757..25997d83b 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -151,19 +151,19 @@ Traefik log format: json | common (Default: ```common```) Log level set to traefik logs. (Default: ```ERROR```) `--metrics.datadog`: -DataDog metrics exporter type. (Default: ```false```) +Datadog metrics exporter type. (Default: ```false```) `--metrics.datadog.addentrypointslabels`: Enable metrics on entry points. (Default: ```true```) `--metrics.datadog.address`: -DataDog's address. (Default: ```localhost:8125```) +Datadog's address. (Default: ```localhost:8125```) `--metrics.datadog.addserviceslabels`: Enable metrics on services. (Default: ```true```) `--metrics.datadog.pushinterval`: -DataDog push interval. (Default: ```10```) +Datadog push interval. (Default: ```10```) `--metrics.influxdb`: InfluxDB metrics exporter type. (Default: ```false```) @@ -457,13 +457,13 @@ Add cert file for self-signed certificate. OpenTracing configuration. (Default: ```false```) `--tracing.datadog`: -Settings for DataDog. (Default: ```false```) +Settings for Datadog. (Default: ```false```) `--tracing.datadog.bagageprefixheadername`: Specifies the header name prefix that will be used to store baggage items in a map. `--tracing.datadog.debug`: -Enable DataDog debug. (Default: ```false```) +Enable Datadog debug. (Default: ```false```) `--tracing.datadog.globaltag`: Key:Value tag to be set on all the spans. diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index e578642e9..d199ae786 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -151,19 +151,19 @@ Traefik log format: json | common (Default: ```common```) Log level set to traefik logs. (Default: ```ERROR```) `TRAEFIK_METRICS_DATADOG`: -DataDog metrics exporter type. (Default: ```false```) +Datadog metrics exporter type. (Default: ```false```) `TRAEFIK_METRICS_DATADOG_ADDENTRYPOINTSLABELS`: Enable metrics on entry points. (Default: ```true```) `TRAEFIK_METRICS_DATADOG_ADDRESS`: -DataDog's address. (Default: ```localhost:8125```) +Datadog's address. (Default: ```localhost:8125```) `TRAEFIK_METRICS_DATADOG_ADDSERVICESLABELS`: Enable metrics on services. (Default: ```true```) `TRAEFIK_METRICS_DATADOG_PUSHINTERVAL`: -DataDog push interval. (Default: ```10```) +Datadog push interval. (Default: ```10```) `TRAEFIK_METRICS_INFLUXDB`: InfluxDB metrics exporter type. (Default: ```false```) @@ -457,13 +457,13 @@ Add cert file for self-signed certificate. OpenTracing configuration. (Default: ```false```) `TRAEFIK_TRACING_DATADOG`: -Settings for DataDog. (Default: ```false```) +Settings for Datadog. (Default: ```false```) `TRAEFIK_TRACING_DATADOG_BAGAGEPREFIXHEADERNAME`: Specifies the header name prefix that will be used to store baggage items in a map. `TRAEFIK_TRACING_DATADOG_DEBUG`: -Enable DataDog debug. (Default: ```false```) +Enable Datadog debug. (Default: ```false```) `TRAEFIK_TRACING_DATADOG_GLOBALTAG`: Key:Value tag to be set on all the spans. diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 8c75d5170..ca9ea195b 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -115,7 +115,7 @@ buckets = [42.0, 42.0] addEntryPointsLabels = true addServicesLabels = true - [metrics.dataDog] + [metrics.datadog] address = "foobar" pushInterval = "10s" addEntryPointsLabels = true @@ -183,7 +183,7 @@ id128Bit = true debug = true sampleRate = 42.0 - [tracing.dataDog] + [tracing.datadog] localAgentHostPort = "foobar" globalTag = "foobar" debug = true diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index f6a91a75c..2c94f0947 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -122,7 +122,7 @@ metrics: - 42 addEntryPointsLabels: true addServicesLabels: true - dataDog: + datadog: address: foobar pushInterval: 42 addEntryPointsLabels: true @@ -188,7 +188,7 @@ tracing: id128Bit: true debug: true sampleRate: 42 - dataDog: + datadog: localAgentHostPort: foobar globalTag: foobar debug: true diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 533ffc2f7..b7f09c0e1 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -122,7 +122,7 @@ nav: - 'Access Logs': 'observability/access-logs.md' - 'Metrics': - 'Overview': 'observability/metrics/overview.md' - - 'DataDog': 'observability/metrics/datadog.md' + - 'Datadog': 'observability/metrics/datadog.md' - 'InfluxDB': 'observability/metrics/influxdb.md' - 'Prometheus': 'observability/metrics/prometheus.md' - 'StatsD': 'observability/metrics/statsd.md' @@ -130,7 +130,7 @@ nav: - 'Overview': 'observability/tracing/overview.md' - 'Jaeger': 'observability/tracing/jaeger.md' - 'Zipkin': 'observability/tracing/zipkin.md' - - 'DataDog': 'observability/tracing/datadog.md' + - 'Datadog': 'observability/tracing/datadog.md' - 'Instana': 'observability/tracing/instana.md' - 'Haystack': 'observability/tracing/haystack.md' - 'User Guides': diff --git a/pkg/anonymize/anonymize_config_test.go b/pkg/anonymize/anonymize_config_test.go index 6dfd372f7..179bf45d2 100644 --- a/pkg/anonymize/anonymize_config_test.go +++ b/pkg/anonymize/anonymize_config_test.go @@ -186,7 +186,7 @@ func TestDo_globalConfiguration(t *testing.T) { Prometheus: &types.Prometheus{ Buckets: []float64{0.1, 0.3, 1.2, 5}, }, - DataDog: &types.DataDog{ + Datadog: &types.Datadog{ Address: "localhost:8181", PushInterval: 12, }, @@ -226,7 +226,7 @@ func TestDo_globalConfiguration(t *testing.T) { Debug: true, SampleRate: 53, }, - DataDog: &datadog.Config{ + Datadog: &datadog.Config{ LocalAgentHostPort: "ggg", GlobalTag: "eee", Debug: true, diff --git a/pkg/config/dynamic/fixtures/sample.toml b/pkg/config/dynamic/fixtures/sample.toml index a90cee3f6..53e9db906 100644 --- a/pkg/config/dynamic/fixtures/sample.toml +++ b/pkg/config/dynamic/fixtures/sample.toml @@ -119,7 +119,7 @@ buckets = [42.0, 42.0] entryPoint = "foobar" middlewares = ["foobar", "foobar"] - [metrics.dataDog] + [metrics.datadog] address = "foobar" pushInterval = "10s" [metrics.statsD] @@ -179,7 +179,7 @@ id128Bit = true debug = true sampleRate = 42.0 - [tracing.dataDog] + [tracing.datadog] localAgentHostPort = "foobar" globalTag = "foobar" debug = true diff --git a/pkg/config/file/file_node_test.go b/pkg/config/file/file_node_test.go index 1d9db2cde..0a7ed6720 100644 --- a/pkg/config/file/file_node_test.go +++ b/pkg/config/file/file_node_test.go @@ -143,7 +143,7 @@ func Test_decodeFileToNode_Toml(t *testing.T) { {Name: "format", Value: "foobar"}, {Name: "level", Value: "foobar"}}}, {Name: "metrics", Children: []*parser.Node{ - {Name: "dataDog", Children: []*parser.Node{ + {Name: "datadog", Children: []*parser.Node{ {Name: "address", Value: "foobar"}, {Name: "pushInterval", Value: "10s"}}}, {Name: "influxDB", Children: []*parser.Node{ @@ -251,7 +251,7 @@ func Test_decodeFileToNode_Toml(t *testing.T) { {Name: "maxIdleConnsPerHost", Value: "42"}, {Name: "rootCAs", Value: "foobar,foobar"}}}, {Name: "tracing", Children: []*parser.Node{ - {Name: "dataDog", Children: []*parser.Node{ + {Name: "datadog", Children: []*parser.Node{ {Name: "bagagePrefixHeaderName", Value: "foobar"}, {Name: "debug", Value: "true"}, {Name: "globalTag", Value: "foobar"}, @@ -378,7 +378,7 @@ func Test_decodeFileToNode_Yaml(t *testing.T) { {Name: "format", Value: "foobar"}, {Name: "level", Value: "foobar"}}}, {Name: "metrics", Children: []*parser.Node{ - {Name: "dataDog", Children: []*parser.Node{ + {Name: "datadog", Children: []*parser.Node{ {Name: "address", Value: "foobar"}, {Name: "pushInterval", Value: "10s"}}}, {Name: "influxDB", Children: []*parser.Node{ @@ -486,7 +486,7 @@ func Test_decodeFileToNode_Yaml(t *testing.T) { {Name: "maxIdleConnsPerHost", Value: "42"}, {Name: "rootCAs", Value: "foobar,foobar"}}}, {Name: "tracing", Children: []*parser.Node{ - {Name: "dataDog", Children: []*parser.Node{ + {Name: "datadog", Children: []*parser.Node{ {Name: "bagagePrefixHeaderName", Value: "foobar"}, {Name: "debug", Value: "true"}, {Name: "globalTag", Value: "foobar"}, diff --git a/pkg/config/file/fixtures/sample.toml b/pkg/config/file/fixtures/sample.toml index 920ee573b..53c7cc0a1 100644 --- a/pkg/config/file/fixtures/sample.toml +++ b/pkg/config/file/fixtures/sample.toml @@ -119,7 +119,7 @@ buckets = [42.0, 42.0] entryPoint = "foobar" middlewares = ["foobar", "foobar"] - [metrics.dataDog] + [metrics.datadog] address = "foobar" pushInterval = "10s" [metrics.statsD] @@ -179,7 +179,7 @@ id128Bit = true debug = true sampleRate = 42.0 - [tracing.dataDog] + [tracing.datadog] localAgentHostPort = "foobar" globalTag = "foobar" debug = true diff --git a/pkg/config/file/fixtures/sample.yml b/pkg/config/file/fixtures/sample.yml index 1cbd3e724..e22829d50 100644 --- a/pkg/config/file/fixtures/sample.yml +++ b/pkg/config/file/fixtures/sample.yml @@ -130,7 +130,7 @@ metrics: middlewares: - foobar - foobar - dataDog: + datadog: address: foobar pushInterval: 10s statsD: @@ -190,7 +190,7 @@ tracing: id128Bit: true debug: true sampleRate: 42 - dataDog: + datadog: localAgentHostPort: foobar globalTag: foobar debug: true diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index a701b5e6c..3dcf771a9 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -139,7 +139,7 @@ type Tracing struct { SpanNameLimit int `description:"Set the maximum character limit for Span names (default 0 = no limit)." json:"spanNameLimit,omitempty" toml:"spanNameLimit,omitempty" yaml:"spanNameLimit,omitempty" export:"true"` Jaeger *jaeger.Config `description:"Settings for Jaeger." json:"jaeger,omitempty" toml:"jaeger,omitempty" yaml:"jaeger,omitempty" export:"true" label:"allowEmpty"` Zipkin *zipkin.Config `description:"Settings for Zipkin." json:"zipkin,omitempty" toml:"zipkin,omitempty" yaml:"zipkin,omitempty" export:"true" label:"allowEmpty"` - DataDog *datadog.Config `description:"Settings for DataDog." json:"dataDog,omitempty" toml:"dataDog,omitempty" yaml:"dataDog,omitempty" export:"true" label:"allowEmpty"` + Datadog *datadog.Config `description:"Settings for Datadog." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" export:"true" label:"allowEmpty"` Instana *instana.Config `description:"Settings for Instana." json:"instana,omitempty" toml:"instana,omitempty" yaml:"instana,omitempty" export:"true" label:"allowEmpty"` Haystack *haystack.Config `description:"Settings for Haystack." json:"haystack,omitempty" toml:"haystack,omitempty" yaml:"haystack,omitempty" export:"true" label:"allowEmpty"` } diff --git a/pkg/metrics/datadog.go b/pkg/metrics/datadog.go index fcd564461..988fb0b7a 100644 --- a/pkg/metrics/datadog.go +++ b/pkg/metrics/datadog.go @@ -35,7 +35,7 @@ const ( ) // RegisterDatadog registers the metrics pusher if this didn't happen yet and creates a datadog Registry instance. -func RegisterDatadog(ctx context.Context, config *types.DataDog) Registry { +func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry { if datadogTicker == nil { datadogTicker = initDatadogClient(ctx, config) } @@ -66,7 +66,7 @@ func RegisterDatadog(ctx context.Context, config *types.DataDog) Registry { return registry } -func initDatadogClient(ctx context.Context, config *types.DataDog) *time.Ticker { +func initDatadogClient(ctx context.Context, config *types.Datadog) *time.Ticker { address := config.Address if len(address) == 0 { address = "localhost:8125" diff --git a/pkg/metrics/datadog_test.go b/pkg/metrics/datadog_test.go index 32e4fc1d7..08a85061c 100644 --- a/pkg/metrics/datadog_test.go +++ b/pkg/metrics/datadog_test.go @@ -16,7 +16,7 @@ func TestDatadog(t *testing.T) { // 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 - datadogRegistry := RegisterDatadog(context.Background(), &types.DataDog{Address: ":18125", PushInterval: types.Duration(time.Second), AddEntryPointsLabels: true, AddServicesLabels: true}) + datadogRegistry := RegisterDatadog(context.Background(), &types.Datadog{Address: ":18125", PushInterval: types.Duration(time.Second), AddEntryPointsLabels: true, AddServicesLabels: true}) defer StopDatadog() if !datadogRegistry.IsEpEnabled() || !datadogRegistry.IsSvcEnabled() { diff --git a/pkg/server/server.go b/pkg/server/server.go index 59dca31b3..5a62e75c7 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -66,11 +66,11 @@ func setupTracing(conf *static.Tracing) tracing.Backend { } } - if conf.DataDog != nil { + if conf.Datadog != nil { if backend != nil { - log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create DataDog backend.") + log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Datadog backend.") } else { - backend = conf.DataDog + backend = conf.Datadog } } @@ -307,11 +307,11 @@ func registerMetricClients(metricsConfig *types.Metrics) metrics.Registry { } } - if metricsConfig.DataDog != nil { + if metricsConfig.Datadog != nil { ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "datadog")) - registries = append(registries, metrics.RegisterDatadog(ctx, metricsConfig.DataDog)) - log.FromContext(ctx).Debugf("Configured DataDog metrics: pushing to %s once every %s", - metricsConfig.DataDog.Address, metricsConfig.DataDog.PushInterval) + registries = append(registries, metrics.RegisterDatadog(ctx, metricsConfig.Datadog)) + log.FromContext(ctx).Debugf("Configured Datadog metrics: pushing to %s once every %s", + metricsConfig.Datadog.Address, metricsConfig.Datadog.PushInterval) } if metricsConfig.StatsD != nil { diff --git a/pkg/tracing/datadog/datadog.go b/pkg/tracing/datadog/datadog.go index d297fe916..71589a92a 100644 --- a/pkg/tracing/datadog/datadog.go +++ b/pkg/tracing/datadog/datadog.go @@ -17,7 +17,7 @@ const Name = "datadog" type Config struct { LocalAgentHostPort string `description:"Set datadog-agent's host:port that the reporter will used." json:"localAgentHostPort,omitempty" toml:"localAgentHostPort,omitempty" yaml:"localAgentHostPort,omitempty"` GlobalTag string `description:"Key:Value tag to be set on all the spans." json:"globalTag,omitempty" toml:"globalTag,omitempty" yaml:"globalTag,omitempty" export:"true"` - Debug bool `description:"Enable DataDog debug." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"` + Debug bool `description:"Enable Datadog debug." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"` PrioritySampling bool `description:"Enable 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"` TraceIDHeaderName string `description:"Specifies the header name that will be used to store the trace ID." json:"traceIDHeaderName,omitempty" toml:"traceIDHeaderName,omitempty" yaml:"traceIDHeaderName,omitempty" export:"true"` ParentIDHeaderName string `description:"Specifies the header name that will be used to store the parent ID." json:"parentIDHeaderName,omitempty" toml:"parentIDHeaderName,omitempty" yaml:"parentIDHeaderName,omitempty" export:"true"` @@ -62,7 +62,7 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error // Without this, child spans are getting the NOOP tracer opentracing.SetGlobalTracer(tracer) - log.WithoutContext().Debug("DataDog tracer configured") + log.WithoutContext().Debug("Datadog tracer configured") return tracer, nil, nil } diff --git a/pkg/tracing/haystack/haystack.go b/pkg/tracing/haystack/haystack.go index aa48375de..47b6266e6 100644 --- a/pkg/tracing/haystack/haystack.go +++ b/pkg/tracing/haystack/haystack.go @@ -63,7 +63,7 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error // Without this, child spans are getting the NOOP tracer opentracing.SetGlobalTracer(tracer) - log.WithoutContext().Debug("DataDog tracer configured") + log.WithoutContext().Debug("haystack tracer configured") return tracer, closer, nil } diff --git a/pkg/types/metrics.go b/pkg/types/metrics.go index f05d1a77c..dc25367b7 100644 --- a/pkg/types/metrics.go +++ b/pkg/types/metrics.go @@ -7,7 +7,7 @@ import ( // Metrics provides options to expose and send Traefik metrics to different third party monitoring systems. type Metrics struct { Prometheus *Prometheus `description:"Prometheus metrics exporter type." json:"prometheus,omitempty" toml:"prometheus,omitempty" yaml:"prometheus,omitempty" export:"true" label:"allowEmpty"` - DataDog *DataDog `description:"DataDog metrics exporter type." json:"dataDog,omitempty" toml:"dataDog,omitempty" yaml:"dataDog,omitempty" export:"true" label:"allowEmpty"` + Datadog *Datadog `description:"Datadog metrics exporter type." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" export:"true" label:"allowEmpty"` StatsD *Statsd `description:"StatsD metrics exporter type." json:"statsD,omitempty" toml:"statsD,omitempty" yaml:"statsD,omitempty" export:"true" label:"allowEmpty"` InfluxDB *InfluxDB `description:"InfluxDB metrics exporter type." json:"influxDB,omitempty" toml:"influxDB,omitempty" yaml:"influxDB,omitempty" label:"allowEmpty"` } @@ -26,16 +26,16 @@ func (p *Prometheus) SetDefaults() { p.AddServicesLabels = true } -// DataDog contains address and metrics pushing interval configuration. -type DataDog struct { - Address string `description:"DataDog's address." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` - PushInterval Duration `description:"DataDog push interval." json:"pushInterval,omitempty" toml:"pushInterval,omitempty" yaml:"pushInterval,omitempty" export:"true"` +// Datadog contains address and metrics pushing interval configuration. +type Datadog struct { + Address string `description:"Datadog's address." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` + PushInterval Duration `description:"Datadog push interval." json:"pushInterval,omitempty" toml:"pushInterval,omitempty" yaml:"pushInterval,omitempty" export:"true"` AddEntryPointsLabels bool `description:"Enable metrics on entry points." json:"addEntryPointsLabels,omitempty" toml:"addEntryPointsLabels,omitempty" yaml:"addEntryPointsLabels,omitempty" export:"true"` AddServicesLabels bool `description:"Enable metrics on services." json:"addServicesLabels,omitempty" toml:"addServicesLabels,omitempty" yaml:"addServicesLabels,omitempty" export:"true"` } // SetDefaults sets the default values. -func (d *DataDog) SetDefaults() { +func (d *Datadog) SetDefaults() { d.Address = "localhost:8125" d.PushInterval = Duration(10 * time.Second) d.AddEntryPointsLabels = true From 07eb9c5970e8d19b175aebd462bca9fb6bf1b128 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 2 Sep 2019 12:26:04 +0200 Subject: [PATCH 10/37] Update restrictions in the documentation. --- docs/content/contributing/data-collection.md | 2 +- docs/content/https/tls.md | 10 +++++----- docs/content/operations/api.md | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/content/contributing/data-collection.md b/docs/content/contributing/data-collection.md index 03a6d90bc..4442fc78e 100644 --- a/docs/content/contributing/data-collection.md +++ b/docs/content/contributing/data-collection.md @@ -9,7 +9,7 @@ Understanding how you use Traefik is very important to us: it helps us improve t For this very reason, the sendAnonymousUsage option is mandatory: we want you to take time to consider whether or not you wish to share anonymous data with us so we can benefit from your experience and use cases. !!! warning - During the beta stage only, leaving this option unset will not prevent Traefik from running but will generate an error log indicating that it enables data collection by default. + Before the GA, leaving this option unset will not prevent Traefik from running but will generate an error log indicating that it enables data collection by default. !!! example "Enabling Data Collection" diff --git a/docs/content/https/tls.md b/docs/content/https/tls.md index d9dd7b850..21cbe5835 100644 --- a/docs/content/https/tls.md +++ b/docs/content/https/tls.md @@ -35,7 +35,7 @@ tls: !!! important "File Provider Only" In the above example, we've used the [file provider](../providers/file.md) to handle these definitions. - In its current beta version, it is the only available method to configure the certificates (as well as the options and the stores). + It is the only available method to configure the certificates (as well as the options and the stores). ## Certificates Stores @@ -52,9 +52,9 @@ tls: default: {} ``` -!!! important "Beta restriction" +!!! important "Restriction" - During the beta version, any store definition other than the default one (named `default`) will be ignored, + Any store definition other than the default one (named `default`) will be ignored, and there is thefore only one globally available TLS store. In the `tls.certificates` section, a list of stores can then be specified to indicate where the certificates should be stored: @@ -85,9 +85,9 @@ tls: keyFile: /path/to/other-domain.key ``` -!!! important "Beta restriction" +!!! important "Restriction" - During the beta version, the `stores` list will actually be ignored and automatically set to `["default"]`. + The `stores` list will actually be ignored and automatically set to `["default"]`. ### Default Certificate diff --git a/docs/content/operations/api.md b/docs/content/operations/api.md index 1cae400b5..6cbd012c9 100644 --- a/docs/content/operations/api.md +++ b/docs/content/operations/api.md @@ -1,7 +1,7 @@ # API !!! important - In the beta version, you can't configure middlewares (basic authentication or white listing) anymore, but as security is important, this will change before the RC version. + In the RC version, you can't configure middlewares (basic authentication or white listing) anymore, but as security is important, this will change before the GA version. Traefik exposes a number of information through an API handler, such as the configuration of all routers, services, middlewares, etc. From cb7c5a8ca118c97df229f0343ff42a91feef8c5d Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Tue, 3 Sep 2019 11:52:04 +0200 Subject: [PATCH 11/37] Update Zipkin OpenTracing driver to latest 0.4.3 release --- docs/content/observability/tracing/zipkin.md | 34 +++-------------- .../reference/static-configuration/cli-ref.md | 5 +-- .../reference/static-configuration/env-ref.md | 5 +-- .../reference/static-configuration/file.toml | 1 - .../reference/static-configuration/file.yaml | 1 - go.mod | 6 +-- go.sum | 12 +++++- .../fixtures/tracing/simple-zipkin.toml | 3 +- integration/resources/compose/tracing.yml | 2 +- pkg/anonymize/anonymize_config_test.go | 1 - pkg/config/file/file_node_test.go | 2 - pkg/config/file/fixtures/sample.toml | 1 - pkg/config/file/fixtures/sample.yml | 1 - pkg/tracing/zipkin/zipkin.go | 38 ++++++++++++------- 14 files changed, 48 insertions(+), 64 deletions(-) diff --git a/docs/content/observability/tracing/zipkin.md b/docs/content/observability/tracing/zipkin.md index 101040566..8aa1c0283 100644 --- a/docs/content/observability/tracing/zipkin.md +++ b/docs/content/observability/tracing/zipkin.md @@ -18,46 +18,24 @@ tracing: #### `httpEndpoint` -_Required, Default="http://localhost:9411/api/v1/spans"_ +_Required, Default="http://localhost:9411/api/v2/spans"_ Zipkin HTTP endpoint used to send data. ```toml tab="File (TOML)" [tracing] [tracing.zipkin] - httpEndpoint = "http://localhost:9411/api/v1/spans" + httpEndpoint = "http://localhost:9411/api/v2/spans" ``` ```yaml tab="File (YAML)" tracing: zipkin: - httpEndpoint: http://localhost:9411/api/v1/spans + httpEndpoint: http://localhost:9411/api/v2/spans ``` ```bash tab="CLI" ---tracing.zipkin.httpEndpoint="http://localhost:9411/api/v1/spans" -``` - -#### `debug` - -_Optional, Default=false_ - -Enable Zipkin debug. - -```toml tab="File (TOML)" -[tracing] - [tracing.zipkin] - debug = true -``` - -```yaml tab="File (YAML)" -tracing: - zipkin: - debug: true -``` - -```bash tab="CLI" ---tracing.zipkin.debug=true +--tracing.zipkin.httpEndpoint="http://localhost:9411/api/v2/spans" ``` #### `sameSpan` @@ -86,7 +64,7 @@ tracing: _Optional, Default=true_ -Use Zipkin 128 bit root span IDs. +Use Zipkin 128 bit trace IDs. ```toml tab="File (TOML)" [tracing] @@ -124,4 +102,4 @@ tracing: ```bash tab="CLI" --tracing.zipkin.sampleRate="0.2" -``` \ No newline at end of file +``` diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 25997d83b..ecea25aa8 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -561,11 +561,8 @@ Set the maximum character limit for Span names (default 0 = no limit). (Default: `--tracing.zipkin`: Settings for Zipkin. (Default: ```false```) -`--tracing.zipkin.debug`: -Enable Zipkin debug. (Default: ```false```) - `--tracing.zipkin.httpendpoint`: -HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v1/spans```) +HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v2/spans```) `--tracing.zipkin.id128bit`: Use Zipkin 128 bit root span IDs. (Default: ```true```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index d199ae786..194cd0897 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -561,11 +561,8 @@ Set the maximum character limit for Span names (default 0 = no limit). (Default: `TRAEFIK_TRACING_ZIPKIN`: Settings for Zipkin. (Default: ```false```) -`TRAEFIK_TRACING_ZIPKIN_DEBUG`: -Enable Zipkin debug. (Default: ```false```) - `TRAEFIK_TRACING_ZIPKIN_HTTPENDPOINT`: -HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v1/spans```) +HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v2/spans```) `TRAEFIK_TRACING_ZIPKIN_ID128BIT`: Use Zipkin 128 bit root span IDs. (Default: ```true```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index ca9ea195b..b4d1f88b8 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -181,7 +181,6 @@ httpEndpoint = "foobar" sameSpan = true id128Bit = true - debug = true sampleRate = 42.0 [tracing.datadog] localAgentHostPort = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 2c94f0947..12f7c011f 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -186,7 +186,6 @@ tracing: httpEndpoint: foobar sameSpan: true id128Bit: true - debug: true sampleRate: 42 datadog: localAgentHostPort: foobar diff --git a/go.mod b/go.mod index faffae895..c910ddf8f 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/golang/protobuf v1.3.2 github.com/google/go-github/v28 v28.0.0 github.com/googleapis/gnostic v0.1.0 // indirect - github.com/gorilla/mux v1.6.2 + github.com/gorilla/mux v1.7.3 github.com/gorilla/websocket v1.4.0 github.com/hashicorp/go-version v1.2.0 github.com/huandu/xstrings v1.2.0 // indirect @@ -65,10 +65,10 @@ require ( github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v1.0.0-rc8 // indirect - github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect github.com/opentracing/basictracer-go v1.0.0 // indirect github.com/opentracing/opentracing-go v1.1.0 - github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5 + github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.3 + github.com/openzipkin/zipkin-go v0.2.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/philhofer/fwd v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 diff --git a/go.sum b/go.sum index 8932bc8e5..aa48a1794 100644 --- a/go.sum +++ b/go.sum @@ -161,6 +161,7 @@ github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZi github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -193,6 +194,7 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI= @@ -317,6 +319,7 @@ github.com/linode/linodego v0.10.0 h1:AMdb82HVgY8o3mjBXJcUv9B+fnJjfDMn2rNRGbX+jv github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= 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/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 h1:Kg/NPZLLC3aAFr1YToMs98dbCdhootQ1hZIvZU28hAQ= @@ -383,9 +386,11 @@ github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7l github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5 h1:82Tnq9OJpn+h5xgGpss5/mOv3KXdjtkdorFSOUusjM8= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5/go.mod h1:uVHyebswE1cCXr2A73cRM2frx5ld1RJUCJkFNZ90ZiI= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.3 h1:XudIMByQMXJ6oDHy4SipNyo35LxjA69Z7v1nL0aAZvA= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.3/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1 h1:noL5/5Uf1HpVl3wNsfkZhIKbSWCVi5jgqkONNx8PXcA= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/oracle/oci-go-sdk v7.0.0+incompatible h1:oj5ESjXwwkFRdhZSnPlShvLWYdt/IZ65RQxveYM3maA= github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014 h1:37VE5TYj2m/FLA9SNr4z0+A0JefvTmR60Zwf8XSEV7c= @@ -396,6 +401,7 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -441,6 +447,7 @@ github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2 github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -604,6 +611,7 @@ google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3 google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM= diff --git a/integration/fixtures/tracing/simple-zipkin.toml b/integration/fixtures/tracing/simple-zipkin.toml index 46f8ff697..41f858dbe 100644 --- a/integration/fixtures/tracing/simple-zipkin.toml +++ b/integration/fixtures/tracing/simple-zipkin.toml @@ -14,8 +14,7 @@ [tracing] servicename = "tracing" [tracing.zipkin] - httpEndpoint = "http://{{.IP}}:9411/api/v1/spans" - debug = true + httpEndpoint = "http://{{.IP}}:9411/api/v2/spans" [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/resources/compose/tracing.yml b/integration/resources/compose/tracing.yml index 51f3eb8f0..2e3f1de7b 100644 --- a/integration/resources/compose/tracing.yml +++ b/integration/resources/compose/tracing.yml @@ -1,5 +1,5 @@ zipkin: - image: openzipkin/zipkin:2.12.6 + image: openzipkin/zipkin:2.16.2 environment: STORAGE_TYPE: mem JAVA_OPTS: -Dlogging.level.zipkin=DEBUG diff --git a/pkg/anonymize/anonymize_config_test.go b/pkg/anonymize/anonymize_config_test.go index 179bf45d2..683c70a1b 100644 --- a/pkg/anonymize/anonymize_config_test.go +++ b/pkg/anonymize/anonymize_config_test.go @@ -223,7 +223,6 @@ func TestDo_globalConfiguration(t *testing.T) { HTTPEndpoint: "fff", SameSpan: true, ID128Bit: true, - Debug: true, SampleRate: 53, }, Datadog: &datadog.Config{ diff --git a/pkg/config/file/file_node_test.go b/pkg/config/file/file_node_test.go index 0a7ed6720..4b5b4e975 100644 --- a/pkg/config/file/file_node_test.go +++ b/pkg/config/file/file_node_test.go @@ -282,7 +282,6 @@ func Test_decodeFileToNode_Toml(t *testing.T) { {Name: "serviceName", Value: "foobar"}, {Name: "spanNameLimit", Value: "42"}, {Name: "zipkin", Children: []*parser.Node{ - {Name: "debug", Value: "true"}, {Name: "httpEndpoint", Value: "foobar"}, {Name: "id128Bit", Value: "true"}, {Name: "sameSpan", Value: "true"}, @@ -517,7 +516,6 @@ func Test_decodeFileToNode_Yaml(t *testing.T) { {Name: "serviceName", Value: "foobar"}, {Name: "spanNameLimit", Value: "42"}, {Name: "zipkin", Children: []*parser.Node{ - {Name: "debug", Value: "true"}, {Name: "httpEndpoint", Value: "foobar"}, {Name: "id128Bit", Value: "true"}, {Name: "sameSpan", Value: "true"}, diff --git a/pkg/config/file/fixtures/sample.toml b/pkg/config/file/fixtures/sample.toml index 53c7cc0a1..0b1ff7f17 100644 --- a/pkg/config/file/fixtures/sample.toml +++ b/pkg/config/file/fixtures/sample.toml @@ -177,7 +177,6 @@ httpEndpoint = "foobar" sameSpan = true id128Bit = true - debug = true sampleRate = 42.0 [tracing.datadog] localAgentHostPort = "foobar" diff --git a/pkg/config/file/fixtures/sample.yml b/pkg/config/file/fixtures/sample.yml index e22829d50..b1bf1ac47 100644 --- a/pkg/config/file/fixtures/sample.yml +++ b/pkg/config/file/fixtures/sample.yml @@ -188,7 +188,6 @@ tracing: httpEndpoint: foobar sameSpan: true id128Bit: true - debug: true sampleRate: 42 datadog: localAgentHostPort: foobar diff --git a/pkg/tracing/zipkin/zipkin.go b/pkg/tracing/zipkin/zipkin.go index 52885ca4a..7a6548fb3 100644 --- a/pkg/tracing/zipkin/zipkin.go +++ b/pkg/tracing/zipkin/zipkin.go @@ -6,7 +6,9 @@ import ( "github.com/containous/traefik/v2/pkg/log" "github.com/opentracing/opentracing-go" - zipkin "github.com/openzipkin-contrib/zipkin-go-opentracing" + zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing" + "github.com/openzipkin/zipkin-go" + "github.com/openzipkin/zipkin-go/reporter/http" ) // Name sets the name of this tracer. @@ -17,43 +19,53 @@ type Config struct { HTTPEndpoint string `description:"HTTP Endpoint to report traces to." json:"httpEndpoint,omitempty" toml:"httpEndpoint,omitempty" yaml:"httpEndpoint,omitempty"` SameSpan bool `description:"Use Zipkin SameSpan RPC style traces." json:"sameSpan,omitempty" toml:"sameSpan,omitempty" yaml:"sameSpan,omitempty" export:"true"` ID128Bit bool `description:"Use Zipkin 128 bit root span IDs." json:"id128Bit,omitempty" toml:"id128Bit,omitempty" yaml:"id128Bit,omitempty" export:"true"` - Debug bool `description:"Enable Zipkin debug." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"` SampleRate float64 `description:"The rate between 0.0 and 1.0 of requests to trace." json:"sampleRate,omitempty" toml:"sampleRate,omitempty" yaml:"sampleRate,omitempty" export:"true"` } // SetDefaults sets the default values. func (c *Config) SetDefaults() { - c.HTTPEndpoint = "http://localhost:9411/api/v1/spans" + c.HTTPEndpoint = "http://localhost:9411/api/v2/spans" c.SameSpan = false c.ID128Bit = true - c.Debug = false c.SampleRate = 1.0 } // Setup sets up the tracer func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) { - collector, err := zipkin.NewHTTPCollector(c.HTTPEndpoint) + // create our local endpoint + endpoint, err := zipkin.NewEndpoint(serviceName, "0.0.0.0:0") if err != nil { return nil, nil, err } - recorder := zipkin.NewRecorder(collector, c.Debug, "0.0.0.0:0", serviceName) + // create our sampler + sampler, err := zipkin.NewBoundarySampler(c.SampleRate, time.Now().Unix()) + if err != nil { + return nil, nil, err + } - tracer, err := zipkin.NewTracer( - recorder, - zipkin.ClientServerSameSpan(c.SameSpan), - zipkin.TraceID128Bit(c.ID128Bit), - zipkin.DebugMode(c.Debug), - zipkin.WithSampler(zipkin.NewBoundarySampler(c.SampleRate, time.Now().Unix())), + // create the span reporter + reporter := http.NewReporter(c.HTTPEndpoint) + + // create the native Zipkin tracer + nativeTracer, err := zipkin.NewTracer( + reporter, + zipkin.WithLocalEndpoint(endpoint), + zipkin.WithSharedSpans(c.SameSpan), + zipkin.WithTraceID128Bit(c.ID128Bit), + zipkin.WithSampler(sampler), ) if err != nil { return nil, nil, err } + // wrap the Zipkin native tracer with the OpenTracing Bridge + tracer := zipkinot.Wrap(nativeTracer) + // Without this, child spans are getting the NOOP tracer opentracing.SetGlobalTracer(tracer) log.WithoutContext().Debug("Zipkin tracer configured") - return tracer, collector, nil + return tracer, reporter, nil } From 3ed57e01a6ee3f52c9f7708e9445b1754e5d7046 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 3 Sep 2019 12:18:03 +0200 Subject: [PATCH 12/37] Update go version to go 1.13rc2 --- .semaphoreci/setup.sh | 2 +- build.Dockerfile | 2 +- docs/content/contributing/building-testing.md | 2 +- exp.Dockerfile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.semaphoreci/setup.sh b/.semaphoreci/setup.sh index 568eea2fc..2fa285763 100755 --- a/.semaphoreci/setup.sh +++ b/.semaphoreci/setup.sh @@ -21,7 +21,7 @@ if [ -n "$SHOULD_TEST" ]; then docker version; fi export GO_VERSION=1.12 if [ -f "./go.mod" ]; then GO_VERSION="$(grep '^go .*' go.mod | awk '{print $2}')"; export GO_VERSION; fi -if [ "${GO_VERSION}" == '1.13' ]; then export GO_VERSION=1.13rc1; fi +if [ "${GO_VERSION}" == '1.13' ]; then export GO_VERSION=1.13rc2; fi echo "Selected Go version: ${GO_VERSION}" if [ -f "./.semaphoreci/golang.sh" ]; then ./.semaphoreci/golang.sh; fi diff --git a/build.Dockerfile b/build.Dockerfile index 27c308562..1fe4290eb 100644 --- a/build.Dockerfile +++ b/build.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.13rc1-alpine +FROM golang:1.13rc2-alpine RUN apk --update upgrade \ && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ diff --git a/docs/content/contributing/building-testing.md b/docs/content/contributing/building-testing.md index 95b713490..e165fbdcb 100644 --- a/docs/content/contributing/building-testing.md +++ b/docs/content/contributing/building-testing.md @@ -28,7 +28,7 @@ Successfully tagged traefik-webui:latest [...] docker build -t "traefik-dev:4475--feature-documentation" -f build.Dockerfile . Sending build context to Docker daemon 279MB -Step 1/10 : FROM golang:1.13rc1-alpine +Step 1/10 : FROM golang:1.13rc2-alpine ---> f4bfb3d22bda [...] Successfully built 5c3c1a911277 diff --git a/exp.Dockerfile b/exp.Dockerfile index 6f59b73e3..319742177 100644 --- a/exp.Dockerfile +++ b/exp.Dockerfile @@ -12,7 +12,7 @@ RUN yarn install RUN npm run build # BUILD -FROM golang:1.13rc1-alpine as gobuild +FROM golang:1.13rc2-alpine as gobuild RUN apk --update upgrade \ && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ From b8ed6f158882da3a456c2e58788210eb9854b3bd Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 3 Sep 2019 14:34:04 +0200 Subject: [PATCH 13/37] Re enable ratelimit integration tests --- .../assets/img/middleware/ratelimit.png | Bin 69593 -> 0 bytes docs/content/middlewares/ratelimit.md | 2 -- integration/access_log_test.go | 2 -- .../tracing/simple-jaeger-collector.toml | 15 +++-------- .../fixtures/tracing/simple-jaeger.toml | 16 +++--------- .../fixtures/tracing/simple-zipkin.toml | 15 +++-------- integration/resources/compose/access_log.yml | 24 ++++++++---------- integration/tracing_test.go | 10 ++------ pkg/config/dynamic/fixtures/sample.toml | 18 ++++++------- pkg/config/file/fixtures/sample.toml | 18 ++++++------- 10 files changed, 41 insertions(+), 79 deletions(-) delete mode 100644 docs/content/assets/img/middleware/ratelimit.png diff --git a/docs/content/assets/img/middleware/ratelimit.png b/docs/content/assets/img/middleware/ratelimit.png deleted file mode 100644 index 049af712e14212dba61f353f00876cdc84b30e39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69593 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 Date: Tue, 3 Sep 2019 15:02:05 +0200 Subject: [PATCH 14/37] fix buffering middleware --- cmd/traefik/traefik.go | 4 ++-- pkg/server/middleware/middlewares.go | 4 ++-- pkg/server/middleware/middlewares_test.go | 13 +++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 6c46fef78..8702855b9 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -299,14 +299,14 @@ You haven't specified the sendAnonymousUsage option, it will be enabled by defau Stats collection is enabled. Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration. Help us improve Traefik by leaving this feature on :) -More details on: https://docs.traefik.io/basics/#collected-data +More details on: https://docs.traefik.io/v2.0/contributing/data-collection/ `) collect(staticConfiguration) } else { log.WithoutContext().Info(` Stats collection is disabled. Help us improve Traefik by turning this feature on :) -More details on: https://docs.traefik.io/basics/#collected-data +More details on: https://docs.traefik.io/v2.0/contributing/data-collection/ `) } } diff --git a/pkg/server/middleware/middlewares.go b/pkg/server/middleware/middlewares.go index 4fd747780..3e5d2c154 100644 --- a/pkg/server/middleware/middlewares.go +++ b/pkg/server/middleware/middlewares.go @@ -123,7 +123,7 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) ( } // Buffering - if config.Buffering != nil && config.InFlightReq.Amount != 0 { + if config.Buffering != nil { if middleware != nil { return nil, badConf } @@ -213,7 +213,7 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) ( } // InFlightReq - if config.InFlightReq != nil && config.InFlightReq.Amount != 0 { + if config.InFlightReq != nil { if middleware != nil { return nil, badConf } diff --git a/pkg/server/middleware/middlewares_test.go b/pkg/server/middleware/middlewares_test.go index a3d855c44..b747390c5 100644 --- a/pkg/server/middleware/middlewares_test.go +++ b/pkg/server/middleware/middlewares_test.go @@ -314,6 +314,14 @@ func TestBuilder_buildConstructor(t *testing.T) { Prefix: "foo/", }, }, + "buff-foo": { + Buffering: &dynamic.Buffering{ + MaxRequestBodyBytes: 1, + MemRequestBodyBytes: 2, + MaxResponseBodyBytes: 3, + MemResponseBodyBytes: 5, + }, + }, } rtConf := runtime.NewConfig(dynamic.Configuration{ @@ -338,6 +346,11 @@ func TestBuilder_buildConstructor(t *testing.T) { middlewareID: "cb-foo", expectedError: false, }, + { + desc: "Should create a buffering middleware", + middlewareID: "buff-foo", + expectedError: false, + }, { desc: "Should not create an empty AddPrefix middleware when given an empty prefix", middlewareID: "ap-empty", From 10acbb8d921b3b8cd13c3dcd0ad86a5e40730737 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 3 Sep 2019 15:22:05 +0200 Subject: [PATCH 15/37] Don't panic with undefined middleware --- pkg/responsemodifiers/response_modifier.go | 5 +++++ .../response_modifier_test.go | 21 +++++++++++++------ pkg/server/middleware/middlewares.go | 6 +++++- pkg/server/middleware/middlewares_test.go | 1 - 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/pkg/responsemodifiers/response_modifier.go b/pkg/responsemodifiers/response_modifier.go index 507627d69..97c83e895 100644 --- a/pkg/responsemodifiers/response_modifier.go +++ b/pkg/responsemodifiers/response_modifier.go @@ -23,6 +23,11 @@ func (f *Builder) Build(ctx context.Context, names []string) func(*http.Response for _, middleName := range names { if conf, ok := f.configs[middleName]; ok { + if conf == nil || conf.Middleware == nil { + getLogger(ctx, middleName, "undefined").Error("Invalid Middleware configuration (ResponseModifier)") + continue + } + if conf.Headers != nil { getLogger(ctx, middleName, "Headers").Debug("Creating Middleware (ResponseModifier)") diff --git a/pkg/responsemodifiers/response_modifier_test.go b/pkg/responsemodifiers/response_modifier_test.go index 79c1f1132..9b3d7806b 100644 --- a/pkg/responsemodifiers/response_modifier_test.go +++ b/pkg/responsemodifiers/response_modifier_test.go @@ -47,7 +47,7 @@ func TestBuilderBuild(t *testing.T) { assertResponse: func(t *testing.T, resp *http.Response) { t.Helper() - assert.Equal(t, resp.Header.Get("X-Foo"), "foo") + assert.Equal(t, "foo", resp.Header.Get("X-Foo")) }, }, { @@ -85,7 +85,7 @@ func TestBuilderBuild(t *testing.T) { assertResponse: func(t *testing.T, resp *http.Response) { t.Helper() - assert.Equal(t, resp.Header.Get("Referrer-Policy"), "no-referrer") + assert.Equal(t, "no-referrer", resp.Header.Get("Referrer-Policy")) }, }, { @@ -107,8 +107,8 @@ func TestBuilderBuild(t *testing.T) { assertResponse: func(t *testing.T, resp *http.Response) { t.Helper() - assert.Equal(t, resp.Header.Get("X-Foo"), "foo") - assert.Equal(t, resp.Header.Get("X-Bar"), "bar") + assert.Equal(t, "foo", resp.Header.Get("X-Foo")) + assert.Equal(t, "bar", resp.Header.Get("X-Bar")) }, }, { @@ -130,7 +130,7 @@ func TestBuilderBuild(t *testing.T) { assertResponse: func(t *testing.T, resp *http.Response) { t.Helper() - assert.Equal(t, resp.Header.Get("X-Foo"), "foo") + assert.Equal(t, "foo", resp.Header.Get("X-Foo")) }, }, { @@ -157,9 +157,18 @@ func TestBuilderBuild(t *testing.T) { assertResponse: func(t *testing.T, resp *http.Response) { t.Helper() - assert.Equal(t, resp.Header.Get("X-Foo"), "foo") + assert.Equal(t, "foo", resp.Header.Get("X-Foo")) }, }, + { + desc: "nil middleware", + middlewares: []string{"foo"}, + buildResponse: stubResponse, + conf: map[string]*dynamic.Middleware{ + "foo": nil, + }, + assertResponse: func(t *testing.T, resp *http.Response) {}, + }, } for _, test := range testCases { diff --git a/pkg/server/middleware/middlewares.go b/pkg/server/middleware/middlewares.go index 3e5d2c154..e93dee542 100644 --- a/pkg/server/middleware/middlewares.go +++ b/pkg/server/middleware/middlewares.go @@ -102,6 +102,10 @@ func checkRecursion(ctx context.Context, middlewareName string) (context.Context // it is the responsibility of the caller to make sure that b.configs[middlewareName].Middleware exists func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) (alice.Constructor, error) { config := b.configs[middlewareName] + if config == nil || config.Middleware == nil { + return nil, fmt.Errorf("invalid middleware %q configuration", middlewareName) + } + var middleware alice.Constructor badConf := errors.New("cannot create middleware: multi-types middleware not supported, consider declaring two different pieces of middleware instead") @@ -314,7 +318,7 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) ( } if middleware == nil { - return nil, errors.New("middleware does not exist") + return nil, fmt.Errorf("middleware %q does not exist", middlewareName) } return tracing.Wrap(ctx, middleware), nil diff --git a/pkg/server/middleware/middlewares_test.go b/pkg/server/middleware/middlewares_test.go index b747390c5..52a89484b 100644 --- a/pkg/server/middleware/middlewares_test.go +++ b/pkg/server/middleware/middlewares_test.go @@ -369,7 +369,6 @@ func TestBuilder_buildConstructor(t *testing.T) { t.Parallel() constructor, err := middlewaresBuilder.buildConstructor(context.Background(), test.middlewareID) - require.NoError(t, err) middleware, err2 := constructor(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {})) From 261e7c174494b3327780361c2cae2cf46ee437f9 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Doumenjou Date: Tue, 3 Sep 2019 18:02:05 +0200 Subject: [PATCH 16/37] Fix some documentation issues --- docs/content/middlewares/basicauth.md | 6 +-- docs/content/middlewares/circuitbreaker.md | 3 +- docs/content/middlewares/compress.md | 2 +- docs/content/middlewares/errorpages.md | 2 +- docs/content/middlewares/headers.md | 49 ++++++++++--------- docs/content/middlewares/inflightreq.md | 2 +- docs/content/middlewares/ipwhitelist.md | 2 +- docs/content/middlewares/passtlsclientcert.md | 2 +- docs/content/middlewares/ratelimit.md | 2 +- docs/content/providers/docker.md | 2 +- docs/content/providers/file.md | 4 +- docs/content/routing/routers/index.md | 2 +- docs/content/user-guides/marathon.md | 2 +- 13 files changed, 40 insertions(+), 40 deletions(-) diff --git a/docs/content/middlewares/basicauth.md b/docs/content/middlewares/basicauth.md index 83f97d0cb..cd032f03f 100644 --- a/docs/content/middlewares/basicauth.md +++ b/docs/content/middlewares/basicauth.md @@ -79,10 +79,6 @@ Passwords must be encoded using MD5, SHA1, or BCrypt. The `users` option is an array of authorized users. Each user will be declared using the `name:encoded-password` format. -!!! Note - - If both `users` and `usersFile` are provided, the two are merged. The content of `usersFile` has precedence over `users`. - ### `usersFile` The `usersFile` option is the path to an external file that contains the authorized users for the middleware. @@ -106,7 +102,7 @@ You can customize the realm for the authentication with the `realm` option. The ### `headerField` -You can customize the header field for the authenticated user using the `headerField`option. +You can define a header field to store the authenticated user using the `headerField`option. ```yaml tab="Docker" labels: diff --git a/docs/content/middlewares/circuitbreaker.md b/docs/content/middlewares/circuitbreaker.md index 03f2c0c19..1f4c928ed 100644 --- a/docs/content/middlewares/circuitbreaker.md +++ b/docs/content/middlewares/circuitbreaker.md @@ -132,7 +132,7 @@ For example, the expression `LatencyAtQuantileMS(50.0) > 100` will trigger the c !!! Note - You must provide a float number (with the leading .0) for the quantile value + You must provide a float number (with the trailing .0) for the quantile value #### Using multiple metrics @@ -153,7 +153,6 @@ Here is the list of supported operators: - Greater or equal than (`>=`) - Lesser than (`<`) - Lesser or equal than (`<=`) -- Not (`!`) - Equal (`==`) - Not Equal (`!=`) diff --git a/docs/content/middlewares/compress.md b/docs/content/middlewares/compress.md index a1b07b84e..8137899f2 100644 --- a/docs/content/middlewares/compress.md +++ b/docs/content/middlewares/compress.md @@ -55,6 +55,6 @@ http: Responses are compressed when: -* The response body is larger than `512` bytes. +* The response body is larger than `1400` bytes. * The `Accept-Encoding` request header contains `gzip`. * The response is not already compressed, i.e. the `Content-Encoding` response header is not already set. diff --git a/docs/content/middlewares/errorpages.md b/docs/content/middlewares/errorpages.md index 29ee280ba..e3ae0c110 100644 --- a/docs/content/middlewares/errorpages.md +++ b/docs/content/middlewares/errorpages.md @@ -77,7 +77,7 @@ http: ``` !!! note - In this example, the error page URL is based on the status code (`query=/{status}.html)`. + In this example, the error page URL is based on the status code (`query=/{status}.html`). ## Configuration Options diff --git a/docs/content/middlewares/headers.md b/docs/content/middlewares/headers.md index a81be1a52..9ba57f386 100644 --- a/docs/content/middlewares/headers.md +++ b/docs/content/middlewares/headers.md @@ -70,7 +70,12 @@ http: `X-Script-Name` header added to the proxied request, the `X-Custom-Request-Header` header removed from the request, and the `X-Custom-Response-Header` header removed from the response. -Please note that is not possible to remove headers through the use of labels (Docker, Rancher, Marathon, ...) for now. +Please note that it is not possible to remove headers through the use of labels (Docker, Rancher, Marathon, ...) for now. + +```yaml tab="Docker" +labels: + - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" +``` ```yaml tab="Kubernetes" apiVersion: traefik.containo.us/v1alpha1 @@ -86,17 +91,17 @@ spec: X-Custom-Response-Header: "" # Removes ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" -``` - ```json tab="Marathon" "labels": { "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test", } ``` +```yaml tab="Rancher" +labels: + - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" +``` + ```toml tab="File (TOML)" [http.middlewares] [http.middlewares.testHeader.headers] @@ -121,7 +126,7 @@ http: ### Using Security Headers -Security related headers (HSTS headers, SSL redirection, Browser XSS filter, etc) can be added and configured per frontend in a similar manner to the custom headers above. +Security related headers (HSTS headers, SSL redirection, Browser XSS filter, etc) can be added and configured in a manner similar to the custom headers above. This functionality allows for some easy security features to quickly be set. ```yaml tab="Docker" @@ -141,12 +146,6 @@ spec: sslRedirect: "true" ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.testheader.headers.framedeny=true" - - "traefik.http.middlewares.testheader.headers.sslredirect=true" -``` - ```json tab="Marathon" "labels": { "traefik.http.middlewares.testheader.headers.framedeny": "true", @@ -154,6 +153,12 @@ labels: } ``` +```yaml tab="Rancher" +labels: + - "traefik.http.middlewares.testheader.headers.framedeny=true" + - "traefik.http.middlewares.testheader.headers.sslredirect=true" +``` + ```toml tab="File (TOML)" [http.middlewares] [http.middlewares.testHeader.headers] @@ -172,7 +177,7 @@ http: ### CORS Headers -CORS (Cross-Origin Resource Sharing) headers can be added and configured per frontend in a similar manner to the custom headers above. +CORS (Cross-Origin Resource Sharing) headers can be added and configured in a manner similar to the custom headers above. This functionality allows for more advanced security features to quickly be set. ```yaml tab="Docker" @@ -199,14 +204,6 @@ spec: addVaryHeader: "true" ``` -```yaml tab="Rancher" -labels: - - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" - - "traefik.http.middlewares.testheader.headers.accesscontrolalloworigin=origin-list-or-null" - - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100" - - "traefik.http.middlewares.testheader.headers.addvaryheader=true" -``` - ```json tab="Marathon" "labels": { "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods": "GET,OPTIONS,PUT", @@ -216,6 +213,14 @@ labels: } ``` +```yaml tab="Rancher" +labels: + - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" + - "traefik.http.middlewares.testheader.headers.accesscontrolalloworigin=origin-list-or-null" + - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100" + - "traefik.http.middlewares.testheader.headers.addvaryheader=true" +``` + ```toml tab="File (TOML)" [http.middlewares] [http.middlewares.testHeader.headers] diff --git a/docs/content/middlewares/inflightreq.md b/docs/content/middlewares/inflightreq.md index 9b07b7a82..770a3463d 100644 --- a/docs/content/middlewares/inflightreq.md +++ b/docs/content/middlewares/inflightreq.md @@ -74,7 +74,7 @@ The `ipStrategy` option defines two parameters that sets how Traefik will determ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take the IP located at the `depth` position (starting from the right). - If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty. -- `depth` is ignored if its value is is lesser than or equal to 0. +- `depth` is ignored if its value is lesser than or equal to 0. !!! note "Example of Depth & X-Forwarded-For" diff --git a/docs/content/middlewares/ipwhitelist.md b/docs/content/middlewares/ipwhitelist.md index 869ba0af8..1594c13cc 100644 --- a/docs/content/middlewares/ipwhitelist.md +++ b/docs/content/middlewares/ipwhitelist.md @@ -144,7 +144,7 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th !!! note - If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty. - - `depth` is ignored if its value is is lesser than or equal to 0. + - `depth` is ignored if its value is lesser than or equal to 0. #### `ipStrategy.excludedIPs` diff --git a/docs/content/middlewares/passtlsclientcert.md b/docs/content/middlewares/passtlsclientcert.md index 46b6aec36..6498000e3 100644 --- a/docs/content/middlewares/passtlsclientcert.md +++ b/docs/content/middlewares/passtlsclientcert.md @@ -219,7 +219,7 @@ PassTLSClientCert can add two headers to the request: !!! note The headers are filled with escaped string so it can be safely placed inside a URL query. -In the following example, you can see a complete certificate. We will use each part of it to explains the middleware options. +In the following example, you can see a complete certificate. We will use each part of it to explain the middleware options. ??? example "A complete client tls certificate" diff --git a/docs/content/middlewares/ratelimit.md b/docs/content/middlewares/ratelimit.md index b1d7a0a84..fcd0d4eb4 100644 --- a/docs/content/middlewares/ratelimit.md +++ b/docs/content/middlewares/ratelimit.md @@ -171,7 +171,7 @@ The `ipStrategy` option defines two parameters that sets how Traefik will determ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take the IP located at the `depth` position (starting from the right). - If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty. -- `depth` is ignored if its value is is lesser than or equal to 0. +- `depth` is ignored if its value is lesser than or equal to 0. !!! note "Example of Depth & X-Forwarded-For" diff --git a/docs/content/providers/docker.md b/docs/content/providers/docker.md index 6e20e5e4b..f0a030073 100644 --- a/docs/content/providers/docker.md +++ b/docs/content/providers/docker.md @@ -477,7 +477,7 @@ You can declare TCP Routers and/or Services using labels. # ... labels: - traefik.tcp.routers.my-router.rule="HostSNI(`my-host.com`)" - - traefik.tcp.routers.my-router.rule.tls="true" + - traefik.tcp.routers.my-router.tls="true" - traefik.tcp.services.my-service.loadbalancer.server.port="4123" ``` diff --git a/docs/content/providers/file.md b/docs/content/providers/file.md index 48f9a62a0..78e471a1c 100644 --- a/docs/content/providers/file.md +++ b/docs/content/providers/file.md @@ -46,7 +46,7 @@ You can write these configuration elements: entryPoints = ["web"] middlewares = ["my-basic-auth"] service = "service-foo" - rule = "Path(`foo`)" + rule = "Path(`/foo`)" # Add the middleware [http.middlewares] @@ -75,7 +75,7 @@ You can write these configuration elements: middlewares: - my-basic-auth service: service-foo - rule: Path(`foo`) + rule: Path(`/foo`) # Add the middleware middlewares: diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index 4951d7240..642292d98 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -216,7 +216,7 @@ The table below lists all the available matchers: | ```Host(`domain-1`, ...)``` | Check if the request domain targets one of the given `domains`. | | ```HostRegexp(`traefik.io`, `{subdomain:[a-z]+}.traefik.io`, ...)``` | Check if the request domain matches the given `regexp`. | | ```Method(`GET`, ...)``` | Check if the request method is one of the given `methods` (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`) | -| ```Path(`path`, `/articles/{category}/{id:[0-9]+}`, ...)``` | Match exact request path. It accepts a sequence of literal and regular expression paths. | +| ```Path(`/path`, `/articles/{category}/{id:[0-9]+}`, ...)``` | Match exact request path. It accepts a sequence of literal and regular expression paths. | | ```PathPrefix(`/products/`, `/articles/{category}/{id:[0-9]+}`)``` | Match request prefix path. It accepts a sequence of literal and regular expression prefix paths. | | ```Query(`foo=bar`, `bar=baz`)``` | Match` Query String parameters. It accepts a sequence of key=value pairs. | diff --git a/docs/content/user-guides/marathon.md b/docs/content/user-guides/marathon.md index e47489e91..847a96016 100644 --- a/docs/content/user-guides/marathon.md +++ b/docs/content/user-guides/marathon.md @@ -98,7 +98,7 @@ The remaining section is going to explore them along with a benefit/cost trade-o 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 is that Marathon does not persist the health check results. +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. From 770b3739e05d46a4d8442577267ef571d70a0452 Mon Sep 17 00:00:00 2001 From: Julien Salleyron Date: Tue, 3 Sep 2019 19:20:04 +0200 Subject: [PATCH 17/37] The chain middleware in k8s use middlewareRef --- docs/content/middlewares/chain.md | 6 +- integration/fixtures/k8s/04-ingressroute.yml | 14 +- integration/testdata/rawdata-crd.json | 38 +++-- pkg/provider/kubernetes/crd/kubernetes.go | 53 ++++++- .../crd/traefik/v1alpha1/middleware.go | 36 ++++- .../traefik/v1alpha1/zz_generated.deepcopy.go | 143 ++++++++++++++++++ 6 files changed, 269 insertions(+), 21 deletions(-) diff --git a/docs/content/middlewares/chain.md b/docs/content/middlewares/chain.md index 8ad38f7dd..3d7b6d53c 100644 --- a/docs/content/middlewares/chain.md +++ b/docs/content/middlewares/chain.md @@ -51,9 +51,9 @@ metadata: spec: chain: middlewares: - - https-only - - known-ips - - auth-users + - name: https-only + - name: known-ips + - name: auth-users --- apiVersion: traefik.containo.us/v1alpha1 kind: Middleware diff --git a/integration/fixtures/k8s/04-ingressroute.yml b/integration/fixtures/k8s/04-ingressroute.yml index 596073206..85643e638 100644 --- a/integration/fixtures/k8s/04-ingressroute.yml +++ b/integration/fixtures/k8s/04-ingressroute.yml @@ -1,5 +1,17 @@ apiVersion: traefik.containo.us/v1alpha1 kind: Middleware +metadata: + name: mychain + namespace: default + +spec: + chain: + middlewares: + - name: stripprefix + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware metadata: name: stripprefix namespace: default @@ -26,4 +38,4 @@ spec: - name: whoami port: 80 middlewares: - - name: stripprefix + - name: mychain diff --git a/integration/testdata/rawdata-crd.json b/integration/testdata/rawdata-crd.json index 696e34dd2..5bf6512a4 100644 --- a/integration/testdata/rawdata-crd.json +++ b/integration/testdata/rawdata-crd.json @@ -20,7 +20,7 @@ "web" ], "middlewares": [ - "default/stripprefix" + "default/mychain" ], "service": "default/test2.route-23c7f4c450289ee29016", "rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/tobestripped`)", @@ -31,16 +31,24 @@ } }, "middlewares": { - "default/stripprefix@kubernetescrd": { - "stripPrefix": { - "prefixes": [ - "/tobestripped" + "default/mychain@kubernetescrd": { + "chain": { + "middlewares": [ + "default/stripprefix" ] }, "status": "enabled", "usedBy": [ "default/test2.route-23c7f4c450289ee29016@kubernetescrd" ] + }, + "default/stripprefix@kubernetescrd": { + "stripPrefix": { + "prefixes": [ + "/tobestripped" + ] + }, + "status": "enabled" } }, "services": { @@ -48,10 +56,10 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.2:80" + "url": "http://10.42.0.3:80" }, { - "url": "http://10.42.0.6:80" + "url": "http://10.42.0.5:80" } ], "passHostHeader": true @@ -61,18 +69,18 @@ "default/test.route-6b204d94623b3df4370c@kubernetescrd" ], "serverStatus": { - "http://10.42.0.2:80": "UP", - "http://10.42.0.6:80": "UP" + "http://10.42.0.3:80": "UP", + "http://10.42.0.5:80": "UP" } }, "default/test2.route-23c7f4c450289ee29016@kubernetescrd": { "loadBalancer": { "servers": [ { - "url": "http://10.42.0.2:80" + "url": "http://10.42.0.3:80" }, { - "url": "http://10.42.0.6:80" + "url": "http://10.42.0.5:80" } ], "passHostHeader": true @@ -82,8 +90,8 @@ "default/test2.route-23c7f4c450289ee29016@kubernetescrd" ], "serverStatus": { - "http://10.42.0.2:80": "UP", - "http://10.42.0.6:80": "UP" + "http://10.42.0.3:80": "UP", + "http://10.42.0.5:80": "UP" } } }, @@ -109,10 +117,10 @@ "loadBalancer": { "servers": [ { - "address": "10.42.0.4:8080" + "address": "10.42.0.6:8080" }, { - "address": "10.42.0.5:8080" + "address": "10.42.0.7:8080" } ] }, diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index f3307ab8d..6296463a6 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -15,6 +15,7 @@ import ( "github.com/containous/traefik/v2/pkg/config/dynamic" "github.com/containous/traefik/v2/pkg/job" "github.com/containous/traefik/v2/pkg/log" + "github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" "github.com/containous/traefik/v2/pkg/safe" "github.com/containous/traefik/v2/pkg/tls" corev1 "k8s.io/api/core/v1" @@ -146,12 +147,62 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) } for _, middleware := range client.GetMiddlewares() { - conf.HTTP.Middlewares[makeID(middleware.Namespace, middleware.Name)] = &middleware.Spec + id := makeID(middleware.Namespace, middleware.Name) + ctxMid := log.With(ctx, log.Str(log.MiddlewareName, id)) + conf.HTTP.Middlewares[id] = &dynamic.Middleware{ + AddPrefix: middleware.Spec.AddPrefix, + StripPrefix: middleware.Spec.StripPrefix, + StripPrefixRegex: middleware.Spec.StripPrefixRegex, + ReplacePath: middleware.Spec.ReplacePath, + ReplacePathRegex: middleware.Spec.ReplacePathRegex, + Chain: createChainMiddleware(ctxMid, middleware.Namespace, middleware.Spec.Chain), + IPWhiteList: middleware.Spec.IPWhiteList, + Headers: middleware.Spec.Headers, + Errors: middleware.Spec.Errors, + RateLimit: middleware.Spec.RateLimit, + RedirectRegex: middleware.Spec.RedirectRegex, + RedirectScheme: middleware.Spec.RedirectScheme, + BasicAuth: middleware.Spec.BasicAuth, + DigestAuth: middleware.Spec.DigestAuth, + ForwardAuth: middleware.Spec.ForwardAuth, + InFlightReq: middleware.Spec.InFlightReq, + Buffering: middleware.Spec.Buffering, + CircuitBreaker: middleware.Spec.CircuitBreaker, + Compress: middleware.Spec.Compress, + PassTLSClientCert: middleware.Spec.PassTLSClientCert, + Retry: middleware.Spec.Retry, + } + } return conf } +func createChainMiddleware(ctx context.Context, namespace string, chain *v1alpha1.Chain) *dynamic.Chain { + if chain == nil { + return nil + } + + var mds []string + for _, mi := range chain.Middlewares { + if strings.Contains(mi.Name, "@") { + if len(mi.Namespace) > 0 { + log.FromContext(ctx). + Warnf("namespace %q is ignored in cross-provider context", mi.Namespace) + } + mds = append(mds, mi.Name) + continue + } + + ns := mi.Namespace + if len(ns) == 0 { + ns = namespace + } + mds = append(mds, makeID(ns, mi.Name)) + } + return &dynamic.Chain{Middlewares: mds} +} + func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options { tlsOptionsCRD := client.GetTLSOptions() var tlsOptions map[string]tls.Options diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go index c01f12c99..c5c2c4154 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go @@ -13,7 +13,41 @@ type Middleware struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` - Spec dynamic.Middleware `json:"spec"` + Spec MiddlewareSpec `json:"spec"` +} + +// +k8s:deepcopy-gen=true + +// Middleware holds the Middleware configuration. +type MiddlewareSpec struct { + AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty" toml:"addPrefix,omitempty" yaml:"addPrefix,omitempty"` + StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty" toml:"stripPrefix,omitempty" yaml:"stripPrefix,omitempty"` + StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty" toml:"stripPrefixRegex,omitempty" yaml:"stripPrefixRegex,omitempty"` + ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty" toml:"replacePath,omitempty" yaml:"replacePath,omitempty"` + ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty" toml:"replacePathRegex,omitempty" yaml:"replacePathRegex,omitempty"` + Chain *Chain `json:"chain,omitempty" toml:"chain,omitempty" yaml:"chain,omitempty"` + IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty"` + Headers *dynamic.Headers `json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty"` + Errors *dynamic.ErrorPage `json:"errors,omitempty" toml:"errors,omitempty" yaml:"errors,omitempty"` + RateLimit *dynamic.RateLimit `json:"rateLimit,omitempty" toml:"rateLimit,omitempty" yaml:"rateLimit,omitempty"` + RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty" toml:"redirectRegex,omitempty" yaml:"redirectRegex,omitempty"` + RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty" toml:"redirectScheme,omitempty" yaml:"redirectScheme,omitempty"` + BasicAuth *dynamic.BasicAuth `json:"basicAuth,omitempty" toml:"basicAuth,omitempty" yaml:"basicAuth,omitempty"` + DigestAuth *dynamic.DigestAuth `json:"digestAuth,omitempty" toml:"digestAuth,omitempty" yaml:"digestAuth,omitempty"` + ForwardAuth *dynamic.ForwardAuth `json:"forwardAuth,omitempty" toml:"forwardAuth,omitempty" yaml:"forwardAuth,omitempty"` + InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty" toml:"inFlightReq,omitempty" yaml:"inFlightReq,omitempty"` + Buffering *dynamic.Buffering `json:"buffering,omitempty" toml:"buffering,omitempty" yaml:"buffering,omitempty"` + CircuitBreaker *dynamic.CircuitBreaker `json:"circuitBreaker,omitempty" toml:"circuitBreaker,omitempty" yaml:"circuitBreaker,omitempty"` + Compress *dynamic.Compress `json:"compress,omitempty" toml:"compress,omitempty" yaml:"compress,omitempty" label:"allowEmpty"` + PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty" toml:"passTLSClientCert,omitempty" yaml:"passTLSClientCert,omitempty"` + Retry *dynamic.Retry `json:"retry,omitempty" toml:"retry,omitempty" yaml:"retry,omitempty"` +} + +// +k8s:deepcopy-gen=true + +// Chain holds a chain of middlewares +type Chain struct { + Middlewares []MiddlewareRef `json:"middlewares,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go index 047f0fcaa..67aa55d0c 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go @@ -29,9 +29,31 @@ THE SOFTWARE. package v1alpha1 import ( + dynamic "github.com/containous/traefik/v2/pkg/config/dynamic" runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Chain) DeepCopyInto(out *Chain) { + *out = *in + if in.Middlewares != nil { + in, out := &in.Middlewares, &out.Middlewares + *out = make([]MiddlewareRef, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Chain. +func (in *Chain) DeepCopy() *Chain { + if in == nil { + return nil + } + out := new(Chain) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientAuth) DeepCopyInto(out *ClientAuth) { *out = *in @@ -338,6 +360,127 @@ func (in *MiddlewareRef) DeepCopy() *MiddlewareRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) { + *out = *in + if in.AddPrefix != nil { + in, out := &in.AddPrefix, &out.AddPrefix + *out = new(dynamic.AddPrefix) + **out = **in + } + if in.StripPrefix != nil { + in, out := &in.StripPrefix, &out.StripPrefix + *out = new(dynamic.StripPrefix) + (*in).DeepCopyInto(*out) + } + if in.StripPrefixRegex != nil { + in, out := &in.StripPrefixRegex, &out.StripPrefixRegex + *out = new(dynamic.StripPrefixRegex) + (*in).DeepCopyInto(*out) + } + if in.ReplacePath != nil { + in, out := &in.ReplacePath, &out.ReplacePath + *out = new(dynamic.ReplacePath) + **out = **in + } + if in.ReplacePathRegex != nil { + in, out := &in.ReplacePathRegex, &out.ReplacePathRegex + *out = new(dynamic.ReplacePathRegex) + **out = **in + } + if in.Chain != nil { + in, out := &in.Chain, &out.Chain + *out = new(Chain) + (*in).DeepCopyInto(*out) + } + if in.IPWhiteList != nil { + in, out := &in.IPWhiteList, &out.IPWhiteList + *out = new(dynamic.IPWhiteList) + (*in).DeepCopyInto(*out) + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = new(dynamic.Headers) + (*in).DeepCopyInto(*out) + } + if in.Errors != nil { + in, out := &in.Errors, &out.Errors + *out = new(dynamic.ErrorPage) + (*in).DeepCopyInto(*out) + } + if in.RateLimit != nil { + in, out := &in.RateLimit, &out.RateLimit + *out = new(dynamic.RateLimit) + (*in).DeepCopyInto(*out) + } + if in.RedirectRegex != nil { + in, out := &in.RedirectRegex, &out.RedirectRegex + *out = new(dynamic.RedirectRegex) + **out = **in + } + if in.RedirectScheme != nil { + in, out := &in.RedirectScheme, &out.RedirectScheme + *out = new(dynamic.RedirectScheme) + **out = **in + } + if in.BasicAuth != nil { + in, out := &in.BasicAuth, &out.BasicAuth + *out = new(dynamic.BasicAuth) + (*in).DeepCopyInto(*out) + } + if in.DigestAuth != nil { + in, out := &in.DigestAuth, &out.DigestAuth + *out = new(dynamic.DigestAuth) + (*in).DeepCopyInto(*out) + } + if in.ForwardAuth != nil { + in, out := &in.ForwardAuth, &out.ForwardAuth + *out = new(dynamic.ForwardAuth) + (*in).DeepCopyInto(*out) + } + if in.InFlightReq != nil { + in, out := &in.InFlightReq, &out.InFlightReq + *out = new(dynamic.InFlightReq) + (*in).DeepCopyInto(*out) + } + if in.Buffering != nil { + in, out := &in.Buffering, &out.Buffering + *out = new(dynamic.Buffering) + **out = **in + } + if in.CircuitBreaker != nil { + in, out := &in.CircuitBreaker, &out.CircuitBreaker + *out = new(dynamic.CircuitBreaker) + **out = **in + } + if in.Compress != nil { + in, out := &in.Compress, &out.Compress + *out = new(dynamic.Compress) + **out = **in + } + if in.PassTLSClientCert != nil { + in, out := &in.PassTLSClientCert, &out.PassTLSClientCert + *out = new(dynamic.PassTLSClientCert) + (*in).DeepCopyInto(*out) + } + if in.Retry != nil { + in, out := &in.Retry, &out.Retry + *out = new(dynamic.Retry) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MiddlewareSpec. +func (in *MiddlewareSpec) DeepCopy() *MiddlewareSpec { + if in == nil { + return nil + } + out := new(MiddlewareSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Route) DeepCopyInto(out *Route) { *out = *in From f843f260ee6a1dbb99e800aa951929658bc98421 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 3 Sep 2019 20:32:03 +0200 Subject: [PATCH 18/37] fix: stripPrefix and stripPrefixRegex. --- docs/content/middlewares/stripprefixregex.md | 19 ++---- .../fixtures/https/https_redirect.toml | 4 +- pkg/middlewares/stripprefix/strip_prefix.go | 2 +- .../stripprefix/strip_prefix_test.go | 8 ++- .../stripprefixregex/strip_prefix_regex.go | 61 +++++++++---------- .../strip_prefix_regex_test.go | 13 +++- 6 files changed, 55 insertions(+), 52 deletions(-) diff --git a/docs/content/middlewares/stripprefixregex.md b/docs/content/middlewares/stripprefixregex.md index 84e55d979..4daee17c4 100644 --- a/docs/content/middlewares/stripprefixregex.md +++ b/docs/content/middlewares/stripprefixregex.md @@ -3,20 +3,16 @@ Removing Prefixes From the Path Before Forwarding the Request (Using a Regex) {: .subtitle } -`TODO: add schema` - Remove the matching prefixes from the URL path. ## Configuration Examples ```yaml tab="Docker" -# Replace the path by /foo labels: -- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=^/foo/(.*)", +- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/", ``` ```yaml tab="Kubernetes" -# Replace the path by /foo apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: @@ -24,36 +20,33 @@ metadata: spec: stripPrefixRegex: regex: - - "^/foo/(.*)" + - "/foo/[a-z0-9]+/[0-9]+/" ``` ```json tab="Marathon" "labels": { - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex": "^/foo/(.*)" + "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex": "/foo/[a-z0-9]+/[0-9]+/" } ``` ```yaml tab="Rancher" -# Replace the path by /foo labels: -- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=^/foo/(.*)", +- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/", ``` ```toml tab="File (TOML)" -# Replace the path by /foo [http.middlewares] [http.middlewares.test-stripprefixregex.stripPrefixRegex] - regex = ["^/foo/(.*)"] + regex = ["/foo/[a-z0-9]+/[0-9]+/"] ``` ```yaml tab="File (YAML)" -# Replace the path by /foo http: middlewares: test-stripprefixregex: stripPrefixRegex: regex: - - "^/foo/(.*)" + - "/foo/[a-z0-9]+/[0-9]+/" ``` ## Configuration Options diff --git a/integration/fixtures/https/https_redirect.toml b/integration/fixtures/https/https_redirect.toml index e9e9f78bc..3147488c4 100644 --- a/integration/fixtures/https/https_redirect.toml +++ b/integration/fixtures/https/https_redirect.toml @@ -150,9 +150,9 @@ [http.middlewares.foo-slash-add-prefix.addPrefix] prefix = "/foo/" [http.middlewares.id-strip-regex-prefix.stripPrefixRegex] - regex = ["/{id:[a-z]+}"] + regex = ["/[a-z]+"] [http.middlewares.id-slash-strip-regex-prefix.stripPrefixRegex] - regex = ["/{id:[a-z]+}/"] + regex = ["/[a-z]+/"] [http.middlewares.api-regex-replace.replacePathRegex] regex = "/api" replacement = "/" diff --git a/pkg/middlewares/stripprefix/strip_prefix.go b/pkg/middlewares/stripprefix/strip_prefix.go index 42a113206..31bc5ae90 100644 --- a/pkg/middlewares/stripprefix/strip_prefix.go +++ b/pkg/middlewares/stripprefix/strip_prefix.go @@ -49,7 +49,7 @@ func (s *stripPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) { return } } - http.NotFound(rw, req) + s.next.ServeHTTP(rw, req) } func (s *stripPrefix) serveRequest(rw http.ResponseWriter, req *http.Request, prefix string) { diff --git a/pkg/middlewares/stripprefix/strip_prefix_test.go b/pkg/middlewares/stripprefix/strip_prefix_test.go index 31d417162..449720902 100644 --- a/pkg/middlewares/stripprefix/strip_prefix_test.go +++ b/pkg/middlewares/stripprefix/strip_prefix_test.go @@ -28,7 +28,8 @@ func TestStripPrefix(t *testing.T) { Prefixes: []string{}, }, path: "/noprefixes", - expectedStatusCode: http.StatusNotFound, + expectedStatusCode: http.StatusOK, + expectedPath: "/noprefixes", }, { desc: "wildcard (.*) requests", @@ -76,7 +77,8 @@ func TestStripPrefix(t *testing.T) { Prefixes: []string{"/stat/"}, }, path: "/status", - expectedStatusCode: http.StatusNotFound, + expectedStatusCode: http.StatusOK, + expectedPath: "/status", }, { desc: "general prefix on matching path", @@ -149,6 +151,8 @@ func TestStripPrefix(t *testing.T) { require.NoError(t, err) req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost"+test.path, nil) + req.RequestURI = req.URL.RequestURI() + resp := &httptest.ResponseRecorder{Code: http.StatusOK} handler.ServeHTTP(resp, req) diff --git a/pkg/middlewares/stripprefixregex/strip_prefix_regex.go b/pkg/middlewares/stripprefixregex/strip_prefix_regex.go index c2c98328e..6cc82f178 100644 --- a/pkg/middlewares/stripprefixregex/strip_prefix_regex.go +++ b/pkg/middlewares/stripprefixregex/strip_prefix_regex.go @@ -3,13 +3,13 @@ package stripprefixregex import ( "context" "net/http" + "regexp" "strings" "github.com/containous/traefik/v2/pkg/config/dynamic" "github.com/containous/traefik/v2/pkg/middlewares" "github.com/containous/traefik/v2/pkg/middlewares/stripprefix" "github.com/containous/traefik/v2/pkg/tracing" - "github.com/gorilla/mux" "github.com/opentracing/opentracing-go/ext" ) @@ -19,9 +19,9 @@ const ( // StripPrefixRegex is a middleware used to strip prefix from an URL request. type stripPrefixRegex struct { - next http.Handler - router *mux.Router - name string + next http.Handler + expressions []*regexp.Regexp + name string } // New builds a new StripPrefixRegex middleware. @@ -29,13 +29,16 @@ func New(ctx context.Context, next http.Handler, config dynamic.StripPrefixRegex middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware") stripPrefix := stripPrefixRegex{ - next: next, - router: mux.NewRouter(), - name: name, + next: next, + name: name, } - for _, prefix := range config.Regex { - stripPrefix.router.PathPrefix(prefix) + for _, exp := range config.Regex { + reg, err := regexp.Compile(strings.TrimSpace(exp)) + if err != nil { + return nil, err + } + stripPrefix.expressions = append(stripPrefix.expressions, reg) } return &stripPrefix, nil @@ -46,32 +49,28 @@ func (s *stripPrefixRegex) GetTracingInformation() (string, ext.SpanKindEnum) { } func (s *stripPrefixRegex) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - var match mux.RouteMatch - if s.router.Match(req, &match) { - params := make([]string, 0, len(match.Vars)*2) - for key, val := range match.Vars { - params = append(params, key) - params = append(params, val) - } + for _, exp := range s.expressions { + parts := exp.FindStringSubmatch(req.URL.Path) + if len(parts) > 0 && len(parts[0]) > 0 { + prefix := parts[0] + if !strings.HasPrefix(req.URL.Path, prefix) { + continue + } - prefix, err := match.Route.URL(params...) - if err != nil || len(prefix.Path) > len(req.URL.Path) { - logger := middlewares.GetLogger(req.Context(), s.name, typeName) - logger.Error("Error in stripPrefix middleware", err) + req.Header.Add(stripprefix.ForwardedPrefixHeader, prefix) + + req.URL.Path = strings.Replace(req.URL.Path, prefix, "", 1) + if req.URL.RawPath != "" { + req.URL.RawPath = req.URL.RawPath[len(prefix):] + } + + req.RequestURI = ensureLeadingSlash(req.URL.RequestURI()) + s.next.ServeHTTP(rw, req) return } - - req.URL.Path = req.URL.Path[len(prefix.Path):] - if req.URL.RawPath != "" { - req.URL.RawPath = req.URL.RawPath[len(prefix.Path):] - } - req.Header.Add(stripprefix.ForwardedPrefixHeader, prefix.Path) - req.RequestURI = ensureLeadingSlash(req.URL.RequestURI()) - - s.next.ServeHTTP(rw, req) - return } - http.NotFound(rw, req) + + s.next.ServeHTTP(rw, req) } func ensureLeadingSlash(str string) string { diff --git a/pkg/middlewares/stripprefixregex/strip_prefix_regex_test.go b/pkg/middlewares/stripprefixregex/strip_prefix_regex_test.go index df67d9f57..297fa7192 100644 --- a/pkg/middlewares/stripprefixregex/strip_prefix_regex_test.go +++ b/pkg/middlewares/stripprefixregex/strip_prefix_regex_test.go @@ -15,7 +15,7 @@ import ( func TestStripPrefixRegex(t *testing.T) { testPrefixRegex := dynamic.StripPrefixRegex{ - Regex: []string{"/a/api/", "/b/{regex}/", "/c/{category}/{id:[0-9]+}/"}, + Regex: []string{"/a/api/", "/b/([a-z0-9]+)/", "/c/[a-z0-9]+/[0-9]+/"}, } testCases := []struct { @@ -27,7 +27,13 @@ func TestStripPrefixRegex(t *testing.T) { }{ { path: "/a/test", - expectedStatusCode: http.StatusNotFound, + expectedStatusCode: http.StatusOK, + expectedPath: "/a/test", + }, + { + path: "/a/test", + expectedStatusCode: http.StatusOK, + expectedPath: "/a/test", }, { path: "/a/api/test", @@ -65,7 +71,8 @@ func TestStripPrefixRegex(t *testing.T) { }, { path: "/c/api/abc/test4", - expectedStatusCode: http.StatusNotFound, + expectedStatusCode: http.StatusOK, + expectedPath: "/c/api/abc/test4", }, { path: "/a/api/a%2Fb", From b77bb690de02668918282f130bf637fb9e3b2a37 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 3 Sep 2019 21:18:03 +0200 Subject: [PATCH 19/37] Prepare release v2.0.0-rc2 --- CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2854b13d2..969eb5bc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Change Log +## [v2.0.0-rc2](https://github.com/containous/traefik/tree/v2.0.0-rc2) (2019-09-03) +[All Commits](https://github.com/containous/traefik/compare/v2.0.0-rc1...v2.0.0-rc2) + +**Enhancements:** +- **[api]** Improve API for the web UI ([#5267](https://github.com/containous/traefik/pull/5267) by [ldez](https://github.com/ldez)) +- **[middleware,tracing]** Re enable ratelimit integration tests ([#5288](https://github.com/containous/traefik/pull/5288) by [mmatur](https://github.com/mmatur)) +- **[tracing]** Update Zipkin OpenTracing driver to latest 0.4.3 release ([#5283](https://github.com/containous/traefik/pull/5283) by [basvanbeek](https://github.com/basvanbeek)) + +**Bug fixes:** +- **[api]** Add errors about unknown entryPoint in runtime api ([#5265](https://github.com/containous/traefik/pull/5265) by [juliens](https://github.com/juliens)) +- **[metrics,tracing]** fix: Datadog case. ([#5272](https://github.com/containous/traefik/pull/5272) by [ldez](https://github.com/ldez)) +- **[middleware,k8s,k8s/crd]** The chain middleware in k8s use middlewareRef ([#5290](https://github.com/containous/traefik/pull/5290) by [juliens](https://github.com/juliens)) +- **[middleware]** Don't panic with undefined middleware ([#5289](https://github.com/containous/traefik/pull/5289) by [ldez](https://github.com/ldez)) +- **[middleware]** fix buffering middleware ([#5281](https://github.com/containous/traefik/pull/5281) by [ldez](https://github.com/ldez)) +- **[middleware]** fix: stripPrefix and stripPrefixRegex. ([#5291](https://github.com/containous/traefik/pull/5291) by [ldez](https://github.com/ldez)) +- **[service,websocket]** Fix recovered panic when websocket is mirrored ([#5255](https://github.com/containous/traefik/pull/5255) by [juliens](https://github.com/juliens)) +- **[webui]** Rest provider icon in the webui ([#5261](https://github.com/containous/traefik/pull/5261) by [mmatur](https://github.com/mmatur)) +- Fix trailing slash with check new version ([#5266](https://github.com/containous/traefik/pull/5266) by [mmatur](https://github.com/mmatur)) + +**Documentation:** +- **[middleware]** fix: stripPrefixRegex documentation. ([#5273](https://github.com/containous/traefik/pull/5273) by [ldez](https://github.com/ldez)) +- Fix some documentation issues ([#5286](https://github.com/containous/traefik/pull/5286) by [jbdoumenjou](https://github.com/jbdoumenjou)) +- Update restrictions in the documentation. ([#5270](https://github.com/containous/traefik/pull/5270) by [ldez](https://github.com/ldez)) +- Base of the migration guide ([#5263](https://github.com/containous/traefik/pull/5263) by [jbdoumenjou](https://github.com/jbdoumenjou)) + ## [v2.0.0-rc1](https://github.com/containous/traefik/tree/v2.0.0-rc1) (2019-08-26) [All Commits](https://github.com/containous/traefik/compare/v2.0.0-beta1...v2.0.0-rc1) From 81a1f618f99823e3187130652a81a510a07c8a3f Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 4 Sep 2019 11:16:03 +0200 Subject: [PATCH 20/37] Update to go 1.13 --- .semaphoreci/setup.sh | 7 ++----- build.Dockerfile | 2 +- docs/content/contributing/building-testing.md | 2 +- exp.Dockerfile | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.semaphoreci/setup.sh b/.semaphoreci/setup.sh index 2fa285763..f087c644d 100755 --- a/.semaphoreci/setup.sh +++ b/.semaphoreci/setup.sh @@ -18,10 +18,9 @@ echo ${SHOULD_TEST} #if [ -n "$SHOULD_TEST" ]; then sudo -E apt-get -yq update; fi #if [ -n "$SHOULD_TEST" ]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-ce=${DOCKER_VERSION}*; fi if [ -n "$SHOULD_TEST" ]; then docker version; fi - -export GO_VERSION=1.12 +export GO_VERSION=1.13 if [ -f "./go.mod" ]; then GO_VERSION="$(grep '^go .*' go.mod | awk '{print $2}')"; export GO_VERSION; fi -if [ "${GO_VERSION}" == '1.13' ]; then export GO_VERSION=1.13rc2; fi +#if [ "${GO_VERSION}" == '1.13' ]; then export GO_VERSION=1.13rc2; fi echo "Selected Go version: ${GO_VERSION}" if [ -f "./.semaphoreci/golang.sh" ]; then ./.semaphoreci/golang.sh; fi @@ -34,5 +33,3 @@ if [ -f "./go.mod" ]; then export GOPROXY=https://proxy.golang.org; fi if [ -f "./go.mod" ]; then go mod download; fi df - - diff --git a/build.Dockerfile b/build.Dockerfile index 1fe4290eb..2425f04f0 100644 --- a/build.Dockerfile +++ b/build.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.13rc2-alpine +FROM golang:1.13-alpine RUN apk --update upgrade \ && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ diff --git a/docs/content/contributing/building-testing.md b/docs/content/contributing/building-testing.md index e165fbdcb..65240f216 100644 --- a/docs/content/contributing/building-testing.md +++ b/docs/content/contributing/building-testing.md @@ -28,7 +28,7 @@ Successfully tagged traefik-webui:latest [...] docker build -t "traefik-dev:4475--feature-documentation" -f build.Dockerfile . Sending build context to Docker daemon 279MB -Step 1/10 : FROM golang:1.13rc2-alpine +Step 1/10 : FROM golang:1.13-alpine ---> f4bfb3d22bda [...] Successfully built 5c3c1a911277 diff --git a/exp.Dockerfile b/exp.Dockerfile index 319742177..b12c512b8 100644 --- a/exp.Dockerfile +++ b/exp.Dockerfile @@ -12,7 +12,7 @@ RUN yarn install RUN npm run build # BUILD -FROM golang:1.13rc2-alpine as gobuild +FROM golang:1.13-alpine as gobuild RUN apk --update upgrade \ && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ From 3689990bd5abbc83837bb71e8b2ff2d951612d1c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Doumenjou Date: Wed, 4 Sep 2019 17:28:03 +0200 Subject: [PATCH 21/37] Enhance the Retry Middleware Documentation Co-authored-by: Mathieu Lonjaret --- docs/content/middlewares/retry.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/content/middlewares/retry.md b/docs/content/middlewares/retry.md index 439cb9cbf..e7704c862 100644 --- a/docs/content/middlewares/retry.md +++ b/docs/content/middlewares/retry.md @@ -5,7 +5,8 @@ Retrying until it Succeeds `TODO: add schema` -Retry to send request on attempt failure. +The Retry middleware is in charge of reissuing a request a given number of times to a backend server if that server does not reply. +To be clear, as soon as the server answers, the middleware stops retrying, regardless of the response status. ## Configuration Examples @@ -60,4 +61,4 @@ http: _mandatory_ -The `attempts` option defines how many times to try sending the request. \ No newline at end of file +The `attempts` option defines how many times the request should be retried. \ No newline at end of file From 6712423dd1d04d0a10dee144e2742e2e5fcc5034 Mon Sep 17 00:00:00 2001 From: mpl Date: Thu, 5 Sep 2019 10:48:04 +0200 Subject: [PATCH 22/37] misc documentation fixes --- docs/content/observability/access-logs.md | 15 +++++++-------- docs/content/providers/docker.md | 1 + docs/content/providers/marathon.md | 4 ++-- docs/content/routing/routers/index.md | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/content/observability/access-logs.md b/docs/content/observability/access-logs.md index 00a29cf79..0effd5d1b 100644 --- a/docs/content/observability/access-logs.md +++ b/docs/content/observability/access-logs.md @@ -152,15 +152,14 @@ accessLog: format: json fields: defaultMode: keep - fields: + names: + ClientUsername: drop + headers: + defaultMode: keep names: - ClientUsername: drop - headers: - defaultMode: keep - names: - - User-Agent: redact - - Authorization: drop - - Content-Type: keep + - User-Agent: redact + - Authorization: drop + - Content-Type: keep ``` ```bash tab="CLI" diff --git a/docs/content/providers/docker.md b/docs/content/providers/docker.md index f0a030073..5e45f6cf4 100644 --- a/docs/content/providers/docker.md +++ b/docs/content/providers/docker.md @@ -77,6 +77,7 @@ Attach labels to your containers and let Traefik do the rest! deploy: labels: - traefik.http.routers.my-container.rule=Host(`my-domain`) + - traefik.http.services.my-container-service.loadbalancer.server.port=8080 ``` !!! important "Labels in Docker Swarm Mode" diff --git a/docs/content/providers/marathon.md b/docs/content/providers/marathon.md index e19e9877c..762b7a0f7 100644 --- a/docs/content/providers/marathon.md +++ b/docs/content/providers/marathon.md @@ -243,7 +243,7 @@ That is to say, if none of the application's labels match the expression, no rou In addition, the expression also matched against the application's 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 `LabelRegexp("key", "value")`, as well as the usual boolean logic. +The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")`, 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 joined together in a single string with the `:` separator. ??? example "Constraints Expression Examples" @@ -275,7 +275,7 @@ In addition, to match against marathon constraints, the function `MarathonConstr ```toml # Includes only applications having a label with key `a.label.name` and a value matching the `a.+` regular expression. - constraints = "LabelRegexp(`a.label.name`, `a.+`)" + constraints = "LabelRegex(`a.label.name`, `a.+`)" ``` ```toml diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index 642292d98..c9067a1af 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -631,7 +631,7 @@ Services are the target for the router. rule: "HostSNI(`foo-domain`)" service: service-id # will terminate the TLS request by default - tld: {} + tls: {} ``` ??? example "Configuring passthrough" From 1959e1fd4412176c02bc3a6d7a6e318b5cd14684 Mon Sep 17 00:00:00 2001 From: Julien Salleyron Date: Thu, 5 Sep 2019 13:42:04 +0200 Subject: [PATCH 23/37] Auth middlewares in kubernetes CRD uses secrets --- docs/content/middlewares/basicauth.md | 222 +++++++- docs/content/middlewares/digestauth.md | 237 ++++++++- docs/content/middlewares/forwardauth.md | 491 ++++++++++++++++-- docs/content/observability/access-logs.md | 6 +- pkg/middlewares/buffering/buffering.go | 2 +- .../kubernetes/crd/fixtures/with_auth.yml | 65 +++ pkg/provider/kubernetes/crd/kubernetes.go | 196 ++++++- .../kubernetes/crd/kubernetes_test.go | 37 ++ .../crd/traefik/v1alpha1/middleware.go | 81 ++- .../traefik/v1alpha1/zz_generated.deepcopy.go | 84 ++- pkg/server/router/tcp/router.go | 9 +- 11 files changed, 1306 insertions(+), 124 deletions(-) create mode 100644 pkg/provider/kubernetes/crd/fixtures/with_auth.yml diff --git a/docs/content/middlewares/basicauth.md b/docs/content/middlewares/basicauth.md index cd032f03f..2e44eb076 100644 --- a/docs/content/middlewares/basicauth.md +++ b/docs/content/middlewares/basicauth.md @@ -16,7 +16,7 @@ The BasicAuth middleware is a quick way to restrict access to your services to k # To create user:password pair, it's possible to use this command: # echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g labels: - - "traefik.http.middlewares.test-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" +- "traefik.http.middlewares.test-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" ``` ```yaml tab="Kubernetes" @@ -27,9 +27,7 @@ metadata: name: test-auth spec: basicAuth: - users: - - test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/ - - test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 + secret: secretName ``` ```json tab="Marathon" @@ -41,7 +39,7 @@ spec: ```yaml tab="Rancher" # Declaring the user list labels: - - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" +- "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" ``` ```toml tab="File (TOML)" @@ -79,12 +77,140 @@ Passwords must be encoded using MD5, SHA1, or BCrypt. The `users` option is an array of authorized users. Each user will be declared using the `name:encoded-password` format. +!!! Note + + - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. + - For security reasons, the field `users` doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. + +```yaml tab="Docker" +# Declaring the user list +# +# Note: all dollar signs in the hash need to be doubled for escaping. +# To create user:password pair, it's possible to use this command: +# echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g +labels: +- "traefik.http.middlewares.test-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" +``` + +```yaml tab="Kubernetes" +# Declaring the user list +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + basicAuth: + secret: authsecret + +--- +apiVersion: v1 +kind: Secret +metadata: + name: authsecret + namespace: default + +data: + users: |2 + dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5 + aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK +``` + +```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" +``` + +```toml tab="File (TOML)" +# Declaring the user list +[http.middlewares] + [http.middlewares.test-auth.basicAuth] + users = [ + "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", + "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + ] +``` + +```yaml tab="File (YAML)" +# Declaring the user list +http: + middlewares: + test-auth: + basicAuth: + users: + - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" + - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" +``` + ### `usersFile` The `usersFile` option is the path to an external file that contains the authorized users for the middleware. The file content is a list of `name:encoded-password`. +!!! Note + + - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. + - Because it does not make much sense to refer to a file path on Kubernetes, the `usersFile` field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. + +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + basicAuth: + secret: authsecret + +--- +apiVersion: v1 +kind: Secret +metadata: + name: authsecret + namespace: default + +data: + users: |2 + dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5 + aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK +``` + +```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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.basicAuth] + usersFile = "/path/to/my/usersfile" +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + basicAuth: + usersFile: "/path/to/my/usersfile" +``` + ??? example "A file containing test/test and test2/test2" ```txt @@ -92,21 +218,57 @@ The file content is a list of `name:encoded-password`. test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 ``` -!!! Note - - If both `users` and `usersFile` are provided, the two are merged. The content of `usersFile` has precedence over `users`. - ### `realm` You can customize the realm for the authentication with the `realm` option. The default value is `traefik`. +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + 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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.basicAuth] + realm = "MyRealm" +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + basicAuth: + realm: "MyRealm" +``` + ### `headerField` You can define a header field to store the authenticated user using the `headerField`option. ```yaml tab="Docker" labels: - - "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" +- "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" ``` ```yaml tab="Kubernetes" @@ -144,3 +306,43 @@ http: ### `removeHeader` Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.) + +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.basicauth.removeheader=true" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + 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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.basicAuth] + removeHeader = true +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + basicAuth: + removeHeader: true +``` diff --git a/docs/content/middlewares/digestauth.md b/docs/content/middlewares/digestauth.md index 7af3a5390..0462599bd 100644 --- a/docs/content/middlewares/digestauth.md +++ b/docs/content/middlewares/digestauth.md @@ -10,6 +10,7 @@ The DigestAuth middleware is a quick way to restrict access to your services to ## Configuration Examples ```yaml tab="Docker" +# Declaring the user list labels: - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" ``` @@ -22,9 +23,82 @@ metadata: name: test-auth spec: digestAuth: - users: - - test:traefik:a2688e031edb4be6a3797f3882655c05 - - test2:traefik:518845800f9e2bfb1f1f740ec24f074e + secret: userssecret +``` + +```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" +``` + +```toml tab="File (TOML)" +# Declaring the user list +[http.middlewares] + [http.middlewares.test-auth.digestAuth] + users = [ + "test:traefik:a2688e031edb4be6a3797f3882655c05", + "test2:traefik:518845800f9e2bfb1f1f740ec24f074e", + ] +``` + +```yaml tab="File (YAML)" +# Declaring the user list +http: + middlewares: + test-auth: + digestAuth: + users: + - "test:traefik:a2688e031edb4be6a3797f3882655c05" + - "test2:traefik:518845800f9e2bfb1f1f740ec24f074e" +``` + +## Configuration Options + +!!! tip + + Use `htdigest` to generate passwords. + +### `users` + +The `users` option is an array of authorized users. Each user will be declared using the `name:realm:encoded-password` format. + +!!! Note + + - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. + - For security reasons, the field `users` doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. + +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + digestAuth: + secret: authsecret + +--- +apiVersion: v1 +kind: Secret +metadata: + name: authsecret + namespace: default + +data: + users: |2 + dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5 + aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK ``` ```json tab="Marathon" @@ -57,26 +131,69 @@ http: - "test2:traefik:518845800f9e2bfb1f1f740ec24f074e" ``` -!!! tip - - Use `htdigest` to generate passwords. - -## Configuration Options - -### `users` - -The `users` option is an array of authorized users. Each user will be declared using the `name:realm:encoded-password` format. - -!!! Note - - If both `users` and `usersFile` are provided, the two are merged. The content of `usersFile` has precedence over `users`. - ### `usersFile` The `usersFile` option is the path to an external file that contains the authorized users for the middleware. The file content is a list of `name:realm:encoded-password`. +!!! Note + + - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. + - Because it does not make much sense to refer to a file path on Kubernetes, the `usersFile` field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. + +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + digestAuth: + secret: authsecret + +--- +apiVersion: v1 +kind: Secret +metadata: + name: authsecret + namespace: default + +data: + users: |2 + dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5 + aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK +``` + +```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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.digestAuth] + usersFile = "/path/to/my/usersfile" +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + digestAuth: + usersFile: "/path/to/my/usersfile" +``` + ??? example "A file containing test/test and test2/test2" ```txt @@ -84,20 +201,54 @@ The file content is a list of `name:realm:encoded-password`. test2:traefik:518845800f9e2bfb1f1f740ec24f074e ``` -!!! Note - - If both `users` and `usersFile` are provided, the two are merged. The content of `usersFile` has precedence over `users`. - ### `realm` You can customize the realm for the authentication with the `realm` option. The default value is `traefik`. +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + 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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.digestAuth] + realm = "MyRealm" +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + digestAuth: + realm: "MyRealm" +``` + ### `headerField` You can customize the header field for the authenticated user using the `headerField`option. -Example "File -- Passing Authenticated User to Services Via Headers" - ```yaml tab="Docker" labels: - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" @@ -143,3 +294,43 @@ http: ### `removeHeader` Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.) + +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.digestauth.removeheader=true" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + 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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.digestAuth] + removeHeader = true +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + digestAuth: + removeHeader: true +``` diff --git a/docs/content/middlewares/forwardauth.md b/docs/content/middlewares/forwardauth.md index 29c02b7a8..3bd35b84f 100644 --- a/docs/content/middlewares/forwardauth.md +++ b/docs/content/middlewares/forwardauth.md @@ -15,12 +15,99 @@ Otherwise, the response from the authentication server is returned. # Forward authentication to authserver.com labels: - "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth" -- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" -- "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" -- "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true" -- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" -- "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify=true" -- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" +``` + +```yaml tab="Kubernetes" +# Forward authentication to authserver.com +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + forwardAuth: + address: https://authserver.com/auth +``` + +```json tab="Marathon" +"labels": { + "traefik.http.middlewares.test-auth.forwardauth.address": "https://authserver.com/auth" +} +``` + +```yaml tab="Rancher" +# Forward authentication to authserver.com +labels: +- "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth" +``` + +```toml tab="File (TOML)" +# Forward authentication to authserver.com +[http.middlewares] + [http.middlewares.test-auth.forwardAuth] + address = "https://authserver.com/auth" +``` + +```yaml tab="File (YAML)" +# Forward authentication to authserver.com +http: + middlewares: + test-auth: + forwardAuth: + address: "https://authserver.com/auth" +``` + +## Configuration Options + +### `address` + +The `address` option defines the authentication server address. + +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + forwardAuth: + address: https://authserver.com/auth +``` + +```json tab="Marathon" +"labels": { + "traefik.http.middlewares.test-auth.forwardauth.address": "https://authserver.com/auth" +} +``` + +```yaml tab="Rancher" +labels: +- "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.forwardAuth] + address = "https://authserver.com/auth" +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + forwardAuth: + address: "https://authserver.com/auth" +``` + +### `trustForwardHeader` + +Set the `trustForwardHeader` option to `true` to trust all the existing `X-Forwarded-*` headers. + +```yaml tab="Docker" +labels: - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" ``` @@ -33,89 +120,381 @@ spec: forwardAuth: address: https://authserver.com/auth trustForwardHeader: true - authResponseHeaders: - - X-Auth-User - - X-Secret - tls: - ca: path/to/local.crt - caOptional: true - cert: path/to/foo.cert - key: path/to/foo.key ``` ```json tab="Marathon" "labels": { - "traefik.http.middlewares.test-auth.forwardauth.address": "https://authserver.com/auth", - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders": "X-Auth-User,X-Secret", - "traefik.http.middlewares.test-auth.forwardauth.tls.ca": "path/to/local.crt", - "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional": "true", - "traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert", - "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify": "true", - "traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key", "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader": "true" } ``` ```yaml tab="Rancher" -# Forward authentication to authserver.com labels: -- "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth" -- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" -- "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" -- "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true" -- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" -- "traefik.http.middlewares.test-auth.forwardauth.tls.InisecureSkipVerify=true" -- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" ``` ```toml tab="File (TOML)" -# Forward authentication to authserver.com [http.middlewares] [http.middlewares.test-auth.forwardAuth] address = "https://authserver.com/auth" trustForwardHeader = true - authResponseHeaders = ["X-Auth-User", "X-Secret"] - - [http.middlewares.test-auth.forwardAuth.tls] - ca = "path/to/local.crt" - caOptional = true - cert = "path/to/foo.cert" - key = "path/to/foo.key" ``` ```yaml tab="File (YAML)" -# Forward authentication to authserver.com http: middlewares: test-auth: forwardAuth: address: "https://authserver.com/auth" trustForwardHeader: true - authResponseHeaders: - - "X-Auth-User" - - "X-Secret" - tls: - ca: "path/to/local.crt" - caOptional: true - cert: "path/to/foo.cert" - key: "path/to/foo.key" ``` -## Configuration Options - -### `address` - -The `address` option defines the authentication server address. - -### `trustForwardHeader` - -Set the `trustForwardHeader` option to `true` to trust all the existing `X-Forwarded-*` headers. - ### `authResponseHeaders` The `authResponseHeaders` option is the list of the headers to copy from the authentication server to the request. +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + forwardAuth: + address: https://authserver.com/auth + 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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.forwardAuth] + address = "https://authserver.com/auth" + authResponseHeaders = ["X-Auth-User", "X-Secret"] +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + forwardAuth: + address: "https://authserver.com/auth" + authResponseHeaders: + - "X-Auth-User" + - "X-Secret" +``` + ### `tls` The `tls` option is the TLS configuration from Traefik to the authentication server. + +#### `tls.ca` + +TODO + +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + forwardAuth: + address: https://authserver.com/auth + tls: + caSecret: mycasercret + +--- +apiVersion: v1 +kind: Secret +metadata: + name: mycasercret + namespace: default + +data: + ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= +``` + +```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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.forwardAuth] + address = "https://authserver.com/auth" + [http.middlewares.test-auth.forwardAuth.tls] + ca = "path/to/local.crt" +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + forwardAuth: + address: "https://authserver.com/auth" + tls: + ca: "path/to/local.crt" +``` + +#### `tls.caOptional` + +TODO + +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + forwardAuth: + address: https://authserver.com/auth + tls: + caOptional: true +``` + +```json tab="Marathon" +"labels": { + "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional": "true" +} +``` + +```yaml tab="Rancher" +labels: +- "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.forwardAuth] + address = "https://authserver.com/auth" + [http.middlewares.test-auth.forwardAuth.tls] + caOptional = true +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + forwardAuth: + address: "https://authserver.com/auth" + tls: + caOptional: true +``` + +#### `tls.cert` + +TODO + +```yaml tab="Docker" +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="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + forwardAuth: + address: https://authserver.com/auth + tls: + certSecret: mytlscert + +--- +apiVersion: v1 +kind: Secret +metadata: + name: mytlscert + namespace: default + +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= +``` + +```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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.forwardAuth] + address = "https://authserver.com/auth" + [http.middlewares.test-auth.forwardAuth.tls] + cert = "path/to/foo.cert" + key = "path/to/foo.key" +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + forwardAuth: + address: "https://authserver.com/auth" + tls: + cert: "path/to/foo.cert" + key: "path/to/foo.key" +``` + +!!! Note + For security reasons, the field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. + +#### `tls.key` + +TODO + +```yaml tab="Docker" +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="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + forwardAuth: + address: https://authserver.com/auth + tls: + certSecret: mytlscert + +--- +apiVersion: v1 +kind: Secret +metadata: + name: mytlscert + namespace: default + +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= +``` + +```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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.forwardAuth] + address = "https://authserver.com/auth" + [http.middlewares.test-auth.forwardAuth.tls] + cert = "path/to/foo.cert" + key = "path/to/foo.key" +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + forwardAuth: + address: "https://authserver.com/auth" + tls: + cert: "path/to/foo.cert" + key: "path/to/foo.key" +``` + +!!! Note + For security reasons, the field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. + +#### `tls.insecureSkipVerify` + +TODO + +```yaml tab="Docker" +labels: +- "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify=true" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: test-auth +spec: + forwardAuth: + address: https://authserver.com/auth + 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" +``` + +```toml tab="File (TOML)" +[http.middlewares] + [http.middlewares.test-auth.forwardAuth] + address = "https://authserver.com/auth" + insecureSkipVerify: true +``` + +```yaml tab="File (YAML)" +http: + middlewares: + test-auth: + forwardAuth: + address: "https://authserver.com/auth" + insecureSkipVerify: true +``` diff --git a/docs/content/observability/access-logs.md b/docs/content/observability/access-logs.md index 0effd5d1b..2c00e9dd2 100644 --- a/docs/content/observability/access-logs.md +++ b/docs/content/observability/access-logs.md @@ -157,9 +157,9 @@ accessLog: headers: defaultMode: keep names: - - User-Agent: redact - - Authorization: drop - - Content-Type: keep + User-Agent: redact + Authorization: drop + Content-Type: keep ``` ```bash tab="CLI" diff --git a/pkg/middlewares/buffering/buffering.go b/pkg/middlewares/buffering/buffering.go index 97fdd1314..e6183a723 100644 --- a/pkg/middlewares/buffering/buffering.go +++ b/pkg/middlewares/buffering/buffering.go @@ -24,7 +24,7 @@ type buffer struct { func New(ctx context.Context, next http.Handler, config dynamic.Buffering, name string) (http.Handler, error) { logger := middlewares.GetLogger(ctx, name, typeName) logger.Debug("Creating middleware") - logger.Debug("Setting up buffering: request limits: %d (mem), %d (max), response limits: %d (mem), %d (max) with retry: '%s'", + logger.Debugf("Setting up buffering: request limits: %d (mem), %d (max), response limits: %d (mem), %d (max) with retry: '%s'", config.MemRequestBodyBytes, config.MaxRequestBodyBytes, config.MemResponseBodyBytes, config.MaxResponseBodyBytes, config.RetryExpression) oxyBuffer, err := oxybuffer.New( diff --git a/pkg/provider/kubernetes/crd/fixtures/with_auth.yml b/pkg/provider/kubernetes/crd/fixtures/with_auth.yml new file mode 100644 index 000000000..b03b82b64 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/with_auth.yml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Secret +metadata: + name: authsecret + namespace: default + +data: + users: |2 + dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5 + aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK +--- +apiVersion: v1 +kind: Secret +metadata: + name: casecret + namespace: default + +data: + ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + +--- +apiVersion: v1 +kind: Secret +metadata: + name: tlssecret + namespace: default + +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: basicauth + namespace: default + +spec: + basicAuth: + secret: authsecret + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: digestauth + namespace: default + +spec: + digestAuth: + secret: authsecret +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: forwardauth + namespace: default + +spec: + forwardAuth: + address: test.com + tls: + certSecret: tlssecret + caSecret: casecret diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 6296463a6..c8fbd61f2 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -1,6 +1,8 @@ package crd import ( + "bufio" + "bytes" "context" "crypto/sha256" "fmt" @@ -149,6 +151,25 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) for _, middleware := range client.GetMiddlewares() { id := makeID(middleware.Namespace, middleware.Name) ctxMid := log.With(ctx, log.Str(log.MiddlewareName, id)) + + basicAuth, err := createBasicAuthMiddleware(client, middleware.Namespace, middleware.Spec.BasicAuth) + if err != nil { + log.FromContext(ctxMid).Errorf("Error while reading basic auth middleware: %v", err) + continue + } + + digestAuth, err := createDigestAuthMiddleware(client, middleware.Namespace, middleware.Spec.DigestAuth) + if err != nil { + log.FromContext(ctxMid).Errorf("Error while reading digest auth middleware: %v", err) + continue + } + + forwardAuth, err := createForwardAuthMiddleware(client, middleware.Namespace, middleware.Spec.ForwardAuth) + if err != nil { + log.FromContext(ctxMid).Errorf("Error while reading forward auth middleware: %v", err) + continue + } + conf.HTTP.Middlewares[id] = &dynamic.Middleware{ AddPrefix: middleware.Spec.AddPrefix, StripPrefix: middleware.Spec.StripPrefix, @@ -162,9 +183,9 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) RateLimit: middleware.Spec.RateLimit, RedirectRegex: middleware.Spec.RedirectRegex, RedirectScheme: middleware.Spec.RedirectScheme, - BasicAuth: middleware.Spec.BasicAuth, - DigestAuth: middleware.Spec.DigestAuth, - ForwardAuth: middleware.Spec.ForwardAuth, + BasicAuth: basicAuth, + DigestAuth: digestAuth, + ForwardAuth: forwardAuth, InFlightReq: middleware.Spec.InFlightReq, Buffering: middleware.Spec.Buffering, CircuitBreaker: middleware.Spec.CircuitBreaker, @@ -178,6 +199,175 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) return conf } +func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *v1alpha1.ForwardAuth) (*dynamic.ForwardAuth, error) { + if auth == nil { + return nil, nil + } + if len(auth.Address) == 0 { + return nil, fmt.Errorf("forward authentication requires an address") + } + + forwardAuth := &dynamic.ForwardAuth{ + Address: auth.Address, + TrustForwardHeader: auth.TrustForwardHeader, + AuthResponseHeaders: auth.AuthResponseHeaders, + } + + if auth.TLS == nil { + return forwardAuth, nil + } + + forwardAuth.TLS = &dynamic.ClientTLS{ + CAOptional: auth.TLS.CAOptional, + InsecureSkipVerify: auth.TLS.InsecureSkipVerify, + } + + if len(auth.TLS.CASecret) > 0 { + caSecret, err := loadCASecret(namespace, auth.TLS.CASecret, k8sClient) + if err != nil { + return nil, fmt.Errorf("failed to load auth ca secret: %v", err) + } + forwardAuth.TLS.CA = caSecret + } + + if len(auth.TLS.CertSecret) > 0 { + authSecretCert, authSecretKey, err := loadAuthTLSSecret(namespace, auth.TLS.CertSecret, k8sClient) + if err != nil { + return nil, fmt.Errorf("failed to load auth secret: %s", err) + } + forwardAuth.TLS.Cert = authSecretCert + forwardAuth.TLS.Key = authSecretKey + } + + return forwardAuth, nil +} + +func loadCASecret(namespace, secretName string, k8sClient Client) (string, error) { + secret, ok, err := k8sClient.GetSecret(namespace, secretName) + if err != nil { + return "", fmt.Errorf("failed to fetch secret '%s/%s': %s", namespace, secretName, err) + } + if !ok { + return "", fmt.Errorf("secret '%s/%s' not found", namespace, secretName) + } + if secret == nil { + return "", fmt.Errorf("data for secret '%s/%s' must not be nil", namespace, secretName) + } + if len(secret.Data) != 1 { + return "", fmt.Errorf("found %d elements for secret '%s/%s', must be single element exactly", len(secret.Data), namespace, secretName) + } + + for _, v := range secret.Data { + return string(v), nil + } + return "", nil +} + +func loadAuthTLSSecret(namespace, secretName string, k8sClient Client) (string, string, error) { + secret, exists, err := k8sClient.GetSecret(namespace, secretName) + if err != nil { + return "", "", fmt.Errorf("failed to fetch secret '%s/%s': %s", namespace, secretName, err) + } + if !exists { + return "", "", fmt.Errorf("secret '%s/%s' does not exist", namespace, secretName) + } + if secret == nil { + return "", "", fmt.Errorf("data for secret '%s/%s' must not be nil", namespace, secretName) + } + if len(secret.Data) != 2 { + return "", "", fmt.Errorf("found %d elements for secret '%s/%s', must be two elements exactly", len(secret.Data), namespace, secretName) + } + + return getCertificateBlocks(secret, namespace, secretName) +} + +func createBasicAuthMiddleware(client Client, namespace string, basicAuth *v1alpha1.BasicAuth) (*dynamic.BasicAuth, error) { + if basicAuth == nil { + return nil, nil + } + + credentials, err := getAuthCredentials(client, basicAuth.Secret, namespace) + if err != nil { + return nil, err + } + + return &dynamic.BasicAuth{ + Users: credentials, + Realm: basicAuth.Realm, + RemoveHeader: basicAuth.RemoveHeader, + HeaderField: basicAuth.HeaderField, + }, nil +} + +func createDigestAuthMiddleware(client Client, namespace string, digestAuth *v1alpha1.DigestAuth) (*dynamic.DigestAuth, error) { + if digestAuth == nil { + return nil, nil + } + + credentials, err := getAuthCredentials(client, digestAuth.Secret, namespace) + if err != nil { + return nil, err + } + + return &dynamic.DigestAuth{ + Users: credentials, + Realm: digestAuth.Realm, + RemoveHeader: digestAuth.RemoveHeader, + HeaderField: digestAuth.HeaderField, + }, nil +} + +func getAuthCredentials(k8sClient Client, authSecret, namespace string) ([]string, error) { + if authSecret == "" { + return nil, fmt.Errorf("auth secret must be set") + } + + auth, err := loadAuthCredentials(namespace, authSecret, k8sClient) + if err != nil { + return nil, fmt.Errorf("failed to load auth credentials: %s", err) + } + + return auth, nil +} + +func loadAuthCredentials(namespace, secretName string, k8sClient Client) ([]string, error) { + secret, ok, err := k8sClient.GetSecret(namespace, secretName) + if err != nil { + return nil, fmt.Errorf("failed to fetch secret '%s/%s': %s", namespace, secretName, err) + } + if !ok { + return nil, fmt.Errorf("secret '%s/%s' not found", namespace, secretName) + } + if secret == nil { + return nil, fmt.Errorf("data for secret '%s/%s' must not be nil", namespace, secretName) + } + if len(secret.Data) != 1 { + return nil, fmt.Errorf("found %d elements for secret '%s/%s', must be single element exactly", len(secret.Data), namespace, secretName) + } + + var firstSecret []byte + for _, v := range secret.Data { + firstSecret = v + break + } + + var credentials []string + scanner := bufio.NewScanner(bytes.NewReader(firstSecret)) + for scanner.Scan() { + if cred := scanner.Text(); len(cred) > 0 { + credentials = append(credentials, cred) + } + } + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error reading secret for %v/%v: %v", namespace, secretName, err) + } + if len(credentials) == 0 { + return nil, fmt.Errorf("secret '%s/%s' does not contain any credentials", namespace, secretName) + } + + return credentials, nil +} + func createChainMiddleware(ctx context.Context, namespace string, chain *v1alpha1.Chain) *dynamic.Chain { if chain == nil { return nil diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go index cb9d87408..be7a3adef 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_test.go +++ b/pkg/provider/kubernetes/crd/kubernetes_test.go @@ -1461,6 +1461,43 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, }, + { + desc: "Simple Ingress Route, with basic auth middleware", + paths: []string{"services.yml", "with_auth.yml"}, + expected: &dynamic.Configuration{ + TLS: &dynamic.TLSConfiguration{}, + 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{ + "default/basicauth": { + BasicAuth: &dynamic.BasicAuth{ + Users: dynamic.Users{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, + }, + }, + "default/digestauth": { + DigestAuth: &dynamic.DigestAuth{ + Users: dynamic.Users{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, + }, + }, + "default/forwardauth": { + ForwardAuth: &dynamic.ForwardAuth{ + Address: "test.com", + TLS: &dynamic.ClientTLS{ + CA: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----", + Cert: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----", + Key: "-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----", + }, + }, + }, + }, + Services: map[string]*dynamic.Service{}, + }, + }, + }, { desc: "port selected by name (TODO)", }, diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go index c5c2c4154..486f8987f 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/middleware.go @@ -18,29 +18,29 @@ type Middleware struct { // +k8s:deepcopy-gen=true -// Middleware holds the Middleware configuration. +// MiddlewareSpec holds the Middleware configuration. type MiddlewareSpec struct { - AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty" toml:"addPrefix,omitempty" yaml:"addPrefix,omitempty"` - StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty" toml:"stripPrefix,omitempty" yaml:"stripPrefix,omitempty"` - StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty" toml:"stripPrefixRegex,omitempty" yaml:"stripPrefixRegex,omitempty"` - ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty" toml:"replacePath,omitempty" yaml:"replacePath,omitempty"` - ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty" toml:"replacePathRegex,omitempty" yaml:"replacePathRegex,omitempty"` - Chain *Chain `json:"chain,omitempty" toml:"chain,omitempty" yaml:"chain,omitempty"` - IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty"` - Headers *dynamic.Headers `json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty"` - Errors *dynamic.ErrorPage `json:"errors,omitempty" toml:"errors,omitempty" yaml:"errors,omitempty"` - RateLimit *dynamic.RateLimit `json:"rateLimit,omitempty" toml:"rateLimit,omitempty" yaml:"rateLimit,omitempty"` - RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty" toml:"redirectRegex,omitempty" yaml:"redirectRegex,omitempty"` - RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty" toml:"redirectScheme,omitempty" yaml:"redirectScheme,omitempty"` - BasicAuth *dynamic.BasicAuth `json:"basicAuth,omitempty" toml:"basicAuth,omitempty" yaml:"basicAuth,omitempty"` - DigestAuth *dynamic.DigestAuth `json:"digestAuth,omitempty" toml:"digestAuth,omitempty" yaml:"digestAuth,omitempty"` - ForwardAuth *dynamic.ForwardAuth `json:"forwardAuth,omitempty" toml:"forwardAuth,omitempty" yaml:"forwardAuth,omitempty"` - InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty" toml:"inFlightReq,omitempty" yaml:"inFlightReq,omitempty"` - Buffering *dynamic.Buffering `json:"buffering,omitempty" toml:"buffering,omitempty" yaml:"buffering,omitempty"` - CircuitBreaker *dynamic.CircuitBreaker `json:"circuitBreaker,omitempty" toml:"circuitBreaker,omitempty" yaml:"circuitBreaker,omitempty"` - Compress *dynamic.Compress `json:"compress,omitempty" toml:"compress,omitempty" yaml:"compress,omitempty" label:"allowEmpty"` - PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty" toml:"passTLSClientCert,omitempty" yaml:"passTLSClientCert,omitempty"` - Retry *dynamic.Retry `json:"retry,omitempty" toml:"retry,omitempty" yaml:"retry,omitempty"` + AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty"` + StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty"` + StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty"` + ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty"` + ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty"` + Chain *Chain `json:"chain,omitempty"` + IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty"` + Headers *dynamic.Headers `json:"headers,omitempty"` + Errors *dynamic.ErrorPage `json:"errors,omitempty"` + RateLimit *dynamic.RateLimit `json:"rateLimit,omitempty"` + RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty"` + RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty"` + BasicAuth *BasicAuth `json:"basicAuth,omitempty"` + DigestAuth *DigestAuth `json:"digestAuth,omitempty"` + ForwardAuth *ForwardAuth `json:"forwardAuth,omitempty"` + InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty"` + Buffering *dynamic.Buffering `json:"buffering,omitempty"` + CircuitBreaker *dynamic.CircuitBreaker `json:"circuitBreaker,omitempty"` + Compress *dynamic.Compress `json:"compress,omitempty"` + PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty"` + Retry *dynamic.Retry `json:"retry,omitempty"` } // +k8s:deepcopy-gen=true @@ -50,6 +50,43 @@ type Chain struct { Middlewares []MiddlewareRef `json:"middlewares,omitempty"` } +// +k8s:deepcopy-gen=true + +// BasicAuth holds the HTTP basic authentication configuration. +type BasicAuth struct { + Secret string `json:"secret,omitempty"` + Realm string `json:"realm,omitempty"` + RemoveHeader bool `json:"removeHeader,omitempty"` + HeaderField string `json:"headerField,omitempty"` +} + +// +k8s:deepcopy-gen=true + +// DigestAuth holds the Digest HTTP authentication configuration. +type DigestAuth struct { + Secret string `json:"secret,omitempty"` + RemoveHeader bool `json:"removeHeader,omitempty"` + Realm string `json:"realm,omitempty"` + HeaderField string `json:"headerField,omitempty"` +} + +// +k8s:deepcopy-gen=true + +// ForwardAuth holds the http forward authentication configuration. +type ForwardAuth struct { + Address string `json:"address,omitempty"` + TrustForwardHeader bool `json:"trustForwardHeader,omitempty"` + AuthResponseHeaders []string `json:"authResponseHeaders,omitempty"` + TLS *ClientTLS `json:"tls,omitempty"` +} + +type ClientTLS struct { + CASecret string `json:"caSecret,omitempty"` + CAOptional bool `json:"caOptional,omitempty"` + CertSecret string `json:"certSecret,omitempty"` + InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` +} + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // MiddlewareList is a list of Middleware resources. diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go index 67aa55d0c..65ea369c8 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go @@ -33,6 +33,22 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BasicAuth) DeepCopyInto(out *BasicAuth) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BasicAuth. +func (in *BasicAuth) DeepCopy() *BasicAuth { + if in == nil { + return nil + } + out := new(BasicAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Chain) DeepCopyInto(out *Chain) { *out = *in @@ -75,6 +91,64 @@ func (in *ClientAuth) DeepCopy() *ClientAuth { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientTLS) DeepCopyInto(out *ClientTLS) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTLS. +func (in *ClientTLS) DeepCopy() *ClientTLS { + if in == nil { + return nil + } + out := new(ClientTLS) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DigestAuth) DeepCopyInto(out *DigestAuth) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DigestAuth. +func (in *DigestAuth) DeepCopy() *DigestAuth { + if in == nil { + return nil + } + out := new(DigestAuth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ForwardAuth) DeepCopyInto(out *ForwardAuth) { + *out = *in + if in.AuthResponseHeaders != nil { + in, out := &in.AuthResponseHeaders, &out.AuthResponseHeaders + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(ClientTLS) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ForwardAuth. +func (in *ForwardAuth) DeepCopy() *ForwardAuth { + if in == nil { + return nil + } + out := new(ForwardAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HealthCheck) DeepCopyInto(out *HealthCheck) { *out = *in @@ -425,17 +499,17 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) { } if in.BasicAuth != nil { in, out := &in.BasicAuth, &out.BasicAuth - *out = new(dynamic.BasicAuth) - (*in).DeepCopyInto(*out) + *out = new(BasicAuth) + **out = **in } if in.DigestAuth != nil { in, out := &in.DigestAuth, &out.DigestAuth - *out = new(dynamic.DigestAuth) - (*in).DeepCopyInto(*out) + *out = new(DigestAuth) + **out = **in } if in.ForwardAuth != nil { in, out := &in.ForwardAuth, &out.ForwardAuth - *out = new(dynamic.ForwardAuth) + *out = new(ForwardAuth) (*in).DeepCopyInto(*out) } if in.InFlightReq != nil { diff --git a/pkg/server/router/tcp/router.go b/pkg/server/router/tcp/router.go index bf4931695..55b42ba9d 100644 --- a/pkg/server/router/tcp/router.go +++ b/pkg/server/router/tcp/router.go @@ -177,6 +177,13 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string continue } + if routerConfig.Rule == "" { + err := errors.New("router has no rule") + routerConfig.AddError(err, true) + logger.Error(err) + continue + } + handler, err := m.serviceManager.BuildTCP(ctxRouter, routerConfig.Service) if err != nil { routerConfig.AddError(err, true) @@ -188,7 +195,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string if err != nil { routerErr := fmt.Errorf("unknown rule %s", routerConfig.Rule) routerConfig.AddError(routerErr, true) - logger.Debug(routerErr) + logger.Error(routerErr) continue } From d044c0f4ccf5e2429a3e501ee33887dedc782beb Mon Sep 17 00:00:00 2001 From: Julien Salleyron Date: Fri, 6 Sep 2019 15:08:04 +0200 Subject: [PATCH 24/37] New API security --- .../observability/metrics/prometheus.md | 31 +++++ docs/content/operations/api.md | 85 +++++++++++++- docs/content/operations/ping.md | 35 +++++- .../reference/static-configuration/cli-ref.md | 16 ++- .../reference/static-configuration/env-ref.md | 16 ++- .../reference/static-configuration/file.toml | 4 + .../reference/static-configuration/file.yaml | 8 +- integration/fixtures/access_log_config.toml | 1 + integration/fixtures/acme/acme_base.toml | 1 + integration/fixtures/acme/acme_domains.toml | 1 + .../acme/acme_multiple_resolvers.toml | 1 + integration/fixtures/acme/acme_tcp.toml | 1 + integration/fixtures/acme/acme_tls.toml | 1 + .../fixtures/acme/acme_tls_dynamic.toml | 1 + .../acme/acme_tls_multiple_entrypoints.toml | 1 + integration/fixtures/docker/minimal.toml | 1 + integration/fixtures/docker/simple.toml | 1 + integration/fixtures/grpc/config.toml | 1 + integration/fixtures/grpc/config_h2c.toml | 1 + .../fixtures/grpc/config_h2c_termination.toml | 1 + .../fixtures/grpc/config_insecure.toml | 1 + integration/fixtures/grpc/config_retry.toml | 1 + .../healthcheck/multiple-entrypoints.toml | 1 + .../fixtures/healthcheck/port_overload.toml | 1 + integration/fixtures/healthcheck/simple.toml | 1 + .../https/clientca/https_1ca1config.toml | 1 + .../https/clientca/https_2ca1config.toml | 1 + .../https/clientca/https_2ca2config.toml | 1 + .../fixtures/https/dynamic_https_sni.toml | 1 + .../https/dynamic_https_sni_default_cert.toml | 1 + .../fixtures/https/https_redirect.toml | 1 + integration/fixtures/https/https_sni.toml | 1 + .../https_sni_case_insensitive_dynamic.toml | 1 + .../https/https_sni_default_cert.toml | 1 + .../fixtures/https/https_sni_strict.toml | 1 + .../fixtures/https/https_tls_options.toml | 1 + integration/fixtures/https/rootcas/https.toml | 1 + .../https/rootcas/https_with_file.toml | 1 + integration/fixtures/k8s_crd.toml | 1 + integration/fixtures/k8s_default.toml | 1 + integration/fixtures/marathon/simple.toml | 1 + integration/fixtures/mirror.toml | 1 + integration/fixtures/multiple_provider.toml | 1 + integration/fixtures/multiprovider.toml | 2 + integration/fixtures/proxy-protocol/with.toml | 1 + .../fixtures/proxy-protocol/without.toml | 1 + integration/fixtures/ratelimit/simple.toml | 1 + integration/fixtures/rest/simple.toml | 2 + integration/fixtures/rest/simple_secure.toml | 27 +++++ integration/fixtures/retry/simple.toml | 1 + integration/fixtures/router_errors.toml | 1 + integration/fixtures/service_errors.toml | 1 + integration/fixtures/simple_auth.toml | 1 + integration/fixtures/simple_hostresolver.toml | 1 + integration/fixtures/simple_secure_api.toml | 25 ++++ integration/fixtures/simple_stats.toml | 1 + integration/fixtures/simple_web.toml | 1 + integration/fixtures/simple_whitelist.toml | 3 +- .../tcp/catch-all-no-tls-with-https.toml | 1 + .../fixtures/tcp/catch-all-no-tls.toml | 1 + integration/fixtures/tcp/mixed.toml | 1 + .../fixtures/tcp/multi-tls-options.toml | 1 + .../fixtures/tcp/non-tls-fallback.toml | 1 + integration/fixtures/tcp/non-tls.toml | 1 + .../fixtures/timeout/forwarding_timeouts.toml | 1 + integration/fixtures/timeout/keepalive.toml | 1 + .../fixtures/tlsclientheaders/simple.toml | 1 + .../tracing/simple-jaeger-collector.toml | 1 + .../fixtures/tracing/simple-jaeger.toml | 1 + .../fixtures/tracing/simple-zipkin.toml | 1 + integration/fixtures/traefik_log_config.toml | 1 + integration/fixtures/websocket/config.toml | 1 + .../fixtures/websocket/config_https.toml | 1 + integration/fixtures/wrr.toml | 1 + integration/fixtures/wrr_sticky.toml | 1 + integration/rest_test.go | 108 +++++++++++++++++- integration/simple_test.go | 57 +++++---- pkg/api/handler.go | 9 ++ pkg/config/static/static_config.go | 7 +- pkg/ping/ping.go | 2 + pkg/provider/rest/rest.go | 8 ++ .../router/route_appender_aggregator.go | 22 ++-- .../router/route_appender_aggregator_test.go | 74 +++--------- pkg/server/router/route_appender_factory.go | 5 +- pkg/server/router/router_test.go | 10 +- pkg/server/server.go | 14 ++- pkg/server/server_configuration.go | 9 +- pkg/server/service/service.go | 20 +++- pkg/server/service/service_test.go | 6 +- pkg/types/metrics.go | 2 + 90 files changed, 538 insertions(+), 132 deletions(-) create mode 100644 integration/fixtures/rest/simple_secure.toml create mode 100644 integration/fixtures/simple_secure_api.toml diff --git a/docs/content/observability/metrics/prometheus.md b/docs/content/observability/metrics/prometheus.md index ac8a43dc3..13c3b17b8 100644 --- a/docs/content/observability/metrics/prometheus.md +++ b/docs/content/observability/metrics/prometheus.md @@ -85,3 +85,34 @@ metrics: ```bash tab="CLI" --metrics.prometheus.addServicesLabels=true ``` + +#### `entryPoint` + +_Optional, Default=traefik_ + +Entry point used to expose metrics. + +```toml tab="File (TOML)" +[entryPoints] + [entryPoints.metrics] + address = ":8082" + +[metrics] + [metrics.prometheus] + entryPoint = "metrics" +``` + +```yaml tab="File (YAML)" +entryPoints: + metrics: + address: ":8082" + +metrics: + prometheus: + entryPoint: metrics +``` + +```bash tab="CLI" +--entryPoints.metrics.address=":8082" +--metrics.prometheus..entryPoint="metrics" +``` diff --git a/docs/content/operations/api.md b/docs/content/operations/api.md index 6cbd012c9..61141ad3d 100644 --- a/docs/content/operations/api.md +++ b/docs/content/operations/api.md @@ -1,8 +1,5 @@ # API -!!! important - In the RC version, you can't configure middlewares (basic authentication or white listing) anymore, but as security is important, this will change before the GA version. - Traefik exposes a number of information through an API handler, such as the configuration of all routers, services, middlewares, etc. As with all features of Traefik, this handler can be enabled with the [static configuration](../getting-started/configuration-overview.md#the-static-configuration). @@ -22,11 +19,10 @@ would be to apply the following protection mechanisms: keeping it restricted to internal networks (as in the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege), applied to networks). -!!! important - In the beta version, you can't configure middlewares (basic authentication or white listing) anymore, but as security is important, this will change before the RC version. - ## Configuration +If you enable the API, a new special `service` named `api@internal` is created and then can be reference in a router. + To enable the API handler: ```toml tab="File (TOML)" @@ -41,6 +37,83 @@ api: {} --api=true ``` +And then you will able to reference it like this. + +```yaml tab="Docker" + - "traefik.http.routers.api.rule=PathPrefix(`/api`) || PathPrefix(`/dashboard`)" + - "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" +``` + +```json tab="Marathon" +"labels": { + "traefik.http.routers.api.rule": "PathPrefix(`/api`) || PathPrefix(`/dashboard`)" + "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" +# Declaring the user list +labels: + - "traefik.http.routers.api.rule=PathPrefix(`/api`) || PathPrefix(`/dashboard`)" + - "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" +``` + +```toml tab="File (TOML)" +[http.routers.my-api] + rule="PathPrefix(`/api`) || PathPrefix(`/dashboard`)" + service="api@internal" + middlewares=["auth"] + +[http.middlewares.auth.basicAuth] + users = [ + "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", + "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + ] +``` + +```yaml tab="File (YAML)" +http: + routers: + api: + rule: PathPrefix(`/api`) || PathPrefix(`/dashboard`) + service: api@internal + middlewares: + - auth + middlewares: + auth: + basicAuth: + users: + - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" + - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" +``` + +### `insecure` + +Enable the API in `insecure` mode, which means that the API will be available directly on the entryPoint named `traefik`. + +!!! Note + If the entryPoint named `traefik` is not configured, it will be automatically created on port 8080. + +```toml tab="File (TOML)" +[api] + insecure = true +``` + +```yaml tab="File (YAML)" +api: + insecure: true +``` + +```bash tab="CLI" +--api.insecure=true +``` + ### `dashboard` _Optional, Default=true_ diff --git a/docs/content/operations/ping.md b/docs/content/operations/ping.md index deee3d641..6298a3e7d 100644 --- a/docs/content/operations/ping.md +++ b/docs/content/operations/ping.md @@ -5,7 +5,7 @@ Checking the Health of Your Traefik Instances ## Configuration Examples -??? example "Enabling /ping" +!!! example "Enabling /ping" ```toml tab="File (TOML)" [ping] @@ -19,10 +19,39 @@ ping: {} --ping=true ``` +## Configuration Options + +The `/ping` health-check URL is enabled with the command-line `--ping` or config file option `[ping]`. + +You can customize the `entryPoint` where the `/ping` is active with the `entryPoint` option (default value: `traefik`) + | Path | Method | Description | |---------|---------------|-----------------------------------------------------------------------------------------------------| | `/ping` | `GET`, `HEAD` | A simple endpoint to check for Traefik process liveness. Return a code `200` with the content: `OK` | -## Configuration Options +### `entryPoint` -The `/ping` health-check URL is enabled with the command-line `--ping` or config file option `[ping]`. \ No newline at end of file +Enabling /ping on a dedicated EntryPoint. + +```toml tab="File (TOML)" +[entryPoints] + [entryPoints.ping] + address = ":8082" + +[ping] + entryPoint = "ping" +``` + +```yaml tab="File (YAML)" +entryPoints: + ping: + address: ":8082" + +ping: + entryPoint: "ping" +``` + +```bash tab="CLI" +--entryPoints.ping.address=":8082" +--ping.entryPoint="ping" +``` diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index ecea25aa8..62514adab 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -45,6 +45,9 @@ Activate dashboard. (Default: ```true```) `--api.debug`: Enable additional endpoints for debugging and profiling. (Default: ```false```) +`--api.insecure`: +Activate API on an insecure entryPoints named traefik. (Default: ```false```) + `--certificatesresolvers.`: Certificates resolvers configuration. (Default: ```false```) @@ -207,6 +210,9 @@ Enable metrics on services. (Default: ```true```) `--metrics.prometheus.buckets`: Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000```) +`--metrics.prometheus.entrypoint`: +EntryPoint (Default: ```traefik```) + `--metrics.statsd`: StatsD metrics exporter type. (Default: ```false```) @@ -223,7 +229,10 @@ Enable metrics on services. (Default: ```true```) StatsD push interval. (Default: ```10```) `--ping`: -Enable ping. (Default: ```true```) +Enable ping. (Default: ```false```) + +`--ping.entrypoint`: +EntryPoint (Default: ```traefik```) `--providers.docker`: Enable Docker backend with default settings. (Default: ```false```) @@ -433,7 +442,10 @@ Defines the polling interval in seconds. (Default: ```15```) Watch provider. (Default: ```true```) `--providers.rest`: -Enable Rest backend with default settings. (Default: ```true```) +Enable Rest backend with default settings. (Default: ```false```) + +`--providers.rest.insecure`: +Activate REST Provider on an insecure entryPoints named traefik. (Default: ```false```) `--serverstransport.forwardingtimeouts.dialtimeout`: The amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists. (Default: ```30```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 194cd0897..14da23d49 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -45,6 +45,9 @@ Activate dashboard. (Default: ```true```) `TRAEFIK_API_DEBUG`: Enable additional endpoints for debugging and profiling. (Default: ```false```) +`TRAEFIK_API_INSECURE`: +Activate API on an insecure entryPoints named traefik. (Default: ```false```) + `TRAEFIK_CERTIFICATESRESOLVERS_`: Certificates resolvers configuration. (Default: ```false```) @@ -207,6 +210,9 @@ Enable metrics on services. (Default: ```true```) `TRAEFIK_METRICS_PROMETHEUS_BUCKETS`: Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000```) +`TRAEFIK_METRICS_PROMETHEUS_ENTRYPOINT`: +EntryPoint (Default: ```traefik```) + `TRAEFIK_METRICS_STATSD`: StatsD metrics exporter type. (Default: ```false```) @@ -223,7 +229,10 @@ Enable metrics on services. (Default: ```true```) StatsD push interval. (Default: ```10```) `TRAEFIK_PING`: -Enable ping. (Default: ```true```) +Enable ping. (Default: ```false```) + +`TRAEFIK_PING_ENTRYPOINT`: +EntryPoint (Default: ```traefik```) `TRAEFIK_PROVIDERS_DOCKER`: Enable Docker backend with default settings. (Default: ```false```) @@ -433,7 +442,10 @@ Defines the polling interval in seconds. (Default: ```15```) Watch provider. (Default: ```true```) `TRAEFIK_PROVIDERS_REST`: -Enable Rest backend with default settings. (Default: ```true```) +Enable Rest backend with default settings. (Default: ```false```) + +`TRAEFIK_PROVIDERS_REST_INSECURE`: +Activate REST Provider on an insecure entryPoints named traefik. (Default: ```false```) `TRAEFIK_SERVERSTRANSPORT_FORWARDINGTIMEOUTS_DIALTIMEOUT`: The amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists. (Default: ```30```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index b4d1f88b8..4f4542f63 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -96,6 +96,7 @@ labelSelector = "foobar" ingressClass = "foobar" [providers.rest] + insecure = true [providers.rancher] constraints = "foobar" watch = true @@ -107,6 +108,7 @@ prefix = "foobar" [api] + insecure = true dashboard = true debug = true @@ -115,6 +117,7 @@ buckets = [42.0, 42.0] addEntryPointsLabels = true addServicesLabels = true + entryPoint = "foobar" [metrics.datadog] address = "foobar" pushInterval = "10s" @@ -137,6 +140,7 @@ addServicesLabels = true [ping] + entryPoint = "foobar" [log] level = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 12f7c011f..6080d9037 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -102,7 +102,8 @@ providers: - foobar labelSelector: foobar ingressClass: foobar - rest: {} + rest: + insecure: true rancher: constraints: foobar watch: true @@ -113,6 +114,7 @@ providers: intervalPoll: true prefix: foobar api: + insecure: true dashboard: true debug: true metrics: @@ -122,6 +124,7 @@ metrics: - 42 addEntryPointsLabels: true addServicesLabels: true + entryPoint: foobar datadog: address: foobar pushInterval: 42 @@ -142,7 +145,8 @@ metrics: password: foobar addEntryPointsLabels: true addServicesLabels: true -ping: {} +ping: + entryPoint: foobar log: level: foobar filePath: foobar diff --git a/integration/fixtures/access_log_config.toml b/integration/fixtures/access_log_config.toml index 19f5416e3..68e653788 100644 --- a/integration/fixtures/access_log_config.toml +++ b/integration/fixtures/access_log_config.toml @@ -22,6 +22,7 @@ address = ":8008" [api] + insecure = true [providers] [providers.docker] diff --git a/integration/fixtures/acme/acme_base.toml b/integration/fixtures/acme/acme_base.toml index ae8b2be83..9a8242e63 100644 --- a/integration/fixtures/acme/acme_base.toml +++ b/integration/fixtures/acme/acme_base.toml @@ -31,6 +31,7 @@ {{end}} [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/acme/acme_domains.toml b/integration/fixtures/acme/acme_domains.toml index 72f047acf..e9b150eb3 100644 --- a/integration/fixtures/acme/acme_domains.toml +++ b/integration/fixtures/acme/acme_domains.toml @@ -31,6 +31,7 @@ {{end}} [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/acme/acme_multiple_resolvers.toml b/integration/fixtures/acme/acme_multiple_resolvers.toml index 73313d3f3..6da4a2a48 100644 --- a/integration/fixtures/acme/acme_multiple_resolvers.toml +++ b/integration/fixtures/acme/acme_multiple_resolvers.toml @@ -31,6 +31,7 @@ {{end}} [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/acme/acme_tcp.toml b/integration/fixtures/acme/acme_tcp.toml index c016a4139..3bf7e3721 100644 --- a/integration/fixtures/acme/acme_tcp.toml +++ b/integration/fixtures/acme/acme_tcp.toml @@ -31,6 +31,7 @@ {{end}} [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/acme/acme_tls.toml b/integration/fixtures/acme/acme_tls.toml index 2319974bd..990ba69d4 100644 --- a/integration/fixtures/acme/acme_tls.toml +++ b/integration/fixtures/acme/acme_tls.toml @@ -31,6 +31,7 @@ {{end}} [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/acme/acme_tls_dynamic.toml b/integration/fixtures/acme/acme_tls_dynamic.toml index eac99adc1..832ae1f27 100644 --- a/integration/fixtures/acme/acme_tls_dynamic.toml +++ b/integration/fixtures/acme/acme_tls_dynamic.toml @@ -31,6 +31,7 @@ {{end}} [api] + insecure = true [providers] [providers.file] diff --git a/integration/fixtures/acme/acme_tls_multiple_entrypoints.toml b/integration/fixtures/acme/acme_tls_multiple_entrypoints.toml index f4601b695..3ffbdfad8 100644 --- a/integration/fixtures/acme/acme_tls_multiple_entrypoints.toml +++ b/integration/fixtures/acme/acme_tls_multiple_entrypoints.toml @@ -34,3 +34,4 @@ {{end}} [api] + insecure = true diff --git a/integration/fixtures/docker/minimal.toml b/integration/fixtures/docker/minimal.toml index 4ba52559e..8e6024d84 100644 --- a/integration/fixtures/docker/minimal.toml +++ b/integration/fixtures/docker/minimal.toml @@ -10,6 +10,7 @@ address = ":8000" [api] + insecure = true [providers] [providers.docker] diff --git a/integration/fixtures/docker/simple.toml b/integration/fixtures/docker/simple.toml index 630fd5549..a2c0de53f 100644 --- a/integration/fixtures/docker/simple.toml +++ b/integration/fixtures/docker/simple.toml @@ -10,6 +10,7 @@ address = ":8000" [api] + insecure = true [providers] [providers.docker] diff --git a/integration/fixtures/grpc/config.toml b/integration/fixtures/grpc/config.toml index 5ebf5e946..1e8aac3a0 100644 --- a/integration/fixtures/grpc/config.toml +++ b/integration/fixtures/grpc/config.toml @@ -13,6 +13,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/grpc/config_h2c.toml b/integration/fixtures/grpc/config_h2c.toml index 8dfcc99da..683b72f58 100644 --- a/integration/fixtures/grpc/config_h2c.toml +++ b/integration/fixtures/grpc/config_h2c.toml @@ -10,6 +10,7 @@ address = ":8081" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/grpc/config_h2c_termination.toml b/integration/fixtures/grpc/config_h2c_termination.toml index 10fbdaeaa..f4188fbe7 100644 --- a/integration/fixtures/grpc/config_h2c_termination.toml +++ b/integration/fixtures/grpc/config_h2c_termination.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/grpc/config_insecure.toml b/integration/fixtures/grpc/config_insecure.toml index 417ebdd22..997a23c5b 100644 --- a/integration/fixtures/grpc/config_insecure.toml +++ b/integration/fixtures/grpc/config_insecure.toml @@ -13,6 +13,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/grpc/config_retry.toml b/integration/fixtures/grpc/config_retry.toml index dfd316ea5..e3d5efe99 100644 --- a/integration/fixtures/grpc/config_retry.toml +++ b/integration/fixtures/grpc/config_retry.toml @@ -13,6 +13,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/healthcheck/multiple-entrypoints.toml b/integration/fixtures/healthcheck/multiple-entrypoints.toml index 3c1d60f3c..12bab7274 100644 --- a/integration/fixtures/healthcheck/multiple-entrypoints.toml +++ b/integration/fixtures/healthcheck/multiple-entrypoints.toml @@ -12,6 +12,7 @@ address = ":9000" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/healthcheck/port_overload.toml b/integration/fixtures/healthcheck/port_overload.toml index 40b24391b..eb7accedd 100644 --- a/integration/fixtures/healthcheck/port_overload.toml +++ b/integration/fixtures/healthcheck/port_overload.toml @@ -10,6 +10,7 @@ address = ":8000" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/healthcheck/simple.toml b/integration/fixtures/healthcheck/simple.toml index 92bc1e4d7..a2338a8b0 100644 --- a/integration/fixtures/healthcheck/simple.toml +++ b/integration/fixtures/healthcheck/simple.toml @@ -10,6 +10,7 @@ address = ":8000" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/clientca/https_1ca1config.toml b/integration/fixtures/https/clientca/https_1ca1config.toml index f52896e55..951fa703d 100644 --- a/integration/fixtures/https/clientca/https_1ca1config.toml +++ b/integration/fixtures/https/clientca/https_1ca1config.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/clientca/https_2ca1config.toml b/integration/fixtures/https/clientca/https_2ca1config.toml index 948374c04..1ccc98954 100644 --- a/integration/fixtures/https/clientca/https_2ca1config.toml +++ b/integration/fixtures/https/clientca/https_2ca1config.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/clientca/https_2ca2config.toml b/integration/fixtures/https/clientca/https_2ca2config.toml index 5757ac602..43725bcb2 100644 --- a/integration/fixtures/https/clientca/https_2ca2config.toml +++ b/integration/fixtures/https/clientca/https_2ca2config.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/dynamic_https_sni.toml b/integration/fixtures/https/dynamic_https_sni.toml index 2a7ff45fa..20b82c0dd 100644 --- a/integration/fixtures/https/dynamic_https_sni.toml +++ b/integration/fixtures/https/dynamic_https_sni.toml @@ -13,6 +13,7 @@ address = ":8443" [api] + insecure = true [providers] [providers.file] diff --git a/integration/fixtures/https/dynamic_https_sni_default_cert.toml b/integration/fixtures/https/dynamic_https_sni_default_cert.toml index 05f3c1b6d..d8e6f8d45 100644 --- a/integration/fixtures/https/dynamic_https_sni_default_cert.toml +++ b/integration/fixtures/https/dynamic_https_sni_default_cert.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/https_redirect.toml b/integration/fixtures/https/https_redirect.toml index 3147488c4..6ee48d0ca 100644 --- a/integration/fixtures/https/https_redirect.toml +++ b/integration/fixtures/https/https_redirect.toml @@ -13,6 +13,7 @@ address = ":8443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/https_sni.toml b/integration/fixtures/https/https_sni.toml index c5212af6a..a847d3de0 100644 --- a/integration/fixtures/https/https_sni.toml +++ b/integration/fixtures/https/https_sni.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml b/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml index 614a54ee1..9e63fff4b 100644 --- a/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml +++ b/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/https_sni_default_cert.toml b/integration/fixtures/https/https_sni_default_cert.toml index 05f3c1b6d..d8e6f8d45 100644 --- a/integration/fixtures/https/https_sni_default_cert.toml +++ b/integration/fixtures/https/https_sni_default_cert.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/https_sni_strict.toml b/integration/fixtures/https/https_sni_strict.toml index 9ada0a5e6..09f442c00 100644 --- a/integration/fixtures/https/https_sni_strict.toml +++ b/integration/fixtures/https/https_sni_strict.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/https_tls_options.toml b/integration/fixtures/https/https_tls_options.toml index 4e7dfde43..9bd67c277 100644 --- a/integration/fixtures/https/https_tls_options.toml +++ b/integration/fixtures/https/https_tls_options.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/rootcas/https.toml b/integration/fixtures/https/rootcas/https.toml index 54b502faa..2525c7473 100644 --- a/integration/fixtures/https/rootcas/https.toml +++ b/integration/fixtures/https/rootcas/https.toml @@ -29,6 +29,7 @@ fblo6RBxUQ== address = ":8081" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/https/rootcas/https_with_file.toml b/integration/fixtures/https/rootcas/https_with_file.toml index 21e957df8..62a79ac11 100644 --- a/integration/fixtures/https/rootcas/https_with_file.toml +++ b/integration/fixtures/https/rootcas/https_with_file.toml @@ -14,6 +14,7 @@ address = ":8081" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/k8s_crd.toml b/integration/fixtures/k8s_crd.toml index 21bfa9855..891e3f13e 100644 --- a/integration/fixtures/k8s_crd.toml +++ b/integration/fixtures/k8s_crd.toml @@ -6,6 +6,7 @@ level = "DEBUG" [api] + insecure = true [entryPoints] [entryPoints.footcp] diff --git a/integration/fixtures/k8s_default.toml b/integration/fixtures/k8s_default.toml index 2b39f0f65..ede432aed 100644 --- a/integration/fixtures/k8s_default.toml +++ b/integration/fixtures/k8s_default.toml @@ -3,6 +3,7 @@ sendAnonymousUsage = false [api] + insecure = true [log] level = "DEBUG" diff --git a/integration/fixtures/marathon/simple.toml b/integration/fixtures/marathon/simple.toml index 81082bfe4..f8b4e7266 100644 --- a/integration/fixtures/marathon/simple.toml +++ b/integration/fixtures/marathon/simple.toml @@ -12,6 +12,7 @@ address = ":9090" [api] + insecure = true [providers] [providers.marathon] diff --git a/integration/fixtures/mirror.toml b/integration/fixtures/mirror.toml index a5a07cce8..9448eec7a 100644 --- a/integration/fixtures/mirror.toml +++ b/integration/fixtures/mirror.toml @@ -3,6 +3,7 @@ sendAnonymousUsage = false [api] + insecure = true [log] level = "DEBUG" diff --git a/integration/fixtures/multiple_provider.toml b/integration/fixtures/multiple_provider.toml index 0ac809de2..e5f972d38 100644 --- a/integration/fixtures/multiple_provider.toml +++ b/integration/fixtures/multiple_provider.toml @@ -10,6 +10,7 @@ address = ":8000" [api] + insecure = true [providers] [providers.docker] diff --git a/integration/fixtures/multiprovider.toml b/integration/fixtures/multiprovider.toml index 23c0161ae..bc59d7fab 100644 --- a/integration/fixtures/multiprovider.toml +++ b/integration/fixtures/multiprovider.toml @@ -6,6 +6,7 @@ level = "DEBUG" [api] + insecure = true [entryPoints] [entryPoints.web] @@ -13,6 +14,7 @@ [providers] [providers.rest] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/proxy-protocol/with.toml b/integration/fixtures/proxy-protocol/with.toml index f16361986..c47e97dc5 100644 --- a/integration/fixtures/proxy-protocol/with.toml +++ b/integration/fixtures/proxy-protocol/with.toml @@ -12,6 +12,7 @@ trustedIPs = ["{{.HaproxyIP}}"] [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/proxy-protocol/without.toml b/integration/fixtures/proxy-protocol/without.toml index ef95ca5c7..71b982486 100644 --- a/integration/fixtures/proxy-protocol/without.toml +++ b/integration/fixtures/proxy-protocol/without.toml @@ -12,6 +12,7 @@ trustedIPs = ["1.2.3.4"] [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/ratelimit/simple.toml b/integration/fixtures/ratelimit/simple.toml index 7bdb5a367..aed8d0293 100644 --- a/integration/fixtures/ratelimit/simple.toml +++ b/integration/fixtures/ratelimit/simple.toml @@ -3,6 +3,7 @@ sendAnonymousUsage = false [api] + insecure = true [log] level = "DEBUG" diff --git a/integration/fixtures/rest/simple.toml b/integration/fixtures/rest/simple.toml index 575c6e2e4..8bf7ff14c 100644 --- a/integration/fixtures/rest/simple.toml +++ b/integration/fixtures/rest/simple.toml @@ -10,6 +10,8 @@ address = ":8000" [api] + insecure = true [providers] [providers.rest] + insecure = true diff --git a/integration/fixtures/rest/simple_secure.toml b/integration/fixtures/rest/simple_secure.toml new file mode 100644 index 000000000..312c8f628 --- /dev/null +++ b/integration/fixtures/rest/simple_secure.toml @@ -0,0 +1,27 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[log] + level = "DEBUG" + +[entryPoints] + [entryPoints.web] + address = ":8000" + +[api] + insecure = true + +[providers.rest] + +[providers.file] + filename = "{{ .SelfFilename }}" + +[http.routers.rest] + rule="PathPrefix(`/secure`)" + service="rest@internal" + middlewares=["strip"] + +[http.middlewares.strip.stripPrefix] + prefixes = [ "/secure" ] + diff --git a/integration/fixtures/retry/simple.toml b/integration/fixtures/retry/simple.toml index fea2a4a60..c9e287ae3 100644 --- a/integration/fixtures/retry/simple.toml +++ b/integration/fixtures/retry/simple.toml @@ -10,6 +10,7 @@ address = ":8000" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/router_errors.toml b/integration/fixtures/router_errors.toml index 3e9a75f29..db9429e3c 100644 --- a/integration/fixtures/router_errors.toml +++ b/integration/fixtures/router_errors.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/service_errors.toml b/integration/fixtures/service_errors.toml index 3bdc495bb..cb0997a83 100644 --- a/integration/fixtures/service_errors.toml +++ b/integration/fixtures/service_errors.toml @@ -10,6 +10,7 @@ address = ":4443" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/simple_auth.toml b/integration/fixtures/simple_auth.toml index 51476e428..1edc7ea6b 100644 --- a/integration/fixtures/simple_auth.toml +++ b/integration/fixtures/simple_auth.toml @@ -13,6 +13,7 @@ address = ":8001" [api] + insecure = true middlewares = ["authentication@file"] [ping] diff --git a/integration/fixtures/simple_hostresolver.toml b/integration/fixtures/simple_hostresolver.toml index 77627f89b..01789610a 100644 --- a/integration/fixtures/simple_hostresolver.toml +++ b/integration/fixtures/simple_hostresolver.toml @@ -10,6 +10,7 @@ address = ":8000" [api] + insecure = true [providers] [providers.docker] diff --git a/integration/fixtures/simple_secure_api.toml b/integration/fixtures/simple_secure_api.toml new file mode 100644 index 000000000..f10759fbf --- /dev/null +++ b/integration/fixtures/simple_secure_api.toml @@ -0,0 +1,25 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[entryPoints] + [entryPoints.web] + address = ":8000" + + [entryPoints.traefik] + address = ":8080" + + +[api] + +[providers.file] + filename = "{{ .SelfFilename }}" + +[http.routers.api] + rule="PathPrefix(`/secure`)" + service="api@internal" + middlewares=["strip"] + +[http.middlewares.strip.stripPrefix] + prefixes = [ "/secure" ] + diff --git a/integration/fixtures/simple_stats.toml b/integration/fixtures/simple_stats.toml index 4283299db..eeb4c2533 100644 --- a/integration/fixtures/simple_stats.toml +++ b/integration/fixtures/simple_stats.toml @@ -10,6 +10,7 @@ address = ":8000" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/simple_web.toml b/integration/fixtures/simple_web.toml index 8751d9479..1d17ccb57 100644 --- a/integration/fixtures/simple_web.toml +++ b/integration/fixtures/simple_web.toml @@ -10,3 +10,4 @@ address = ":8000" [api] + insecure = true diff --git a/integration/fixtures/simple_whitelist.toml b/integration/fixtures/simple_whitelist.toml index bef0e455d..03fa451e4 100644 --- a/integration/fixtures/simple_whitelist.toml +++ b/integration/fixtures/simple_whitelist.toml @@ -9,9 +9,10 @@ [entryPoints.web] address = ":8000" [entryPoints.web.ForwardedHeaders] - insecure=true + insecure = true [api] + insecure = true [providers] [providers.docker] diff --git a/integration/fixtures/tcp/catch-all-no-tls-with-https.toml b/integration/fixtures/tcp/catch-all-no-tls-with-https.toml index cc65bda34..1f9a18aaa 100644 --- a/integration/fixtures/tcp/catch-all-no-tls-with-https.toml +++ b/integration/fixtures/tcp/catch-all-no-tls-with-https.toml @@ -10,6 +10,7 @@ address = ":8093" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/tcp/catch-all-no-tls.toml b/integration/fixtures/tcp/catch-all-no-tls.toml index 0132822ee..3e79f8f79 100644 --- a/integration/fixtures/tcp/catch-all-no-tls.toml +++ b/integration/fixtures/tcp/catch-all-no-tls.toml @@ -10,6 +10,7 @@ address = ":8093" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/tcp/mixed.toml b/integration/fixtures/tcp/mixed.toml index e673276ad..ef25965ec 100644 --- a/integration/fixtures/tcp/mixed.toml +++ b/integration/fixtures/tcp/mixed.toml @@ -10,6 +10,7 @@ address = ":8093" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/tcp/multi-tls-options.toml b/integration/fixtures/tcp/multi-tls-options.toml index b36dae76a..1dee6c285 100644 --- a/integration/fixtures/tcp/multi-tls-options.toml +++ b/integration/fixtures/tcp/multi-tls-options.toml @@ -10,6 +10,7 @@ address = ":8093" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/tcp/non-tls-fallback.toml b/integration/fixtures/tcp/non-tls-fallback.toml index 45ff3caa7..ed15f1072 100644 --- a/integration/fixtures/tcp/non-tls-fallback.toml +++ b/integration/fixtures/tcp/non-tls-fallback.toml @@ -10,6 +10,7 @@ address = ":8093" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/tcp/non-tls.toml b/integration/fixtures/tcp/non-tls.toml index 6c7acf6df..37b840825 100644 --- a/integration/fixtures/tcp/non-tls.toml +++ b/integration/fixtures/tcp/non-tls.toml @@ -10,6 +10,7 @@ address = ":8093" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/timeout/forwarding_timeouts.toml b/integration/fixtures/timeout/forwarding_timeouts.toml index 9df89a175..0dc5d4933 100644 --- a/integration/fixtures/timeout/forwarding_timeouts.toml +++ b/integration/fixtures/timeout/forwarding_timeouts.toml @@ -17,6 +17,7 @@ format = "json" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/timeout/keepalive.toml b/integration/fixtures/timeout/keepalive.toml index 4a8924362..f3d7c3df7 100644 --- a/integration/fixtures/timeout/keepalive.toml +++ b/integration/fixtures/timeout/keepalive.toml @@ -13,6 +13,7 @@ address = ":8000" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/tlsclientheaders/simple.toml b/integration/fixtures/tlsclientheaders/simple.toml index 5e6af461d..207ad6006 100644 --- a/integration/fixtures/tlsclientheaders/simple.toml +++ b/integration/fixtures/tlsclientheaders/simple.toml @@ -13,6 +13,7 @@ address = ":8443" [api] + insecure = true [providers] [providers.docker] diff --git a/integration/fixtures/tracing/simple-jaeger-collector.toml b/integration/fixtures/tracing/simple-jaeger-collector.toml index 559f9a149..d10d5b914 100644 --- a/integration/fixtures/tracing/simple-jaeger-collector.toml +++ b/integration/fixtures/tracing/simple-jaeger-collector.toml @@ -6,6 +6,7 @@ level = "DEBUG" [api] + insecure = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/tracing/simple-jaeger.toml b/integration/fixtures/tracing/simple-jaeger.toml index 6f5e7da3a..fea514f79 100644 --- a/integration/fixtures/tracing/simple-jaeger.toml +++ b/integration/fixtures/tracing/simple-jaeger.toml @@ -6,6 +6,7 @@ level = "DEBUG" [api] + insecure = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/tracing/simple-zipkin.toml b/integration/fixtures/tracing/simple-zipkin.toml index c5bc9d143..43842b70e 100644 --- a/integration/fixtures/tracing/simple-zipkin.toml +++ b/integration/fixtures/tracing/simple-zipkin.toml @@ -6,6 +6,7 @@ level = "DEBUG" [api] + insecure = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/traefik_log_config.toml b/integration/fixtures/traefik_log_config.toml index e7b077c61..3ca5cc771 100644 --- a/integration/fixtures/traefik_log_config.toml +++ b/integration/fixtures/traefik_log_config.toml @@ -14,6 +14,7 @@ address = ":8000" [api] + insecure = true dashboard = false [providers] diff --git a/integration/fixtures/websocket/config.toml b/integration/fixtures/websocket/config.toml index 3e357c057..83a499ce7 100644 --- a/integration/fixtures/websocket/config.toml +++ b/integration/fixtures/websocket/config.toml @@ -10,6 +10,7 @@ address = ":8000" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/websocket/config_https.toml b/integration/fixtures/websocket/config_https.toml index c878e1ef3..91549eeaa 100644 --- a/integration/fixtures/websocket/config_https.toml +++ b/integration/fixtures/websocket/config_https.toml @@ -13,6 +13,7 @@ address = ":8000" [api] + insecure = true [providers.file] filename = "{{ .SelfFilename }}" diff --git a/integration/fixtures/wrr.toml b/integration/fixtures/wrr.toml index ad63ceb0d..67c6801fc 100644 --- a/integration/fixtures/wrr.toml +++ b/integration/fixtures/wrr.toml @@ -3,6 +3,7 @@ sendAnonymousUsage = false [api] + insecure = true [log] level = "DEBUG" diff --git a/integration/fixtures/wrr_sticky.toml b/integration/fixtures/wrr_sticky.toml index 4181dde54..0d63558c5 100644 --- a/integration/fixtures/wrr_sticky.toml +++ b/integration/fixtures/wrr_sticky.toml @@ -3,6 +3,7 @@ sendAnonymousUsage = false [api] + insecure = true [log] level = "DEBUG" diff --git a/integration/rest_test.go b/integration/rest_test.go index 692542c9f..d87092571 100644 --- a/integration/rest_test.go +++ b/integration/rest_test.go @@ -4,6 +4,8 @@ import ( "bytes" "encoding/json" "net/http" + "os" + "strings" "time" "github.com/containous/traefik/v2/integration/try" @@ -20,7 +22,7 @@ func (s *RestSuite) SetUpSuite(c *check.C) { s.composeProject.Start(c) } -func (s *RestSuite) TestSimpleConfiguration(c *check.C) { +func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) { cmd, display := s.traefikCmd(withConfigFile("fixtures/rest/simple.toml")) defer display(c) @@ -110,3 +112,107 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) { c.Assert(err, checker.IsNil) } } + +func (s *RestSuite) TestSimpleConfiguration(c *check.C) { + file := s.adaptFile(c, "fixtures/rest/simple_secure.toml", struct{}{}) + defer os.Remove(file) + + cmd, display := s.traefikCmd(withConfigFile(file)) + + defer display(c) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + // Expected a 404 as we did not configure anything. + err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound)) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2000*time.Millisecond, try.BodyContains("PathPrefix(`/secure`)")) + c.Assert(err, checker.IsNil) + + request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", strings.NewReader("{}")) + c.Assert(err, checker.IsNil) + + response, err := http.DefaultClient.Do(request) + c.Assert(err, checker.IsNil) + c.Assert(response.StatusCode, checker.Equals, http.StatusNotFound) + + testCase := []struct { + desc string + config *dynamic.Configuration + ruleMatch string + }{ + { + desc: "deploy http configuration", + config: &dynamic.Configuration{ + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "router1": { + EntryPoints: []string{"web"}, + Middlewares: []string{}, + Service: "service1", + Rule: "PathPrefix(`/`)", + }, + }, + Services: map[string]*dynamic.Service{ + "service1": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80", + }, + }, + }, + }, + }, + }, + }, + ruleMatch: "PathPrefix(`/`)", + }, + { + desc: "deploy tcp configuration", + config: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "router1": { + EntryPoints: []string{"web"}, + Service: "service1", + Rule: "HostSNI(`*`)", + }, + }, + Services: map[string]*dynamic.TCPService{ + "service1": { + LoadBalancer: &dynamic.TCPLoadBalancerService{ + Servers: []dynamic.TCPServer{ + { + Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80", + }, + }, + }, + }, + }, + }, + }, + ruleMatch: "HostSNI(`*`)", + }, + } + + for _, test := range testCase { + json, err := json.Marshal(test.config) + c.Assert(err, checker.IsNil) + + request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8000/secure/api/providers/rest", bytes.NewReader(json)) + c.Assert(err, checker.IsNil) + + response, err := http.DefaultClient.Do(request) + c.Assert(err, checker.IsNil) + c.Assert(response.StatusCode, checker.Equals, http.StatusOK) + + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains(test.ruleMatch)) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) + } +} diff --git a/integration/simple_test.go b/integration/simple_test.go index b95151295..3fb721287 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -161,33 +161,6 @@ func (s *SimpleSuite) TestRequestAcceptGraceTimeout(c *check.C) { } } -func (s *SimpleSuite) TestApiOnSameEntryPoint(c *check.C) { - c.Skip("Waiting for new api handler implementation") - s.createComposeProject(c, "base") - s.composeProject.Start(c) - - cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--api.entryPoint=http", "--log.level=DEBUG", "--providers.docker") - defer output(c) - - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer cmd.Process.Kill() - - // TODO validate : run on 80 - // Expected a 404 as we did not configure anything - err = try.GetRequest("http://127.0.0.1:8000/test", 1*time.Second, try.StatusCodeIs(http.StatusNotFound)) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://127.0.0.1:8000/api/rawdata", 1*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://127.0.0.1:8000/api/rawdata", 1*time.Second, try.BodyContains("PathPrefix")) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://127.0.0.1:8000/whoami", 1*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) -} - func (s *SimpleSuite) TestStatsWithMultipleEntryPoint(c *check.C) { c.Skip("Stats is missing") s.createComposeProject(c, "stats") @@ -250,7 +223,7 @@ func (s *SimpleSuite) TestDefaultEntryPointHTTP(c *check.C) { s.createComposeProject(c, "base") s.composeProject.Start(c) - cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api") + cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api.insecure") defer output(c) err := cmd.Start() @@ -268,7 +241,7 @@ func (s *SimpleSuite) TestWithNonExistingEntryPoint(c *check.C) { s.createComposeProject(c, "base") s.composeProject.Start(c) - cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api") + cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api.insecure") defer output(c) err := cmd.Start() @@ -286,7 +259,7 @@ func (s *SimpleSuite) TestMetricsPrometheusDefaultEntryPoint(c *check.C) { s.createComposeProject(c, "base") s.composeProject.Start(c) - cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--api", "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0", "--providers.docker", "--log.level=DEBUG") + cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--api.insecure", "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0", "--providers.docker", "--log.level=DEBUG") defer output(c) err := cmd.Start() @@ -785,3 +758,27 @@ func (s *SimpleSuite) TestMirrorCanceled(c *check.C) { c.Assert(val1, checker.Equals, int32(0)) c.Assert(val2, checker.Equals, int32(0)) } + +func (s *SimpleSuite) TestSecureAPI(c *check.C) { + s.createComposeProject(c, "base") + s.composeProject.Start(c) + + file := s.adaptFile(c, "./fixtures/simple_secure_api.toml", struct{}{}) + defer os.Remove(file) + + cmd, output := s.traefikCmd(withConfigFile(file)) + defer output(c) + + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + err = try.GetRequest("http://127.0.0.1:8000/secure/api/rawdata", 1*time.Second, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8000/api/rawdata", 1*time.Second, try.StatusCodeIs(http.StatusNotFound)) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.StatusCodeIs(http.StatusNotFound)) + c.Assert(err, checker.IsNil) +} diff --git a/pkg/api/handler.go b/pkg/api/handler.go index 4b707c568..87f844c6c 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -55,6 +55,15 @@ type Handler struct { dashboardAssets *assetfs.AssetFS } +// NewBuilder returns a http.Handler builder based on runtime.Configuration +func NewBuilder(staticConfig static.Configuration) func(*runtime.Configuration) http.Handler { + return func(configuration *runtime.Configuration) http.Handler { + router := mux.NewRouter() + New(staticConfig, configuration).Append(router) + return router + } +} + // New returns a Handler defined by staticConfig, and if provided, by runtimeConfig. // It finishes populating the information provided in the runtimeConfig. func New(staticConfig static.Configuration, runtimeConfig *runtime.Configuration) *Handler { diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index 3dcf771a9..f7caa20cc 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -85,6 +85,7 @@ type ServersTransport struct { // 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"` Dashboard bool `description:"Activate dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty" export:"true"` Debug bool `description:"Enable additional endpoints for debugging and profiling." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"` // TODO: Re-enable statistics @@ -173,9 +174,9 @@ func (c *Configuration) SetEffectiveConfiguration() { } } - if (c.API != nil) || - (c.Ping != nil) || - (c.Metrics != nil && c.Metrics.Prometheus != nil) || + if (c.API != nil && c.API.Insecure) || + (c.Ping != nil && c.Ping.EntryPoint == DefaultInternalEntryPointName) || + (c.Metrics != nil && c.Metrics.Prometheus != nil && c.Metrics.Prometheus.EntryPoint == DefaultInternalEntryPointName) || (c.Providers.Rest != nil) { if _, ok := c.EntryPoints[DefaultInternalEntryPointName]; !ok { ep := &EntryPoint{Address: ":8080"} diff --git a/pkg/ping/ping.go b/pkg/ping/ping.go index 44383d8bc..e839aa6c3 100644 --- a/pkg/ping/ping.go +++ b/pkg/ping/ping.go @@ -10,11 +10,13 @@ import ( // Handler expose ping routes. type Handler struct { + EntryPoint string `description:"EntryPoint" export:"true" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"` terminating bool } // SetDefaults sets the default values. func (h *Handler) SetDefaults() { + h.EntryPoint = "traefik" } // WithContext causes the ping endpoint to serve non 200 responses. diff --git a/pkg/provider/rest/rest.go b/pkg/provider/rest/rest.go index 8c3c082a6..ed62466de 100644 --- a/pkg/provider/rest/rest.go +++ b/pkg/provider/rest/rest.go @@ -18,6 +18,7 @@ var _ provider.Provider = (*Provider)(nil) // Provider is a provider.Provider implementation that provides a Rest API. type Provider struct { + Insecure bool `description:"Activate REST Provider directly on the entryPoint named traefik." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"` configurationChan chan<- dynamic.Message } @@ -32,6 +33,13 @@ func (p *Provider) Init() error { return nil } +// Handler creates an http.Handler for the Rest API +func (p *Provider) Handler() http.Handler { + router := mux.NewRouter() + p.Append(router) + return router +} + // Append add rest provider routes on a router. func (p *Provider) Append(systemRouter *mux.Router) { systemRouter. diff --git a/pkg/server/router/route_appender_aggregator.go b/pkg/server/router/route_appender_aggregator.go index 71702a6d6..410b7820d 100644 --- a/pkg/server/router/route_appender_aggregator.go +++ b/pkg/server/router/route_appender_aggregator.go @@ -19,30 +19,30 @@ type chainBuilder interface { } // NewRouteAppenderAggregator Creates a new RouteAppenderAggregator -func NewRouteAppenderAggregator(ctx context.Context, chainBuilder chainBuilder, conf static.Configuration, +func NewRouteAppenderAggregator(ctx context.Context, conf static.Configuration, entryPointName string, runtimeConfiguration *runtime.Configuration) *RouteAppenderAggregator { aggregator := &RouteAppenderAggregator{} + if conf.Ping != nil && conf.Ping.EntryPoint == entryPointName { + aggregator.AddAppender(conf.Ping) + } + + if conf.Metrics != nil && conf.Metrics.Prometheus != nil && conf.Metrics.Prometheus.EntryPoint == entryPointName { + aggregator.AddAppender(metrics.PrometheusHandler{}) + } + if entryPointName != "traefik" { return aggregator } - if conf.Providers != nil && conf.Providers.Rest != nil { + if conf.Providers != nil && conf.Providers.Rest != nil && conf.Providers.Rest.Insecure { aggregator.AddAppender(conf.Providers.Rest) } - if conf.API != nil { + if conf.API != nil && conf.API.Insecure { aggregator.AddAppender(api.New(conf, runtimeConfiguration)) } - if conf.Ping != nil { - aggregator.AddAppender(conf.Ping) - } - - if conf.Metrics != nil && conf.Metrics.Prometheus != nil { - aggregator.AddAppender(metrics.PrometheusHandler{}) - } - return aggregator } diff --git a/pkg/server/router/route_appender_aggregator_test.go b/pkg/server/router/route_appender_aggregator_test.go index ffc9c9d6f..bfa27ae58 100644 --- a/pkg/server/router/route_appender_aggregator_test.go +++ b/pkg/server/router/route_appender_aggregator_test.go @@ -6,72 +6,23 @@ import ( "net/http/httptest" "testing" - "github.com/containous/alice" "github.com/containous/traefik/v2/pkg/config/static" - "github.com/containous/traefik/v2/pkg/ping" "github.com/gorilla/mux" "github.com/stretchr/testify/assert" ) -type ChainBuilderMock struct { - middles map[string]alice.Constructor -} - -func (c *ChainBuilderMock) BuildChain(ctx context.Context, middles []string) *alice.Chain { - chain := alice.New() - - for _, mName := range middles { - if constructor, ok := c.middles[mName]; ok { - chain = chain.Append(constructor) - } - } - - return &chain -} - func TestNewRouteAppenderAggregator(t *testing.T) { - t.Skip("Waiting for new api handler implementation") testCases := []struct { desc string staticConf static.Configuration - middles map[string]alice.Constructor expected map[string]int }{ { - desc: "API with auth, ping without auth", + desc: "Secure API", staticConf: static.Configuration{ Global: &static.Global{}, - API: &static.API{ - // EntryPoint: "traefik", - // Middlewares: []string{"dumb"}, - }, - Ping: &ping.Handler{ - // EntryPoint: "traefik", - }, - EntryPoints: static.EntryPoints{ - "traefik": {}, - }, - }, - middles: map[string]alice.Constructor{ - "dumb": func(_ http.Handler) (http.Handler, error) { - return http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusUnauthorized) - }), nil - }, - }, - expected: map[string]int{ - "/wrong": http.StatusBadGateway, - "/ping": http.StatusOK, - // "/.well-known/acme-challenge/token": http.StatusNotFound, // FIXME - "/api/rawdata": http.StatusUnauthorized, - }, - }, - { - desc: "Wrong entrypoint name", - staticConf: static.Configuration{ - Global: &static.Global{}, - API: &static.API{ - // EntryPoint: "no", + API: &static.API{ + Insecure: false, }, EntryPoints: static.EntryPoints{ "traefik": {}, @@ -81,6 +32,21 @@ func TestNewRouteAppenderAggregator(t *testing.T) { "/api/providers": http.StatusBadGateway, }, }, + { + desc: "Insecure API", + staticConf: static.Configuration{ + Global: &static.Global{}, + API: &static.API{ + Insecure: true, + }, + EntryPoints: static.EntryPoints{ + "traefik": {}, + }, + }, + expected: map[string]int{ + "/api/rawdata": http.StatusOK, + }, + }, } for _, test := range testCases { @@ -88,11 +54,9 @@ func TestNewRouteAppenderAggregator(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - chainBuilder := &ChainBuilderMock{middles: test.middles} - ctx := context.Background() - router := NewRouteAppenderAggregator(ctx, chainBuilder, test.staticConf, "traefik", nil) + router := NewRouteAppenderAggregator(ctx, test.staticConf, "traefik", nil) internalMuxRouter := mux.NewRouter() router.Append(internalMuxRouter) diff --git a/pkg/server/router/route_appender_factory.go b/pkg/server/router/route_appender_factory.go index 7831e3b34..21be5d4c9 100644 --- a/pkg/server/router/route_appender_factory.go +++ b/pkg/server/router/route_appender_factory.go @@ -6,7 +6,6 @@ import ( "github.com/containous/traefik/v2/pkg/config/runtime" "github.com/containous/traefik/v2/pkg/config/static" "github.com/containous/traefik/v2/pkg/provider/acme" - "github.com/containous/traefik/v2/pkg/server/middleware" "github.com/containous/traefik/v2/pkg/types" ) @@ -27,8 +26,8 @@ type RouteAppenderFactory struct { } // NewAppender Creates a new RouteAppender -func (r *RouteAppenderFactory) NewAppender(ctx context.Context, middlewaresBuilder *middleware.Builder, runtimeConfiguration *runtime.Configuration) types.RouteAppender { - aggregator := NewRouteAppenderAggregator(ctx, middlewaresBuilder, r.staticConfiguration, r.entryPointName, runtimeConfiguration) +func (r *RouteAppenderFactory) NewAppender(ctx context.Context, runtimeConfiguration *runtime.Configuration) types.RouteAppender { + aggregator := NewRouteAppenderAggregator(ctx, r.staticConfiguration, r.entryPointName, runtimeConfiguration) for _, p := range r.acmeProvider { if p != nil && p.HTTPChallenge != nil && p.HTTPChallenge.EntryPoint == r.entryPointName { diff --git a/pkg/server/router/router_test.go b/pkg/server/router/router_test.go index 1ff4c43f4..b113d5c36 100644 --- a/pkg/server/router/router_test.go +++ b/pkg/server/router/router_test.go @@ -306,7 +306,7 @@ func TestRouterManager_Get(t *testing.T) { Middlewares: test.middlewaresConfig, }, }) - serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil) + serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil, nil, nil) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager) responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory) @@ -407,7 +407,7 @@ func TestAccessLog(t *testing.T) { Middlewares: test.middlewaresConfig, }, }) - serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil) + serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil, nil, nil) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager) responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory) @@ -693,7 +693,7 @@ func TestRuntimeConfiguration(t *testing.T) { Middlewares: test.middlewareConfig, }, }) - serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil) + serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil, nil, nil) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager) responseModifierFactory := responsemodifiers.NewBuilder(map[string]*runtime.MiddlewareInfo{}) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory) @@ -767,7 +767,7 @@ func BenchmarkRouterServe(b *testing.B) { Middlewares: map[string]*dynamic.Middleware{}, }, }) - serviceManager := service.NewManager(rtConf.Services, &staticTransport{res}, nil, nil) + serviceManager := service.NewManager(rtConf.Services, &staticTransport{res}, nil, nil, nil, nil) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager) responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory) @@ -808,7 +808,7 @@ func BenchmarkService(b *testing.B) { Services: serviceConfig, }, }) - serviceManager := service.NewManager(rtConf.Services, &staticTransport{res}, nil, nil) + serviceManager := service.NewManager(rtConf.Services, &staticTransport{res}, nil, nil, nil, nil) w := httptest.NewRecorder() req := testhelpers.MustNewRequest(http.MethodGet, "http://foo.bar/", nil) diff --git a/pkg/server/server.go b/pkg/server/server.go index 5a62e75c7..7a67e46f9 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -9,6 +9,7 @@ import ( "sync" "time" + "github.com/containous/traefik/v2/pkg/api" "github.com/containous/traefik/v2/pkg/config/dynamic" "github.com/containous/traefik/v2/pkg/config/runtime" "github.com/containous/traefik/v2/pkg/config/static" @@ -18,7 +19,6 @@ import ( "github.com/containous/traefik/v2/pkg/middlewares/requestdecorator" "github.com/containous/traefik/v2/pkg/provider" "github.com/containous/traefik/v2/pkg/safe" - "github.com/containous/traefik/v2/pkg/server/middleware" "github.com/containous/traefik/v2/pkg/tls" "github.com/containous/traefik/v2/pkg/tracing" "github.com/containous/traefik/v2/pkg/tracing/jaeger" @@ -44,11 +44,13 @@ type Server struct { requestDecorator *requestdecorator.RequestDecorator providersThrottleDuration time.Duration tlsManager *tls.Manager + api func(configuration *runtime.Configuration) http.Handler + restHandler http.Handler } // RouteAppenderFactory the route appender factory interface type RouteAppenderFactory interface { - NewAppender(ctx context.Context, middlewaresBuilder *middleware.Builder, runtimeConfiguration *runtime.Configuration) types.RouteAppender + NewAppender(ctx context.Context, runtimeConfiguration *runtime.Configuration) types.RouteAppender } func setupTracing(conf *static.Tracing) tracing.Backend { @@ -103,6 +105,14 @@ func setupTracing(conf *static.Tracing) tracing.Backend { func NewServer(staticConfiguration static.Configuration, provider provider.Provider, entryPoints TCPEntryPoints, tlsManager *tls.Manager) *Server { server := &Server{} + if staticConfiguration.API != nil { + server.api = api.NewBuilder(staticConfiguration) + } + + if staticConfiguration.Providers != nil && staticConfiguration.Providers.Rest != nil { + server.restHandler = staticConfiguration.Providers.Rest.Handler() + } + server.provider = provider server.entryPointsTCP = entryPoints server.configurationChan = make(chan dynamic.Message, 100) diff --git a/pkg/server/server_configuration.go b/pkg/server/server_configuration.go index cc9acc707..c4b703504 100644 --- a/pkg/server/server_configuration.go +++ b/pkg/server/server_configuration.go @@ -97,7 +97,12 @@ func (s *Server) createTCPRouters(ctx context.Context, configuration *runtime.Co // createHTTPHandlers returns, for the given configuration and entryPoints, the HTTP handlers for non-TLS connections, and for the TLS ones. the given configuration must not be nil. its fields will get mutated. func (s *Server) createHTTPHandlers(ctx context.Context, configuration *runtime.Configuration, entryPoints []string) (map[string]http.Handler, map[string]http.Handler) { - serviceManager := service.NewManager(configuration.Services, s.defaultRoundTripper, s.metricsRegistry, s.routinesPool) + var apiHandler http.Handler + if s.api != nil { + apiHandler = s.api(configuration) + } + + serviceManager := service.NewManager(configuration.Services, s.defaultRoundTripper, s.metricsRegistry, s.routinesPool, apiHandler, s.restHandler) middlewaresBuilder := middleware.NewBuilder(configuration.Middlewares, serviceManager) responseModifierFactory := responsemodifiers.NewBuilder(configuration.Middlewares) routerManager := router.NewManager(configuration, serviceManager, middlewaresBuilder, responseModifierFactory) @@ -114,7 +119,7 @@ func (s *Server) createHTTPHandlers(ctx context.Context, configuration *runtime. factory := s.entryPointsTCP[entryPointName].RouteAppenderFactory if factory != nil { // FIXME remove currentConfigurations - appender := factory.NewAppender(ctx, middlewaresBuilder, configuration) + appender := factory.NewAppender(ctx, configuration) appender.Append(internalMuxRouter) } diff --git a/pkg/server/service/service.go b/pkg/server/service/service.go index 1595d0452..1181b2584 100644 --- a/pkg/server/service/service.go +++ b/pkg/server/service/service.go @@ -34,7 +34,7 @@ const ( ) // NewManager creates a new Manager -func NewManager(configs map[string]*runtime.ServiceInfo, defaultRoundTripper http.RoundTripper, metricsRegistry metrics.Registry, routinePool *safe.Pool) *Manager { +func NewManager(configs map[string]*runtime.ServiceInfo, defaultRoundTripper http.RoundTripper, metricsRegistry metrics.Registry, routinePool *safe.Pool, api http.Handler, rest http.Handler) *Manager { return &Manager{ routinePool: routinePool, metricsRegistry: metricsRegistry, @@ -42,6 +42,8 @@ func NewManager(configs map[string]*runtime.ServiceInfo, defaultRoundTripper htt defaultRoundTripper: defaultRoundTripper, balancers: make(map[string][]healthcheck.BalancerHandler), configs: configs, + api: api, + rest: rest, } } @@ -53,10 +55,26 @@ type Manager struct { defaultRoundTripper http.RoundTripper balancers map[string][]healthcheck.BalancerHandler configs map[string]*runtime.ServiceInfo + api http.Handler + rest http.Handler } // BuildHTTP Creates a http.Handler for a service configuration. func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string, responseModifier func(*http.Response) error) (http.Handler, error) { + if serviceName == "api@internal" { + if m.api == nil { + return nil, errors.New("api is not enabled") + } + return m.api, nil + } + + if serviceName == "rest@internal" { + if m.rest == nil { + return nil, errors.New("rest is not enabled") + } + return m.rest, nil + } + ctx := log.With(rootCtx, log.Str(log.ServiceName, serviceName)) serviceName = internal.GetQualifiedName(ctx, serviceName) diff --git a/pkg/server/service/service_test.go b/pkg/server/service/service_test.go index c2bb707b7..9fb0edd09 100644 --- a/pkg/server/service/service_test.go +++ b/pkg/server/service/service_test.go @@ -80,7 +80,7 @@ func TestGetLoadBalancer(t *testing.T) { } func TestGetLoadBalancerServiceHandler(t *testing.T) { - sm := NewManager(nil, http.DefaultTransport, nil, nil) + sm := NewManager(nil, http.DefaultTransport, nil, nil, nil, nil) server1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-From", "first") @@ -332,7 +332,7 @@ func TestManager_Build(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - manager := NewManager(test.configs, http.DefaultTransport, nil, nil) + manager := NewManager(test.configs, http.DefaultTransport, nil, nil, nil, nil) ctx := context.Background() if len(test.providerName) > 0 { @@ -353,7 +353,7 @@ func TestMultipleTypeOnBuildHTTP(t *testing.T) { Weighted: &dynamic.WeightedRoundRobin{}, }, }, - }, http.DefaultTransport, nil, nil) + }, http.DefaultTransport, nil, nil, nil, nil) _, err := manager.BuildHTTP(context.Background(), "test@file", nil) assert.Error(t, err, "cannot create service: multi-types service not supported, consider declaring two different pieces of service instead") diff --git a/pkg/types/metrics.go b/pkg/types/metrics.go index dc25367b7..4fcebf550 100644 --- a/pkg/types/metrics.go +++ b/pkg/types/metrics.go @@ -17,6 +17,7 @@ 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"` AddServicesLabels bool `description:"Enable metrics on services." json:"addServicesLabels,omitempty" toml:"addServicesLabels,omitempty" yaml:"addServicesLabels,omitempty" export:"true"` + EntryPoint string `description:"EntryPoint" export:"true" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"` } // SetDefaults sets the default values. @@ -24,6 +25,7 @@ func (p *Prometheus) SetDefaults() { p.Buckets = []float64{0.1, 0.3, 1.2, 5} p.AddEntryPointsLabels = true p.AddServicesLabels = true + p.EntryPoint = "traefik" } // Datadog contains address and metrics pushing interval configuration. From 605a9b2817490c55dd6073959c3ccccbb2a827bf Mon Sep 17 00:00:00 2001 From: mpl Date: Mon, 9 Sep 2019 09:24:03 +0200 Subject: [PATCH 25/37] Default to CLF when accesslog format is unsupported --- docs/content/observability/access-logs.md | 3 +-- pkg/middlewares/accesslog/logger.go | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/observability/access-logs.md b/docs/content/observability/access-logs.md index 2c00e9dd2..5e6551a51 100644 --- a/docs/content/observability/access-logs.md +++ b/docs/content/observability/access-logs.md @@ -26,12 +26,11 @@ accessLog: {} By default access logs are written to the standard output. To write the logs into a log file, use the `filePath` option. -in the Common Log Format (CLF), extended with additional fields. - ### `format` By default, logs are written using the Common Log Format (CLF). To write logs in JSON, use `json` in the `format` option. +If the given format is unsupported, the default (CLF) is used instead. !!! note "Common Log Format" diff --git a/pkg/middlewares/accesslog/logger.go b/pkg/middlewares/accesslog/logger.go index 4cce7fe06..1f6b80b4b 100644 --- a/pkg/middlewares/accesslog/logger.go +++ b/pkg/middlewares/accesslog/logger.go @@ -77,7 +77,8 @@ func NewHandler(config *types.AccessLog) (*Handler, error) { case JSONFormat: formatter = new(logrus.JSONFormatter) default: - return nil, fmt.Errorf("unsupported access log format: %s", config.Format) + log.WithoutContext().Errorf("unsupported access log format: %q, defaulting to common format instead.", config.Format) + formatter = new(CommonLogFormatter) } logger := &logrus.Logger{ From 232c113dae46cd026227aa50da7a7f06389094af Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 9 Sep 2019 10:36:08 +0200 Subject: [PATCH 26/37] Misc documentation fixes --- .semaphoreci/setup.sh | 2 +- docs/content/https/tls.md | 12 +- docs/content/middlewares/forwardauth.md | 10 +- docs/content/middlewares/overview.md | 4 +- docs/content/middlewares/redirectregex.md | 4 +- docs/content/middlewares/stripprefix.md | 6 +- docs/content/middlewares/stripprefixregex.md | 4 +- docs/content/migration/v1-to-v2.md | 9 ++ docs/content/operations/ping.md | 2 +- docs/content/providers/docker.md | 114 ++++++++++++++++++- docs/content/providers/marathon.md | 109 +++++++++++++++--- docs/content/providers/rancher.md | 4 +- docs/content/routing/entrypoints.md | 4 +- 13 files changed, 242 insertions(+), 42 deletions(-) diff --git a/.semaphoreci/setup.sh b/.semaphoreci/setup.sh index f087c644d..c3cb1ebc9 100755 --- a/.semaphoreci/setup.sh +++ b/.semaphoreci/setup.sh @@ -18,7 +18,7 @@ echo ${SHOULD_TEST} #if [ -n "$SHOULD_TEST" ]; then sudo -E apt-get -yq update; fi #if [ -n "$SHOULD_TEST" ]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-ce=${DOCKER_VERSION}*; fi if [ -n "$SHOULD_TEST" ]; then docker version; fi -export GO_VERSION=1.13 +export GO_VERSION=1.12 if [ -f "./go.mod" ]; then GO_VERSION="$(grep '^go .*' go.mod | awk '{print $2}')"; export GO_VERSION; fi #if [ "${GO_VERSION}" == '1.13' ]; then export GO_VERSION=1.13rc2; fi echo "Selected Go version: ${GO_VERSION}" diff --git a/docs/content/https/tls.md b/docs/content/https/tls.md index 21cbe5835..9dcf660cc 100644 --- a/docs/content/https/tls.md +++ b/docs/content/https/tls.md @@ -141,17 +141,17 @@ tls: ### Client Authentication (mTLS) -Traefik supports mutual authentication, through the `ClientAuth` section. +Traefik supports mutual authentication, through the `clientAuth` section. -For authentication policies that require verification of the client certificate, the certificate authority for the certificate should be set in `ClientAuth.caFiles`. +For authentication policies that require verification of the client certificate, the certificate authority for the certificate should be set in `clientAuth.caFiles`. -The `ClientAuth.clientAuthType` option governs the behaviour as follows: +The `clientAuth.clientAuthType` option governs the behaviour as follows: - `NoClientCert`: disregards any client certificate. - `RequestClientCert`: asks for a certificate but proceeds anyway if none is provided. -- `RequireAnyClientCert`: requires a certificate but does not verify if it is signed by a CA listed in `ClientAuth.caFiles`. -- `VerifyClientCertIfGiven`: if a certificate is provided, verifies if it is signed by a CA listed in `ClientAuth.caFiles`. Otherwise proceeds without any certificate. -- `RequireAndVerifyClientCert`: requires a certificate, which must be signed by a CA listed in `ClientAuth.caFiles`. +- `RequireAnyClientCert`: requires a certificate but does not verify if it is signed by a CA listed in `clientAuth.caFiles`. +- `VerifyClientCertIfGiven`: if a certificate is provided, verifies if it is signed by a CA listed in `clientAuth.caFiles`. Otherwise proceeds without any certificate. +- `RequireAndVerifyClientCert`: requires a certificate, which must be signed by a CA listed in `clientAuth.caFiles`. ```toml tab="TOML" [tls.options] diff --git a/docs/content/middlewares/forwardauth.md b/docs/content/middlewares/forwardauth.md index 3bd35b84f..9b9f7678e 100644 --- a/docs/content/middlewares/forwardauth.md +++ b/docs/content/middlewares/forwardauth.md @@ -206,7 +206,7 @@ The `tls` option is the TLS configuration from Traefik to the authentication ser #### `tls.ca` -TODO +TODO add description. ```yaml tab="Docker" labels: @@ -266,7 +266,7 @@ http: #### `tls.caOptional` -TODO +TODO add description. ```yaml tab="Docker" labels: @@ -316,7 +316,7 @@ http: #### `tls.cert` -TODO +TODO add description. ```yaml tab="Docker" labels: @@ -385,7 +385,7 @@ http: #### `tls.key` -TODO +TODO add description. ```yaml tab="Docker" labels: @@ -454,7 +454,7 @@ http: #### `tls.insecureSkipVerify` -TODO +TODO add description. ```yaml tab="Docker" labels: diff --git a/docs/content/middlewares/overview.md b/docs/content/middlewares/overview.md index a69ccddca..fc90847dd 100644 --- a/docs/content/middlewares/overview.md +++ b/docs/content/middlewares/overview.md @@ -66,7 +66,7 @@ spec: ```json tab="Marathon" "labels": { "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", - "traefik.http.router.router1.middlewares": "foo-add-prefix@marathon" + "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" } ``` @@ -76,7 +76,7 @@ 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.router.router1.middlewares=foo-add-prefix@rancher" + - "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher" ``` ```toml tab="File (TOML)" diff --git a/docs/content/middlewares/redirectregex.md b/docs/content/middlewares/redirectregex.md index 2d1a19d76..c34da5133 100644 --- a/docs/content/middlewares/redirectregex.md +++ b/docs/content/middlewares/redirectregex.md @@ -11,6 +11,7 @@ RegexRedirect redirect a request from an url to another with regex matching and ```yaml tab="Docker" # 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}" @@ -37,9 +38,10 @@ spec: ```yaml tab="Rancher" # Redirect with domain replacement +# Note: all dollar signs need to be doubled for escaping. labels: - "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^http://localhost/(.*)" -- "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/${1}" +- "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}" ``` ```toml tab="File (TOML)" diff --git a/docs/content/middlewares/stripprefix.md b/docs/content/middlewares/stripprefix.md index 8b2fe0ab2..14e1df748 100644 --- a/docs/content/middlewares/stripprefix.md +++ b/docs/content/middlewares/stripprefix.md @@ -12,7 +12,7 @@ Remove the specified prefixes from the URL path. ```yaml tab="Docker" # Strip prefix /foobar and /fiibar labels: -- "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar, /fiibar" +- "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" ``` ```yaml tab="Kubernetes" @@ -30,14 +30,14 @@ spec: ```json tab="Marathon" "labels": { - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes": "/foobar, /fiibar" + "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" +- "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" ``` ```toml tab="File (TOML)" diff --git a/docs/content/middlewares/stripprefixregex.md b/docs/content/middlewares/stripprefixregex.md index 4daee17c4..f73184650 100644 --- a/docs/content/middlewares/stripprefixregex.md +++ b/docs/content/middlewares/stripprefixregex.md @@ -9,7 +9,7 @@ Remove the matching prefixes from the URL path. ```yaml tab="Docker" labels: -- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/", +- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" ``` ```yaml tab="Kubernetes" @@ -31,7 +31,7 @@ spec: ```yaml tab="Rancher" labels: -- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/", +- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" ``` ```toml tab="File (TOML)" diff --git a/docs/content/migration/v1-to-v2.md b/docs/content/migration/v1-to-v2.md index a1564a9fc..ba0742c0f 100644 --- a/docs/content/migration/v1-to-v2.md +++ b/docs/content/migration/v1-to-v2.md @@ -8,6 +8,15 @@ which require one to update their configuration when they migrate from v1 to v2. The goal of this page is to recapitulate all of these changes, and in particular to give examples, feature by feature, of how the configuration looked like in v1, and how it now looks like in v2. +!!! Note "Migration Helper" + + We created a tool to help during the migration: [traefik-migration-tool](https://github.com/containous/traefik-migration-tool) + + This tool allows to: + + - convert `Ingress` to Traefik `IngressRoute` resources. + - convert `acme.json` file from v1 to v2 format. + ## Frontends and Backends Are Dead...
... Long Live Routers, Middlewares, and Services During the transition from v1 to v2, a number of internal pieces and components of Traefik were rewritten and reorganized. diff --git a/docs/content/operations/ping.md b/docs/content/operations/ping.md index 6298a3e7d..26c03fca4 100644 --- a/docs/content/operations/ping.md +++ b/docs/content/operations/ping.md @@ -5,7 +5,7 @@ Checking the Health of Your Traefik Instances ## Configuration Examples -!!! example "Enabling /ping" +To enable the API handler: ```toml tab="File (TOML)" [ping] diff --git a/docs/content/providers/docker.md b/docs/content/providers/docker.md index 5e45f6cf4..a7e2fab9b 100644 --- a/docs/content/providers/docker.md +++ b/docs/content/providers/docker.md @@ -388,7 +388,7 @@ Constraints is an expression that Traefik matches against the container's labels That is to say, if none of the container's labels match the expression, no route for the container is created. If the expression is empty, all detected containers are included. -The expression syntax is based on the `Label("key", "value")`, and `LabelRegexp("key", "value")` functions, as well as the usual boolean logic, as shown in examples below. +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" @@ -419,11 +419,121 @@ The expression syntax is based on the `Label("key", "value")`, and `LabelRegexp( ```toml # Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression. - constraints = "LabelRegexp(`a.label.name`, `a.+`)" + constraints = "LabelRegex(`a.label.name`, `a.+`)" ``` See also [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). +### `tls` + +_Optional_ + +#### `tls.ca` + +TODO add description. + +```toml tab="File (TOML)" +[providers.docker.tls] + ca = "path/to/ca.crt" +``` + +```yaml tab="File (YAML)" +providers: + docker: + tls: + ca: path/to/ca.crt +``` + +```bash tab="CLI" +--providers.docker.tls.ca=path/to/ca.crt +``` + +#### `tls.caOptional` + +TODO add description. + +```toml tab="File (TOML)" +[providers.docker.tls] + caOptional = true +``` + +```yaml tab="File (YAML)" +providers: + docker: + tls: + caOptional: true +``` + +```bash tab="CLI" +--providers.docker.tls.caOptional=true +``` + +#### `tls.cert` + +TODO add description. + +```toml tab="File (TOML)" +[providers.docker.tls] + cert = "path/to/foo.cert" + key = "path/to/foo.key" +``` + +```yaml tab="File (YAML)" +providers: + docker: + tls: + cert: path/to/foo.cert + key: path/to/foo.key +``` + +```bash tab="CLI" +--providers.docker.tls.cert=path/to/foo.cert +--providers.docker.tls.key=path/to/foo.key +``` + +#### `tls.key` + +TODO add description. + +```toml tab="File (TOML)" +[providers.docker.tls] + cert = "path/to/foo.cert" + key = "path/to/foo.key" +``` + +```yaml tab="File (YAML)" +providers: + docker: + tls: + cert: path/to/foo.cert + key: path/to/foo.key +``` + +```bash tab="CLI" +--providers.docker.tls.cert=path/to/foo.cert +--providers.docker.tls.key=path/to/foo.key +``` + +#### `tls.insecureSkipVerify` + +TODO add description. + +```toml tab="File (TOML)" +[providers.docker.tls] + insecureSkipVerify = true +``` + +```yaml tab="File (YAML)" +providers: + docker: + tls: + insecureSkipVerify: true +``` + +```bash tab="CLI" +--providers.docker.tls.insecureSkipVerify=true +``` + ## Routing Configuration Options ### General diff --git a/docs/content/providers/marathon.md b/docs/content/providers/marathon.md index 762b7a0f7..b7064c869 100644 --- a/docs/content/providers/marathon.md +++ b/docs/content/providers/marathon.md @@ -398,37 +398,116 @@ when waiting for the first response header from a Marathon master. Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration), or directly as a number of seconds. -### `TLS` +### `tls` _Optional_ +#### `tls.ca` + +TODO add description. + +```toml tab="File (TOML)" +[providers.marathon.tls] + ca = "path/to/ca.crt" +``` + +```yaml tab="File (YAML)" +providers: + marathon: + tls: + ca: path/to/ca.crt +``` + +```bash tab="CLI" +--providers.marathon.tls.ca=path/to/ca.crt +``` + +#### `tls.caOptional` + +TODO add description. + +```toml tab="File (TOML)" +[providers.marathon.tls] + caOptional = true +``` + +```yaml tab="File (YAML)" +providers: + marathon: + tls: + caOptional: true +``` + +```bash tab="CLI" +--providers.marathon.tls.caOptional=true +``` + +#### `tls.cert` + +TODO add description. + +```toml tab="File (TOML)" +[providers.marathon.tls] + cert = "path/to/foo.cert" + key = "path/to/foo.key" +``` + +```yaml tab="File (YAML)" +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 +``` + +#### `tls.key` + +TODO add description. + +```toml tab="File (TOML)" +[providers.marathon.tls] + cert = "path/to/foo.cert" + key = "path/to/foo.key" +``` + +```yaml tab="File (YAML)" +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 +``` + +#### `tls.insecureSkipVerify` + +TODO add description. + ```toml tab="File (TOML)" [providers.marathon.tls] - ca = "/etc/ssl/ca.crt" - cert = "/etc/ssl/marathon.cert" - key = "/etc/ssl/marathon.key" insecureSkipVerify = true ``` ```yaml tab="File (YAML)" providers: - marathon + marathon: tls: - ca: "/etc/ssl/ca.crt" - cert: "/etc/ssl/marathon.cert" - key: "/etc/ssl/marathon.key" - insecureSkipVerify: true + insecureSkipVerify: true ``` ```bash tab="CLI" ---providers.marathon.tls.ca="/etc/ssl/ca.crt" ---providers.marathon.tls.cert="/etc/ssl/marathon.cert" ---providers.marathon.tls.key="/etc/ssl/marathon.key" ---providers.marathon.tls.insecureskipverify=true +--providers.marathon.tls.insecureSkipVerify=true ``` -TLS client configuration. [tls/#Config](https://golang.org/pkg/crypto/tls/#Config). - ### `tlsHandshakeTimeout` _Optional, Default=5s_ diff --git a/docs/content/providers/rancher.md b/docs/content/providers/rancher.md index f3aa97121..5931476bc 100644 --- a/docs/content/providers/rancher.md +++ b/docs/content/providers/rancher.md @@ -239,7 +239,7 @@ Constraints is an expression that Traefik matches against the container's labels That is to say, if none of the container's labels match the expression, no route for the container is created. If the expression is empty, all detected containers are included. -The expression syntax is based on the `Label("key", "value")`, and `LabelRegexp("key", "value")` functions, as well as the usual boolean logic, as shown in examples below. +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" @@ -270,7 +270,7 @@ The expression syntax is based on the `Label("key", "value")`, and `LabelRegexp( ```toml # Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression. - constraints = "LabelRegexp(`a.label.name`, `a.+`)" + constraints = "LabelRegex(`a.label.name`, `a.+`)" ``` See also [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). diff --git a/docs/content/routing/entrypoints.md b/docs/content/routing/entrypoints.md index df8d9e676..f51412c8a 100644 --- a/docs/content/routing/entrypoints.md +++ b/docs/content/routing/entrypoints.md @@ -149,7 +149,7 @@ If the proxyprotocol header is passed, then the version is determined automatica entryPoints: web: address: ":80" - proxyProtocol + proxyProtocol: trustedIPs: - "127.0.0.1/32" - "192.168.1.7" @@ -213,7 +213,7 @@ You can configure Traefik to trust the forwarded headers information (`X-Forward entryPoints: web: address: ":80" - forwardedHeaders + forwardedHeaders: trustedIPs: - "127.0.0.1/32" - "192.168.1.7" From be90b20a5da7c7a4a207e29b37176b0a625d641d Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 9 Sep 2019 13:52:04 +0200 Subject: [PATCH 27/37] fix: TLS domains with IngressRoute. --- pkg/provider/kubernetes/crd/kubernetes_http.go | 1 + pkg/provider/kubernetes/crd/kubernetes_tcp.go | 1 + .../crd/traefik/v1alpha1/ingressroute.go | 6 ++++-- .../crd/traefik/v1alpha1/ingressroutetcp.go | 2 ++ .../crd/traefik/v1alpha1/zz_generated.deepcopy.go | 15 +++++++++++++++ 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/pkg/provider/kubernetes/crd/kubernetes_http.go b/pkg/provider/kubernetes/crd/kubernetes_http.go index 059e41b9c..037191e11 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_http.go +++ b/pkg/provider/kubernetes/crd/kubernetes_http.go @@ -123,6 +123,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli if ingressRoute.Spec.TLS != nil { tlsConf := &dynamic.RouterTLSConfig{ CertResolver: ingressRoute.Spec.TLS.CertResolver, + Domains: ingressRoute.Spec.TLS.Domains, } if ingressRoute.Spec.TLS.Options != nil && len(ingressRoute.Spec.TLS.Options.Name) > 0 { diff --git a/pkg/provider/kubernetes/crd/kubernetes_tcp.go b/pkg/provider/kubernetes/crd/kubernetes_tcp.go index ea64d89ca..33744a95b 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_tcp.go +++ b/pkg/provider/kubernetes/crd/kubernetes_tcp.go @@ -80,6 +80,7 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client conf.Routers[serviceName].TLS = &dynamic.RouterTCPTLSConfig{ Passthrough: ingressRouteTCP.Spec.TLS.Passthrough, CertResolver: ingressRouteTCP.Spec.TLS.CertResolver, + Domains: ingressRouteTCP.Spec.TLS.Domains, } if ingressRouteTCP.Spec.TLS.Options != nil && len(ingressRouteTCP.Spec.TLS.Options.Name) > 0 { diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroute.go index bf6074039..6a1a56782 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroute.go @@ -1,6 +1,7 @@ package v1alpha1 import ( + "github.com/containous/traefik/v2/pkg/types" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -32,8 +33,9 @@ type TLS struct { // certificate details. SecretName string `json:"secretName"` // Options is a reference to a TLSOption, that specifies the parameters of the TLS connection. - Options *TLSOptionRef `json:"options"` - CertResolver string `json:"certResolver"` + Options *TLSOptionRef `json:"options,omitempty"` + CertResolver string `json:"certResolver,omitempty"` + Domains []types.Domain `json:"domains,omitempty"` } // TLSOptionRef is a ref to the TLSOption resources. diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go index c97bb109e..dde55c694 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go @@ -1,6 +1,7 @@ package v1alpha1 import ( + "github.com/containous/traefik/v2/pkg/types" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -32,6 +33,7 @@ type TLSTCP struct { // Options is a reference to a TLSOption, that specifies the parameters of the TLS connection. Options *TLSOptionTCPRef `json:"options"` CertResolver string `json:"certResolver"` + Domains []types.Domain `json:"domains,omitempty"` } // TLSOptionTCPRef is a ref to the TLSOption resources. diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go index 65ea369c8..b51b8c394 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go @@ -30,6 +30,7 @@ package v1alpha1 import ( dynamic "github.com/containous/traefik/v2/pkg/config/dynamic" + types "github.com/containous/traefik/v2/pkg/types" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -654,6 +655,13 @@ func (in *TLS) DeepCopyInto(out *TLS) { *out = new(TLSOptionRef) **out = **in } + if in.Domains != nil { + in, out := &in.Domains, &out.Domains + *out = make([]types.Domain, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -789,6 +797,13 @@ func (in *TLSTCP) DeepCopyInto(out *TLSTCP) { *out = new(TLSOptionTCPRef) **out = **in } + if in.Domains != nil { + in, out := &in.Domains, &out.Domains + *out = make([]types.Domain, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } From 25f4c23ab245d28f6e35e332ad98290a307f17ca Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Mon, 9 Sep 2019 14:52:04 +0200 Subject: [PATCH 28/37] Write HTTP server logs into the global logger. --- pkg/server/server_entrypoint_tcp.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index 17dbc5c81..c3c4c43b8 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -3,6 +3,7 @@ package server import ( "context" "fmt" + stdlog "log" "net" "net/http" "sync" @@ -16,10 +17,13 @@ import ( "github.com/containous/traefik/v2/pkg/middlewares/forwardedheaders" "github.com/containous/traefik/v2/pkg/safe" "github.com/containous/traefik/v2/pkg/tcp" + "github.com/sirupsen/logrus" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) +var httpServerLogger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "", 0) + type httpForwarder struct { net.Listener connChan chan net.Conn @@ -352,7 +356,8 @@ func createHTTPServer(ln net.Listener, configuration *static.EntryPoint, withH2c } serverHTTP := &http.Server{ - Handler: handler, + Handler: handler, + ErrorLog: httpServerLogger, } listener := newHTTPForwarder(ln) From 2b828765e3d679c116bf69ad43eaab6971fb199a Mon Sep 17 00:00:00 2001 From: mpl Date: Mon, 9 Sep 2019 20:02:04 +0200 Subject: [PATCH 29/37] Improve rate limiter tests Co-authored-by: Julien Salleyron --- .../ratelimiter/rate_limiter_test.go | 103 +++++++++++++----- 1 file changed, 77 insertions(+), 26 deletions(-) diff --git a/pkg/middlewares/ratelimiter/rate_limiter_test.go b/pkg/middlewares/ratelimiter/rate_limiter_test.go index 94fcedba8..6273ca356 100644 --- a/pkg/middlewares/ratelimiter/rate_limiter_test.go +++ b/pkg/middlewares/ratelimiter/rate_limiter_test.go @@ -73,9 +73,11 @@ func TestNewRateLimiter(t *testing.T) { func TestRateLimit(t *testing.T) { testCases := []struct { - desc string - config dynamic.RateLimit - reqCount int + desc string + config dynamic.RateLimit + loadDuration time.Duration + incomingLoad int // in reqs/s + burst int }{ { desc: "Average is respected", @@ -83,15 +85,47 @@ func TestRateLimit(t *testing.T) { Average: 100, Burst: 1, }, - reqCount: 200, + loadDuration: 2 * time.Second, + incomingLoad: 400, }, { - desc: "Burst is taken into account", + desc: "burst allowed, no bursty traffic", + config: dynamic.RateLimit{ + Average: 100, + Burst: 100, + }, + loadDuration: 2 * time.Second, + incomingLoad: 200, + }, + { + desc: "burst allowed, initial burst, under capacity", + config: dynamic.RateLimit{ + Average: 100, + Burst: 100, + }, + loadDuration: 2 * time.Second, + incomingLoad: 200, + burst: 50, + }, + { + desc: "burst allowed, initial burst, over capacity", + config: dynamic.RateLimit{ + Average: 100, + Burst: 100, + }, + loadDuration: 2 * time.Second, + incomingLoad: 200, + burst: 150, + }, + { + desc: "burst over average, initial burst, over capacity", config: dynamic.RateLimit{ Average: 100, Burst: 200, }, - reqCount: 300, + loadDuration: 2 * time.Second, + incomingLoad: 200, + burst: 300, }, { desc: "Zero average ==> no rate limiting", @@ -99,26 +133,32 @@ func TestRateLimit(t *testing.T) { Average: 0, Burst: 1, }, - reqCount: 100, + incomingLoad: 1000, + loadDuration: time.Second, }, } for _, test := range testCases { test := test t.Run(test.desc, func(t *testing.T) { + t.Parallel() reqCount := 0 + dropped := 0 next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { reqCount++ }) - h, err := New(context.Background(), next, test.config, "rate-limiter") require.NoError(t, err) + period := time.Duration(1e9 / test.incomingLoad) start := time.Now() + end := start.Add(test.loadDuration) + ticker := time.NewTicker(period) + defer ticker.Stop() for { - if reqCount >= test.reqCount { + if time.Now().After(end) { break } @@ -127,34 +167,45 @@ func TestRateLimit(t *testing.T) { w := httptest.NewRecorder() h.ServeHTTP(w, req) - // TODO(mpl): predict and count the 200 VS the 429? + if w.Result().StatusCode != http.StatusOK { + dropped++ + } + if test.burst > 0 && reqCount < test.burst { + // if a burst is defined we first hammer the server with test.burst requests as fast as possible + continue + } + <-ticker.C } - stop := time.Now() elapsed := stop.Sub(start) + if test.config.Average == 0 { - if elapsed > time.Millisecond { - t.Fatalf("rate should not have been limited, but: %d requests in %v", reqCount, elapsed) + if reqCount < 75*test.incomingLoad/100 { + t.Fatalf("we (arbitrarily) expect at least 75%% of the requests to go through with no rate limiting, and yet only %d/%d went through", reqCount, test.incomingLoad) + } + if dropped != 0 { + t.Fatalf("no request should have been dropped if rate limiting is disabled, and yet %d were", dropped) } return } - // Assume allowed burst is initially consumed in an infinitesimal period of time - var expectedDuration time.Duration - if test.config.Average != 0 { - expectedDuration = time.Duration((int64(test.reqCount)-test.config.Burst+1)/test.config.Average) * time.Second - } - + // Note that even when there is no bursty traffic, + // we take into account the configured burst, + // because it also helps absorbing non-bursty traffic. + wantCount := int(test.config.Average*int64(test.loadDuration/time.Second) + test.config.Burst) // Allow for a 2% leeway - minDuration := expectedDuration * 98 / 100 - maxDuration := expectedDuration * 102 / 100 - - if elapsed < minDuration { - t.Fatalf("rate was faster than expected: %d requests in %v", reqCount, elapsed) - } - if elapsed > maxDuration { + maxCount := wantCount * 102 / 100 + // With very high CPU loads, + // we can expect some extra delay in addition to the rate limiting we already do, + // so we allow for some extra leeway there. + // Feel free to adjust wrt to the load on e.g. the CI. + minCount := wantCount * 95 / 100 + if reqCount < minCount { t.Fatalf("rate was slower than expected: %d requests in %v", reqCount, elapsed) } + if reqCount > maxCount { + t.Fatalf("rate was faster than expected: %d requests in %v", reqCount, elapsed) + } }) } } From fcc1109e766902cc9be5c60d8e53e95a132e49a0 Mon Sep 17 00:00:00 2001 From: Jorge Gonzalez Date: Tue, 10 Sep 2019 14:40:05 +0200 Subject: [PATCH 30/37] Add more pages in the WebUI --- README.md | 3 +- docs/content/assets/img/dashboard-health.png | Bin 212684 -> 0 bytes docs/content/assets/img/dashboard-main.png | Bin 280575 -> 0 bytes docs/content/assets/img/webui-dashboard.png | Bin 0 -> 127729 bytes docs/content/middlewares/passtlsclientcert.md | 4 +- docs/content/middlewares/redirectregex.md | 4 +- docs/content/middlewares/redirectscheme.md | 4 +- docs/content/middlewares/replacepath.md | 4 +- docs/content/middlewares/replacepathregex.md | 4 +- docs/content/middlewares/retry.md | 4 +- docs/content/middlewares/stripprefix.md | 4 +- docs/content/operations/dashboard.md | 17 +- webui/package-lock.json | 137 +- webui/package.json | 2 - webui/quasar.conf.js | 3 +- webui/src/_middleware/Boot.js | 13 + webui/src/_services/EntrypointsService.js | 13 +- webui/src/_services/HttpService.js | 75 + webui/src/_services/TcpService.js | 52 + webui/src/assets/middlewares-empty.svg | 7 + .../src/components/_commons/BooleanState.vue | 53 + webui/src/components/_commons/MainTable.vue | 249 ++++ webui/src/components/_commons/NavBar.vue | 2 + .../components/_commons/PanelHealthCheck.vue | 125 ++ .../components/_commons/PanelMiddlewares.vue | 1204 +++++++++++++++++ .../_commons/PanelMirroringServices.vue | 133 ++ .../_commons/PanelRouterDetails.vue | 204 +++ .../src/components/_commons/PanelServers.vue | 123 ++ .../_commons/PanelServiceDetails.vue | 192 +++ webui/src/components/_commons/PanelTLS.vue | 141 ++ .../_commons/PanelWeightedServices.vue | 124 ++ webui/src/components/_commons/TLSState.vue | 26 + webui/src/components/_commons/ToolBar.vue | 113 ++ .../src/components/_commons/ToolBarTable.vue | 92 ++ webui/src/components/dashboard/PanelChart.vue | 9 +- webui/src/components/dashboard/PanelEntry.vue | 39 +- .../src/components/dashboard/PanelFeature.vue | 26 +- webui/src/components/http/ToolBar.vue | 65 - webui/src/components/tcp/ToolBar.vue | 62 - webui/src/css/sass/_variables.scss | 4 + webui/src/css/sass/app.scss | 50 + webui/src/pages/_commons/MiddlewareDetail.vue | 161 +++ webui/src/pages/_commons/RouterDetail.vue | 293 ++++ webui/src/pages/_commons/ServiceDetail.vue | 239 ++++ webui/src/pages/http/Middlewares.vue | 108 +- webui/src/pages/http/Routers.vue | 108 +- webui/src/pages/http/Services.vue | 108 +- webui/src/pages/tcp/Routers.vue | 108 +- webui/src/pages/tcp/Services.vue | 108 +- webui/src/router/routes.js | 144 ++ webui/src/statics/app-logo-128x128.png | Bin 9181 -> 18503 bytes .../src/statics/icons/apple-icon-120x120.png | Bin 8350 -> 16881 bytes .../src/statics/icons/apple-icon-152x152.png | Bin 10707 -> 22642 bytes .../src/statics/icons/apple-icon-167x167.png | Bin 12058 -> 25533 bytes .../src/statics/icons/apple-icon-180x180.png | Bin 12908 -> 25485 bytes webui/src/statics/icons/favicon-16x16.png | Bin 2583 -> 468 bytes webui/src/statics/icons/favicon-32x32.png | Bin 3854 -> 1300 bytes webui/src/statics/icons/favicon-96x96.png | Bin 13495 -> 4714 bytes webui/src/statics/icons/favicon.ico | Bin 10134 -> 10134 bytes webui/src/statics/icons/icon-128x128.png | Bin 9181 -> 18503 bytes webui/src/statics/icons/icon-192x192.png | Bin 13796 -> 29398 bytes webui/src/statics/icons/icon-256x256.png | Bin 18868 -> 43335 bytes webui/src/statics/icons/icon-384x384.png | Bin 28922 -> 74465 bytes webui/src/statics/icons/icon-512x512.png | Bin 39953 -> 111619 bytes webui/src/statics/icons/ms-icon-144x144.png | Bin 10204 -> 20217 bytes webui/src/statics/icons/safari-pinned-tab.svg | 4 +- webui/src/statics/providers/kubernetescrd.svg | 6 + .../statics/providers/kubernetesingress.svg | 6 + webui/src/store/entrypoints/actions.js | 17 +- webui/src/store/entrypoints/getters.js | 7 + webui/src/store/entrypoints/mutations.js | 19 + webui/src/store/http/actions.js | 79 ++ webui/src/store/http/getters.js | 41 + webui/src/store/http/index.js | 12 + webui/src/store/http/mutations.js | 113 ++ webui/src/store/http/state.js | 8 + webui/src/store/index.js | 6 +- webui/src/store/tcp/actions.js | 53 + webui/src/store/tcp/getters.js | 27 + webui/src/store/tcp/index.js | 12 + webui/src/store/tcp/mutations.js | 75 + webui/src/store/tcp/state.js | 6 + 82 files changed, 5005 insertions(+), 249 deletions(-) delete mode 100644 docs/content/assets/img/dashboard-health.png delete mode 100644 docs/content/assets/img/dashboard-main.png create mode 100644 docs/content/assets/img/webui-dashboard.png create mode 100644 webui/src/_services/HttpService.js create mode 100644 webui/src/_services/TcpService.js create mode 100644 webui/src/assets/middlewares-empty.svg create mode 100644 webui/src/components/_commons/BooleanState.vue create mode 100644 webui/src/components/_commons/MainTable.vue create mode 100644 webui/src/components/_commons/PanelHealthCheck.vue create mode 100644 webui/src/components/_commons/PanelMiddlewares.vue create mode 100644 webui/src/components/_commons/PanelMirroringServices.vue create mode 100644 webui/src/components/_commons/PanelRouterDetails.vue create mode 100644 webui/src/components/_commons/PanelServers.vue create mode 100644 webui/src/components/_commons/PanelServiceDetails.vue create mode 100644 webui/src/components/_commons/PanelTLS.vue create mode 100644 webui/src/components/_commons/PanelWeightedServices.vue create mode 100644 webui/src/components/_commons/TLSState.vue create mode 100644 webui/src/components/_commons/ToolBar.vue create mode 100644 webui/src/components/_commons/ToolBarTable.vue delete mode 100644 webui/src/components/http/ToolBar.vue delete mode 100644 webui/src/components/tcp/ToolBar.vue create mode 100644 webui/src/pages/_commons/MiddlewareDetail.vue create mode 100644 webui/src/pages/_commons/RouterDetail.vue create mode 100644 webui/src/pages/_commons/ServiceDetail.vue mode change 100644 => 100755 webui/src/statics/app-logo-128x128.png mode change 100644 => 100755 webui/src/statics/icons/apple-icon-120x120.png mode change 100644 => 100755 webui/src/statics/icons/apple-icon-152x152.png mode change 100644 => 100755 webui/src/statics/icons/apple-icon-167x167.png mode change 100644 => 100755 webui/src/statics/icons/apple-icon-180x180.png mode change 100644 => 100755 webui/src/statics/icons/favicon-16x16.png mode change 100644 => 100755 webui/src/statics/icons/favicon-32x32.png mode change 100644 => 100755 webui/src/statics/icons/favicon-96x96.png mode change 100644 => 100755 webui/src/statics/icons/icon-128x128.png mode change 100644 => 100755 webui/src/statics/icons/icon-192x192.png mode change 100644 => 100755 webui/src/statics/icons/icon-256x256.png mode change 100644 => 100755 webui/src/statics/icons/icon-384x384.png mode change 100644 => 100755 webui/src/statics/icons/icon-512x512.png mode change 100644 => 100755 webui/src/statics/icons/ms-icon-144x144.png mode change 100644 => 100755 webui/src/statics/icons/safari-pinned-tab.svg create mode 100644 webui/src/statics/providers/kubernetescrd.svg create mode 100644 webui/src/statics/providers/kubernetesingress.svg create mode 100644 webui/src/store/http/actions.js create mode 100644 webui/src/store/http/getters.js create mode 100644 webui/src/store/http/index.js create mode 100644 webui/src/store/http/mutations.js create mode 100644 webui/src/store/http/state.js create mode 100644 webui/src/store/tcp/actions.js create mode 100644 webui/src/store/tcp/getters.js create mode 100644 webui/src/store/tcp/index.js create mode 100644 webui/src/store/tcp/mutations.js create mode 100644 webui/src/store/tcp/state.js diff --git a/README.md b/README.md index e55fa5880..517a88b55 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,7 @@ To get your hands on Traefik, you can use the [5-Minute Quickstart](http://docs. You can access the simple HTML frontend of Traefik. -![Web UI Providers](docs/content/assets/img/dashboard-main.png) -![Web UI Health](docs/content/assets/img/dashboard-health.png) +![Web UI Providers](docs/content/assets/img/webui-dashboard.png) ## Documentation diff --git a/docs/content/assets/img/dashboard-health.png b/docs/content/assets/img/dashboard-health.png deleted file mode 100644 index cf316097513ac83791460d3d4f8f463504503790..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 212684 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
Bg8&}b^2(@H@^wH2lq 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%0AmAo`7_FOsJuw?iIm?G72 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≀m9Wg57+)Z@ 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 L%_rrG&tLr?=9csO diff --git a/docs/content/assets/img/dashboard-main.png b/docs/content/assets/img/dashboard-main.png deleted file mode 100644 index 62a90e5e93fa0fcece2678a9c36b537ee26e0ad4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 280575 zcmeFZXIPV4(?6*4jx&E|}q zvx}1rpSzWtjg7Ory^F`%xdyp2XZ}8;ruf+4W%9~opozg^%IRtR%+>Z+k21qK^LW+H zObW0^e}k`vl6XDeez@ZBEXJq;^X*Y#i>Tp2L{5ZXb)s`-%}j2DpZI{aSWRMU5E33m zSHlbXFp4UmfCV|*sD>H7ckQ=+WJhCbP#>5lc+qz6SfP8%6$pxV@AY4GPdiLL*DO}# zohIZ&e*Pl!{QIL^Rm>*)d&AGqPX(`sU-)-pBlGL05B}YBX7$o}tF!-Zd!h0-!7FH{lCguQ)M(uqYk2=!0|LtNl7V+ zX!ZO#4I?9uTJ`D4A?}p=-=n|6O@AsUKhZ4T9s#R8)Kntx=sG!}zz_(Ov|7P-? z=25q>JiGsoo_31jbLChcP zRM`{0{B$LlifI^&%@KoOubS(iGcumwDqKe7PiEzBM*jJJL^w14?Dj}s07(RmM&kpI zi%!J~&SJiOQ}mx@n(oJ<%tM^g{$O)yj67|R0?9)xAMZ|&FuBwYEIP^8O(3*^&dnv) z^}s=ZQ6m`w{%YJB@!*-a)ao#B5bb9CHyDr&j5~2m`~G3Q33mHTe1|-e1&}n&$kGC;;>VEC+D|4 zz)x7KCh+?o6D)r&7DXBBAEI5I7$wh>rQe?RY1Z`O{QlJzifRi=7e@p4r(dRyfC>#y zic9YU`W0>|?DT)r3HtPxf%i!UKOiyVdWgbne&cvjnm;MwgpF5&UhW{zvhCcz$-nw4 z;+%D{-#q?gPvzLQhcTkq%)cY+Uib$%KU1mZk$|(@yeN15W)@#w)Z% z28S;GQ2oQa^s{DiGWbgJsI&Ud^Ma`^<4gE|G+j8B*N9)%pqA<9pz-ZGzx7a-bU$Vr z)VxUS$}#!NKlpha$CL!X@U}LO*5KImaiIogR6{>!$!lxDAz+&N@*m>8wO>)C{#?;} zkpf{e^Nqjj9FU(+6M*@4k##sWiyc_`;;~llkR9u@1=s5P?0LsKW&MBqlg8}E8v+|5 znWY!pnTAG%gxlml=LKC6BX-}uP&o-4_oJibX!*9i)&9p=f(*(4L2Q~YFRz#+x7uv3 z_J|$5!16YJsASCXr{eaJL^#8ZE#4^&J$WnoRaA>L@Tiy{Se>OUx373DqZK2&oy5x3+`P;G?|_u#=PF%a@gX0cJ%&m(##fTxPz0E_iu3KQuf%cFd7f1<)rL zdcS$Ivmb7fAj6_$Y{ZC-VwDG#+V(83rT?+&Pp^k3K3&ODi`ibvj4E$PH3Fjkj@MYU z?ZK*y^zg`!WVyb6oG1o~Tdms#T{wT<13wEpLEauWgqh-_I$aGzWHm{2Ilm0X|SWCQ=DRA(2r4ndLe%?vcki*cZvdmB6hvQ z-`p2Pk1HDB(hn6+6G}lntH^4fIzWRQ;p3uDQlC@Or14MdM71cuMHHaN`v$TUCCeY` zX9rp(^jd%iFj_dVnj*x3NbX6$hbetwCGdVu87X91(8;Q>^ z$Fc+KeE>g)SF^Q~-D2X1KU8tc(tb9}BkQdhPI$0JFTEUXH>^p zIVMeVr)y{tXF1JER}cuKnVv1SfYcPc68b7z{>QkDjT4?Wmjq`Y zIu1!P@T%!6yxCTrJAWbK%13sw3XowbZm52W=n5J72F@oY_Q?qVnUL_bZoQ|CCP4{p z+%hkc|2o&&$#^Gk0gL2u+S5dh6f%`__wAKBN3~4VYDdtY7OkcoH9Nnp|6?H-DqY!R zU-fFva)MVrZB)O&f8^BK0~aAtSZQ;EHAj4T&zeFjzP=Fxu4c*W0~i4qynyL^i!=`x z5G%$2aP3U}z{snp8RhKJEAiJH$Rva#k{(`?{Uav&EL{N<6o0Du<=&GMi!>k)CMfLm zM+Mk1Q0A}=e}K%}I5?R&57;oPpO0qHqs(gDZ2xh9ewI@6l7gR?t+9B7Xvh0#9S4_?g3fJGTlDjR}(!Hg#{mTwZ0I^xg4jXeEGA(MSxZej_lLr{Z4(l`s2# zFp>p+)~^7C0hwRfIQB{Ajfltie+9&i>m{tbtCw2TLp9YnXs(>e zY#3VI{9XMSCYJslw?8?CctUnpkEIMepP(apBo3}#9V+{zBI=@>6Nl>7+1&oj zk7Mo&#Tt`Dy&h1SBX*a|AzF($Q;FBO`J{l^pmS-vtM?BuuowB+n$z{thDt<2j)TIy z+I;KOxQ(_uLym*cW%W;`sv5$=vC%TXfRI5OOWDi%t-es7n&a;j8y02BMq{gg(XPm4 z%^HH*=*S%|N7+xoY|N@0KP;HkB#r8}0h(V|=<_`iEkRT-t54%ebN1bcPFJO$ZbI&a?^ z^z?4@kGP!tw_3?@vFc#N-vYH`&?d{z`Y*z%`kOCe_k5j zOp%m)eoX3-V|H(~xqE{?S5kV>-y8*g7SE=_5~-JZRz11$@!!Om#n@H#V?~N2&Vuq6 zB^|K|%b8N^MyVzGcKE{E4rYN%W!0>@@>GLW_W3^g4kC8kJ3)UjKODf1nk7LO6!S@Q zd?Usg^h&2W4&rJ7eMtMoJbz1BE4#ItA?B ziHrt7qpY4jc@*?;d5)!hZ@J6BvAu=g$g65}>IF_CwxX9I6cax013m81aa@zq^>(O2 zXp7|)>vI{wWC}UOMtPu>d5^sNWbBi3CjTH8f7rT!dyMKMMywIh-k{ZdD)r)~_^vh&Ay)&0f=hy`is{ z;yPCL)uOgP#I7IG3cBV5kX$bK%nbZ>oHKk+<9j1=JRn*uZh?D;mrz4hPMYg}O&`0x zBtGU>0O2`|guzM-4RA@RW`@UDw;s?JrM9}(Td`l%Z%0oN6QSRG5YBJ%08-V&yyBAO z48vt8e|ZrjSvon5s6zR|dcVgIu00ugKuGNI(iI+J5B$)u|50fCquSWx zOL~YW)kSzkvEo#kku{m{*&gI=O1@<5y0U##?T=us28IU!;5?naW&}^{9@SeZWI29+u>w($3o(Mt z4dlN~+L=gfa(-LTiy-=(RH39M`fL8K=9bdcRd|7_1X2M@lu|c=QcJrTu88L&EYQ?Y zPT$kD3Q#GrzuJj*GQ=}vf|!K59ZDGfUjFH{{`SuRKH~DM9c0A3q5nQr8lB`2l%Y#tr^3%%pE>7lS`rO3~2 zDI79vgL<5vO<506(M>8^qd^TGb{%otJ4f3fs*+Ir0}Php^L2tpvOG)|nF46d;aiTo z3~Ime`uiLJWZ@@q)z;6OpNqPH-sA+S^`P6JOW$r=aSSiZWCuzsv#tW&X3eD@3z;R{ z&aa@9qL}pi4lqP_4++~&0VNY#rCm9^3-ugXt)BV%v%FJcLQ1Q19rT9 z+mKl{D-+%0!!Ds85E88QATg!bLM=eMLP>Wr_OaK<+7OGSgPR)F+KO(^j94gBmW1gI zHH{s|cN@mpZMrCbrFoD`WfMF(I)7BFul2p^(pED${raEhv&#gOXR;n3O+8Lw^06~N z)QNy581(TS3#;%r5h*yT{c__c#C*%D+I=tTcACHoSmaHKYeLsv$n-7~$7h)*O1iP7 z5MwUxPIh0VbV|x=Uhh^NgLsgZep}H$cBD*Rj0zfQ_$8JIFY@R`AVw?nm53dn_|6KV zE-<60t!p<6lx-7iQlJ-eQD>mbG&6+&8hEz$I>{CSJz?ZH@P6REmLO{NEO9}bDtgEv zJ~LelGcT@?XIu^(4|t%&6hl#4s@s{d7e23^0FJ{EW0C1vhKBP98JlqN@ldRT{@3R)so$(|7ViKQt0;oCwV%hy;6S~??cC%~KP2|1D;@xktm1*fvE zyHNe(mroPo%oDG<4D-6WEMZ#e8tz{d$s8PU?D;Zp6+9!glPERO)WFMmSi8r%=ayYQr<$-N(js*`o664adM{ql-z1u+s97k< zSgU0kFRvz|4 zNn$l7Ctve$xuh&7iuUsa^kRf|V@fm@@Tn-bcNx6~hw=z#VQlTaPkgeks^7WyWJ|<& z;_9{Oxq?B`qNSeeq0mbMpxJ#dSk%W^`Zr1+xWnKxVk!x+WU(M0n@Rp6o_ZETI!9x} z88eQuMVdQOB~CTPgGCP#k5?#AfGCmkhLe$$#IZ_UrSizu!cEk;Y0M~|(PP;pUJejy zS^pR^bdzRapIwq*s0+$%-%G!wT{#b42c8Z=U&ePD&GB+Hjn?OU(UEgM>7}TefSrap z{+&SQ!eU5YFhp9Ch{bgI`mPJ}`1fJ2YRlPj73v2b$epq|{FCrI;dDwpS^0WMD{U1z zk%|P@$=POwWG(j<;WM^EZ_eZp4o#yXwqGb0eLl};e%r;uv)ag?N02$Sz)m>lHXS-u zE|b)hm3w7pH`oI~Q~E=eNTdmcXZ=mM=QL5Ft-)3oFAmY3N{?h!FXn~cva)D6Ma_co z!e2O*a&SZLzVTrIoUQqRC_R3SnyRhzTJ6Qb<0^Z+uo}<~0DF^j zKM(gD%^=fj<_UN>Re`U&GAJf>X`|BetBM#!^BM@Up_OQpdwOv?oeB@Za$<19P1Tcl> z1GsjiAiioDx*>M=fF*{zJNnKQjOvjLO-&+n_dWG5lrpi@L^^h2t|^%DsXNFA7$*1& zSmAu{URDQ)p9jqqOL+QkAJSW>TI7h=CUQ1wR&{P`1sUrM2Pm!?Fd{RR`KB{=QksHc z){&~ip;Sy|{nwwk;nxebqEaj3!N!YnBAe*DLn`Dr=}8WckWGEgwE>Psx#LicTn)b4ipNXeyQEq_hu2z3eh8oVC-$C_b5G8g+|!yBFWtEfnl+zDvJkznFGP zQt;{e7#3l$(0Ts!koogx$*P0Li_ho{_dldwgRk}~eSCf^+@&#bHw*IB%ac&)|5D|{ zHB!kFZ(2uec(=9E{VeX5LxU6^12zA&lPAA2qOWv23zo{})it^Xf=2?=WtmE2X`Ggu zNuF>=o~69+b_qx{VMr{`Th$KkN!%=)WGEcQIMnl29f>n)SwN`JbpP%JFq{c80U0gX^6o?@YZ`53_waugFMUpUJqE`~uGpofBXa zYo0;px4C9MU-?+fCEiKk@q|0f=CHZ#O+W3QEF4Qruhgnx+}~e|`k9EEVuTcf=cfw? z#`%2Fhl|+<*kq%Q!7Wb(e8aVs8201Is4d#-u50brY(*hFLve4+W=rrwb%(70jTo(w z)c%1<`9ZI19*9eaFPnM{0>ZRdmxoVl;XYaJ+*d03w z-?TN4UCgaenL1Wn6Tm;qaK>Y*F6lj4rQU8g7g$nkyJUE5R9?SnRDO@OqrU{+XK$mt zNuOornCU6I`^l3^!LnFj&9J_xny~5vr|~&;y@~8ja#^9zRm!(-Ls_OpNST;qW<#7u z+IX)n{FV*aYbxzEHZnRDhsHV^z9wRkFS6@v&D3rTMt@~YV)q^M^rjau@QaHh?F?Yg zJ#0ORynl~d!$G%-$N7}&;0wsqD19$TP1umtz{Zzf%;L(3E%y&wdRs_FhKC7p2#m`C z1l{OV`!Mn|hR~{6UIuPP?t9;9xy zij{WGU7->;j9(on-_*jeEh>BE-?^+7s^g~@YfX4h>%+J_r}L)3tqU~p)RCpZq*zwd zTG6j0!7O&I0?=S@4c zKYW}J<9V>cP{SdqfhQT4VXy=7lN|dE{RasS4)po4Xw%TCJ=nFW?p|LW35bll*tpb6y`?=ZOFaRne?YUt`dx zDwad5M;1zb8D@@aW6&iO-*~xASb0I9uBkSEe|Yncif8|+1@P6|!QQq)diQllpFUiO z5X^0P9z9>^E6U3a9J_Ge`u+1@8~d#ibKQPAF=BU{IT@55>-_F*c3Pe~)OplUrbHiG9-CY@1}@zxSC3CtoAZ z9RRJzvitOyD`v!TGN~INe2i05%}MWAd{=~IH|B;qC!eWidh!e7h92kTR8HswiHq~O zzE}_i7Y~N8)A+JE?u}YS;fwF54iEJ$IzWnhu3wAeFg4|_aCzaBWtt&nXyYM1Rp7TA zht&TfB}CLpUz<6550k0iIY#ieC`%aNTA)Oma_-HHy~B8k9`F~YN5{K2=2 za|!!SRkud)ot7t>#w`BEF|3Eh^_%F&2g}{`%E(B%IR__D>gMK^vc<;BVxG=78y?G> z3cs@K91`Ac^>wk=6}XaefU$BDx7czMnPXOP;^XVTd)PytyNhhB2`*pY_WH0^jq-XR zzj#l^yR?%qHN+&z9lCMjBfK|HR32DLS1_`{X-N=zn2g|mu;pXrqW9d#uZ{lYy_;~l zHOz#5e$ytd?)vX*O;dsJbSA!>sI*Bp5{P2j{+?9hoMx;F&@;#pJ~ZR=Jl{53CXrW+ zi%OM6OjT>`x79KQaS7SI6}H`$BZ5CHHD~5cib_uSjw5Z|_ER|wLQtQGJMQ@TrzS8RHhOt3F?f(&prp?9vsv?~8`_?s{+*S)^Br`P70tr#qvq|soHY9}k7=p`_k%Qk zl0ScKo0v+MI6Y)+fphE{EgmItWqaYZnH73$*)O}HQW1(<+)mbKfop~W0QxXAp++Y+ zQ~hEXFV(a%Ayvsetw%Q$v+Gjy{vqp{2Q%4+2fTa3q2{nLMZ6dLN!&bVIa1}+>`5?XC_ZR^~Ynwii?g+&^`E0;=zHq&6H2Amuj++ zBMy}{_=Gk-4vENl43LoTE?4Z;c{dx&SS$BeRCp=L2b6+ok+N-X$;m%e0s%t9V;Pz1 zD6Dw(oC{UV%dI;`+IHXei0E#w2|5SOBEMkZ=~sQ<`i+6}Xg<7i^{#!N#o(sM@C z2~Sk&!ez~@(G%lMDrr=8OQrW&_9I4oWG2tMO!8ONhD9WzgcCR*n|eJ{C!Ia78Z<&G zob{@V#TLhSVK#76=P)I3!Zo7Q1SheE`K;Mk*M zkvqvm+Gl;GOCP>tQN?vZg*2fvxT8kB58U0a5-ABkEyIb|L66-s6$Q%!|6&v4<9zH6 zi|3k6xXSl|2)Hhyr{P7!An<%rCz&2~I^#F89c8~L)i`OyLR7I74hOaP!Pk+Wz=RKz z2(W3^obzBDDN`xL-t-Pl}k%M3Em(whJD3?r)`?n&2S#iftQz^{8 zmD}Y)ml|(3!@j)x~8 zKTrQgS}&et5dpfPu5LcC!8w)0rbpWXmzuYNyU?|8^cus8>W^L+&~)hxj~eF0r*aVj zGJ~JPF}a5~OIYPWnl4s6i_df_^yuprwV|!8Iq+(Fc^&<+9_Y9<(;h<%IIWOkQuv zF3_>)4Ala%4jtGOz3d6BygB1zE`;SaR|_&O>&_Z;0MXt(eDEY}#6`#Yhm;fl7Ed-# zrvO@{h(}X}i9vNJkAfjT!U%9@DAHCtm6As~vQZzDH+aBqbFDXWRmamXmMP8M=|g1o zZBFqnMi+RebRkz1$^g2m$l)Q99l0#r+;=7+gJv>7`V;L9`n%q1rG=W%Rq|EhN|Uv4 zFw5k%hOZ_SL!XSq66(sgE3LUU!Q~T6670GfF?@(x+D#W3%nd(k?Sa9hbRDY}lMeig zj=(#mYYB9xPhvl9mFOWsgI|*>;_WV_Df|1{LCC2RV#j*#>7#$ju;BY!Q8Y(e7bv9; zfC*ZwgOwr;gQHulJ5^~S&M_8NZw_lG$zL5N5-d9`(16D(4ao0l0y>Q?@}#OXfkKCI z9XzZHx;4F+>rql`;^G1t>mnz^FK~-Li@dqO4w=XK!f!0p6`FZ#)3#%uPdq=!XcO!4 zee50$@*Co8NbKCs+_@j#weUdyP1IejzIKev+6DB5@y&&(GTfn;oo1oitzfw^hw0Od z&2R@$k9nNnJB-m`0Dm>Hr&^V18e}D7j1o_AU`ZZmN&>1-)>K_Q0uR@}g|eA-|5h30 ztkJyAjAGcQy_x2EZJlaocVsLiRKH{QcFaHXm2bx@Xwo zrH4vw9QGUIJL=+due2RTcv}#Q&HfE{+R7pELd!T2^Em%bn^Z0PKud>w|B`xmr~mz-9LpMgp|Ye@AZewX z3HPacQvT)yu!wEHs#Drg^X@l(fWAkOdvQy!4vJd{SbVO#W$Jo*7JA=I7RT_nBM&YM zz(M*t`Z(mH;(P%>oPv|d(?Q?sY?Z)+ish&|NDuG4@UT9Wwr-Bs-#*~#I8UFyw(^+? zWyRmx{O9ueduwY+l!+21vB?Scm8{(Zcy&C@tR$Mvm}wWYcUhxmK2I`-a;>Z7=4AdC z%NX_Ycu&g5HHMbe0N<-sA78ZiW@9H)wRRJ`!3}!3IUbUp+@NVqysB2hgA|@t@#~WUIzg_f@J(5FT&>q-XKlG4YsVD7N z75WMHH#ePmCoo=+mbEgnIT)#G51qQg(|rUN#s#vN!#7$foRU%&4X3JgFM?DDWxY4l z6XO4dm>?4&QH1^vBCRj-vl_jV(B9DvNs_7^RaJ@Q_qFZ(P}j^6YXTd$^NIIst`P(D zpAB)KMUmyC%E&eO&$l8{a7ti2j!85Z=T_XqQ-g_Tef-RQ`=#xZBE6G3NqRmTZy%mI z)t*oTKlPG@Z(2hhkjgC16uAHcrHfh&Z;PYdW1p(xnk3>8>KfMg1w9e-8Bwo*vM21A zct+MA>9@OfW(_}3Zfu0S#s_%LUx9DRqLGhO78($brROsv z6=*9;Xq@928Nmkb1s3J}n29Fz3!>X?tLrz^L3I{~skm%?VppO8XuURdLQJ7_Hk0<* zM*II{`-QA|J806f3%+R?!z9fTkPC=!*E^y4ZYqUw#83lAzp{cGbRDy>p{dW+)f8gh z>|ITK<8_>?%BmB0P{Z3?w7&3~9RvEMD%$MCB!>IQF>YT#Rj2lCWDAe5Qdk|5OBzU4 zb)S%aHc>CUMZ%_3tApA}4y?A2t#s@q(Wg3VqHc$8Xi)mDdb?R>(7d7!HBmx2m%l)h5(U}YRJt z-M#TyhC@^z0jlP&*L4MYi0Q4m#wxYEI7QFw1`L}=AOXEa-Q=Xn%wgH@PNb#{baOh z_P#(~Sq*2jq*S?eX_GJXs%%OaCo|t@pvc~M-tyo*L$4Zld^DNF)#anfd<(<_9vvGm zK-18+nO@uzgWR{-t@2be@i{zSUG&7BBor%+kDpvj)R=D(b8F+++qX?sDSxZ9X{jlv z-W7BCxBB-+zSUMM1fE7dpSLL9H$bs%v1FBkd8_b_L#WYniD$u}9m(tdccN(0=V&{| z;l@~&c6UR12Y2V_G|~q7f`48khzkG!8v=^T*fSLi>1S;B zclnG3XuWupmK|bIB?ETYCPPpGqgV1xXArOckP$DM-S}c%CM!T3&Ps|OzGS?-tZ7AS z6V-ejCYlfdk5HJ2hwNK~bl!n=-%vlXP2N}x?zk5-JQdP429zqHPKc|YpuYQ|(@fUb zCIxwVjbc~F4nomK4$|v{W4GilwMK5AIRF>nrq7M~*T~`1`A;WaTW*@2J{=MFCs!#A zn&kFLr88&^887GdDKgTDt$FL#Xfq|5icDieE=q8l+F*oHp*#GQ^~()$U5u7KLNp&#Bc&)AQMRZaUN7oV25&$uXbUFGW@%a|;(CFQHeWM+(B zS1e=CzV=)P6DFnv8R->c@fv#UGyxK+j7qEE$07`@+FPJ6Yt)GW%HX8snTzr0#4I1ksL{X5ptw!!`L2bi>1HbvjMcz})j(Xa-cU{XvJO178psqR^ zSZsE|-S@T;<&HhyEpzKc47TJMl*v_%G9I;W0_z`jLr8?fL8Z38--Ji; z@o5ifn&f~J05T8c*r9^&{1K`lO8WG_-0{_N20azfg_%R55F_=@d)aO zsa4tty}Dg0C#W|xv&hY67vouHoLkCTkAl1VNG{zS=&8D--oFq7l_ITj&Rb`31(;=p zhtTG=e^S}r6Jgq3E!H-u_tsr&XbA$jA)V7UnC|85dF*TlRlI*EdOIM>o2RT#S@^fY zVhSb25^Vh^gh?2?sVJK_8U%7Y`Zht#i)sE6fj)fYAaHQ!yQBCKUdU;oGKIFi&%&4`IVPv)yiF=Y+6vCTvu)w)8FW+tZN^TG>5JVQwbY*sZ~{sdYZYc{_OG1io6#ltzvX)ZrjGzJ35A zTGW^f$a>z+SZX1l-PZ^{`(p+@5m9XXF$l_apK;RJkQga?$>v&{o1H! z&b<0zEiiz{y)u0A*|qD5(^#FYJrCJ-2V?$$z?iJ1=ljEaSnSz6uDZ})4V>X!G8ru`TmpW zC6!-CYcc~*D@UVfz1}_N2)Zv|B${q=rjjkZ^JxJYS)^#cJ6h!6)jmQ)lti81RRh#} zf(BAWf<4JmqZGZMn&CnMxde50Y$W}=w-k+x_T|+W^%rTe$B6)eq@e--yPa#@WOzoh~dHN(pun$0~w`@L5X{I+;&?F2?TIZ=j=N)355 zq>t3+3HKSmy={xeIkgf6zaRg)q9Sw8V7p_(BR=@alX$tf4Wyv?Jvf5Zd1IS7XY5*R^3#LvFaLYxUXm+E18__7z*I!+?Jcb>__X z={yuUFUxDE6ww~AwJ;%l@6Q_LSAm&Q42OGZntGd)H=3*aej-!2zrJp+*8Y8|$)C3! z4K7-7I2^O>F4uqg{%p(`JbYeO`iUX@@Mi~gzSaQdu)&U40n+SoSxI_7B~w-Feqq zmlMrbgQx8^b>3-WF9zELI#hh{AUe)|NTs925Ch{@g&cc(R4Dt&4IKs*4f)@ z(=laZLG$go}}x2m;PW+ii!5?=C=9rG_RHzyldEAgc2JL44$Qe6=O| zuB4OZ1x|8|Ac6Ww%Lf5EKT(GlS^YjQruu3XHJntl1nm7F9s3<^v{ifHVSO88j^Z|U zcD!Vuq|1vxRY?J2aNf#S*rt=lX{@BB^1;LYbt%`u^QNsA?B@$2zZ9@fva%GEltu=u z9U5_YlGWqj2X)}+TEHJN2?}~C3W|%0mUWddH$eJB7NvP=gFpQ>SM38>0L2q|cg)F{ zz0O`K1KgaRl9jtJ?*3X@LGEhWV9~K=f}2%MXecFFO!BN<^IQLex21S#VFustQHwid z%QQF}D4g$~@Kc@2_Pd1MmZ$ai>ySlPGBq_lnA)w+^_uc-v)eKIgT~c5GJf|}y%ZTJ z8s+q)=j_3@8|09nkqYtI3S?wgqg^Cp8+jw|;oov{{}4T} z8$NFp|G@N~+Rshs>FHTy|W`fSx3M^-}ed~pz6{9l{Ea0T4C2?eT&vlk!kTDm@bly_R0 zA#2k5HNxD2P1+O2iMGLbKH!9@D#bnM_#TC-q#2o81;-yMh)D0Yb+4?=uceq?W2JsH zx4J96bsVrDJ#BijHS8<>=C`?f75VpXIPlMGmwtnLFI{T-%^XYpALtgVo#J0H3Hh~Z zuaaz^|AyOTPWKxDdZB%(e!cNxs8fwxssF2?5kLU%{sKmv`EJBTKlnS}uO9p|Jg*{k z`1Q*EpeF|WeaO!fhFrf*Lgg{s=C|0%E-owlE8LMN{`gY7`$h5#- zRwAQ3q_`(+DEwIxZaHv7z@fN6Q42OcG2>c?Wc9TIx&4=&S6EZiXX51ovo zJiOycU36}HxokM_(({qZ74$)N3Tv170~CxfWIZCahXV5cw{s)Wwx_qG-s^`@gtB}6 zm}aqhm?`8=(dY|Z$H5%I^76S1RDDCCNj0imP}cKDK3eR4E6=Yz_DUL9+`2wUd&>&4 zvxF{R+6W6t*UQ~ZVtLBQ1udRfN;+@LL?+5L3RfJJNg;bK@0}& zmLKbu&&v&~%91ql9D6kMT#adb^+}U&_j! zt;anno1`}kPS9YBObN6;K8(2D!s(RAP~)e!GM}H&O0tHyXqS_mwep8C%h|uY(Z?*a zl&){X9{k!pS!O6(TOWQ|*-37&nw|!V3%1YTIs2`+WpvJfxJ+H+9o9C-KSlcL$N>k7 z0fE3O-|vM7?Z96`j2G&m78Wzt?3@eZ+^UiRN$OWhb!+I_ilIG5Wx&^tT|C1FSAfMr zRjcE%$Q@Tbh*nu!S8W)>)MgKWHAPgWZ zefSt=t>L0A4%a}L{QMD=|N9w9_tlrIlbuw9by|pNEM#H98VxRf#^yo*w3yk=R{k_P zvXWY^TR{2MO3)R#v|az{NIscSI69Q2VwNq0jgemIN-*VH)wQ>rMutb}w8DWFC)h!F z5M!lcZrvPYGR<~YIQL=hU6#zOK^ z^#6VB6|T#VV%+g@nCM?)K@ZEQ0FJP%+Nt~YkzY|gr^O!9|9$aHMO5Libbkhyo(5k& zhZ0+83Tx{4lA^h+SUJZnEBd+#QIJ1Q{pqjwoh?vCkZ(n5x)9NHrNI?N!UucbCj(F_ zt0b`(?glG^%f|oX7XIn+;*fj!vZEEx$_%GRI<1ptY)YUeq~P$|Xp2Ce5mJn4tc+yy z+YD&XD9Hx#g=U!yzrz~gmCYR|n@2f9?*@dIA|@gi-i|0!n;|RGm7;wf;FJlB zt#nolpV_3~_zR>-Vs)sj!{tnLnJm19) zkbIgUKE0FdTABc8e>uAsNyr|%4DxWOC@XUjAQAt_@2lKMJM)? zG((-hrVKd0W2eOMUws=51iZ;fU$A23#x8n$k>YWLY#+d^2pJpvEL>;4O}dxgB-3TnX*;&Th{#Ak$8W7cS=qH?R9KECQ4h}SD8p(ETP zxzodx^xvRsf~9)A?o|ZX!$Y)BW=r!Lt6Z{On!jfcm$+JQvSbYTvv>$KYp+P3Ow7Q* z0A1m>r%}&#cplAvH0eyGm}WSz1zA*|sO`V3f18P^W_3|+cf#HKWPfps=n^PREq}Bw zRj^9;NivPKZrho&aF#piBK7>}*QxzAUV80$l_E=Z8^WrLo3$lH;g%M{!tegHzrPIr z^hLn_lDNdZiF*= z2OB;&N^j}sifN08h?uVkAXJEx=0>*{(%YzQ`k>PnvbUYq0Gzq7P3+2wX%zbGNZ&7- zm8F-h==YBnxasLM0e`&4{=}kO{Oi}RIS!RoRJO>6`}r=*6Svm3w)hn$CZ?`M z`P2O)@^Q;z1X`gm{Z(OqzOFPswz_l-c%CV^kMlp=zPSH03KkD73fMtPy3TwHC6a%+ zs6#toGsf@76-$#FEu0;VjgRWrg9PU8%kQg2-jOVMe){3o{Y^|!02GLwaGq!R!R)9g zm-HWkjVbC-3DfoKL#7{C?DQj~vX-C#tsWMeFquTPv{}+4j z9o2N&{Q){Z-x+4c!t0BQN}EvxrAw8T%nYN52q;y$ih$Grp%_{m>qwO@1c*wL8d`u5 zlBh@vgh)%Mi3&*sQY0aSkdSQj-BHi}v1j*>-Lq$R|A-!vZ+XhSpXc7sz0ZBtb-h>b z8$h(EDMDv0Yc!Y{AZit!%{G#>B@6nd5?EGSH&mDX18oDfY-|`t$yco^jHcA>P&H;d zE#v8L-;VC~p^*nXGzJW1KOHOTH#%hmTRsnVI!P<1Fj0bD^Y)5ZU;PS0qk?x}+3g`# z6?s#xM+WBRsc>tw>;V+)6fit5n72@5>wHqcXc=G=UK{}Cv>i?qBDnq6TX`SHtYRF( z8iKAR>r^Oe8W{qL9}c$_H@Pat7ojJ}vZo})Gu~#gwQ>DxJV??F+4EhBAA6qe7bAhq zyq{MQh=8T{H_r~#c=!&y*kGC8jPj2+rQnv=a(0)Y^K;hDFv1!VqN4nN5FysAyN5(H zFXAaftK6r%77v$|%AywpBzvapWxdbb(m_fQnK#pL;rfSlnc!vVclTGV^98|-@`b}a z2gqN*>dC#kEq3Kli7+EGvvFD?D@?Lo@@%?VCMLdE!bn zc^1+=(HV!F2Dxmx&se3bg=gUaxywRbnYd5622~rzu*1)emJ!S4*hCvN>BoJVM0%fW zv^?8ueIiSrJ39mhT^nmbjE$U2T^|=#&Effr4%zqr}FGf#a#o=b)q`+=)U&Ig(*DB5y2`f_%&EFKN0 zPPYV|Gf#MFC}U#>ID)p zXcyH~Gn>4rs%*lmL~7T~lf7~rV!$1YN3zf?1?O`Izlk=NYzZ&u;0AeNDnoPIXx`wv zlrS7_HQL{=Zyn`gE*Y&lKA>A8Nxk6Hlm9TiD5fqs<*(EKNceB)p8{Ou1Byh%;R% z-4xnAmVzRY!AcknzD{@cOG1@cC3413cg(|H>JAOwG&!ail-KC-qj9ia;8DB8Ed&%F z0!dP}Xw|pujMvAI3TiWU<6vfvnZaAHmX$fngqAz?1Jx->a=gJT%I$8C|Iw0wK z@ZpkDd~IHE8?WU~nB0@F2ATR4x`4_@Yu9FWcbu^{c$##qTcm|5YQ)8d0QVK;0jHgKn`e}v1M$zw*DK~@FD;61G@pbNI zPD(mEyN|Sp^_g40m%yz^=y$Peg^;nzN9IxL9ZeUq0&i|&dQu{!>oot+w zt&jTJ*IMqZcQDmW@Q3R9QHlptali)~k=_Tb3&%SH{8b_A7xzXwI3Fg4aeRDEnZ#WI z`R88W8s9unbK5c7$@G6lB(``?z+fpp zAipzm_~|i0u#>qR&6%Q#Xxdc>Lr5 zqNSh;i_;-2LgM~8vzsTffz3&M|9a0QMI7!CNM!d-NUgsZ5cBTFPIjMg_u8C-lT~!@ zfMw$PhqQ>`(NfgA#YT8-PrUd~O4s{<^D~gmH+vi=dJ3u^++TSaB$ZgTC-5Iu+l`x@ zeq7cI93C90+U>v&`&a&IgDak{&C(apvAt*`@wo7Uzg3Y-o@L<$b6o+*$zQ|plzDDW zaTzcAgY(n{pE}zoDQHsawpl2Tf|&ttHSYG%Fp5Q$l#xZLMWUD}kCVNOy5cT_0%jLG z*38a-FMDP5&71J*;JVuDjcOMcW{jqb%qXSjXzy=Ub6CF7+uqT*3-a=TUAdLP!K#qA zKf7cnb^Ijm~c-k&soM8Sq(SfcJNpykLQKy3TON2{vz@sTeU<-F;I z3aI(&mBeOO#e*s+wz!dvWVrnkdlJhH>O6_bt2L z@uRMQGyJl=f0mS-?R{0NHX+f%<5vRkkL#hikKo z@P95UFU+7SL`TXmLg(igK}OLbS_PN|mhhb=G@=^;)iU@8JYPgysnE>Pjb=`_^lZLQ zx9`Awe6bv^_OXCveu*Io#=@H7mJ zY*#J$JzpPUhaOyugjoi<^hM_EWN6ZL7~T5++B)G z2L~HHUz-3US!#ZbUH&DE59ftm(6qv)Q(L|sX3dfRwCC2`-^N-)G9}JIq_D#5J7oX( z4;NwAt9I|+?L%&Hgaa_|FB8B~i+DS&WkQOY45mO6=nm)NdT2}NEie3ww;TETe)#o! zITw`YI}I*%$OLvxeWt|P+pBdlu$mihl%^|SytUoz@_pPqhxOk4f%FBRqm-7rw`?q^E>5y40ussbIhmuv9Wf%x7D?=8 zpMFqyc=%9o?Uo^Ki z_w^qpq1$R|_U!8VG=cb(nVE^x1ASrU1Fsgh;v4yr&KK|F{JVUC_Ww-fjxdFOQ!$$( zVW-u$*l|A@@r!EGn|?Rn-7|rUUhUFf`t)ac5*u|uv?UVps$_rrxI$5)t3n`eHX$2k-WE*-RiYIRz>fM)r;|O`a*ND zyEi(Mj;{K^h|or_Xk2V?^BTZ!*j#Io!JtZCs)XUBs|d?GNlAI?3N{>)=Dsf_)?)vC zHN5we6)!U@5#5~E4;6%yHGl$H?8U%e{9cilgcBqQF;o#Ic`e<4Vx@h7kClT%Sg z{8T#AqwMJ1+Ihm?VAJ}J1ncdYQgs>9l=p1C`(ZEJ(LZ-2W2qoP!yQOJYhs>D_QU0$ z&*e6~)OPaK1r4X5&)ZeUgx=697|O{QQD4ScTFw~<#qvl5{@)O;^V!I}T~rxr^4?zA z$cHfwd5e?_T6)&D29X%4ZZpIwV4=VsLaRBps#xMtZD_R~NdcI3B#Kkpz6Rpmf6ee+ z8q$Q1cwo5&CIYxQSc3=OlwPyzA%52#z``in%vX1)L zR8yNp?TR`4(x3MoG2YpB-c=T`heIoAgo5ISyWxqN`q<=0xIjc2Po6YS zi97+4&kVL08hshz0ijr|P#69-*W}I)*SKTYcFx6~kUg{22L$#I@4YINVuD>Yaa%_p zD~Y_XsYqRIJB*1k9mtmI^cJXFTk;0osM3Qc1hN%#%i0}v(-fGvT-K9v_2`5)WinJl z53#Sq-_7J0Fhv_tW&wBMh;;_2#oc}1j2L<2Y*+qO8GjGDms;E#W$98O(c$QYGPdeK>T)rw%# zqzyL0NphhT!r6vc)o}5aMTRoNALOGvq!d<~`UIK~zmZRxPD*#vqZJhC>n8g<7LxD6 z5}3qeYBR;yFyU)HbL6S7%(8s-=Y2i(lOW-F7hmVtUM|h}-|rp1Q$@gS`C!k&(m#dt@OvIFPA-RslO>38QvW=@h>v} zU&dRgn#ZUEH($!TFOV|=I2l7NRlBXCPGs+nbn-uTdcLQ}k~vd00EmaO=cbAX>1mxY zPM~;p-GjR+!{y_hf-70psj`dNBcqKA_BN=PgsrVk##@Zqs7>RKcAacuzyld#QzW~? zS&k^wWBfRI?M;O(nEBDVANr%Z=j?nW6)UaONmax6Q=I9u5#c0qf}Rcp%C`TS>R zx+7TTg{pRUW==#Dh4gJZv#CV`YL@Nmv&PxDfZ)9E@p7+ty?`NoxUb2)Q2AvXBqST_9)DIW1<9&TAKpmy=8O%zOs zOIp*>Gof~u)a}xq)eB`Q7073U&lYr#Wnj)$R8$B*>9m5Tqs~m~`iC(qS)F0+qhuK; zmCVh9?;nV<(UNgVePsQr);MUEb$1)U{0rN&WA@x3*yv9Ipu49Fm7I$QmGp6eUSFdH zN_f`4`{R)tu?dBrd~k*(btvbUt@{F0R(4oS0&Tmed-UCR_S|5NT&A2By5A4VB_zo& z0WN)gf{&3xfcM+byZ}v2P4AwgruRed`vY>wLEUYrn*5Oqf!+J?g)${re2@?XPE!1u zx52xRaeSyib0C$b?H|&cHhrkBHhkFuWe8gys=eTGer6tLEhn#rKlSaa%w(^+AzYe9 zB-6A%DfV2C)|Zv)Ry|rpqrcEQsoT;U93x{00k8_&YV|PipUb;vjXRi1E zFiYHiJfpFSlr`}U)2w}fk25{56#6YAt@1SRYItME`Zqa3kv4rRFtb0jXWu_;*@bAo zyju6QJJdyU5cJEp^z$^Z+5^-bo*eAlhamv})55xmSe3g+G z5p^dHR`=_L{h5B$UIX7T-hICXNz<=eOAD*jeRylm()gQDhPG$v-Gjrp=O(jnu8;j| ziq7-$e%KLoE!?HC(5vy3Ugx>Armb{@Yn`s|7glM<4zeuBq;A*Uopxp|3?tVlb(>tA zF?C3b@RCJTF1tz&o@p`AGqbC$Pu&`JFn~_xt*F9n@ zbUT`^hF{vBxvz__*b%E7sY`2e&RycJUjP`Gd=v2LE#7{TTf01?ZddDi-nm{rtxVou zaqG=J_jbyo4hva0=V41+reT-4ekbYgyXai!TI^l>0EJq2hF6>N*A_I@IoHz1r~k~Y zoWB8BbqR2B`eSwHb)|@Kj6$PX1#)U{Cp)cWsJ5^a<++3GpPUjI*;rUvUszl#PZxk# ztRa#v%w;9?Qrj1oamS1Q$l_KSdQJ>ki*qaMPdHOt9di=&<{Z>nq>^y3*cAL;F6A>9gs{gR^g{6IH#!WJ(?+^$t=k7C{?Jo_FzeS!4MIJ>?t|+#UdV>1Kce#e0 zZRtBuF&&@r_N$~%pF2n}^L=)T)UNu{wB|+iKBV3f;$)#yn(t&vb>YZ?;RmG$Bf?I5 z|EJ%yg4Fk2__p)ZF!|ZJ&@(wBvQT({E^;!hQk#Divi5zwF78%X&($zY&R01|=n1qA z;?+O9)N}Am4oaAkX-mqD)!piT4otN>=so|PLV%Kgm1oPrkk`$~Kx$1+A1N(yzc;*Z zt|y+C?dv?#1X;-V2D;d>9*>Q?V^@~N73q_5&*Dv#MuktG53h^_USf&^W{nLyWRu?- z6B-^6FzyE54>Q)EeJ^az^y(tr3SPKvo&G=lc2ZvH5A8D~kN5=_^FjGc9(zdZ(*p zVdqQAFxk4O`Z7MyF1B>?NbgleBGk7lzE-#CYLTz)H`y*xHTAx~J`Z=iQwB0h4?5

G8o*s$%50k6J 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 diff --git a/docs/content/assets/img/webui-dashboard.png b/docs/content/assets/img/webui-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..80a5178b0857e30b86defcac1d4f2615531e21cf GIT binary patch literal 127729 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

H5{VW#< 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

xCL}X{)S0X+wSqs?s>4i^$!A^*xJcQ^4KZ&{toY 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 PAjf&S`njxgN@xNAvadyV literal 0 HcmV?d00001 diff --git a/docs/content/middlewares/passtlsclientcert.md b/docs/content/middlewares/passtlsclientcert.md index 6498000e3..ff53b05cc 100644 --- a/docs/content/middlewares/passtlsclientcert.md +++ b/docs/content/middlewares/passtlsclientcert.md @@ -3,7 +3,9 @@ Adding Client Certificates in a Header {: .subtitle } -`TODO add schema` + PassTLSClientCert adds in header the selected data from the passed client tls certificate. diff --git a/docs/content/middlewares/redirectregex.md b/docs/content/middlewares/redirectregex.md index c34da5133..6dd1ae3cf 100644 --- a/docs/content/middlewares/redirectregex.md +++ b/docs/content/middlewares/redirectregex.md @@ -3,7 +3,9 @@ Redirecting the Client to a Different Location {: .subtitle } -`TODO: add schema` + RegexRedirect redirect a request from an url to another with regex matching and replacement. diff --git a/docs/content/middlewares/redirectscheme.md b/docs/content/middlewares/redirectscheme.md index 65a01c823..f4af47a16 100644 --- a/docs/content/middlewares/redirectscheme.md +++ b/docs/content/middlewares/redirectscheme.md @@ -3,7 +3,9 @@ Redirecting the Client to a Different Scheme/Port {: .subtitle } -`TODO: add schema` + RegexRedirect redirect request from a scheme to another. diff --git a/docs/content/middlewares/replacepath.md b/docs/content/middlewares/replacepath.md index b491c8033..f2e03d552 100644 --- a/docs/content/middlewares/replacepath.md +++ b/docs/content/middlewares/replacepath.md @@ -3,7 +3,9 @@ Updating the Path Before Forwarding the Request {: .subtitle } -`TODO: add schema` + Replace the path of the request url. diff --git a/docs/content/middlewares/replacepathregex.md b/docs/content/middlewares/replacepathregex.md index fbdb47f0d..a58e302a9 100644 --- a/docs/content/middlewares/replacepathregex.md +++ b/docs/content/middlewares/replacepathregex.md @@ -3,7 +3,9 @@ Updating the Path Before Forwarding the Request (Using a Regex) {: .subtitle } -`TODO: add schema` + The ReplaceRegex replace a path from an url to another with regex matching and replacement. diff --git a/docs/content/middlewares/retry.md b/docs/content/middlewares/retry.md index e7704c862..b61b362f2 100644 --- a/docs/content/middlewares/retry.md +++ b/docs/content/middlewares/retry.md @@ -3,7 +3,9 @@ Retrying until it Succeeds {: .subtitle } -`TODO: add schema` + The Retry middleware is in charge of reissuing a request a given number of times to a backend server if that server does not reply. To be clear, as soon as the server answers, the middleware stops retrying, regardless of the response status. diff --git a/docs/content/middlewares/stripprefix.md b/docs/content/middlewares/stripprefix.md index 14e1df748..2b3515ccb 100644 --- a/docs/content/middlewares/stripprefix.md +++ b/docs/content/middlewares/stripprefix.md @@ -3,7 +3,9 @@ Removing Prefixes From the Path Before Forwarding the Request {: .subtitle } -`TODO: add schema` + Remove the specified prefixes from the URL path. diff --git a/docs/content/operations/dashboard.md b/docs/content/operations/dashboard.md index c0443c199..a73a52ee2 100644 --- a/docs/content/operations/dashboard.md +++ b/docs/content/operations/dashboard.md @@ -5,25 +5,16 @@ See What's Going On The dashboard is the central place that shows you the current active routes handled by Traefik. -!!! warning "Dashboard WIP" - Currently, the dashboard is in a Work In Progress State while being reconstructed for v2. - Therefore, the dashboard is currently not working. -
- Dashboard - Providers -
The dashboard in action with Traefik listening to 3 different providers
-
- -
- Dashboard - Health -
The dashboard shows the health of the system.
+ Dashboard - Providers +
The dashboard in action
By default, the dashboard is available on `/` on port `:8080`. !!! tip "Did You Know?" It is possible to customize the dashboard endpoint. - To learn how, refer to the `Traefik's API documentation`(TODO: add doc and link). + To learn how, refer to the [API documentation](./api.md) ## Enabling the Dashboard @@ -64,4 +55,4 @@ api: !!! tip "Did You Know?" The API provides more features than the Dashboard. - To learn more about it, refer to the `Traefik's API documentation`(TODO: add doc and link). + To learn more about it, refer to the [API documentation](./api.md) diff --git a/webui/package-lock.json b/webui/package-lock.json index ce0c1d3aa..881323f68 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -1,6 +1,6 @@ { "name": "traefik-ui", - "version": "0.1.0", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1465,6 +1465,7 @@ "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, "requires": { "mime-types": "~2.1.24", "negotiator": "0.6.2" @@ -1619,7 +1620,8 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true }, "array-includes": { "version": "3.0.3", @@ -2091,6 +2093,7 @@ "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, "requires": { "bytes": "3.1.0", "content-type": "~1.0.4", @@ -2108,6 +2111,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -2115,7 +2119,8 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -2297,7 +2302,8 @@ "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true }, "cacache": { "version": "11.3.3", @@ -2929,7 +2935,8 @@ "connect-history-api-fallback": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true }, "console-browserify": { "version": "1.1.0", @@ -2971,6 +2978,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, "requires": { "safe-buffer": "5.1.2" } @@ -2978,7 +2986,8 @@ "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true }, "convert-source-map": { "version": "1.6.0", @@ -2992,12 +3001,14 @@ "cookie": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true }, "copy-concurrently": { "version": "1.0.5", @@ -3575,7 +3586,8 @@ "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true }, "des.js": { "version": "1.0.0", @@ -3590,7 +3602,8 @@ "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true }, "detect-node": { "version": "2.0.4", @@ -3751,7 +3764,8 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true }, "ejs": { "version": "2.6.2", @@ -3812,7 +3826,8 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true }, "end-of-stream": { "version": "1.4.1", @@ -3895,7 +3910,8 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true }, "escape-string-regexp": { "version": "1.0.5", @@ -4296,7 +4312,8 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true }, "eventemitter3": { "version": "3.1.2", @@ -4398,6 +4415,7 @@ "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, "requires": { "accepts": "~1.3.7", "array-flatten": "1.1.1", @@ -4435,6 +4453,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -4442,7 +4461,8 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -4681,6 +4701,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -4695,6 +4716,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -4702,7 +4724,8 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -4844,7 +4867,8 @@ "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true }, "fragment-cache": { "version": "0.2.1", @@ -4858,7 +4882,8 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true }, "friendly-errors-webpack-plugin": { "version": "1.7.0", @@ -5515,6 +5540,7 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, "requires": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -5526,7 +5552,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true } } }, @@ -5700,6 +5727,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -5873,7 +5901,8 @@ "ipaddr.js": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "dev": true }, "is-absolute-url": { "version": "2.1.0", @@ -6704,7 +6733,8 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true }, "mem": { "version": "4.3.0", @@ -6846,7 +6876,8 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true }, "merge-source-map": { "version": "1.1.0", @@ -6874,7 +6905,8 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true }, "micromatch": { "version": "4.0.2", @@ -6899,17 +6931,20 @@ "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true }, "mime-db": { "version": "1.40.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true }, "mime-types": { "version": "2.1.24", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, "requires": { "mime-db": "1.40.0" } @@ -7128,7 +7163,8 @@ "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true }, "neo-async": { "version": "2.6.1", @@ -7540,6 +7576,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, "requires": { "ee-first": "1.1.1" } @@ -7803,7 +7840,8 @@ "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true }, "pascalcase": { "version": "0.1.1", @@ -7856,7 +7894,8 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true }, "path-type": { "version": "3.0.0", @@ -8719,6 +8758,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "dev": true, "requires": { "forwarded": "~0.1.2", "ipaddr.js": "1.9.0" @@ -8804,7 +8844,8 @@ "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true }, "quasar": { "version": "1.0.5", @@ -8861,12 +8902,14 @@ "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true }, "raw-body": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, "requires": { "bytes": "3.1.0", "http-errors": "1.7.2", @@ -9382,7 +9425,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "safe-regex": { "version": "1.1.0", @@ -9396,7 +9440,8 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "sass-graph": { "version": "2.2.4", @@ -9713,6 +9758,7 @@ "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, "requires": { "debug": "2.6.9", "depd": "~1.1.2", @@ -9733,6 +9779,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" }, @@ -9740,14 +9787,16 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true } } }, @@ -9817,6 +9866,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -9862,7 +9912,8 @@ "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true }, "sha.js": { "version": "2.4.11", @@ -10321,7 +10372,8 @@ "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true }, "stdout-stream": { "version": "1.4.1", @@ -10792,7 +10844,8 @@ "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true }, "toposort": { "version": "1.0.7", @@ -10885,6 +10938,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, "requires": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -10993,7 +11047,8 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true }, "unquote": { "version": "1.1.1", @@ -11163,7 +11218,8 @@ "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true }, "uuid": { "version": "3.3.2", @@ -11184,7 +11240,8 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true }, "vendors": { "version": "1.0.3", diff --git a/webui/package.json b/webui/package.json index 7553c88db..544f6748c 100644 --- a/webui/package.json +++ b/webui/package.json @@ -20,8 +20,6 @@ "axios": "^0.19.0", "bowser": "^2.5.2", "chart.js": "^2.8.0", - "connect-history-api-fallback": "^1.6.0", - "express": "^4.17.1", "lodash": "^4.17.15", "moment": "^2.24.0", "quasar": "^1.0.0", diff --git a/webui/quasar.conf.js b/webui/quasar.conf.js index 7fb3c3cfd..109fa6130 100644 --- a/webui/quasar.conf.js +++ b/webui/quasar.conf.js @@ -85,7 +85,8 @@ module.exports = function (ctx) { 'QDialog', 'QUploader', 'QTree', - 'QChip' + 'QChip', + 'QBtnToggle' ], directives: [ diff --git a/webui/src/_middleware/Boot.js b/webui/src/_middleware/Boot.js index 8f0a5349f..9fccf11df 100644 --- a/webui/src/_middleware/Boot.js +++ b/webui/src/_middleware/Boot.js @@ -1,4 +1,5 @@ import { APP } from '../_helpers/APP' +import Helps from '../_helpers/Helps' const Boot = { install (Vue, options) { @@ -13,11 +14,23 @@ const Boot = { }, env () { return APP.config.env + }, + appThumbStyle () { + return { + right: '2px', + borderRadius: '2px', + backgroundColor: '#dcdcdc', + width: '6px', + opacity: 0.75 + } } }, methods: { }, filters: { + capFirstLetter (value) { + return Helps.capFirstLetter(value) + } }, created () { } diff --git a/webui/src/_services/EntrypointsService.js b/webui/src/_services/EntrypointsService.js index 71d564759..8dfaffaed 100644 --- a/webui/src/_services/EntrypointsService.js +++ b/webui/src/_services/EntrypointsService.js @@ -10,6 +10,15 @@ function getAll () { }) } -export default { - getAll +function getByName (name) { + return APP.api.get(`${apiBase}/${name}`) + .then(body => { + console.log('Success -> EntrypointsService -> getByName', body.data) + return body.data + }) +} + +export default { + getAll, + getByName } diff --git a/webui/src/_services/HttpService.js b/webui/src/_services/HttpService.js new file mode 100644 index 000000000..19deca0b6 --- /dev/null +++ b/webui/src/_services/HttpService.js @@ -0,0 +1,75 @@ +import { APP } from '../_helpers/APP' + +const apiBase = '/http' + +function getAllRouters (params) { + return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}`) + .then(body => { + const total = body.data ? body.data.length : 0 + return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + .then(body => { + console.log('Success -> HttpService -> getAllRouters', body.data) + // TODO - suggestion: add the total-pages in api response to optimize the query + return { data: body.data || [], total } + }) + }) +} + +function getRouterByName (name) { + return APP.api.get(`${apiBase}/routers/${name}`) + .then(body => { + console.log('Success -> HttpService -> getRouterByName', body.data) + return body.data + }) +} + +function getAllServices (params) { + return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}`) + .then(body => { + const total = body.data ? body.data.length : 0 + return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + .then(body => { + console.log('Success -> HttpService -> getAllServices', body.data) + // TODO - suggestion: add the total-pages in api response to optimize the query + return { data: body.data || [], total } + }) + }) +} + +function getServiceByName (name) { + return APP.api.get(`${apiBase}/services/${name}`) + .then(body => { + console.log('Success -> HttpService -> getServiceByName', body.data) + return body.data + }) +} + +function getAllMiddlewares (params) { + return APP.api.get(`${apiBase}/middlewares?search=${params.query}&status=${params.status}`) + .then(body => { + const total = body.data ? body.data.length : 0 + return APP.api.get(`${apiBase}/middlewares?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + .then(body => { + console.log('Success -> HttpService -> getAllMiddlewares', body.data) + // TODO - suggestion: add the total-pages in api response to optimize the query + return { data: body.data || [], total } + }) + }) +} + +function getMiddlewareByName (name) { + return APP.api.get(`${apiBase}/middlewares/${name}`) + .then(body => { + console.log('Success -> HttpService -> getMiddlewareByName', body.data) + return body.data + }) +} + +export default { + getAllRouters, + getRouterByName, + getAllServices, + getServiceByName, + getAllMiddlewares, + getMiddlewareByName +} diff --git a/webui/src/_services/TcpService.js b/webui/src/_services/TcpService.js new file mode 100644 index 000000000..08f1b6131 --- /dev/null +++ b/webui/src/_services/TcpService.js @@ -0,0 +1,52 @@ +import { APP } from '../_helpers/APP' + +const apiBase = '/tcp' + +function getAllRouters (params) { + return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}`) + .then(body => { + const total = body.data ? body.data.length : 0 + return APP.api.get(`${apiBase}/routers?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + .then(body => { + console.log('Success -> HttpService -> getAllRouters', body.data) + // TODO - suggestion: add the total-pages in api response to optimize the query + return { data: body.data || [], total } + }) + }) +} + +function getRouterByName (name) { + return APP.api.get(`${apiBase}/routers/${name}`) + .then(body => { + console.log('Success -> HttpService -> getRouterByName', body.data) + return body.data + }) +} + +function getAllServices (params) { + return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}`) + .then(body => { + const total = body.data ? body.data.length : 0 + return APP.api.get(`${apiBase}/services?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + .then(body => { + console.log('Success -> HttpService -> getAllServices', body.data) + // TODO - suggestion: add the total-pages in api response to optimize the query + return { data: body.data || [], total } + }) + }) +} + +function getServiceByName (name) { + return APP.api.get(`${apiBase}/services/${name}`) + .then(body => { + console.log('Success -> HttpService -> getServiceByName', body.data) + return body.data + }) +} + +export default { + getAllRouters, + getRouterByName, + getAllServices, + getServiceByName +} diff --git a/webui/src/assets/middlewares-empty.svg b/webui/src/assets/middlewares-empty.svg new file mode 100644 index 000000000..172ad3225 --- /dev/null +++ b/webui/src/assets/middlewares-empty.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/webui/src/components/_commons/BooleanState.vue b/webui/src/components/_commons/BooleanState.vue new file mode 100644 index 000000000..7091b099c --- /dev/null +++ b/webui/src/components/_commons/BooleanState.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/webui/src/components/_commons/MainTable.vue b/webui/src/components/_commons/MainTable.vue new file mode 100644 index 000000000..40ac29e40 --- /dev/null +++ b/webui/src/components/_commons/MainTable.vue @@ -0,0 +1,249 @@ + + + + + diff --git a/webui/src/components/_commons/NavBar.vue b/webui/src/components/_commons/NavBar.vue index 2e1e92d1e..0818f6135 100644 --- a/webui/src/components/_commons/NavBar.vue +++ b/webui/src/components/_commons/NavBar.vue @@ -8,6 +8,8 @@ + + diff --git a/webui/src/components/_commons/PanelHealthCheck.vue b/webui/src/components/_commons/PanelHealthCheck.vue new file mode 100644 index 000000000..7b385d820 --- /dev/null +++ b/webui/src/components/_commons/PanelHealthCheck.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/webui/src/components/_commons/PanelMiddlewares.vue b/webui/src/components/_commons/PanelMiddlewares.vue new file mode 100644 index 000000000..a961e2871 --- /dev/null +++ b/webui/src/components/_commons/PanelMiddlewares.vue @@ -0,0 +1,1204 @@ + + + + + diff --git a/webui/src/components/_commons/PanelMirroringServices.vue b/webui/src/components/_commons/PanelMirroringServices.vue new file mode 100644 index 000000000..defa0eb74 --- /dev/null +++ b/webui/src/components/_commons/PanelMirroringServices.vue @@ -0,0 +1,133 @@ + + + + + diff --git a/webui/src/components/_commons/PanelRouterDetails.vue b/webui/src/components/_commons/PanelRouterDetails.vue new file mode 100644 index 000000000..b5c2aec2a --- /dev/null +++ b/webui/src/components/_commons/PanelRouterDetails.vue @@ -0,0 +1,204 @@ + + + + + diff --git a/webui/src/components/_commons/PanelServers.vue b/webui/src/components/_commons/PanelServers.vue new file mode 100644 index 000000000..36968b476 --- /dev/null +++ b/webui/src/components/_commons/PanelServers.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/webui/src/components/_commons/PanelServiceDetails.vue b/webui/src/components/_commons/PanelServiceDetails.vue new file mode 100644 index 000000000..f173c9b69 --- /dev/null +++ b/webui/src/components/_commons/PanelServiceDetails.vue @@ -0,0 +1,192 @@ + + + + + diff --git a/webui/src/components/_commons/PanelTLS.vue b/webui/src/components/_commons/PanelTLS.vue new file mode 100644 index 000000000..e79ffd52c --- /dev/null +++ b/webui/src/components/_commons/PanelTLS.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/webui/src/components/_commons/PanelWeightedServices.vue b/webui/src/components/_commons/PanelWeightedServices.vue new file mode 100644 index 000000000..fb9147913 --- /dev/null +++ b/webui/src/components/_commons/PanelWeightedServices.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/webui/src/components/_commons/TLSState.vue b/webui/src/components/_commons/TLSState.vue new file mode 100644 index 000000000..7f5f76138 --- /dev/null +++ b/webui/src/components/_commons/TLSState.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/webui/src/components/_commons/ToolBar.vue b/webui/src/components/_commons/ToolBar.vue new file mode 100644 index 000000000..c69f3465f --- /dev/null +++ b/webui/src/components/_commons/ToolBar.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/webui/src/components/_commons/ToolBarTable.vue b/webui/src/components/_commons/ToolBarTable.vue new file mode 100644 index 000000000..0d7bb4f16 --- /dev/null +++ b/webui/src/components/_commons/ToolBarTable.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/webui/src/components/dashboard/PanelChart.vue b/webui/src/components/dashboard/PanelChart.vue index f0eb524db..7f72d71d6 100644 --- a/webui/src/components/dashboard/PanelChart.vue +++ b/webui/src/components/dashboard/PanelChart.vue @@ -5,6 +5,9 @@
{{getName}}
+
+ +
@@ -104,7 +107,7 @@ export default { } else { result = num } - return isNaN(result) ? 0 : result + return isNaN(result) || result < 0 ? 0 : result }, getWarnings (inPercent = false) { const num = this.data.warnings @@ -114,7 +117,7 @@ export default { } else { result = num } - return isNaN(result) ? 0 : result + return isNaN(result) || result < 0 ? 0 : result }, getErrors (inPercent = false) { const num = this.data.errors @@ -124,7 +127,7 @@ export default { } else { result = num } - return isNaN(result) ? 0 : result + return isNaN(result) || result < 0 ? 0 : result }, getData () { return [this.getSuccess(), this.getWarnings(), this.getErrors()] diff --git a/webui/src/components/dashboard/PanelEntry.vue b/webui/src/components/dashboard/PanelEntry.vue index b4d6767fb..2ae06af45 100644 --- a/webui/src/components/dashboard/PanelEntry.vue +++ b/webui/src/components/dashboard/PanelEntry.vue @@ -1,9 +1,9 @@

D% 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%0D&ALvG`E#Bd;ht> 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