diff --git a/README.md b/README.md index cc23c04a0..6e967ab06 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![Twitter](https://img.shields.io/twitter/follow/traefik.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefik) Traefik (pronounced _traffic_) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. -Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher v2](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. +Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher v2](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. Pointing Traefik at your orchestrator should be the _only_ configuration step you need. --- @@ -68,7 +68,6 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t - [Docker](https://doc.traefik.io/traefik/providers/docker/) / [Swarm mode](https://doc.traefik.io/traefik/providers/docker/) - [Kubernetes](https://doc.traefik.io/traefik/providers/kubernetes-crd/) -- [Marathon](https://doc.traefik.io/traefik/providers/marathon/) - [File](https://doc.traefik.io/traefik/providers/file/) ## Quickstart diff --git a/docs/content/https/include-acme-multiple-domains-example.md b/docs/content/https/include-acme-multiple-domains-example.md index 63cb382ba..8395887eb 100644 --- a/docs/content/https/include-acme-multiple-domains-example.md +++ b/docs/content/https/include-acme-multiple-domains-example.md @@ -43,17 +43,6 @@ spec: - '*.example.org' ``` -```json tab="Marathon" -labels: { - "traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)", - "traefik.http.routers.blog.tls": "true", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - "traefik.http.routers.blog.tls.domains[0].main": "example.com", - "traefik.http.routers.blog.tls.domains[0].sans": "*.example.com", - "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" -} -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/include-acme-multiple-domains-from-rule-example.md b/docs/content/https/include-acme-multiple-domains-from-rule-example.md index 9bd522c10..9a758ab20 100644 --- a/docs/content/https/include-acme-multiple-domains-from-rule-example.md +++ b/docs/content/https/include-acme-multiple-domains-from-rule-example.md @@ -35,15 +35,6 @@ spec: certResolver: myresolver ``` -```json tab="Marathon" -labels: { - "traefik.http.routers.blog.rule": "(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`)", - "traefik.http.routers.blog.tls": "true", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" -} -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/include-acme-single-domain-example.md b/docs/content/https/include-acme-single-domain-example.md index 1b87873e1..b7f5c84f0 100644 --- a/docs/content/https/include-acme-single-domain-example.md +++ b/docs/content/https/include-acme-single-domain-example.md @@ -35,15 +35,6 @@ spec: certResolver: myresolver ``` -```json tab="Marathon" -labels: { - "traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)", - "traefik.http.routers.blog.tls": "true", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" -} -``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/tailscale.md b/docs/content/https/tailscale.md index d6b783b2c..a4ab0a79c 100644 --- a/docs/content/https/tailscale.md +++ b/docs/content/https/tailscale.md @@ -120,13 +120,6 @@ A certificate resolver requests certificates for a set of domain names inferred certResolver: myresolver ``` - ```json tab="Marathon" - labels: { - "traefik.http.routers.blog.rule": "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - } - ``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: @@ -185,14 +178,6 @@ A certificate resolver requests certificates for a set of domain names inferred - main: monitoring.yak-bebop.ts.net ``` - ```json tab="Marathon" - labels: { - "traefik.http.routers.blog.rule": "Path(`/metrics`)", - "traefik.http.routers.blog.tls.certresolver": "myresolver", - "traefik.http.routers.blog.tls.domains[0].main": "monitoring.yak-bebop.ts.net", - } - ``` - ```yaml tab="File (YAML)" ## Dynamic configuration http: diff --git a/docs/content/https/tls.md b/docs/content/https/tls.md index dd756dd44..f6d84f5ce 100644 --- a/docs/content/https/tls.md +++ b/docs/content/https/tls.md @@ -219,14 +219,6 @@ labels: - "traefik.tls.stores.default.defaultgeneratedcert.domain.sans=foo.example.org, bar.example.org" ``` -```json tab="Marathon" -labels: { - "traefik.tls.stores.default.defaultgeneratedcert.resolver": "myresolver", - "traefik.tls.stores.default.defaultgeneratedcert.domain.main": "example.org", - "traefik.tls.stores.default.defaultgeneratedcert.domain.sans": "foo.example.org, bar.example.org", -} -``` - ## TLS Options The TLS options allow one to configure some parameters of the TLS connection. diff --git a/docs/content/index.md b/docs/content/index.md index b882fb148..3ee028a79 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -13,7 +13,7 @@ It receives requests on behalf of your system and finds out which components are What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services. The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request. -Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, Mesos, Marathon, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) +Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions). With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state. diff --git a/docs/content/middlewares/http/addprefix.md b/docs/content/middlewares/http/addprefix.md index 05cba3ad5..995524ff2 100644 --- a/docs/content/middlewares/http/addprefix.md +++ b/docs/content/middlewares/http/addprefix.md @@ -36,12 +36,6 @@ spec: - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.add-foo.addprefix.prefix": "/foo" -} -``` - ```yaml tab="File (YAML)" # Prefixing with /foo http: diff --git a/docs/content/middlewares/http/basicauth.md b/docs/content/middlewares/http/basicauth.md index 98e1c1560..7707f270b 100644 --- a/docs/content/middlewares/http/basicauth.md +++ b/docs/content/middlewares/http/basicauth.md @@ -41,12 +41,6 @@ spec: - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" -} -``` - ```yaml tab="File (YAML)" # Declaring the user list http: @@ -151,12 +145,6 @@ data: - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" -} -``` - ```yaml tab="File (YAML)" # Declaring the user list http: @@ -220,12 +208,6 @@ data: - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.usersfile": "/path/to/my/usersfile" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -270,12 +252,6 @@ spec: - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.realm": "MyRealm" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -314,12 +290,6 @@ spec: - "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.my-auth.basicauth.headerField": "X-WebAuth-User" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -358,12 +328,6 @@ spec: - "traefik.http.middlewares.test-auth.basicauth.removeheader=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.basicauth.removeheader": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/buffering.md b/docs/content/middlewares/http/buffering.md index e76d5b40e..6e9d7b9ab 100644 --- a/docs/content/middlewares/http/buffering.md +++ b/docs/content/middlewares/http/buffering.md @@ -40,12 +40,6 @@ spec: - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" # Sets the maximum request body to 2MB http: @@ -91,12 +85,6 @@ spec: - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -136,12 +124,6 @@ spec: - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -183,12 +165,6 @@ spec: - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -228,12 +204,6 @@ spec: - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes": "2000000" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -275,12 +245,6 @@ You can have the Buffering middleware replay the request using `retryExpression` - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" ``` - ```json tab="Marathon" - "labels": { - "traefik.http.middlewares.limit.buffering.retryExpression": "IsNetworkError() && Attempts() < 2" - } - ``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/chain.md b/docs/content/middlewares/http/chain.md index e7cbdc456..ce3806a5d 100644 --- a/docs/content/middlewares/http/chain.md +++ b/docs/content/middlewares/http/chain.md @@ -97,19 +97,6 @@ spec: - "traefik.http.services.service1.loadbalancer.server.port=80" ``` -```json tab="Marathon" -"labels": { - "traefik.http.routers.router1.service": "service1", - "traefik.http.routers.router1.middlewares": "secured", - "traefik.http.routers.router1.rule": "Host(`mydomain`)", - "traefik.http.middlewares.secured.chain.middlewares": "https-only,known-ips,auth-users", - "traefik.http.middlewares.auth-users.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", - "traefik.http.middlewares.https-only.redirectscheme.scheme": "https", - "traefik.http.middlewares.known-ips.ipallowlist.sourceRange": "192.168.1.7,127.0.0.1/32", - "traefik.http.services.service1.loadbalancer.server.port": "80" -} -``` - ```yaml tab="File (YAML)" # ... http: diff --git a/docs/content/middlewares/http/circuitbreaker.md b/docs/content/middlewares/http/circuitbreaker.md index 21cd45fea..7ff406c17 100644 --- a/docs/content/middlewares/http/circuitbreaker.md +++ b/docs/content/middlewares/http/circuitbreaker.md @@ -52,12 +52,6 @@ spec: - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.latency-check.circuitbreaker.expression": "LatencyAtQuantileMS(50.0) > 100" -} -``` - ```yaml tab="File (YAML)" # Latency Check http: diff --git a/docs/content/middlewares/http/compress.md b/docs/content/middlewares/http/compress.md index 90cb5c0be..4a17c9430 100644 --- a/docs/content/middlewares/http/compress.md +++ b/docs/content/middlewares/http/compress.md @@ -36,12 +36,6 @@ spec: - "traefik.http.middlewares.test-compress.compress=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-compress.compress": "true" -} -``` - ```yaml tab="File (YAML)" # Enable compression http: @@ -108,12 +102,6 @@ spec: - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes": "text/event-stream" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -156,12 +144,6 @@ spec: - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes": 1200 -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/contenttype.md b/docs/content/middlewares/http/contenttype.md index 4770defa2..b74bfa6c2 100644 --- a/docs/content/middlewares/http/contenttype.md +++ b/docs/content/middlewares/http/contenttype.md @@ -39,12 +39,6 @@ spec: - "traefik.http.middlewares.autodetect.contenttype=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.autodetect.contenttype": "true" -} -``` - ```yaml tab="File (YAML)" # Enable auto-detection http: diff --git a/docs/content/middlewares/http/digestauth.md b/docs/content/middlewares/http/digestauth.md index 8a24f0580..d49d8f581 100644 --- a/docs/content/middlewares/http/digestauth.md +++ b/docs/content/middlewares/http/digestauth.md @@ -36,12 +36,6 @@ spec: - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" -} -``` - ```yaml tab="File (YAML)" # Declaring the user list http: @@ -108,12 +102,6 @@ data: - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -175,12 +163,6 @@ data: - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.usersfile": "/path/to/my/usersfile" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -225,12 +207,6 @@ spec: - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.realm": "MyRealm" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -269,12 +245,6 @@ spec: - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.my-auth.digestauth.headerField": "X-WebAuth-User" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -313,12 +283,6 @@ spec: - "traefik.http.middlewares.test-auth.digestauth.removeheader=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.digestauth.removeheader": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/errorpages.md b/docs/content/middlewares/http/errorpages.md index 1fd537191..3ec1c1e20 100644 --- a/docs/content/middlewares/http/errorpages.md +++ b/docs/content/middlewares/http/errorpages.md @@ -48,14 +48,6 @@ spec: - "traefik.http.middlewares.test-errors.errors.query=/{status}.html" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-errors.errors.status": "500-599", - "traefik.http.middlewares.test-errors.errors.service": "serviceError", - "traefik.http.middlewares.test-errors.errors.query": "/{status}.html" -} -``` - ```yaml tab="File (YAML)" # Custom Error Page for 5XX http: diff --git a/docs/content/middlewares/http/forwardauth.md b/docs/content/middlewares/http/forwardauth.md index 64e64d60e..f7a038020 100644 --- a/docs/content/middlewares/http/forwardauth.md +++ b/docs/content/middlewares/http/forwardauth.md @@ -38,12 +38,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth" -} -``` - ```yaml tab="File (YAML)" # Forward authentication to example.com http: @@ -97,12 +91,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -141,12 +129,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -190,12 +172,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders": "X-Auth-User,X-Secret" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -241,12 +217,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex": "^X-" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -297,12 +267,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders": "Accept,X-CustomHeader" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -366,12 +330,6 @@ data: - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.tls.ca": "path/to/local.crt" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -431,13 +389,6 @@ data: - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert", - "traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -503,13 +454,6 @@ data: - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert", - "traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -561,12 +505,6 @@ spec: - "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/grpcweb.md b/docs/content/middlewares/http/grpcweb.md index ca5b50850..c76153a26 100644 --- a/docs/content/middlewares/http/grpcweb.md +++ b/docs/content/middlewares/http/grpcweb.md @@ -37,12 +37,6 @@ spec: - "traefik.http.middlewares.test-grpcweb.grpcWeb.allowOrigins=*" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-grpcweb.grpcweb.alloworigins": "*" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/headers.md b/docs/content/middlewares/http/headers.md index ab9474f57..739380b42 100644 --- a/docs/content/middlewares/http/headers.md +++ b/docs/content/middlewares/http/headers.md @@ -44,13 +44,6 @@ spec: - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test", - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "value" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -103,14 +96,6 @@ spec: - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test", - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header": "", - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "", -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -160,14 +145,6 @@ spec: - "traefik.http.middlewares.testheader.headers.browserxssfilter=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.testheader.headers.framedeny": "true", - "traefik.http.middlewares.testheader.headers.browserxssfilter": "true" -} -``` - - ```yaml tab="File (YAML)" http: middlewares: @@ -224,15 +201,6 @@ spec: - "traefik.http.middlewares.testheader.headers.addvaryheader=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods": "GET,OPTIONS,PUT", - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist": "https://foo.bar.org,https://example.org", - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage": "100", - "traefik.http.middlewares.testheader.headers.addvaryheader": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/inflightreq.md b/docs/content/middlewares/http/inflightreq.md index 985a2ea11..71190631e 100644 --- a/docs/content/middlewares/http/inflightreq.md +++ b/docs/content/middlewares/http/inflightreq.md @@ -34,12 +34,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10" -} -``` - ```yaml tab="File (YAML)" # Limiting to 10 simultaneous connections http: @@ -83,12 +77,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10" -} -``` - ```yaml tab="File (YAML)" # Limiting to 10 simultaneous connections http: @@ -153,12 +141,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth": "2" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -215,12 +197,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -264,12 +240,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername": "username" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -310,12 +280,6 @@ spec: - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/ipallowlist.md b/docs/content/middlewares/http/ipallowlist.md index 63701f773..703293d32 100644 --- a/docs/content/middlewares/http/ipallowlist.md +++ b/docs/content/middlewares/http/ipallowlist.md @@ -35,12 +35,6 @@ spec: - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32,192.168.1.7" -} -``` - ```yaml tab="File (YAML)" # Accepts request from defined IP http: @@ -114,13 +108,6 @@ spec: - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32, 192.168.1.7", - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth": "2" -} -``` - ```yaml tab="File (YAML)" # Allowlisting Based on `X-Forwarded-For` with `depth=2` http: @@ -184,12 +171,6 @@ spec: - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" -} -``` - ```yaml tab="File (YAML)" # Exclude from `X-Forwarded-For` http: diff --git a/docs/content/middlewares/http/overview.md b/docs/content/middlewares/http/overview.md index 27277677c..5757b3335 100644 --- a/docs/content/middlewares/http/overview.md +++ b/docs/content/middlewares/http/overview.md @@ -69,13 +69,6 @@ spec: - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", - "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" -} -``` - ```toml tab="File (TOML)" # As TOML Configuration File [http.routers] diff --git a/docs/content/middlewares/http/passtlsclientcert.md b/docs/content/middlewares/http/passtlsclientcert.md index f55982a90..4264dd711 100644 --- a/docs/content/middlewares/http/passtlsclientcert.md +++ b/docs/content/middlewares/http/passtlsclientcert.md @@ -39,12 +39,6 @@ spec: - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem": "true" -} -``` - ```yaml tab="File (YAML)" # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. http: @@ -140,29 +134,6 @@ http: - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true" ``` - ```json tab="Marathon" - "labels": { - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province": "true", - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber": "true" - } - ``` - ```yaml tab="File (YAML)" # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header http: diff --git a/docs/content/middlewares/http/ratelimit.md b/docs/content/middlewares/http/ratelimit.md index 2fb11f6ee..48057fe85 100644 --- a/docs/content/middlewares/http/ratelimit.md +++ b/docs/content/middlewares/http/ratelimit.md @@ -40,13 +40,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.average": "100", - "traefik.http.middlewares.test-ratelimit.ratelimit.burst": "50" -} -``` - ```yaml tab="File (YAML)" # Here, an average of 100 requests per second is allowed. # In addition, a burst of 50 requests is allowed. @@ -100,12 +93,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.average": "100", -} -``` - ```yaml tab="File (YAML)" # 100 reqs/s http: @@ -157,13 +144,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.average": "6", - "traefik.http.middlewares.test-ratelimit.ratelimit.period": "1m", -} -``` - ```yaml tab="File (YAML)" # 6 reqs/minute http: @@ -207,12 +187,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.burst": "100", -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -275,12 +249,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth": "2" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -364,12 +332,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -413,12 +375,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername": "username" -} -``` - ```yaml tab="File (YAML)" http: middlewares: @@ -459,12 +415,6 @@ spec: - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost": "true" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/http/redirectregex.md b/docs/content/middlewares/http/redirectregex.md index 74f0e3c23..fe4da4b30 100644 --- a/docs/content/middlewares/http/redirectregex.md +++ b/docs/content/middlewares/http/redirectregex.md @@ -43,13 +43,6 @@ spec: - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-redirectregex.redirectregex.regex": "^http://localhost/(.*)", - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement": "http://mydomain/${1}" -} -``` - ```yaml tab="File (YAML)" # Redirect with domain replacement http: diff --git a/docs/content/middlewares/http/redirectscheme.md b/docs/content/middlewares/http/redirectscheme.md index 841ec018b..14e715add 100644 --- a/docs/content/middlewares/http/redirectscheme.md +++ b/docs/content/middlewares/http/redirectscheme.md @@ -51,13 +51,6 @@ labels: - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https" - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true" -} -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -108,13 +101,6 @@ labels: - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" ``` -```json tab="Marathon" -"labels": { - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true" -} -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -160,12 +146,6 @@ labels: - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https" -} -``` - ```yaml tab="File (YAML)" # Redirect to https http: @@ -212,13 +192,6 @@ labels: - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443" ``` -```json tab="Marathon" -"labels": { - - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port": "443" -} -``` - ```yaml tab="File (YAML)" # Redirect to https http: diff --git a/docs/content/middlewares/http/replacepath.md b/docs/content/middlewares/http/replacepath.md index e4d138c2c..f2ddf0758 100644 --- a/docs/content/middlewares/http/replacepath.md +++ b/docs/content/middlewares/http/replacepath.md @@ -38,12 +38,6 @@ spec: - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-replacepath.replacepath.path": "/foo" -} -``` - ```yaml tab="File (YAML)" # Replace the path with /foo http: diff --git a/docs/content/middlewares/http/replacepathregex.md b/docs/content/middlewares/http/replacepathregex.md index a2fd561bd..1acd76591 100644 --- a/docs/content/middlewares/http/replacepathregex.md +++ b/docs/content/middlewares/http/replacepathregex.md @@ -41,13 +41,6 @@ spec: - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex": "^/foo/(.*)", - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement": "/bar/$1" -} -``` - ```yaml tab="File (YAML)" # Replace path with regex http: diff --git a/docs/content/middlewares/http/retry.md b/docs/content/middlewares/http/retry.md index 2a3288eac..187d107a6 100644 --- a/docs/content/middlewares/http/retry.md +++ b/docs/content/middlewares/http/retry.md @@ -43,13 +43,6 @@ spec: - "traefik.http.middlewares.test-retry.retry.initialinterval=100ms" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-retry.retry.attempts": "4", - "traefik.http.middlewares.test-retry.retry.initialinterval": "100ms", -} -``` - ```yaml tab="File (YAML)" # Retry 4 times with exponential backoff http: diff --git a/docs/content/middlewares/http/stripprefix.md b/docs/content/middlewares/http/stripprefix.md index f84735cb5..135f7e08a 100644 --- a/docs/content/middlewares/http/stripprefix.md +++ b/docs/content/middlewares/http/stripprefix.md @@ -40,12 +40,6 @@ spec: - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes": "/foobar,/fiibar" -} -``` - ```yaml tab="File (YAML)" # Strip prefix /foobar and /fiibar http: diff --git a/docs/content/middlewares/http/stripprefixregex.md b/docs/content/middlewares/http/stripprefixregex.md index 1a3ec09e6..f6e58d871 100644 --- a/docs/content/middlewares/http/stripprefixregex.md +++ b/docs/content/middlewares/http/stripprefixregex.md @@ -32,12 +32,6 @@ spec: - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex": "/foo/[a-z0-9]+/[0-9]+/" -} -``` - ```yaml tab="File (YAML)" http: middlewares: diff --git a/docs/content/middlewares/overview.md b/docs/content/middlewares/overview.md index 09e17278e..eeb70ea4f 100644 --- a/docs/content/middlewares/overview.md +++ b/docs/content/middlewares/overview.md @@ -66,13 +66,6 @@ spec: - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" ``` -```json tab="Marathon" -"labels": { - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", - "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" -} -``` - ```yaml tab="File (YAML)" # As YAML Configuration File http: diff --git a/docs/content/middlewares/tcp/inflightconn.md b/docs/content/middlewares/tcp/inflightconn.md index 2550181df..9619cd63e 100644 --- a/docs/content/middlewares/tcp/inflightconn.md +++ b/docs/content/middlewares/tcp/inflightconn.md @@ -27,12 +27,6 @@ spec: - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" ``` -```json tab="Marathon" -"labels": { - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount": "10" -} -``` - ```yaml tab="File (YAML)" # Limiting to 10 simultaneous connections. tcp: diff --git a/docs/content/middlewares/tcp/ipallowlist.md b/docs/content/middlewares/tcp/ipallowlist.md index 25730eb1e..fad1f9cbf 100644 --- a/docs/content/middlewares/tcp/ipallowlist.md +++ b/docs/content/middlewares/tcp/ipallowlist.md @@ -35,12 +35,6 @@ spec: - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" ``` -```json tab="Marathon" -"labels": { - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32,192.168.1.7" -} -``` - ```toml tab="File (TOML)" # Accepts request from defined IP [tcp.middlewares] diff --git a/docs/content/middlewares/tcp/overview.md b/docs/content/middlewares/tcp/overview.md index 8fde185e9..dfbdd3f9b 100644 --- a/docs/content/middlewares/tcp/overview.md +++ b/docs/content/middlewares/tcp/overview.md @@ -70,13 +70,6 @@ spec: - "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@consulcatalog" ``` -```json tab="Marathon" -"labels": { - "traefik.tcp.middlewares.foo-ip-allowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7", - "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@marathon" -} -``` - ```toml tab="File (TOML)" # As TOML Configuration File [tcp.routers] diff --git a/docs/content/migration/v2-to-v3.md b/docs/content/migration/v2-to-v3.md index e729d69b3..6c8d36e5e 100644 --- a/docs/content/migration/v2-to-v3.md +++ b/docs/content/migration/v2-to-v3.md @@ -26,7 +26,7 @@ In v3, the reported status code for gRPC requests is now the value of the `Grpc- - The `pilot` option has been removed from the static configuration. - The `tracing.datadog.globaltag` option has been removed. - The `namespace` option of Consul, Consul Catalog and Nomad providers has been removed. -- The `tls.caOptional` option has been removed from the ForwardAuth middleware, as well as from the HTTP, Consul, Etcd, Redis, ZooKeeper, Marathon, Consul Catalog, and Docker providers. +- The `tls.caOptional` option has been removed from the ForwardAuth middleware, as well as from the HTTP, Consul, Etcd, Redis, ZooKeeper, Consul Catalog, and Docker providers. - `sslRedirect`, `sslTemporaryRedirect`, `sslHost`, `sslForceHost` and `featurePolicy` options of the Headers middleware have been removed. - The `forceSlash` option of the StripPrefix middleware has been removed. - the `preferServerCipherSuites` option has been removed. @@ -72,3 +72,7 @@ In v3, the rancher v1 provider has been removed because Rancher v1 is [no longer Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](../providers/kubernetes-crd.md) directly. + +## Marathon provider + +In v3, the Marathon provider has been removed. diff --git a/docs/content/operations/include-api-examples.md b/docs/content/operations/include-api-examples.md index 12ef27edb..aa49dae33 100644 --- a/docs/content/operations/include-api-examples.md +++ b/docs/content/operations/include-api-examples.md @@ -51,15 +51,6 @@ spec: - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" ``` -```json tab="Marathon" -"labels": { - "traefik.http.routers.api.rule": "Host(`traefik.example.com`)", - "traefik.http.routers.api.service": "api@internal", - "traefik.http.routers.api.middlewares": "auth", - "traefik.http.middlewares.auth.basicauth.users": "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" -} -``` - ```yaml tab="File (YAML)" # Dynamic Configuration http: diff --git a/docs/content/operations/include-dashboard-examples.md b/docs/content/operations/include-dashboard-examples.md index da8d0d8ae..9d90c42c4 100644 --- a/docs/content/operations/include-dashboard-examples.md +++ b/docs/content/operations/include-dashboard-examples.md @@ -51,15 +51,6 @@ spec: - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" ``` -```json tab="Marathon" -"labels": { - "traefik.http.routers.dashboard.rule": "Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))", - "traefik.http.routers.dashboard.service": "api@internal", - "traefik.http.routers.dashboard.middlewares": "auth", - "traefik.http.middlewares.auth.basicauth.users": "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" -} -``` - ```yaml tab="File (YAML)" # Dynamic Configuration http: diff --git a/docs/content/providers/marathon.md b/docs/content/providers/marathon.md deleted file mode 100644 index a0ab85ccb..000000000 --- a/docs/content/providers/marathon.md +++ /dev/null @@ -1,583 +0,0 @@ ---- -title: "Traefik Configuration for Marathon" -description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation to learn how." ---- - -# Traefik & Marathon - -Traefik can be configured to use Marathon as a provider. -{: .subtitle } - -For additional information, refer to [Marathon user guide](../user-guides/marathon.md). - -## Configuration Examples - -??? example "Configuring Marathon & Deploying / Exposing Applications" - - Enabling the Marathon provider - - ```yaml tab="File (YAML)" - providers: - marathon: {} - ``` - - ```toml tab="File (TOML)" - [providers.marathon] - ``` - - ```bash tab="CLI" - --providers.marathon=true - ``` - - Attaching labels to Marathon applications - - ```json - { - "id": "/whoami", - "container": { - "type": "DOCKER", - "docker": { - "image": "traefik/whoami", - "network": "BRIDGE", - "portMappings": [ - { - "containerPort": 80, - "hostPort": 0, - "protocol": "tcp" - } - ] - } - }, - "labels": { - "traefik.http.Routers.app.Rule": "PathPrefix(`/app`)" - } - } - ``` - -## Routing Configuration - -See the dedicated section in [routing](../routing/providers/marathon.md). - -## Provider Configuration - -### `basic` - -_Optional_ - -Enables Marathon basic authentication. - -```yaml tab="File (YAML)" -providers: - marathon: - basic: - httpBasicAuthUser: foo - httpBasicPassword: bar -``` - -```toml tab="File (TOML)" -[providers.marathon.basic] - httpBasicAuthUser = "foo" - httpBasicPassword = "bar" -``` - -```bash tab="CLI" ---providers.marathon.basic.httpbasicauthuser=foo ---providers.marathon.basic.httpbasicpassword=bar -``` - -### `dcosToken` - -_Optional_ - -Datacenter Operating System (DCOS) Token for DCOS environment. - -If set, it overrides the Authorization header. - -```toml tab="File (YAML)" -providers: - marathon: - dcosToken: "xxxxxx" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - dcosToken = "xxxxxx" - # ... -``` - -```bash tab="CLI" ---providers.marathon.dcosToken=xxxxxx -``` - -### `defaultRule` - -_Optional, Default=```Host(`{{ normalize .Name }}`)```_ - -The default host rule for all services. - -For a given application, if no routing rule was defined by a label, it is defined by this `defaultRule` instead. - -It must be a valid [Go template](https://pkg.go.dev/text/template/), -and can include [sprig template functions](https://masterminds.github.io/sprig/). - -The app ID can be accessed with the `Name` identifier, -and the template has access to all the labels defined on this Marathon application. - -```yaml tab="File (YAML)" -providers: - marathon: - defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)" - # ... -``` - -```bash tab="CLI" ---providers.marathon.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`) -# ... -``` - -### `dialerTimeout` - -_Optional, Default=5s_ - -Amount of time the Marathon provider should wait before timing out, -when trying to open a TCP connection to a Marathon master. - -The value of `dialerTimeout` should be provided in seconds or as a valid duration format, -see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). - -```yaml tab="File (YAML)" -providers: - marathon: - dialerTimeout: "10s" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - dialerTimeout = "10s" - # ... -``` - -```bash tab="CLI" ---providers.marathon.dialerTimeout=10s -``` - -### `endpoint` - -_Optional, Default=http://127.0.0.1:8080_ - -Marathon server endpoint. - -You can optionally specify multiple endpoints. - -```yaml tab="File (YAML)" -providers: - marathon: - endpoint: "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - endpoint = "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080" - # ... -``` - -```bash tab="CLI" ---providers.marathon.endpoint=http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080 -``` - -### `exposedByDefault` - -_Optional, Default=true_ - -Exposes Marathon applications by default through Traefik. - -If set to `false`, applications that do not have a `traefik.enable=true` label are ignored from the resulting routing configuration. - -For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). - -```yaml tab="File (YAML)" -providers: - marathon: - exposedByDefault: false - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - exposedByDefault = false - # ... -``` - -```bash tab="CLI" ---providers.marathon.exposedByDefault=false -# ... -``` - -### `constraints` - -_Optional, Default=""_ - -The `constraints` option can be set to an expression that Traefik matches against the application labels to determine whether -to create any route for that application. If none of the application labels match the expression, no route for that application is -created. In addition, the expression is also matched against the application constraints, such as described -in [Marathon constraints](https://mesosphere.github.io/marathon/docs/constraints.html). -If the expression is empty, all detected applications are included. - -The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as the usual boolean logic. -In addition, to match against Marathon constraints, the function `MarathonConstraint("field:operator:value")` can be used, where the field, operator, and value parts are concatenated in a single string using the `:` separator. - -??? example "Constraints Expression Examples" - - ```toml - # Includes only applications having a label with key `a.label.name` and value `foo` - constraints = "Label(`a.label.name`, `foo`)" - ``` - - ```toml - # Excludes applications having any label with key `a.label.name` and value `foo` - constraints = "!Label(`a.label.name`, `value`)" - ``` - - ```toml - # With logical AND. - constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)" - ``` - - ```toml - # With logical OR. - constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)" - ``` - - ```toml - # With logical AND and OR, with precedence set by parentheses. - constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))" - ``` - - ```toml - # Includes only applications having a label with key `a.label.name` and a value matching the `a.+` regular expression. - constraints = "LabelRegex(`a.label.name`, `a.+`)" - ``` - - ```toml - # Includes only applications having a Marathon constraint with field `A`, operator `B`, and value `C`. - constraints = "MarathonConstraint(`A:B:C`)" - ``` - - ```toml - # Uses both Marathon constraint and application label with logical operator. - constraints = "MarathonConstraint(`A:B:C`) && Label(`a.label.name`, `value`)" - ``` - -For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). - -```yaml tab="File (YAML)" -providers: - marathon: - constraints: "Label(`a.label.name`,`foo`)" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - constraints = "Label(`a.label.name`,`foo`)" - # ... -``` - -```bash tab="CLI" ---providers.marathon.constraints=Label(`a.label.name`,`foo`) -# ... -``` - -### `forceTaskHostname` - -_Optional, Default=false_ - -By default, the task IP address (as returned by the Marathon API) is used as backend server if an IP-per-task configuration can be found; -otherwise, the name of the host running the task is used. -The latter behavior can be enforced by setting this option to `true`. - -```yaml tab="File (YAML)" -providers: - marathon: - forceTaskHostname: true - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - forceTaskHostname = true - # ... -``` - -```bash tab="CLI" ---providers.marathon.forceTaskHostname=true -# ... -``` - -### `keepAlive` - -_Optional, Default=10s_ - -Set the TCP Keep Alive duration for the Marathon HTTP Client. -The value of `keepAlive` should be provided in seconds or as a valid duration format, -see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). - -```yaml tab="File (YAML)" -providers: - marathon: - keepAlive: "30s" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - keepAlive = "30s" - # ... -``` - -```bash tab="CLI" ---providers.marathon.keepAlive=30s -# ... -``` - -### `respectReadinessChecks` - -_Optional, Default=false_ - -Applications may define readiness checks which are probed by Marathon during deployments periodically, and these check results are exposed via the API. -Enabling `respectReadinessChecks` causes Traefik to filter out tasks whose readiness checks have not succeeded. -Note that the checks are only valid during deployments. - -See the Marathon guide for details. - -```yaml tab="File (YAML)" -providers: - marathon: - respectReadinessChecks: true - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - respectReadinessChecks = true - # ... -``` - -```bash tab="CLI" ---providers.marathon.respectReadinessChecks=true -# ... -``` - -### `responseHeaderTimeout` - -_Optional, Default=60s_ - -Amount of time the Marathon provider should wait before timing out when waiting for the first response header -from a Marathon master. - -The value of `responseHeaderTimeout` should be provided in seconds or as a valid duration format, -see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). - -```yaml tab="File (YAML)" -providers: - marathon: - responseHeaderTimeout: "66s" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - responseHeaderTimeout = "66s" - # ... -``` - -```bash tab="CLI" ---providers.marathon.responseHeaderTimeout=66s -# ... -``` - -### `tls` - -_Optional_ - -Defines the TLS configuration used for the secure connection to Marathon. - -#### `ca` - -`ca` is the path to the certificate authority used for the secure connection to Marathon, -it defaults to the system bundle. - -```yaml tab="File (YAML)" -providers: - marathon: - tls: - ca: path/to/ca.crt -``` - -```toml tab="File (TOML)" -[providers.marathon.tls] - ca = "path/to/ca.crt" -``` - -```bash tab="CLI" ---providers.marathon.tls.ca=path/to/ca.crt -``` - -#### `cert` - -_Optional_ - -`cert` is the path to the public certificate used for the secure connection to Marathon. -When using this option, setting the `key` option is required. - -```yaml tab="File (YAML)" -providers: - marathon: - tls: - cert: path/to/foo.cert - key: path/to/foo.key -``` - -```toml tab="File (TOML)" -[providers.marathon.tls] - cert = "path/to/foo.cert" - key = "path/to/foo.key" -``` - -```bash tab="CLI" ---providers.marathon.tls.cert=path/to/foo.cert ---providers.marathon.tls.key=path/to/foo.key -``` - -#### `key` - -_Optional_ - -`key` is the path to the private key used for the secure connection to Marathon. -When using this option, setting the `cert` option is required. - -```yaml tab="File (YAML)" -providers: - marathon: - tls: - cert: path/to/foo.cert - key: path/to/foo.key -``` - -```toml tab="File (TOML)" -[providers.marathon.tls] - cert = "path/to/foo.cert" - key = "path/to/foo.key" -``` - -```bash tab="CLI" ---providers.marathon.tls.cert=path/to/foo.cert ---providers.marathon.tls.key=path/to/foo.key -``` - -#### `insecureSkipVerify` - -_Optional, Default=false_ - -If `insecureSkipVerify` is `true`, the TLS connection to Marathon accepts any certificate presented by the server regardless of the hostnames it covers. - -```yaml tab="File (YAML)" -providers: - marathon: - tls: - insecureSkipVerify: true -``` - -```toml tab="File (TOML)" -[providers.marathon.tls] - insecureSkipVerify = true -``` - -```bash tab="CLI" ---providers.marathon.tls.insecureSkipVerify=true -``` - -### `tlsHandshakeTimeout` - -_Optional, Default=5s_ - -Amount of time the Marathon provider should wait before timing out, -when waiting for the TLS handshake to complete. - -The value of `tlsHandshakeTimeout` should be provided in seconds or as a valid duration format, -see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). - -```yaml tab="File (YAML)" -providers: - marathon: - tlsHandshakeTimeout: "10s" - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - tlsHandshakeTimeout = "10s" - # ... -``` - -```bash tab="CLI" ---providers.marathon.tlsHandshakeTimeout=10s -# ... -``` - -### `trace` - -_Optional, Default=false_ - -Displays additional provider logs when available. - -```yaml tab="File (YAML)" -providers: - marathon: - trace: true - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - trace = true - # ... -``` - -```bash tab="CLI" ---providers.marathon.trace=true -# ... -``` - -### `watch` - -_Optional, Default=true_ - -When set to `true`, watches for Marathon changes. - -```yaml tab="File (YAML)" -providers: - marathon: - watch: false - # ... -``` - -```toml tab="File (TOML)" -[providers.marathon] - watch = false - # ... -``` - -```bash tab="CLI" ---providers.marathon.watch=false -# ... -``` diff --git a/docs/content/providers/overview.md b/docs/content/providers/overview.md index 9589ce21d..47d6178e8 100644 --- a/docs/content/providers/overview.md +++ b/docs/content/providers/overview.md @@ -141,7 +141,6 @@ Below is the list of the currently supported providers in Traefik. | [Consul Catalog](./consul-catalog.md) | Orchestrator | Label | `consulcatalog` | | [Nomad](./nomad.md) | Orchestrator | Label | `nomad` | | [ECS](./ecs.md) | Orchestrator | Label | `ecs` | -| [Marathon](./marathon.md) | Orchestrator | Label | `marathon` | | [File](./file.md) | Manual | YAML/TOML format | `file` | | [Consul](./consul.md) | KV | KV | `consul` | | [Etcd](./etcd.md) | KV | KV | `etcd` | @@ -215,7 +214,6 @@ List of providers that support these features: - [ECS](./ecs.md#exposedbydefault) - [Consul Catalog](./consul-catalog.md#exposedbydefault) - [Nomad](./nomad.md#exposedbydefault) -- [Marathon](./marathon.md#exposedbydefault) ### Constraints @@ -225,7 +223,6 @@ List of providers that support constraints: - [ECS](./ecs.md#constraints) - [Consul Catalog](./consul-catalog.md#constraints) - [Nomad](./nomad.md#constraints) -- [Marathon](./marathon.md#constraints) - [Kubernetes CRD](./kubernetes-crd.md#labelselector) - [Kubernetes Ingress](./kubernetes-ingress.md#labelselector) - [Kubernetes Gateway](./kubernetes-gateway.md#labelselector) diff --git a/docs/content/reference/dynamic-configuration/marathon-labels.json b/docs/content/reference/dynamic-configuration/marathon-labels.json deleted file mode 100644 index afac8bb13..000000000 --- a/docs/content/reference/dynamic-configuration/marathon-labels.json +++ /dev/null @@ -1,210 +0,0 @@ -"traefik.http.middlewares.middleware00.addprefix.prefix": "foobar", -"traefik.http.middlewares.middleware01.basicauth.headerfield": "foobar", -"traefik.http.middlewares.middleware01.basicauth.realm": "foobar", -"traefik.http.middlewares.middleware01.basicauth.removeheader": "true", -"traefik.http.middlewares.middleware01.basicauth.users": "foobar, foobar", -"traefik.http.middlewares.middleware01.basicauth.usersfile": "foobar", -"traefik.http.middlewares.middleware02.buffering.maxrequestbodybytes": "42", -"traefik.http.middlewares.middleware02.buffering.maxresponsebodybytes": "42", -"traefik.http.middlewares.middleware02.buffering.memrequestbodybytes": "42", -"traefik.http.middlewares.middleware02.buffering.memresponsebodybytes": "42", -"traefik.http.middlewares.middleware02.buffering.retryexpression": "foobar", -"traefik.http.middlewares.middleware03.chain.middlewares": "foobar, foobar", -"traefik.http.middlewares.middleware04.circuitbreaker.expression": "foobar", -"traefik.http.middlewares.middleware04.circuitbreaker.checkperiod": "42s", -"traefik.http.middlewares.middleware04.circuitbreaker.fallbackduration": "42s", -"traefik.http.middlewares.middleware04.circuitbreaker.recoveryduration": "42s", -"traefik.http.middlewares.middleware05.compress": "true", -"traefik.http.middlewares.middleware05.compress.excludedcontenttypes": "foobar, foobar", -"traefik.http.middlewares.middleware05.compress.minresponsebodybytes": "42", -"traefik.http.middlewares.middleware06.contenttype": "true", -"traefik.http.middlewares.middleware07.digestauth.headerfield": "foobar", -"traefik.http.middlewares.middleware07.digestauth.realm": "foobar", -"traefik.http.middlewares.middleware07.digestauth.removeheader": "true", -"traefik.http.middlewares.middleware07.digestauth.users": "foobar, foobar", -"traefik.http.middlewares.middleware07.digestauth.usersfile": "foobar", -"traefik.http.middlewares.middleware08.errors.query": "foobar", -"traefik.http.middlewares.middleware08.errors.service": "foobar", -"traefik.http.middlewares.middleware08.errors.status": "foobar, foobar", -"traefik.http.middlewares.middleware09.forwardauth.address": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.authrequestheaders": "foobar, foobar", -"traefik.http.middlewares.middleware09.forwardauth.authresponseheaders": "foobar, foobar", -"traefik.http.middlewares.middleware09.forwardauth.authresponseheadersregex": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.tls.ca": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.tls.cert": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.tls.insecureskipverify": "true", -"traefik.http.middlewares.middleware09.forwardauth.tls.key": "foobar", -"traefik.http.middlewares.middleware09.forwardauth.trustforwardheader": "true", -"traefik.http.middlewares.middleware10.headers.accesscontrolallowcredentials": "true", -"traefik.http.middlewares.middleware10.headers.accesscontrolallowheaders": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolallowmethods": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlist": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlistregex": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolexposeheaders": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.accesscontrolmaxage": "42", -"traefik.http.middlewares.middleware10.headers.addvaryheader": "true", -"traefik.http.middlewares.middleware10.headers.allowedhosts": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.browserxssfilter": "true", -"traefik.http.middlewares.middleware10.headers.contentsecuritypolicy": "foobar", -"traefik.http.middlewares.middleware10.headers.contenttypenosniff": "true", -"traefik.http.middlewares.middleware10.headers.custombrowserxssvalue": "foobar", -"traefik.http.middlewares.middleware10.headers.customframeoptionsvalue": "foobar", -"traefik.http.middlewares.middleware10.headers.customrequestheaders.name0": "foobar", -"traefik.http.middlewares.middleware10.headers.customrequestheaders.name1": "foobar", -"traefik.http.middlewares.middleware10.headers.customresponseheaders.name0": "foobar", -"traefik.http.middlewares.middleware10.headers.customresponseheaders.name1": "foobar", -"traefik.http.middlewares.middleware10.headers.forcestsheader": "true", -"traefik.http.middlewares.middleware10.headers.framedeny": "true", -"traefik.http.middlewares.middleware10.headers.hostsproxyheaders": "foobar, foobar", -"traefik.http.middlewares.middleware10.headers.isdevelopment": "true", -"traefik.http.middlewares.middleware10.headers.permissionspolicy": "foobar", -"traefik.http.middlewares.middleware10.headers.publickey": "foobar", -"traefik.http.middlewares.middleware10.headers.referrerpolicy": "foobar", -"traefik.http.middlewares.middleware10.headers.sslproxyheaders.name0": "foobar", -"traefik.http.middlewares.middleware10.headers.sslproxyheaders.name1": "foobar", -"traefik.http.middlewares.middleware10.headers.stsincludesubdomains": "true", -"traefik.http.middlewares.middleware10.headers.stspreload": "true", -"traefik.http.middlewares.middleware10.headers.stsseconds": "42", -"traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.depth": "42", -"traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.excludedips": "foobar, foobar", -"traefik.http.middlewares.middleware11.ipallowlist.sourcerange": "foobar, foobar", -"traefik.http.middlewares.middleware12.inflightreq.amount": "42", -"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.depth": "42", -"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.excludedips": "foobar, foobar", -"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.requestheadername": "foobar", -"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.requesthost": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.commonname": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.country": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.domaincomponent": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.locality": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.organization": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.province": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.serialnumber": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.notafter": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.notbefore": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.sans": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.serialnumber": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.commonname": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.country": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.domaincomponent": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.locality": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organization": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organizationalunit": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.province": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.serialnumber": "true", -"traefik.http.middlewares.middleware13.passtlsclientcert.pem": "true", -"traefik.http.middlewares.middleware14.plugin.foobar.foo": "bar", -"traefik.http.middlewares.middleware15.ratelimit.average": "42", -"traefik.http.middlewares.middleware15.ratelimit.burst": "42", -"traefik.http.middlewares.middleware15.ratelimit.period": "42", -"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.ipstrategy.depth": "42", -"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.ipstrategy.excludedips": "foobar, foobar", -"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.requestheadername": "foobar", -"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.requesthost": "true", -"traefik.http.middlewares.middleware16.redirectregex.permanent": "true", -"traefik.http.middlewares.middleware16.redirectregex.regex": "foobar", -"traefik.http.middlewares.middleware16.redirectregex.replacement": "foobar", -"traefik.http.middlewares.middleware17.redirectscheme.permanent": "true", -"traefik.http.middlewares.middleware17.redirectscheme.port": "foobar", -"traefik.http.middlewares.middleware17.redirectscheme.scheme": "foobar", -"traefik.http.middlewares.middleware18.replacepath.path": "foobar", -"traefik.http.middlewares.middleware19.replacepathregex.regex": "foobar", -"traefik.http.middlewares.middleware19.replacepathregex.replacement": "foobar", -"traefik.http.middlewares.middleware20.retry.attempts": "42", -"traefik.http.middlewares.middleware20.retry.initialinterval": "42", -"traefik.http.middlewares.middleware21.stripprefix.prefixes": "foobar, foobar", -"traefik.http.middlewares.middleware22.stripprefixregex.regex": "foobar, foobar", -"traefik.http.middlewares.middleware23.grpcweb.alloworigins": "foobar, foobar", -"traefik.http.routers.router0.entrypoints": "foobar, foobar", -"traefik.http.routers.router0.middlewares": "foobar, foobar", -"traefik.http.routers.router0.priority": "42", -"traefik.http.routers.router0.rule": "foobar", -"traefik.http.routers.router0.service": "foobar", -"traefik.http.routers.router0.tls": "true", -"traefik.http.routers.router0.tls.certresolver": "foobar", -"traefik.http.routers.router0.tls.domains[0].main": "foobar", -"traefik.http.routers.router0.tls.domains[0].sans": "foobar, foobar", -"traefik.http.routers.router0.tls.domains[1].main": "foobar", -"traefik.http.routers.router0.tls.domains[1].sans": "foobar, foobar", -"traefik.http.routers.router0.tls.options": "foobar", -"traefik.http.routers.router1.entrypoints": "foobar, foobar", -"traefik.http.routers.router1.middlewares": "foobar, foobar", -"traefik.http.routers.router1.priority": "42", -"traefik.http.routers.router1.rule": "foobar", -"traefik.http.routers.router1.service": "foobar", -"traefik.http.routers.router1.tls": "true", -"traefik.http.routers.router1.tls.certresolver": "foobar", -"traefik.http.routers.router1.tls.domains[0].main": "foobar", -"traefik.http.routers.router1.tls.domains[0].sans": "foobar, foobar", -"traefik.http.routers.router1.tls.domains[1].main": "foobar", -"traefik.http.routers.router1.tls.domains[1].sans": "foobar, foobar", -"traefik.http.routers.router1.tls.options": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.followredirects": "true", -"traefik.http.services.service01.loadbalancer.healthcheck.headers.name0": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.headers.name1": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.hostname": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.interval": "42s", -"traefik.http.services.service01.loadbalancer.healthcheck.path": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.method": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.status": "42", -"traefik.http.services.service01.loadbalancer.healthcheck.port": "42", -"traefik.http.services.service01.loadbalancer.healthcheck.scheme": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.mode": "foobar", -"traefik.http.services.service01.loadbalancer.healthcheck.timeout": "42s", -"traefik.http.services.service01.loadbalancer.passhostheader": "true", -"traefik.http.services.service01.loadbalancer.responseforwarding.flushinterval": "42s", -"traefik.http.services.service01.loadbalancer.serverstransport": "foobar", -"traefik.http.services.service01.loadbalancer.sticky.cookie": "true", -"traefik.http.services.service01.loadbalancer.sticky.cookie.httponly": "true", -"traefik.http.services.service01.loadbalancer.sticky.cookie.name": "foobar", -"traefik.http.services.service01.loadbalancer.sticky.cookie.samesite": "foobar", -"traefik.http.services.service01.loadbalancer.sticky.cookie.secure": "true", -"traefik.http.services.service01.loadbalancer.server.port": "foobar", -"traefik.http.services.service01.loadbalancer.server.scheme": "foobar", -"traefik.tcp.middlewares.tcpmiddleware00.ipallowlist.sourcerange": "foobar, foobar", -"traefik.tcp.middlewares.tcpmiddleware01.inflightconn.amount": "42", -"traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar", -"traefik.tcp.routers.tcprouter0.middlewares": "foobar, foobar", -"traefik.tcp.routers.tcprouter0.rule": "foobar", -"traefik.tcp.routers.tcprouter0.priority": "42", -"traefik.tcp.routers.tcprouter0.service": "foobar", -"traefik.tcp.routers.tcprouter0.tls": "true", -"traefik.tcp.routers.tcprouter0.tls.certresolver": "foobar", -"traefik.tcp.routers.tcprouter0.tls.domains[0].main": "foobar", -"traefik.tcp.routers.tcprouter0.tls.domains[0].sans": "foobar, foobar", -"traefik.tcp.routers.tcprouter0.tls.domains[1].main": "foobar", -"traefik.tcp.routers.tcprouter0.tls.domains[1].sans": "foobar, foobar", -"traefik.tcp.routers.tcprouter0.tls.options": "foobar", -"traefik.tcp.routers.tcprouter0.tls.passthrough": "true", -"traefik.tcp.routers.tcprouter1.entrypoints": "foobar, foobar", -"traefik.tcp.routers.tcprouter1.middlewares": "foobar, foobar", -"traefik.tcp.routers.tcprouter1.rule": "foobar", -"traefik.tcp.routers.tcprouter1.priority": "42", -"traefik.tcp.routers.tcprouter1.service": "foobar", -"traefik.tcp.routers.tcprouter1.tls": "true", -"traefik.tcp.routers.tcprouter1.tls.certresolver": "foobar", -"traefik.tcp.routers.tcprouter1.tls.domains[0].main": "foobar", -"traefik.tcp.routers.tcprouter1.tls.domains[0].sans": "foobar, foobar", -"traefik.tcp.routers.tcprouter1.tls.domains[1].main": "foobar", -"traefik.tcp.routers.tcprouter1.tls.domains[1].sans": "foobar, foobar", -"traefik.tcp.routers.tcprouter1.tls.options": "foobar", -"traefik.tcp.routers.tcprouter1.tls.passthrough": "true", -"traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version": "42", -"traefik.tcp.services.tcpservice01.loadbalancer.server.port": "foobar", -"traefik.tcp.services.tcpservice01.loadbalancer.server.tls": "true", -"traefik.tcp.services.tcpservice01.loadbalancer.serverstransport": "foobar", -"traefik.udp.routers.udprouter0.entrypoints": "foobar, foobar", -"traefik.udp.routers.udprouter0.service": "foobar", -"traefik.udp.routers.udprouter1.entrypoints": "foobar, foobar", -"traefik.udp.routers.udprouter1.service": "foobar", -"traefik.udp.services.udpservice01.loadbalancer.server.port": "foobar", -"traefik.tls.stores.Store0.defaultcertificate.certfile": "foobar", -"traefik.tls.stores.Store0.defaultcertificate.keyfile": "foobar", -"traefik.tls.stores.Store0.defaultgeneratedcert.domain.main": "foobar", -"traefik.tls.stores.Store0.defaultgeneratedcert.domain.sans": "foobar, foobar", -"traefik.tls.stores.Store0.defaultgeneratedcert.resolver": "foobar", -"traefik.tls.stores.Store1.defaultcertificate.certfile": "foobar", -"traefik.tls.stores.Store1.defaultcertificate.keyfile": "foobar", -"traefik.tls.stores.Store1.defaultgeneratedcert.domain.main": "foobar", -"traefik.tls.stores.Store1.defaultgeneratedcert.domain.sans": "foobar, foobar", -"traefik.tls.stores.Store1.defaultgeneratedcert.resolver": "foobar", diff --git a/docs/content/reference/dynamic-configuration/marathon.json b/docs/content/reference/dynamic-configuration/marathon.json deleted file mode 100644 index 131344a7e..000000000 --- a/docs/content/reference/dynamic-configuration/marathon.json +++ /dev/null @@ -1,2 +0,0 @@ -"traefik.enable": "true", -"traefik.marathon.ipaddressidx": "42", diff --git a/docs/content/reference/dynamic-configuration/marathon.md b/docs/content/reference/dynamic-configuration/marathon.md deleted file mode 100644 index 0e20679f8..000000000 --- a/docs/content/reference/dynamic-configuration/marathon.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Dynamic Configuration with Marathon Labels" -description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation on the Traefik dynamic configuration with Marathon Labels." ---- - -# Marathon Configuration Reference - -Dynamic configuration with Marathon Labels -{: .subtitle } - -```json -"labels": { - --8<-- "content/reference/dynamic-configuration/marathon.json" - --8<-- "content/reference/dynamic-configuration/marathon-labels.json" -} -``` diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 773f07829..1a95f346b 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -798,66 +798,6 @@ Ingress refresh throttle duration (Default: ```0```) `--providers.kubernetesingress.token`: Kubernetes bearer token (not needed for in-cluster client). -`--providers.marathon`: -Enable Marathon backend with default settings. (Default: ```false```) - -`--providers.marathon.basic.httpbasicauthuser`: -Basic authentication User. - -`--providers.marathon.basic.httpbasicpassword`: -Basic authentication Password. - -`--providers.marathon.constraints`: -Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application. - -`--providers.marathon.dcostoken`: -DCOSToken for DCOS environment, This will override the Authorization header. - -`--providers.marathon.defaultrule`: -Default rule. (Default: ```Host(`{{ normalize .Name }}`)```) - -`--providers.marathon.dialertimeout`: -Set a dialer timeout for Marathon. (Default: ```5```) - -`--providers.marathon.endpoint`: -Marathon server endpoint. You can also specify multiple endpoint for Marathon. (Default: ```http://127.0.0.1:8080```) - -`--providers.marathon.exposedbydefault`: -Expose Marathon apps by default. (Default: ```true```) - -`--providers.marathon.forcetaskhostname`: -Force to use the task's hostname. (Default: ```false```) - -`--providers.marathon.keepalive`: -Set a TCP Keep Alive time. (Default: ```10```) - -`--providers.marathon.respectreadinesschecks`: -Filter out tasks with non-successful readiness checks during deployments. (Default: ```false```) - -`--providers.marathon.responseheadertimeout`: -Set a response header timeout for Marathon. (Default: ```60```) - -`--providers.marathon.tls.ca`: -TLS CA - -`--providers.marathon.tls.cert`: -TLS cert - -`--providers.marathon.tls.insecureskipverify`: -TLS insecure skip verify (Default: ```false```) - -`--providers.marathon.tls.key`: -TLS key - -`--providers.marathon.tlshandshaketimeout`: -Set a TLS handshake timeout for Marathon. (Default: ```5```) - -`--providers.marathon.trace`: -Display additional provider logs. (Default: ```false```) - -`--providers.marathon.watch`: -Watch provider. (Default: ```true```) - `--providers.nomad`: Enable Nomad backend with default settings. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 38f8bcba9..065ae8bff 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -798,66 +798,6 @@ Ingress refresh throttle duration (Default: ```0```) `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_TOKEN`: Kubernetes bearer token (not needed for in-cluster client). -`TRAEFIK_PROVIDERS_MARATHON`: -Enable Marathon backend with default settings. (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_BASIC_HTTPBASICAUTHUSER`: -Basic authentication User. - -`TRAEFIK_PROVIDERS_MARATHON_BASIC_HTTPBASICPASSWORD`: -Basic authentication Password. - -`TRAEFIK_PROVIDERS_MARATHON_CONSTRAINTS`: -Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application. - -`TRAEFIK_PROVIDERS_MARATHON_DCOSTOKEN`: -DCOSToken for DCOS environment, This will override the Authorization header. - -`TRAEFIK_PROVIDERS_MARATHON_DEFAULTRULE`: -Default rule. (Default: ```Host(`{{ normalize .Name }}`)```) - -`TRAEFIK_PROVIDERS_MARATHON_DIALERTIMEOUT`: -Set a dialer timeout for Marathon. (Default: ```5```) - -`TRAEFIK_PROVIDERS_MARATHON_ENDPOINT`: -Marathon server endpoint. You can also specify multiple endpoint for Marathon. (Default: ```http://127.0.0.1:8080```) - -`TRAEFIK_PROVIDERS_MARATHON_EXPOSEDBYDEFAULT`: -Expose Marathon apps by default. (Default: ```true```) - -`TRAEFIK_PROVIDERS_MARATHON_FORCETASKHOSTNAME`: -Force to use the task's hostname. (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_KEEPALIVE`: -Set a TCP Keep Alive time. (Default: ```10```) - -`TRAEFIK_PROVIDERS_MARATHON_RESPECTREADINESSCHECKS`: -Filter out tasks with non-successful readiness checks during deployments. (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_RESPONSEHEADERTIMEOUT`: -Set a response header timeout for Marathon. (Default: ```60```) - -`TRAEFIK_PROVIDERS_MARATHON_TLSHANDSHAKETIMEOUT`: -Set a TLS handshake timeout for Marathon. (Default: ```5```) - -`TRAEFIK_PROVIDERS_MARATHON_TLS_CA`: -TLS CA - -`TRAEFIK_PROVIDERS_MARATHON_TLS_CERT`: -TLS cert - -`TRAEFIK_PROVIDERS_MARATHON_TLS_INSECURESKIPVERIFY`: -TLS insecure skip verify (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_TLS_KEY`: -TLS key - -`TRAEFIK_PROVIDERS_MARATHON_TRACE`: -Display additional provider logs. (Default: ```false```) - -`TRAEFIK_PROVIDERS_MARATHON_WATCH`: -Watch provider. (Default: ```true```) - `TRAEFIK_PROVIDERS_NOMAD`: Enable Nomad backend with default settings. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 8e634d9cf..5b68317a9 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -98,28 +98,6 @@ watch = true filename = "foobar" debugLogGeneratedTemplate = true - [providers.marathon] - constraints = "foobar" - trace = true - watch = true - endpoint = "foobar" - defaultRule = "foobar" - exposedByDefault = true - dcosToken = "foobar" - dialerTimeout = "42s" - responseHeaderTimeout = "42s" - tlsHandshakeTimeout = "42s" - keepAlive = "42s" - forceTaskHostname = true - respectReadinessChecks = true - [providers.marathon.tls] - ca = "foobar" - cert = "foobar" - key = "foobar" - insecureSkipVerify = true - [providers.marathon.basic] - httpBasicAuthUser = "foobar" - httpBasicPassword = "foobar" [providers.kubernetesIngress] endpoint = "foobar" token = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 32116d797..1ce4ec6c1 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -105,28 +105,6 @@ providers: watch: true filename: foobar debugLogGeneratedTemplate: true - marathon: - constraints: foobar - trace: true - watch: true - endpoint: foobar - defaultRule: foobar - exposedByDefault: true - dcosToken: foobar - tls: - ca: foobar - cert: foobar - key: foobar - insecureSkipVerify: true - dialerTimeout: 42s - responseHeaderTimeout: 42s - tlsHandshakeTimeout: 42s - keepAlive: 42s - forceTaskHostname: true - basic: - httpBasicAuthUser: foobar - httpBasicPassword: foobar - respectReadinessChecks: true kubernetesIngress: endpoint: foobar token: foobar diff --git a/docs/content/routing/providers/marathon.md b/docs/content/routing/providers/marathon.md deleted file mode 100644 index ea13368ad..000000000 --- a/docs/content/routing/providers/marathon.md +++ /dev/null @@ -1,545 +0,0 @@ ---- -title: "Traefik Routing Configuration for Marathon" -description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation to understand the Traefik routing configuration for Marathon." ---- - -# Traefik & Marathon - -Traefik can be configured to use Marathon as a provider. -{: .subtitle } - -See also [Marathon user guide](../../user-guides/marathon.md). - -## Routing Configuration - -!!! info "Labels" - - - Labels are case insensitive. - - The complete list of labels can be found in [the reference page](../../reference/dynamic-configuration/marathon.md). - -### General - -Traefik creates, for each Marathon application, a corresponding [service](../services/index.md) and [router](../routers/index.md). - -The Service automatically gets a server per instance of the application, -and the router automatically gets a rule defined by defaultRule (if no rule for it was defined in labels). - -#### Service definition - ---8<-- "content/routing/providers/service-by-label.md" - -??? example "Automatic service assignment with labels" - - Service myservice gets automatically assigned to router myproxy. - - ```json - labels: { - "traefik.http.routers.myproxy.rule": "Host(`example.net`)", - "traefik.http.services.myservice.loadbalancer.server.port": "80" - } - ``` - -??? example "Automatic service creation and assignment with labels" - - No service specified or defined, and yet one gets automatically created. - and assigned to router myproxy. - - ```json - labels: { - "traefik.http.routers.myproxy.rule": "Host(`example.net`)" - } - ``` - -### Routers - -To update the configuration of the Router automatically attached to the application, -add labels starting with `traefik.http.routers.{router-name-of-your-choice}.` and followed by the option you want to change. - -For example, to change the routing rule, you could add the label ```"traefik.http.routers.routername.rule": "Host(`example.com`)"```. - -!!! warning "The character `@` is not authorized in the router name ``." - -??? info "`traefik.http.routers..rule`" - - See [rule](../routers/index.md#rule) for more information. - - ```json - "traefik.http.routers.myrouter.rule": "Host(`example.com`)" - ``` - -??? info "`traefik.http.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints) for more information. - - ```json - "traefik.http.routers.myrouter.entrypoints": "ep1,ep2" - ``` - -??? info "`traefik.http.routers..middlewares`" - - See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information. - - ```json - "traefik.http.routers.myrouter.middlewares": "auth,prefix,cb" - ``` - -??? info "`traefik.http.routers..service`" - - See [rule](../routers/index.md#service) for more information. - - ```json - "traefik.http.routers.myrouter.service": "myservice" - ``` - -??? info "`traefik.http.routers..tls`" - - See [tls](../routers/index.md#tls) for more information. - - ```json - "traefik.http.routers.myrouter.tls": "true" - ``` - -??? info "`traefik.http.routers..tls.certresolver`" - - See [certResolver](../routers/index.md#certresolver) for more information. - - ```json - "traefik.http.routers.myrouter.tls.certresolver": "myresolver" - ``` - -??? info "`traefik.http.routers..tls.domains[n].main`" - - See [domains](../routers/index.md#domains) for more information. - - ```json - "traefik.http.routers.myrouter.tls.domains[0].main": "example.org" - ``` - -??? info "`traefik.http.routers..tls.domains[n].sans`" - - See [domains](../routers/index.md#domains) for more information. - - ```json - "traefik.http.routers.myrouter.tls.domains[0].sans": "test.example.org,dev.example.org" - ``` - -??? info "`traefik.http.routers..tls.options`" - - See [options](../routers/index.md#options) for more information. - - ```json - "traefik.http.routers.myrouter.tls.options": "foobar" - ``` - -??? info "`traefik.http.routers..priority`" - - See [priority](../routers/index.md#priority) for more information. - - ```json - "traefik.http.routers.myrouter.priority": "42" - ``` - -### Services - -To update the configuration of the Service automatically attached to the container, -add labels starting with `traefik.http.services.{service-name-of-your-choice}.`, followed by the option you want to change. - -For example, to change the passHostHeader behavior, you'd add the label `"traefik.http.services.servicename.loadbalancer.passhostheader": "false"`. - -!!! warning "The character `@` is not authorized in the service name ``." - -??? info "`traefik.http.services..loadbalancer.server.port`" - - Registers a port. - Useful when the container exposes multiples ports. - - ```json - "traefik.http.services.myservice.loadbalancer.server.port": "8080" - ``` - -??? info "`traefik.http.services..loadbalancer.server.scheme`" - - Overrides the default scheme. - - ```json - "traefik.http.services.myservice.loadbalancer.server.scheme": "http" - ``` - -??? info "`traefik.http.services..loadbalancer.serverstransport`" - - Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. - See [serverstransport](../services/index.md#serverstransport) for more information. - - ```json - "traefik.http.services..loadbalancer.serverstransport": "foobar@file" - ``` - -??? info "`traefik.http.services..loadbalancer.passhostheader`" - - See [pass Host header](../services/index.md#pass-host-header) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.passhostheader": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.headers.`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.headers.X-Foo": "foobar" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.hostname`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.hostname": "example.org" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.interval`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.interval": "10" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.path`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.path": "/foo" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.method`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.method": "foobar" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.status`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.status": "42" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.port`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.port": "42" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.scheme`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.scheme": "http" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.timeout`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.timeout": "10" - ``` - -??? info "`traefik.http.services..loadbalancer.healthcheck.followredirects`" - - See [health check](../services/index.md#health-check) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.healthcheck.followredirects": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.httponly`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie.httponly": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.name`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie.name": "foobar" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.secure`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie.secure": "true" - ``` - -??? info "`traefik.http.services..loadbalancer.sticky.cookie.samesite`" - - See [sticky sessions](../services/index.md#sticky-sessions) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite": "none" - ``` - -??? info "`traefik.http.services..loadbalancer.responseforwarding.flushinterval`" - - See [response forwarding](../services/index.md#response-forwarding) for more information. - - ```json - "traefik.http.services.myservice.loadbalancer.responseforwarding.flushinterval": "10" - ``` - -### Middleware - -You can declare pieces of middleware using labels starting with `traefik.http.middlewares.{middleware-name-of-your-choice}.`, followed by the middleware type/options. - -For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `"traefik.http.middlewares.my-redirect.redirectscheme.scheme": "https"`. - -More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). - -!!! warning "The character `@` is not authorized in the middleware name." - -??? example "Declaring and Referencing a Middleware" - - ```json - { - ... - "labels": { - "traefik.http.middlewares.my-redirect.redirectscheme.scheme": "https", - "traefik.http.routers.my-container.middlewares": "my-redirect" - } - } - ``` - -!!! warning "Conflicts in Declaration" - - If you declare multiple middleware with the same name but with different parameters, the middleware fails to be declared. - -### TCP - -You can declare TCP Routers and/or Services using labels. - -??? example "Declaring TCP Routers and Services" - - ```json - { - ... - "labels": { - "traefik.tcp.routers.my-router.rule": "HostSNI(`example.com`)", - "traefik.tcp.routers.my-router.tls": "true", - "traefik.tcp.services.my-service.loadbalancer.server.port": "4123" - } - } - ``` - -!!! warning "TCP and HTTP" - - If you declare a TCP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no TCP Router/Service is defined). - You can declare both a TCP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually). - -#### TCP Routers - -??? info "`traefik.tcp.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.entrypoints": "ep1,ep2" - ``` - - -??? info "`traefik.tcp.routers..rule`" - - See [rule](../routers/index.md#rule_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.rule": "HostSNI(`example.com`)" - ``` - -??? info "`traefik.tcp.routers..service`" - - See [service](../routers/index.md#services) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.service": "myservice" - ``` - -??? info "`traefik.tcp.routers..tls`" - - See [TLS](../routers/index.md#tls_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls": "true - ``` - -??? info "`traefik.tcp.routers..tls.certresolver`" - - See [certResolver](../routers/index.md#certresolver_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.certresolver": "myresolver" - ``` - -??? info "`traefik.tcp.routers..tls.domains[n].main`" - - See [domains](../routers/index.md#domains_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.domains[0].main": "example.org" - ``` - -??? info "`traefik.tcp.routers..tls.domains[n].sans`" - - See [domains](../routers/index.md#domains_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.domains[0].sans": "test.example.org,dev.example.org" - ``` - -??? info "`traefik.tcp.routers..tls.options`" - - See [options](../routers/index.md#options_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.options": "mysoptions" - ``` - -??? info "`traefik.tcp.routers..tls.passthrough`" - - See [TLS](../routers/index.md#tls_1) for more information. - - ```json - "traefik.tcp.routers.mytcprouter.tls.passthrough": "true" - ``` - -??? info "`traefik.tcp.routers..priority`" - - See [priority](../routers/index.md#priority_1) for more information. - - ```json - "traefik.tcp.routers.myrouter.priority": "42" - ``` - -#### TCP Services - -??? info "`traefik.tcp.services..loadbalancer.server.port`" - - Registers a port of the application. - - ```json - "traefik.tcp.services.mytcpservice.loadbalancer.server.port": "423" - ``` - -??? info "`traefik.tcp.services..loadbalancer.server.tls`" - - Determines whether to use TLS when dialing with the backend. - - ```json - "traefik.tcp.services.mytcpservice.loadbalancer.server.tls": "true" - ``` - -??? info "`traefik.tcp.services..loadbalancer.proxyprotocol.version`" - - See [PROXY protocol](../services/index.md#proxy-protocol) for more information. - - ```json - "traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version": "1" - ``` - -??? info "`traefik.tcp.services..loadbalancer.serverstransport`" - - Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one. - See [serverstransport](../services/index.md#serverstransport_2) for more information. - - ```json - "traefik.tcp.services..loadbalancer.serverstransport": "foobar@file" - ``` - -### UDP - -You can declare UDP Routers and/or Services using labels. - -??? example "Declaring UDP Routers and Services" - - ```json - { - ... - "labels": { - "traefik.udp.routers.my-router.entrypoints": "udp", - "traefik.udp.services.my-service.loadbalancer.server.port": "4123" - } - } - ``` - -!!! warning "UDP and HTTP" - - If you declare a UDP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no UDP Router/Service is defined). - You can declare both a UDP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually). - -#### UDP Routers - -??? info "`traefik.udp.routers..entrypoints`" - - See [entry points](../routers/index.md#entrypoints_2) for more information. - - ```json - "traefik.udp.routers.myudprouter.entrypoints": "ep1,ep2" - ``` - -??? info "`traefik.udp.routers..service`" - - See [service](../routers/index.md#services_1) for more information. - - ```json - "traefik.udp.routers.myudprouter.service": "myservice" - ``` - -#### UDP Services - -??? info "`traefik.udp.services..loadbalancer.server.port`" - - Registers a port of the application. - - ```json - "traefik.udp.services.myudpservice.loadbalancer.server.port": "423" - ``` - -### Specific Provider Options - -#### `traefik.enable` - -```json -"traefik.enable": "true" -``` - -Setting this option controls whether Traefik exposes the application. -It overrides the value of `exposedByDefault`. - -#### `traefik.marathon.ipadressidx` - -```json -"traefik.marathon.ipadressidx": "1" -``` - -If a task has several IP addresses, this option specifies which one, in the list of available addresses, to select. diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index 7253eb24f..12bc83f60 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -557,8 +557,7 @@ which is basically where the request will be passed along to. In general, a service assigned to a router should have been defined, but there are exceptions for label-based providers. -See the specific [docker](../providers/docker.md#service-definition), -or [marathon](../providers/marathon.md#service-definition) documentation. +See the specific [docker](../providers/docker.md#service-definition) documentation. !!! warning "The character `@` is not authorized in the service name." diff --git a/docs/content/user-guides/marathon.md b/docs/content/user-guides/marathon.md deleted file mode 100644 index 2b374ca24..000000000 --- a/docs/content/user-guides/marathon.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: "Traefik Proxy and Marathon Integration Guide |Traefik Docs" -description: "This guide explains how to integrate Marathon and operate the cluster in a reliable way from the Traefik Proxy standpoint." ---- - -# Marathon - -This guide explains how to integrate Marathon and operate the cluster in a reliable way from Traefik's standpoint. - -## Host detection - -Marathon offers multiple ways to run (Docker-containerized) applications, the most popular ones being - -- BRIDGE-networked containers with dynamic high ports exposed -- HOST-networked containers with host machine ports -- containers with dedicated IP addresses ([IP-per-task](https://mesosphere.github.io/marathon/docs/ip-per-task.html)). - -Traefik tries to detect the configured mode and route traffic to the right IP addresses. It is possible to force using task hosts with the `forceTaskHostname` option. - -## Port detection - -Traefik also attempts to determine the right port (which is a [non-trivial matter in Marathon](https://mesosphere.github.io/marathon/docs/ports.html)) from the following sources: - -1. An arbitrary port specified through label `traefik.http.services.serviceName.loadbalancer.server.port=8080` -1. The task port. -1. The port from the application's `portDefinitions` field. -1. The port from the application's `ipAddressPerTask` field. - -### Port label syntax - -To select a port, you can either - -- specify the port directly: `traefik.http.services.serviceName.loadbalancer.server.port=8080` -- specify a port index: `traefik.http.services.serviceName.loadbalancer.server.port=index:0` -- specify a port name: `traefik.http.services.serviceName.loadbalancer.server.port=name:http` -- otherwise the first one is selected. - -## Achieving high availability - -### Scenarios - -There are three scenarios where the availability of a Marathon application could be impaired along with the risk of losing or failing requests: - -- During the startup phase when Traefik already routes requests to the backend even though it has not completed its bootstrapping process yet. -- During the shutdown phase when Traefik still routes requests to the backend while the backend is already terminating. -- During a failure of the application when Traefik has not yet identified the backend as being erroneous. - -The first two scenarios are common with every rolling upgrade of an application (i.e. a new version release or configuration update). - -The following sub-sections describe how to resolve or mitigate each scenario. - -#### Startup - -It is possible to define [readiness checks](https://mesosphere.github.io/marathon/docs/readiness-checks.html) (available since Marathon version 1.1) per application and have Marathon take these into account during the startup phase. - -The idea is that each application provides an HTTP endpoint that Marathon queries periodically during an ongoing deployment in order to mark the associated readiness check result as successful if and only if the endpoint returns a response within the configured HTTP code range. -As long as the check keeps failing, Marathon will not proceed with the deployment (within the configured upgrade strategy bounds). - -Beginning with version 1.4, Traefik respects readiness check results if the Traefik option is set and checks are configured on the applications accordingly. - -!!! note - Due to the way readiness check results are currently exposed by the Marathon API, ready tasks may be taken into rotation with a small delay. - It is on the order of one readiness check timeout interval (as configured on the application specification) and guarantees that non-ready tasks do not receive traffic prematurely. - -If readiness checks are not possible, a current mitigation strategy is to enable [retries](../middlewares/http/retry.md) and make sure that a sufficient number of healthy application tasks exist so that one retry will likely hit one of those. -Apart from its probabilistic nature, the workaround comes at the price of increased latency. - -#### Shutdown - -It is possible to install a [termination handler](https://mesosphere.github.io/marathon/docs/health-checks.html) (available since Marathon version 1.3) with each application whose responsibility it is to delay the shutdown process long enough until the backend has been taken out of load-balancing rotation with reasonable confidence (i.e., Traefik has received an update from the Marathon event bus, recomputes the available Marathon backends, and applies the new configuration). -Specifically, each termination handler should install a signal handler listening for a SIGTERM signal and implement the following steps on signal reception: - -1. Disable Keep-Alive HTTP connections. -1. Keep accepting HTTP requests for a certain period of time. -1. Stop accepting new connections. -1. Finish serving any in-flight requests. -1. Shut down. - -Traefik already ignores Marathon tasks whose state does not match `TASK_RUNNING`; since terminating tasks transition into the `TASK_KILLING` and eventually `TASK_KILLED` state, there is nothing further that needs to be done on Traefik's end. - -How long HTTP requests should continue to be accepted in step 2 depends on how long Traefik needs to receive and process the Marathon configuration update. -Under regular operational conditions, it should be on the order of seconds, with 10 seconds possibly being a good default value. - -Again, configuring Traefik to do retries (as discussed in the previous section) can serve as a decent workaround strategy. -Paired with termination handlers, they would cover for those cases where either the termination sequence or Traefik cannot complete their part of the orchestration process in time. - -#### Failure - -A failing application always happens unexpectedly, and hence, it is very difficult or even impossible to rule out the adversal effects categorically. - -Failure reasons vary broadly and could stretch from unacceptable slowness, a task crash, or a network split. - -There are two mitigation efforts: - -1. Configure [Marathon health checks](https://mesosphere.github.io/marathon/docs/health-checks.html) on each application. -2. Configure Traefik health checks (possibly via the `traefik.http.services.yourServiceName.loadbalancer.healthcheck.*` labels) and make sure they probe with proper frequency. - -The Marathon health check makes sure that applications once deemed dysfunctional are being rescheduled to different slaves. -However, they might take a while to get triggered and the follow-up processes to complete. - -For that reason, the Traefik health check provides an additional check that responds more rapidly and does not require a configuration reload to happen. -Additionally, it protects from cases that the Marathon health check may not be able to cover, such as a network split. - -### (Non-)Alternatives - -There are a few alternatives of varying quality that are frequently asked for. - -The remaining section is going to explore them along with a benefit/cost trade-off. - -#### Reusing Marathon health checks - -It may seem obvious to reuse the Marathon health checks as a signal to Traefik whether an application should be taken into load-balancing rotation or not. - -Apart from the increased latency a failing health check may have, a major problem with this is that Marathon does not persist the health check results. -Consequently, if a master re-election occurs in the Marathon clusters, all health check results will revert to the _unknown_ state, effectively causing all applications inside the cluster to become unavailable and leading to a complete cluster failure. -Re-elections do not only happen during regular maintenance work (often requiring rolling upgrades of the Marathon nodes) but also when the Marathon leader fails spontaneously. -As such, there is no way to handle this situation deterministically. - -Finally, Marathon health checks are not mandatory (the default is to use the task state as reported by Mesos), so requiring them for Traefik would raise the entry barrier for Marathon users. - -Traefik used to use the health check results as a strict requirement but moved away from it as [users reported the dramatic consequences](https://github.com/traefik/traefik/issues/653). - -#### Draining - -Another common approach is to let a proxy drain backends that are supposed to shut down. -That is, once a backend is supposed to shut down, Traefik would stop forwarding requests. - -On the plus side, this would not require any modifications to the application in question. -However, implementing this fully within Traefik seems like a non-trivial undertaking. - -Additionally, the approach is less flexible compared to a custom termination handler since only the latter allows for the implementation of custom termination sequences that go beyond simple request draining (e.g., persisting a snapshot state to disk prior to terminating). - -The feature is currently not implemented; a request for draining in general is at [issue 41](https://github.com/traefik/traefik/issues/41). diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index d45f42498..4819e16c8 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -81,7 +81,6 @@ nav: - 'Consul Catalog': 'providers/consul-catalog.md' - 'Nomad': 'providers/nomad.md' - 'ECS': 'providers/ecs.md' - - 'Marathon': 'providers/marathon.md' - 'File': 'providers/file.md' - 'Consul': 'providers/consul.md' - 'Etcd': 'providers/etcd.md' @@ -101,7 +100,6 @@ nav: - 'Consul Catalog': 'routing/providers/consul-catalog.md' - 'Nomad': 'routing/providers/nomad.md' - 'ECS': 'routing/providers/ecs.md' - - 'Marathon': 'routing/providers/marathon.md' - 'KV': 'routing/providers/kv.md' - 'HTTPS & TLS': - 'Overview': 'https/overview.md' @@ -170,7 +168,6 @@ nav: - 'User Guides': - 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md' - 'gRPC Examples': 'user-guides/grpc.md' - - 'Marathon': 'user-guides/marathon.md' - 'Docker': - 'Basic Example': 'user-guides/docker-compose/basic-example/index.md' - 'HTTPS with Let''s Encrypt': @@ -206,7 +203,6 @@ nav: - 'Nomad': "reference/dynamic-configuration/nomad.md" - 'ECS': 'reference/dynamic-configuration/ecs.md' - 'KV': 'reference/dynamic-configuration/kv.md' - - 'Marathon': 'reference/dynamic-configuration/marathon.md' - 'Deprecation Notices': - 'Releases': 'deprecation/releases.md' - 'Features': 'deprecation/features.md' diff --git a/go.mod b/go.mod index 1ddd41337..bca864e5b 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,6 @@ require ( github.com/docker/docker v20.10.7+incompatible github.com/docker/go-connections v0.4.0 github.com/fatih/structs v1.1.0 - github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2 github.com/go-acme/lego/v4 v4.9.1 github.com/go-check/check v0.0.0-00010101000000-000000000000 github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea @@ -173,7 +172,6 @@ require ( github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/go-licenser v0.3.1 // indirect github.com/elastic/go-sysinfo v1.1.1 // indirect diff --git a/go.sum b/go.sum index 11aa3b6de..8d94db2f0 100644 --- a/go.sum +++ b/go.sum @@ -589,8 +589,6 @@ github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNE github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e h1:rMOGp6HPeMHbdLrZkX2nD+94uqDunc27tXVuS+ey4mQ= -github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -665,8 +663,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2 h1:df6OFl8WNXk82xxP3R9ZPZ5seOA8XZkwLdbEzZF1/xI= -github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2/go.mod h1:GLyXJD41gBO/NPKVPGQbhyyC06eugGy15QEZyUkE2/s= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.87.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= diff --git a/integration/fixtures/marathon/simple.toml b/integration/fixtures/marathon/simple.toml deleted file mode 100644 index d43cdbc2e..000000000 --- a/integration/fixtures/marathon/simple.toml +++ /dev/null @@ -1,22 +0,0 @@ -[global] - checkNewVersion = false - sendAnonymousUsage = false - -[log] - level = "DEBUG" - noColor = true - -[entryPoints] - [entryPoints.web] - address = ":8000" - [entryPoints.traefik] - address = ":9090" - -[api] - insecure = true - -[providers] - [providers.marathon] - endpoint = "{{.MarathonURL}}" - watch = true - exposedByDefault = true diff --git a/integration/integration_test.go b/integration/integration_test.go index d71409d38..8e7f19e25 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -91,8 +91,6 @@ func Test(t *testing.T) { } check.Suite(&KeepAliveSuite{}) check.Suite(&LogRotationSuite{}) - check.Suite(&MarathonSuite{}) - check.Suite(&MarathonSuite15{}) if !useVPN { check.Suite(&ProxyProtocolSuite{}) } diff --git a/integration/marathon15_test.go b/integration/marathon15_test.go deleted file mode 100644 index 493db256a..000000000 --- a/integration/marathon15_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package integration - -import ( - "net/http" - "os" - "time" - - "github.com/gambol99/go-marathon" - "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - checker "github.com/vdemeester/shakers" -) - -// Marathon test suites. -type MarathonSuite15 struct { - BaseSuite - marathonURL string -} - -func (s *MarathonSuite15) SetUpSuite(c *check.C) { - s.createComposeProject(c, "marathon15") - s.composeUp(c) - - s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080" - - // Wait for Marathon readiness prior to creating the client so that we - // don't run into the "all cluster members down" state right from the - // start. - err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) -} - -func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) { - // Start Traefik. - file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct { - MarathonURL string - }{s.marathonURL}) - defer os.Remove(file) - cmd, display := s.traefikCmd(withConfigFile(file)) - defer display(c) - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - // Wait for Traefik to turn ready. - err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound)) - c.Assert(err, checker.IsNil) - - // Prepare Marathon client. - config := marathon.NewDefaultConfig() - config.URL = s.marathonURL - client, err := marathon.NewClient(config) - c.Assert(err, checker.IsNil) - - // Create test application to be deployed. - app := marathon.NewDockerApplication(). - Name("/whoami"). - CPU(0.1). - Memory(32). - EmptyNetworks(). - AddLabel("traefik.http.Routers.rt.Rule", "PathPrefix(`/service`)") - app.Container. - Expose(80). - Docker. - Container("traefik/whoami") - *app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork()) - - // Deploy the test application. - deployApplication(c, client, app) - - // Query application via Traefik. - err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - - // Create test application with services to be deployed. - app = marathon.NewDockerApplication(). - Name("/whoami"). - CPU(0.1). - Memory(32). - EmptyNetworks(). - AddLabel("traefik.http.Routers.app.Rule", "PathPrefix(`/app`)") - app.Container. - Expose(80). - Docker. - Container("traefik/whoami") - *app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork()) - - // Deploy the test application. - deployApplication(c, client, app) - - // Query application via Traefik. - err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) -} diff --git a/integration/marathon_test.go b/integration/marathon_test.go deleted file mode 100644 index 5552e0d0b..000000000 --- a/integration/marathon_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package integration - -import ( - "net/http" - "os" - "time" - - "github.com/gambol99/go-marathon" - "github.com/go-check/check" - "github.com/traefik/traefik/v2/integration/try" - checker "github.com/vdemeester/shakers" -) - -const containerNameMarathon = "marathon" - -// Marathon test suites. -type MarathonSuite struct { - BaseSuite - marathonURL string -} - -func (s *MarathonSuite) SetUpSuite(c *check.C) { - s.createComposeProject(c, "marathon") - s.composeUp(c) - - s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080" - - // Wait for Marathon readiness prior to creating the client so that we - // don't run into the "all cluster members down" state right from the - // start. - err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) -} - -func deployApplication(c *check.C, client marathon.Marathon, application *marathon.Application) { - deploy, err := client.UpdateApplication(application, false) - c.Assert(err, checker.IsNil) - // Wait for deployment to complete. - c.Assert(client.WaitOnDeployment(deploy.DeploymentID, 1*time.Minute), checker.IsNil) -} - -func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) { - // Start Traefik. - file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct { - MarathonURL string - }{s.marathonURL}) - defer os.Remove(file) - - cmd, display := s.traefikCmd(withConfigFile(file)) - defer display(c) - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - // Wait for Traefik to turn ready. - err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound)) - c.Assert(err, checker.IsNil) - - // Prepare Marathon client. - config := marathon.NewDefaultConfig() - config.URL = s.marathonURL - client, err := marathon.NewClient(config) - c.Assert(err, checker.IsNil) - - // Create test application to be deployed. - app := marathon.NewDockerApplication(). - Name("/whoami"). - CPU(0.1). - Memory(32). - AddLabel("traefik.http.Routers.rt.Rule", "PathPrefix(`/service`)") - app.Container.Docker.Bridged(). - Expose(80). - Container("traefik/whoami") - - // Deploy the test application. - deployApplication(c, client, app) - - // Query application via Traefik. - err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - - // Create test application with services to be deployed. - app = marathon.NewDockerApplication(). - Name("/whoami"). - CPU(0.1). - Memory(32). - AddLabel("traefik.http.Routers.app.Rule", "PathPrefix(`/app`)") - app.Container.Docker.Bridged(). - Expose(80). - Container("traefik/whoami") - - // Deploy the test application. - deployApplication(c, client, app) - - // Query application via Traefik. - err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) -} diff --git a/integration/resources/compose/marathon.yml b/integration/resources/compose/marathon.yml deleted file mode 100644 index 5a2be1e67..000000000 --- a/integration/resources/compose/marathon.yml +++ /dev/null @@ -1,60 +0,0 @@ -version: "3.8" -services: - zookeeper: - image: zookeeper:3.4.10 - - mesos-master: - image: mesosphere/mesos-master:1.0.1-2.0.93.ubuntu1404 - # Uncomment published ports for interactive debugging. - # ports: - # - "5050:5050" - environment: - MESOS_HOSTNAME: mesos-master - MESOS_CLUSTER: local - MESOS_REGISTRY: in_memory - MESOS_LOG_DIR: /var/log - MESOS_WORK_DIR: /var/lib/mesos - MESOS_ZK: zk://zookeeper:2181/mesos - - mesos-slave: - image: docker:dind - privileged: true - # Uncomment published ports for interactive debugging. - # ports: - # - "5051:5051" - # docker version in mesosphere/mesos-slave-dind:0.3.0_mesos-1.0.1_docker-1.10.3_ubuntu-14.04.5 is too old and can't - # pull images on new kernels. - command: - - "/bin/sh" - - "-c" - - "(/usr/local/bin/dockerd-entrypoint.sh &); sleep 10; set -x; \ - docker -H unix:///var/run/docker.sock run -d --net=host --privileged \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v /cgroup:/cgroup -v /sys:/sys \ - -v /usr/local/bin/docker:/usr/local/bin/docker \ - -e MESOS_HOSTNAME=$$(hostname -i) \ - -e MESOS_CONTAINERIZERS=docker,mesos \ - -e MESOS_ISOLATOR=cgroups/cpu,cgroups/mem \ - -e MESOS_LOG_DIR=/var/log \ - -e MESOS_MASTER=zk://zookeeper:2181/mesos \ - -e MESOS_PORT=5051 \ - -e MESOS_WORK_DIR=/var/lib/mesos \ - -e MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins \ - -e MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs \ - -e MESOS_DOCKER_STOP_TIMEOUT=60secs \ - -e MESOS_RESOURCES='cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]' \ - mesosphere/mesos-slave:1.0.3; sleep 600" - - marathon: - image: mesosphere/marathon:v1.3.12 - # Uncomment published ports for interactive debugging. - # ports: - # - "8080:8080" - environment: - MARATHON_ZK: zk://zookeeper:2181/marathon - MARATHON_MASTER: zk://zookeeper:2181/mesos - -networks: - default: - name: traefik-test-network - external: true diff --git a/integration/resources/compose/marathon15.yml b/integration/resources/compose/marathon15.yml deleted file mode 100644 index 6a5774fc7..000000000 --- a/integration/resources/compose/marathon15.yml +++ /dev/null @@ -1,59 +0,0 @@ -version: "3.8" -services: - zookeeper: - image: zookeeper:3.4.10 - - mesos-master: - image: mesosphere/mesos-master:1.4.1 - # Uncomment published ports for interactive debugging. - # ports: - # - "5050:5050" - environment: - MESOS_HOSTNAME: mesos-master - MESOS_CLUSTER: local - MESOS_REGISTRY: in_memory - MESOS_LOG_DIR: /var/log - MESOS_WORK_DIR: /var/lib/mesos - MESOS_ZK: zk://zookeeper:2181/mesos - - mesos-slave: - image: docker:dind - privileged: true - # Uncomment published ports for interactive debugging. - # ports: - # - "5051:5051" - command: - - "/bin/sh" - - "-c" - - "(/usr/local/bin/dockerd-entrypoint.sh &); sleep 10; set -x; \ - docker -H unix:///var/run/docker.sock run -d --net=host --privileged \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v /cgroup:/cgroup -v /sys:/sys \ - -v /usr/local/bin/docker:/usr/local/bin/docker \ - -e MESOS_HOSTNAME=$$(hostname -i) \ - -e MESOS_CONTAINERIZERS=docker,mesos \ - -e MESOS_ISOLATOR=cgroups/cpu,cgroups/mem \ - -e MESOS_LOG_DIR=/var/log \ - -e MESOS_MASTER=zk://zookeeper:2181/mesos \ - -e MESOS_PORT=5051 \ - -e MESOS_WORK_DIR=/var/lib/mesos \ - -e MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins \ - -e MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs \ - -e MESOS_DOCKER_STOP_TIMEOUT=60secs \ - -e MESOS_RESOURCES='cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]' \ - -e MESOS_SYSTEMD_ENABLE_SUPPORT=false \ - mesosphere/mesos-slave:1.4.1; sleep 600" - - marathon: - image: mesosphere/marathon:v1.5.9 - # Uncomment published ports for interactive debugging. - # ports: - # - "8080:8080" - environment: - MARATHON_ZK: zk://zookeeper:2181/marathon - MARATHON_MASTER: zk://zookeeper:2181/mesos - -networks: - default: - name: traefik-test-network - external: true diff --git a/pkg/api/handler_overview_test.go b/pkg/api/handler_overview_test.go index 92584b9f8..2985d93ae 100644 --- a/pkg/api/handler_overview_test.go +++ b/pkg/api/handler_overview_test.go @@ -18,7 +18,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/hub" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/ingress" - "github.com/traefik/traefik/v2/pkg/provider/marathon" "github.com/traefik/traefik/v2/pkg/provider/rest" "github.com/traefik/traefik/v2/pkg/tracing/jaeger" "github.com/traefik/traefik/v2/pkg/types" @@ -237,7 +236,6 @@ func TestHandler_Overview(t *testing.T) { Providers: &static.Providers{ Docker: &docker.Provider{}, File: &file.Provider{}, - Marathon: &marathon.Provider{}, KubernetesIngress: &ingress.Provider{}, KubernetesCRD: &crd.Provider{}, Rest: &rest.Provider{}, diff --git a/pkg/api/testdata/overview-providers.json b/pkg/api/testdata/overview-providers.json index 29d9ce9a7..20f134354 100644 --- a/pkg/api/testdata/overview-providers.json +++ b/pkg/api/testdata/overview-providers.json @@ -25,7 +25,6 @@ "providers": [ "Docker", "File", - "Marathon", "KubernetesIngress", "KubernetesCRD", "Rest", diff --git a/pkg/config/dynamic/fixtures/sample.toml b/pkg/config/dynamic/fixtures/sample.toml index b823c67ca..58534c553 100644 --- a/pkg/config/dynamic/fixtures/sample.toml +++ b/pkg/config/dynamic/fixtures/sample.toml @@ -54,28 +54,6 @@ watch = true filename = "foobar" debugLogGeneratedTemplate = true - [providers.marathon] - constraints = "foobar" - trace = true - watch = true - endpoint = "foobar" - defaultRule = "foobar" - exposedByDefault = true - dcosToken = "foobar" - dialerTimeout = 42 - responseHeaderTimeout = 42 - tlsHandshakeTimeout = 42 - keepAlive = 42 - forceTaskHostname = true - respectReadinessChecks = true - [providers.marathon.tls] - ca = "foobar" - cert = "foobar" - key = "foobar" - insecureSkipVerify = true - [providers.marathon.basic] - httpBasicAuthUser = "foobar" - httpBasicPassword = "foobar" [providers.kubernetesIngress] endpoint = "foobar" token = "foobar" diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index 4085bfe31..943e2cdec 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -25,7 +25,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/kv/etcd" "github.com/traefik/traefik/v2/pkg/provider/kv/redis" "github.com/traefik/traefik/v2/pkg/provider/kv/zk" - "github.com/traefik/traefik/v2/pkg/provider/marathon" "github.com/traefik/traefik/v2/pkg/provider/nomad" "github.com/traefik/traefik/v2/pkg/provider/rest" "github.com/traefik/traefik/v2/pkg/tls" @@ -213,7 +212,6 @@ type Providers struct { Docker *docker.Provider `description:"Enable Docker backend with default settings." json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` File *file.Provider `description:"Enable File backend with default settings." json:"file,omitempty" toml:"file,omitempty" yaml:"file,omitempty" export:"true"` - Marathon *marathon.Provider `description:"Enable Marathon backend with default settings." json:"marathon,omitempty" toml:"marathon,omitempty" yaml:"marathon,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesIngress *ingress.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesCRD *crd.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesCRD,omitempty" toml:"kubernetesCRD,omitempty" yaml:"kubernetesCRD,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesGateway *gateway.Provider `description:"Enable Kubernetes gateway api provider with default settings." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` diff --git a/pkg/provider/aggregator/aggregator.go b/pkg/provider/aggregator/aggregator.go index c1164c28e..ccdaa3d5f 100644 --- a/pkg/provider/aggregator/aggregator.go +++ b/pkg/provider/aggregator/aggregator.go @@ -80,10 +80,6 @@ func NewProviderAggregator(conf static.Providers) ProviderAggregator { p.quietAddProvider(conf.Docker) } - if conf.Marathon != nil { - p.quietAddProvider(conf.Marathon) - } - if conf.Rest != nil { p.quietAddProvider(conf.Rest) } diff --git a/pkg/provider/constraints/constraints_labels.go b/pkg/provider/constraints/constraints_labels.go index 6f194ba33..6d74bfbab 100644 --- a/pkg/provider/constraints/constraints_labels.go +++ b/pkg/provider/constraints/constraints_labels.go @@ -3,22 +3,16 @@ package constraints import ( "errors" "regexp" - "strings" "github.com/vulcand/predicate" ) -// MarathonConstraintPrefix is the prefix for each label's key created from a Marathon application constraint. -// It is used in order to create a specific and unique pattern for these labels. -const MarathonConstraintPrefix = "Traefik-Marathon-505F9E15-BDC7-45E7-828D-C06C7BAB8091" - type constraintLabelFunc func(map[string]string) bool // MatchLabels reports whether the expression matches with the given labels. // The expression must match any logical boolean combination of: // - `Label(labelName, labelValue)` -// - `LabelRegex(labelName, regexValue)` -// - `MarathonConstraint(field:operator:value)`. +// - `LabelRegex(labelName, regexValue)`. func MatchLabels(labels map[string]string, expr string) (bool, error) { if expr == "" { return true, nil @@ -31,9 +25,8 @@ func MatchLabels(labels map[string]string, expr string) (bool, error) { OR: orLabelFunc, }, Functions: map[string]interface{}{ - "Label": labelFn, - "LabelRegex": labelRegexFn, - "MarathonConstraint": marathonFn, + "Label": labelFn, + "LabelRegex": labelRegexFn, }, }) if err != nil { @@ -68,19 +61,6 @@ func labelRegexFn(name, expr string) constraintLabelFunc { } } -func marathonFn(value string) constraintLabelFunc { - return func(labels map[string]string) bool { - for k, v := range labels { - if strings.HasPrefix(k, MarathonConstraintPrefix) { - if v == value { - return true - } - } - } - return false - } -} - func andLabelFunc(a, b constraintLabelFunc) constraintLabelFunc { return func(labels map[string]string) bool { return a(labels) && b(labels) diff --git a/pkg/provider/constraints/constraints_labels_test.go b/pkg/provider/constraints/constraints_labels_test.go index 43fb9e0c6..8068735eb 100644 --- a/pkg/provider/constraints/constraints_labels_test.go +++ b/pkg/provider/constraints/constraints_labels_test.go @@ -118,33 +118,6 @@ func TestMatchLabels(t *testing.T) { expr: ``, expected: true, }, - { - expr: `MarathonConstraint("bar")`, - labels: map[string]string{ - "hello": "world", - MarathonConstraintPrefix + "-1": "bar", - MarathonConstraintPrefix + "-2": "foo", - }, - expected: true, - }, - { - expr: `MarathonConstraint("bur")`, - labels: map[string]string{ - "hello": "world", - MarathonConstraintPrefix + "-1": "bar", - MarathonConstraintPrefix + "-2": "foo", - }, - expected: false, - }, - { - expr: `Label("hello", "world") && MarathonConstraint("bar")`, - labels: map[string]string{ - "hello": "world", - MarathonConstraintPrefix + "-1": "bar", - MarathonConstraintPrefix + "-2": "foo", - }, - expected: true, - }, { expr: `LabelRegex("hello", "w\\w+")`, labels: map[string]string{ diff --git a/pkg/provider/marathon/builder_test.go b/pkg/provider/marathon/builder_test.go deleted file mode 100644 index e18110787..000000000 --- a/pkg/provider/marathon/builder_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package marathon - -import ( - "strings" - "time" - - "github.com/gambol99/go-marathon" -) - -const testTaskName = "taskID" - -// Functions related to building applications. - -func withApplications(apps ...marathon.Application) *marathon.Applications { - return &marathon.Applications{Apps: apps} -} - -func application(ops ...func(*marathon.Application)) marathon.Application { - app := marathon.Application{} - app.EmptyLabels() - app.Deployments = []map[string]string{} - app.ReadinessChecks = &[]marathon.ReadinessCheck{} - app.ReadinessCheckResults = &[]marathon.ReadinessCheckResult{} - - for _, op := range ops { - op(&app) - } - - return app -} - -func appID(name string) func(*marathon.Application) { - return func(app *marathon.Application) { - app.Name(name) - } -} - -func appPorts(ports ...int) func(*marathon.Application) { - return func(app *marathon.Application) { - app.Ports = append(app.Ports, ports...) - } -} - -func withLabel(key, value string) func(*marathon.Application) { - return func(app *marathon.Application) { - app.AddLabel(key, value) - } -} - -func constraint(value string) func(*marathon.Application) { - return func(app *marathon.Application) { - app.AddConstraint(strings.Split(value, ":")...) - } -} - -func portDefinition(port int, name string) func(*marathon.Application) { - return func(app *marathon.Application) { - app.AddPortDefinition(marathon.PortDefinition{ - Port: &port, - Name: name, - }) - } -} - -func bridgeNetwork() func(*marathon.Application) { - return func(app *marathon.Application) { - app.SetNetwork("bridge", marathon.BridgeNetworkMode) - } -} - -func containerNetwork() func(*marathon.Application) { - return func(app *marathon.Application) { - app.SetNetwork("cni", marathon.ContainerNetworkMode) - } -} - -func ipAddrPerTask(port int) func(*marathon.Application) { - return func(app *marathon.Application) { - p := marathon.Port{ - Number: port, - Name: "port", - } - disc := marathon.Discovery{} - disc.AddPort(p) - ipAddr := marathon.IPAddressPerTask{} - ipAddr.SetDiscovery(disc) - app.SetIPAddressPerTask(ipAddr) - } -} - -func deployments(ids ...string) func(*marathon.Application) { - return func(app *marathon.Application) { - for _, id := range ids { - app.Deployments = append(app.Deployments, map[string]string{ - "ID": id, - }) - } - } -} - -func readinessCheck(timeout time.Duration) func(*marathon.Application) { - return func(app *marathon.Application) { - app.ReadinessChecks = &[]marathon.ReadinessCheck{ - { - Path: "/ready", - TimeoutSeconds: int(timeout.Seconds()), - }, - } - } -} - -func readinessCheckResult(taskID string, ready bool) func(*marathon.Application) { - return func(app *marathon.Application) { - *app.ReadinessCheckResults = append(*app.ReadinessCheckResults, marathon.ReadinessCheckResult{ - TaskID: taskID, - Ready: ready, - }) - } -} - -func withTasks(tasks ...marathon.Task) func(*marathon.Application) { - return func(application *marathon.Application) { - for _, task := range tasks { - tu := task - application.Tasks = append(application.Tasks, &tu) - } - } -} - -// Functions related to building tasks. - -func task(ops ...func(*marathon.Task)) marathon.Task { - t := &marathon.Task{ - ID: testTaskName, - // The vast majority of tests expect the task state to be TASK_RUNNING. - State: string(taskStateRunning), - } - - for _, op := range ops { - op(t) - } - - return *t -} - -func withTaskID(id string) func(*marathon.Task) { - return func(task *marathon.Task) { - task.ID = id - } -} - -func localhostTask(ops ...func(*marathon.Task)) marathon.Task { - t := task( - host("localhost"), - ipAddresses("127.0.0.1"), - taskState(taskStateRunning), - ) - - for _, op := range ops { - op(&t) - } - - return t -} - -func taskPorts(ports ...int) func(*marathon.Task) { - return func(t *marathon.Task) { - t.Ports = append(t.Ports, ports...) - } -} - -func taskState(state TaskState) func(*marathon.Task) { - return func(t *marathon.Task) { - t.State = string(state) - } -} - -func host(h string) func(*marathon.Task) { - return func(t *marathon.Task) { - t.Host = h - } -} - -func ipAddresses(addresses ...string) func(*marathon.Task) { - return func(t *marathon.Task) { - for _, addr := range addresses { - t.IPAddresses = append(t.IPAddresses, &marathon.IPAddress{ - IPAddress: addr, - Protocol: "tcp", - }) - } - } -} - -func startedAt(timestamp string) func(*marathon.Task) { - return func(t *marathon.Task) { - t.StartedAt = timestamp - } -} - -func startedAtFromNow(offset time.Duration) func(*marathon.Task) { - return func(t *marathon.Task) { - t.StartedAt = time.Now().Add(-offset).Format(time.RFC3339) - } -} diff --git a/pkg/provider/marathon/config.go b/pkg/provider/marathon/config.go deleted file mode 100644 index 5c7e0b059..000000000 --- a/pkg/provider/marathon/config.go +++ /dev/null @@ -1,473 +0,0 @@ -package marathon - -import ( - "context" - "errors" - "fmt" - "math" - "net" - "strconv" - "strings" - - "github.com/gambol99/go-marathon" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/config/label" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/provider/constraints" -) - -func (p *Provider) buildConfiguration(ctx context.Context, applications *marathon.Applications) *dynamic.Configuration { - configurations := make(map[string]*dynamic.Configuration) - - for _, app := range applications.Apps { - logger := log.Ctx(ctx).With().Str("applicationID", app.ID).Logger() - ctxApp := logger.WithContext(ctx) - - extraConf, err := p.getConfiguration(app) - if err != nil { - logger.Error().Err(err).Msg("Skip application") - continue - } - - labels := stringValueMap(app.Labels) - - if app.Constraints != nil { - for i, constraintParts := range *app.Constraints { - key := constraints.MarathonConstraintPrefix + "-" + strconv.Itoa(i) - labels[key] = strings.Join(constraintParts, ":") - } - } - - if !p.keepApplication(ctxApp, extraConf, labels) { - continue - } - - confFromLabel, err := label.DecodeConfiguration(labels) - if err != nil { - logger.Error().Err(err).Send() - continue - } - - var tcpOrUDP bool - if len(confFromLabel.TCP.Routers) > 0 || len(confFromLabel.TCP.Services) > 0 { - tcpOrUDP = true - - err := p.buildTCPServiceConfiguration(ctxApp, app, extraConf, confFromLabel.TCP) - if err != nil { - logger.Error().Err(err).Send() - continue - } - provider.BuildTCPRouterConfiguration(ctxApp, confFromLabel.TCP) - } - - if len(confFromLabel.UDP.Routers) > 0 || len(confFromLabel.UDP.Services) > 0 { - tcpOrUDP = true - - err := p.buildUDPServiceConfiguration(ctxApp, app, extraConf, confFromLabel.UDP) - if err != nil { - logger.Error().Err(err).Send() - } else { - provider.BuildUDPRouterConfiguration(ctxApp, confFromLabel.UDP) - } - } - - if tcpOrUDP && len(confFromLabel.HTTP.Routers) == 0 && - len(confFromLabel.HTTP.Middlewares) == 0 && - len(confFromLabel.HTTP.Services) == 0 { - configurations[app.ID] = confFromLabel - continue - } - - err = p.buildServiceConfiguration(ctxApp, app, extraConf, confFromLabel.HTTP) - if err != nil { - logger.Error().Err(err).Send() - continue - } - - model := struct { - Name string - Labels map[string]string - }{ - Name: app.ID, - Labels: labels, - } - - serviceName := getServiceName(app) - - provider.BuildRouterConfiguration(ctxApp, confFromLabel.HTTP, serviceName, p.defaultRuleTpl, model) - - configurations[app.ID] = confFromLabel - } - - return provider.Merge(ctx, configurations) -} - -func getServiceName(app marathon.Application) string { - return strings.ReplaceAll(strings.TrimPrefix(app.ID, "/"), "/", "_") -} - -func (p *Provider) buildServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.HTTPConfiguration) error { - appName := getServiceName(app) - - logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() - - if len(conf.Services) == 0 { - conf.Services = make(map[string]*dynamic.Service) - lb := &dynamic.ServersLoadBalancer{} - lb.SetDefaults() - conf.Services[appName] = &dynamic.Service{ - LoadBalancer: lb, - } - } - - for serviceName, service := range conf.Services { - var servers []dynamic.Server - - defaultServer := dynamic.Server{} - defaultServer.SetDefaults() - - if len(service.LoadBalancer.Servers) > 0 { - defaultServer = service.LoadBalancer.Servers[0] - } - - for _, task := range app.Tasks { - if !p.taskFilter(ctx, *task, app) { - continue - } - server, err := p.getServer(app, *task, extraConf, defaultServer) - if err != nil { - logger.Error().Err(err).Msg("Skip task") - continue - } - servers = append(servers, server) - } - if len(servers) == 0 { - return fmt.Errorf("no server for the service %s", serviceName) - } - service.LoadBalancer.Servers = servers - } - - return nil -} - -func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.TCPConfiguration) error { - appName := getServiceName(app) - - logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() - - if len(conf.Services) == 0 { - conf.Services = map[string]*dynamic.TCPService{ - appName: { - LoadBalancer: new(dynamic.TCPServersLoadBalancer), - }, - } - } - - for serviceName, service := range conf.Services { - var servers []dynamic.TCPServer - - defaultServer := dynamic.TCPServer{} - - if len(service.LoadBalancer.Servers) > 0 { - defaultServer = service.LoadBalancer.Servers[0] - } - - for _, task := range app.Tasks { - if p.taskFilter(ctx, *task, app) { - server, err := p.getTCPServer(app, *task, extraConf, defaultServer) - if err != nil { - logger.Error().Err(err).Msg("Skip task") - continue - } - servers = append(servers, server) - } - } - if len(servers) == 0 { - return fmt.Errorf("no server for the service %s", serviceName) - } - service.LoadBalancer.Servers = servers - } - - return nil -} - -func (p *Provider) buildUDPServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.UDPConfiguration) error { - appName := getServiceName(app) - logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() - - if len(conf.Services) == 0 { - conf.Services = make(map[string]*dynamic.UDPService) - lb := &dynamic.UDPServersLoadBalancer{} - - conf.Services[appName] = &dynamic.UDPService{ - LoadBalancer: lb, - } - } - - for serviceName, service := range conf.Services { - var servers []dynamic.UDPServer - - defaultServer := dynamic.UDPServer{} - - if len(service.LoadBalancer.Servers) > 0 { - defaultServer = service.LoadBalancer.Servers[0] - } - - for _, task := range app.Tasks { - if p.taskFilter(ctx, *task, app) { - server, err := p.getUDPServer(app, *task, extraConf, defaultServer) - if err != nil { - logger.Error().Err(err).Msg("Skip task") - continue - } - servers = append(servers, server) - } - } - if len(servers) == 0 { - return fmt.Errorf("no server for the service %s", serviceName) - } - service.LoadBalancer.Servers = servers - } - - return nil -} - -func (p *Provider) keepApplication(ctx context.Context, extraConf configuration, labels map[string]string) bool { - logger := log.Ctx(ctx) - - // Filter disabled application. - if !extraConf.Enable { - logger.Debug().Msg("Filtering disabled Marathon application") - return false - } - - // Filter by constraints. - matches, err := constraints.MatchLabels(labels, p.Constraints) - if err != nil { - logger.Error().Err(err).Msg("Error matching constraints expression") - return false - } - if !matches { - logger.Debug().Msgf("Marathon application filtered by constraint expression: %q", p.Constraints) - return false - } - - return true -} - -func (p *Provider) taskFilter(ctx context.Context, task marathon.Task, application marathon.Application) bool { - if task.State != string(taskStateRunning) { - return false - } - - if ready := p.readyChecker.Do(task, application); !ready { - log.Ctx(ctx).Info().Msgf("Filtering unready task %s from application %s", task.ID, application.ID) - return false - } - - return true -} - -func (p *Provider) getTCPServer(app marathon.Application, task marathon.Task, extraConf configuration, defaultServer dynamic.TCPServer) (dynamic.TCPServer, error) { - host, err := p.getServerHost(task, app, extraConf) - if len(host) == 0 { - return dynamic.TCPServer{}, err - } - - port, err := getPort(task, app, defaultServer.Port) - if err != nil { - return dynamic.TCPServer{}, err - } - - server := dynamic.TCPServer{ - Address: net.JoinHostPort(host, port), - } - - return server, nil -} - -func (p *Provider) getUDPServer(app marathon.Application, task marathon.Task, extraConf configuration, defaultServer dynamic.UDPServer) (dynamic.UDPServer, error) { - host, err := p.getServerHost(task, app, extraConf) - if len(host) == 0 { - return dynamic.UDPServer{}, err - } - - port, err := getPort(task, app, defaultServer.Port) - if err != nil { - return dynamic.UDPServer{}, err - } - - server := dynamic.UDPServer{ - Address: net.JoinHostPort(host, port), - } - - return server, nil -} - -func (p *Provider) getServer(app marathon.Application, task marathon.Task, extraConf configuration, defaultServer dynamic.Server) (dynamic.Server, error) { - host, err := p.getServerHost(task, app, extraConf) - if len(host) == 0 { - return dynamic.Server{}, err - } - - port, err := getPort(task, app, defaultServer.Port) - if err != nil { - return dynamic.Server{}, err - } - - server := dynamic.Server{ - URL: fmt.Sprintf("%s://%s", defaultServer.Scheme, net.JoinHostPort(host, port)), - } - - return server, nil -} - -func (p *Provider) getServerHost(task marathon.Task, app marathon.Application, extraConf configuration) (string, error) { - networks := app.Networks - var hostFlag bool - - if networks == nil { - hostFlag = app.IPAddressPerTask == nil - } else { - hostFlag = (*networks)[0].Mode != marathon.ContainerNetworkMode - } - - if hostFlag || p.ForceTaskHostname { - if len(task.Host) == 0 { - return "", fmt.Errorf("host is undefined for task %q app %q", task.ID, app.ID) - } - return task.Host, nil - } - - numTaskIPAddresses := len(task.IPAddresses) - switch numTaskIPAddresses { - case 0: - return "", fmt.Errorf("missing IP address for Marathon application %s on task %s", app.ID, task.ID) - case 1: - return task.IPAddresses[0].IPAddress, nil - default: - if extraConf.Marathon.IPAddressIdx == math.MinInt32 { - return "", fmt.Errorf("found %d task IP addresses but missing IP address index for Marathon application %s on task %s", - numTaskIPAddresses, app.ID, task.ID) - } - if extraConf.Marathon.IPAddressIdx < 0 || extraConf.Marathon.IPAddressIdx > numTaskIPAddresses { - return "", fmt.Errorf("cannot use IP address index to select from %d task IP addresses for Marathon application %s on task %s", - numTaskIPAddresses, app.ID, task.ID) - } - - return task.IPAddresses[extraConf.Marathon.IPAddressIdx].IPAddress, nil - } -} - -func getPort(task marathon.Task, app marathon.Application, serverPort string) (string, error) { - port, err := processPorts(app, task, serverPort) - if err != nil { - return "", fmt.Errorf("unable to process ports for %s %s: %w", app.ID, task.ID, err) - } - - return strconv.Itoa(port), nil -} - -// processPorts returns the configured port. -// An explicitly specified port is preferred. If none is specified, it selects -// one of the available port. The first such found port is returned unless an -// optional index is provided. -func processPorts(app marathon.Application, task marathon.Task, serverPort string) (int, error) { - if len(serverPort) > 0 && !(strings.HasPrefix(serverPort, "index:") || strings.HasPrefix(serverPort, "name:")) { - port, err := strconv.Atoi(serverPort) - if err != nil { - return 0, err - } - - if port <= 0 { - return 0, fmt.Errorf("explicitly specified port %d must be greater than zero", port) - } else if port > 0 { - return port, nil - } - } - - if strings.HasPrefix(serverPort, "name:") { - name := strings.TrimPrefix(serverPort, "name:") - port := retrieveNamedPort(app, name) - - if port == 0 { - return 0, fmt.Errorf("no port with name %s", name) - } - - return port, nil - } - - ports := retrieveAvailablePorts(app, task) - if len(ports) == 0 { - return 0, errors.New("no port found") - } - - portIndex := 0 - if strings.HasPrefix(serverPort, "index:") { - indexString := strings.TrimPrefix(serverPort, "index:") - index, err := strconv.Atoi(indexString) - if err != nil { - return 0, err - } - - if index < 0 || index > len(ports)-1 { - return 0, fmt.Errorf("index %d must be within range (0, %d)", index, len(ports)-1) - } - - portIndex = index - } - - return ports[portIndex], nil -} - -func retrieveNamedPort(app marathon.Application, name string) int { - // Using port definition if available - if app.PortDefinitions != nil && len(*app.PortDefinitions) > 0 { - for _, def := range *app.PortDefinitions { - if def.Port != nil && *def.Port > 0 && def.Name == name { - return *def.Port - } - } - } - - // If using IP-per-task using this port definition - if app.IPAddressPerTask != nil && app.IPAddressPerTask.Discovery != nil && len(*(app.IPAddressPerTask.Discovery.Ports)) > 0 { - for _, def := range *(app.IPAddressPerTask.Discovery.Ports) { - if def.Number > 0 && def.Name == name { - return def.Number - } - } - } - - return 0 -} - -func retrieveAvailablePorts(app marathon.Application, task marathon.Task) []int { - // Using default port configuration - if len(task.Ports) > 0 { - return task.Ports - } - - // Using port definition if available - if app.PortDefinitions != nil && len(*app.PortDefinitions) > 0 { - var ports []int - for _, def := range *app.PortDefinitions { - if def.Port != nil { - ports = append(ports, *def.Port) - } - } - return ports - } - - // If using IP-per-task using this port definition - if app.IPAddressPerTask != nil && app.IPAddressPerTask.Discovery != nil && len(*(app.IPAddressPerTask.Discovery.Ports)) > 0 { - var ports []int - for _, def := range *(app.IPAddressPerTask.Discovery.Ports) { - ports = append(ports, def.Number) - } - return ports - } - - return []int{} -} diff --git a/pkg/provider/marathon/config_test.go b/pkg/provider/marathon/config_test.go deleted file mode 100644 index 8648c7e84..000000000 --- a/pkg/provider/marathon/config_test.go +++ /dev/null @@ -1,2447 +0,0 @@ -package marathon - -import ( - "context" - "math" - "testing" - "time" - - "github.com/gambol99/go-marathon" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" -) - -func Int(v int) *int { return &v } -func Bool(v bool) *bool { return &v } - -func TestGetConfigurationAPIErrors(t *testing.T) { - fakeClient := newFakeClient(true, marathon.Applications{}) - - p := &Provider{ - marathonClient: fakeClient, - } - - actualConfig := p.getConfigurations(context.Background()) - fakeClient.AssertExpectations(t) - - if actualConfig != nil { - t.Errorf("configuration should have been nil, got %v", actualConfig) - } -} - -func TestBuildConfiguration(t *testing.T) { - testCases := []struct { - desc string - applications *marathon.Applications - constraints string - defaultRule string - expected *dynamic.Configuration - }{ - { - desc: "simple application", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "filtered task", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80), taskState(taskStateStaging))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "multiple ports", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "with basic auth", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withLabel("traefik.http.middlewares.Middleware1.basicauth.users", "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), - withLabel("traefik.http.routers.app.middlewares", "Middleware1"), - withTasks(localhostTask(taskPorts(80))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - Middlewares: []string{"Middleware1"}, - }, - }, - Middlewares: map[string]*dynamic.Middleware{ - "Middleware1": { - BasicAuth: &dynamic.BasicAuth{ - Users: []string{ - "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", - "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - }, - }, - }, - }, - Services: map[string]*dynamic.Service{ - "app": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "TCP with IP allowlist", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - - withLabel("traefik.tcp.routers.Test.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.middlewares.Middleware1.ipallowlist.sourcerange", "foobar, fiibar"), - withLabel("traefik.tcp.routers.Test.middlewares", "Middleware1"), - withTasks(localhostTask(taskPorts(80))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "Test": { - Service: "app", - Rule: "HostSNI(`foo.bar`)", - Middlewares: []string{"Middleware1"}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{ - "Middleware1": { - IPAllowList: &dynamic.TCPIPAllowList{ - SourceRange: []string{"foobar", "fiibar"}, - }, - }, - }, - Services: map[string]*dynamic.TCPService{ - "app": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:80", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "2 applications in the same service", - applications: withApplications( - application( - appID("/foo-v000"), - withTasks(localhostTask(taskPorts(8080))), - - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"), - withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"), - ), - application( - appID("/foo-v001"), - withTasks(localhostTask(taskPorts(8081))), - - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"), - withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"), - ), - ), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8080", - }, - { - URL: "http://localhost:8081", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "2 applications with 2 tasks in the same service", - applications: withApplications( - application( - appID("/foo-v000"), - withTasks(localhostTask(taskPorts(8080))), - withTasks(localhostTask(taskPorts(8081))), - - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"), - withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"), - ), - application( - appID("/foo-v001"), - withTasks(localhostTask(taskPorts(8082))), - withTasks(localhostTask(taskPorts(8083))), - - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"), - withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"), - ), - ), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8080", - }, - { - URL: "http://localhost:8081", - }, - { - URL: "http://localhost:8082", - }, - { - URL: "http://localhost:8083", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "2 applications", - applications: withApplications( - application( - appID("/foo"), - withTasks(localhostTask(taskPorts(8080))), - ), - application( - appID("/bar"), - withTasks(localhostTask(taskPorts(8081))), - ), - ), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "foo": { - Service: "foo", - Rule: "Host(`foo.marathon.localhost`)", - }, - "bar": { - Service: "bar", - Rule: "Host(`bar.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "foo": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8080", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - "bar": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8081", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two tasks no labels", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80)), localhostTask(taskPorts(81))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - { - URL: "http://localhost:81", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "simple application with label on service", - applications: withApplications( - application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": {LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }}, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with labels", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.routers.Router1.service", "Service1"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`foo.com`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with rule label", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "app", - Rule: "Host(`foo.com`)", - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with rule label and one service", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`foo.com`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with rule label and two services", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - withLabel("traefik.http.services.Service2.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "Service2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with same service name and different passhostheader", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "false"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - "app2": { - Service: "Service1", - Rule: "Host(`app2.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two identical middleware", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "42"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "42"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - "app2": { - Service: "app2", - Rule: "Host(`app2.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{ - "Middleware1": { - InFlightReq: &dynamic.InFlightReq{ - Amount: 42, - }, - }, - }, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "app2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two different middlewares", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "42"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "41"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - "app2": { - Service: "app2", - Rule: "Host(`app2.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "app2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two different routers with same name", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`bar.com`)"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "app2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two identical routers with same name", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.services.Service1.LoadBalancer.passhostheader", "true"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - withLabel("traefik.http.services.Service1.LoadBalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "Router1": { - Service: "Service1", - Rule: "Host(`foo.com`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "two apps with two identical routers with same name", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - ), - application( - appID("/app2"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "app2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with wrong label", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.wrong.label", "tchouk"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with label port", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.LoadBalancer.server.scheme", "h2c"), - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "90"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "Service1", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "h2c://localhost:90", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with label port on two services", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.http.services.Service1.LoadBalancer.server.port", ""), - withLabel("traefik.http.services.Service2.LoadBalancer.server.port", "8080"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "Service1": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - "Service2": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:8080", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app without port", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask()), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app without port with middleware", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask()), - withLabel("traefik.http.middlewares.Middleware1.basicauth.users", "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with traefik.enable=false", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask()), - withLabel("traefik.enable", "false"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with traefik.enable=false", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask()), - withLabel("traefik.enable", "false"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with non matching constraint", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tags", "foo"), - )), - constraints: `Label("traefik.tags", "bar")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with non matching marathon constraint", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - constraint("rack_id:CLUSTER:rack-1"), - )), - constraints: `MarathonConstraint("rack_id:CLUSTER:rack-2")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with matching marathon constraint", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - constraint("rack_id:CLUSTER:rack-1"), - )), - constraints: `MarathonConstraint("rack_id:CLUSTER:rack-1")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with matching constraint", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tags", "bar"), - )), - constraints: `Label("traefik.tags", "bar")`, - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "app", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with group as subdomain rule", - defaultRule: `Host("{{ .Name | trimPrefix "/" | splitList "/" | strsToItfs | reverse | join "." }}.marathon.localhost")`, - applications: withApplications( - application( - appID("/a/b/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "a_b_app": { - Service: "a_b_app", - Rule: `Host("app.b.a.marathon.localhost")`, - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "a_b_app": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with tcp labels", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.routers.foo.tls", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "app", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "app": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:80", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with udp labels", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.udp.routers.foo.entrypoints", "mydns"), - )), - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{ - "foo": { - Service: "app", - EntryPoints: []string{"mydns"}, - }, - }, - Services: map[string]*dynamic.UDPService{ - "app": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "localhost:80", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with tcp labels without rule", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.tls", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "app": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:80", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with tcp labels with port", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.routers.foo.tls", "true"), - withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "foo", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with udp labels with port", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.udp.routers.foo.entrypoints", "mydns"), - withLabel("traefik.udp.services.foo.loadbalancer.server.port", "8080"), - )), - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{ - "foo": { - Service: "foo", - EntryPoints: []string{"mydns"}, - }, - }, - Services: map[string]*dynamic.UDPService{ - "foo": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - // TODO: replace or delete? - desc: "one app with tcp labels with port, with termination delay", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.routers.foo.tls", "true"), - withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "foo", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with tcp labels with port and http service", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"), - withLabel("traefik.tcp.routers.foo.tls", "true"), - withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"), - withLabel("traefik.http.services.bar.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "foo": { - Service: "foo", - Rule: "HostSNI(`foo.bar`)", - TLS: &dynamic.RouterTCPTLSConfig{}, - }, - }, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{ - "foo": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "bar", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "bar": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - { - desc: "one app with udp labels with port and http service", - applications: withApplications( - application( - appID("/app"), - appPorts(80, 81), - withTasks(localhostTask(taskPorts(80, 81))), - withLabel("traefik.udp.routers.foo.entrypoints", "mydns"), - withLabel("traefik.udp.services.foo.loadbalancer.server.port", "8080"), - withLabel("traefik.http.services.bar.loadbalancer.passhostheader", "true"), - )), - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{ - "foo": { - Service: "foo", - EntryPoints: []string{"mydns"}, - }, - }, - Services: map[string]*dynamic.UDPService{ - "foo": { - LoadBalancer: &dynamic.UDPServersLoadBalancer{ - Servers: []dynamic.UDPServer{ - { - Address: "localhost:8080", - }, - }, - }, - }, - }, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - ServersTransports: map[string]*dynamic.TCPServersTransport{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - Routers: map[string]*dynamic.Router{ - "app": { - Service: "bar", - Rule: "Host(`app.marathon.localhost`)", - }, - }, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "bar": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://localhost:80", - }, - }, - PassHostHeader: Bool(true), - ResponseForwarding: &dynamic.ResponseForwarding{ - FlushInterval: ptypes.Duration(100 * time.Millisecond), - }, - }, - }, - }, - ServersTransports: map[string]*dynamic.ServersTransport{}, - }, - }, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - defaultRule := "Host(`{{ normalize .Name }}.marathon.localhost`)" - if len(test.defaultRule) > 0 { - defaultRule = test.defaultRule - } - - p := &Provider{ - DefaultRule: defaultRule, - ExposedByDefault: true, - } - p.Constraints = test.constraints - - err := p.Init() - require.NoError(t, err) - - actualConfig := p.buildConfiguration(context.Background(), test.applications) - - assert.NotNil(t, actualConfig) - assert.Equal(t, test.expected, actualConfig) - }) - } -} - -func TestApplicationFilterEnabled(t *testing.T) { - testCases := []struct { - desc string - exposedByDefault bool - enabledLabel string - expected bool - }{ - { - desc: "exposed and tolerated by valid label value", - exposedByDefault: true, - enabledLabel: "true", - expected: true, - }, - { - desc: "exposed but overridden by label", - exposedByDefault: true, - enabledLabel: "false", - expected: false, - }, - { - desc: "non-exposed but overridden by label", - exposedByDefault: false, - enabledLabel: "true", - expected: true, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - provider := &Provider{ExposedByDefault: true} - - app := application(withLabel("traefik.enable", test.enabledLabel)) - - extraConf, err := provider.getConfiguration(app) - require.NoError(t, err) - - if provider.keepApplication(context.Background(), extraConf, stringValueMap(app.Labels)) != test.expected { - t.Errorf("got unexpected filtering = %t", !test.expected) - } - }) - } -} - -func TestGetServer(t *testing.T) { - type expected struct { - server dynamic.Server - error string - } - - testCases := []struct { - desc string - provider Provider - app marathon.Application - extraConf configuration - defaultServer dynamic.Server - expected expected - }{ - { - desc: "undefined host", - provider: Provider{}, - app: application(), - extraConf: configuration{}, - defaultServer: dynamic.Server{}, - expected: expected{ - error: `host is undefined for task "taskID" app ""`, - }, - }, - { - desc: "with task port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:80", - }, - }, - }, - { - desc: "without task port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - error: "unable to process ports for /app taskID: no port found", - }, - }, - { - desc: "with default server port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "88", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:88", - }, - }, - }, - { - desc: "with invalid default server port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "aaaa", - }, - expected: expected{ - error: `unable to process ports for /app taskID: strconv.Atoi: parsing "aaaa": invalid syntax`, - }, - }, - { - desc: "with negative default server port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "-6", - }, - expected: expected{ - error: `unable to process ports for /app taskID: explicitly specified port -6 must be greater than zero`, - }, - }, - { - desc: "with port index", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "index:1", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:81", - }, - }, - }, - { - desc: "with out of range port index", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "index:2", - }, - expected: expected{ - error: "unable to process ports for /app taskID: index 2 must be within range (0, 1)", - }, - }, - { - desc: "with invalid port index", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "index:aaa", - }, - expected: expected{ - error: `unable to process ports for /app taskID: strconv.Atoi: parsing "aaa": invalid syntax`, - }, - }, - { - desc: "with port name", - provider: Provider{}, - app: application( - appID("/app"), - portDefinition(80, "fist-port"), - portDefinition(81, "second-port"), - portDefinition(82, "third-port"), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "name:third-port", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:82", - }, - }, - }, - { - desc: "with port name not found", - provider: Provider{}, - app: application( - appID("/app"), - portDefinition(80, "fist-port"), - portDefinition(81, "second-port"), - portDefinition(82, "third-port"), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - Port: "name:other-name", - }, - expected: expected{ - error: `unable to process ports for /app taskID: no port with name other-name`, - }, - }, - { - desc: "with application port and no task port", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - portDefinition(80, "http"), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:80", - }, - }, - }, - { - desc: "with IP per task", - provider: Provider{}, - app: application( - appID("/app"), - appPorts(80), - ipAddrPerTask(88), - withTasks(localhostTask()), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://127.0.0.1:88", - }, - }, - }, - { - desc: "with container network", - provider: Provider{}, - app: application( - containerNetwork(), - appID("/app"), - appPorts(80), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://127.0.0.1:80", - }, - }, - }, - { - desc: "with bridge network", - provider: Provider{}, - app: application( - bridgeNetwork(), - appID("/app"), - appPorts(83), - withTasks(localhostTask(taskPorts(80, 81))), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://localhost:80", - }, - }, - }, - { - desc: "with several IP addresses on task", - provider: Provider{}, - app: application( - ipAddrPerTask(88), - appID("/app"), - appPorts(83), - withTasks( - task( - withTaskID("myTask"), - host("localhost"), - ipAddresses("127.0.0.1", "127.0.0.2"), - taskState(taskStateRunning), - )), - ), - extraConf: configuration{ - Marathon: specificConfiguration{ - IPAddressIdx: 0, - }, - }, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - server: dynamic.Server{ - URL: "http://127.0.0.1:88", - }, - }, - }, - { - desc: "with several IP addresses on task, undefined [MinInt32] IPAddressIdx", - provider: Provider{}, - app: application( - ipAddrPerTask(88), - appID("/app"), - appPorts(83), - withTasks( - task( - host("localhost"), - ipAddresses("127.0.0.1", "127.0.0.2"), - taskState(taskStateRunning), - )), - ), - extraConf: configuration{ - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - error: "found 2 task IP addresses but missing IP address index for Marathon application /app on task taskID", - }, - }, - { - desc: "with several IP addresses on task, IPAddressIdx out of range", - provider: Provider{}, - app: application( - ipAddrPerTask(88), - appID("/app"), - appPorts(83), - withTasks( - task( - host("localhost"), - ipAddresses("127.0.0.1", "127.0.0.2"), - taskState(taskStateRunning), - )), - ), - extraConf: configuration{ - Marathon: specificConfiguration{ - IPAddressIdx: 3, - }, - }, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - error: "cannot use IP address index to select from 2 task IP addresses for Marathon application /app on task taskID", - }, - }, - { - desc: "with task without IP address", - provider: Provider{}, - app: application( - ipAddrPerTask(88), - appID("/app"), - appPorts(83), - withTasks( - task( - host("localhost"), - taskState(taskStateRunning), - )), - ), - extraConf: configuration{}, - defaultServer: dynamic.Server{ - Scheme: "http", - }, - expected: expected{ - error: "missing IP address for Marathon application /app on task taskID", - }, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - task := task() - if len(test.app.Tasks) > 0 { - task = *test.app.Tasks[0] - } - - server, err := test.provider.getServer(test.app, task, test.extraConf, test.defaultServer) - if len(test.expected.error) > 0 { - require.EqualError(t, err, test.expected.error) - } else { - require.NoError(t, err) - - assert.Equal(t, test.expected.server, server) - } - }) - } -} diff --git a/pkg/provider/marathon/fake_client_test.go b/pkg/provider/marathon/fake_client_test.go deleted file mode 100644 index c30941482..000000000 --- a/pkg/provider/marathon/fake_client_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package marathon - -import ( - "errors" - - "github.com/gambol99/go-marathon" - "github.com/stretchr/testify/mock" - "github.com/traefik/traefik/v2/pkg/provider/marathon/mocks" -) - -type fakeClient struct { - mocks.Marathon -} - -func newFakeClient(applicationsError bool, applications marathon.Applications) *fakeClient { - // create an instance of our test object - fakeClient := new(fakeClient) - if applicationsError { - fakeClient.On("Applications", mock.Anything).Return(nil, errors.New("fake Marathon server error")) - } else { - fakeClient.On("Applications", mock.Anything).Return(&applications, nil) - } - return fakeClient -} diff --git a/pkg/provider/marathon/label.go b/pkg/provider/marathon/label.go deleted file mode 100644 index f6da87870..000000000 --- a/pkg/provider/marathon/label.go +++ /dev/null @@ -1,42 +0,0 @@ -package marathon - -import ( - "math" - - "github.com/gambol99/go-marathon" - "github.com/traefik/traefik/v2/pkg/config/label" -) - -type configuration struct { - Enable bool - Marathon specificConfiguration -} - -type specificConfiguration struct { - IPAddressIdx int -} - -func (p *Provider) getConfiguration(app marathon.Application) (configuration, error) { - labels := stringValueMap(app.Labels) - - conf := configuration{ - Enable: p.ExposedByDefault, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - } - - err := label.Decode(labels, &conf, "traefik.marathon.", "traefik.enable") - if err != nil { - return configuration{}, err - } - - return conf, nil -} - -func stringValueMap(mp *map[string]string) map[string]string { - if mp != nil { - return *mp - } - return make(map[string]string) -} diff --git a/pkg/provider/marathon/label_test.go b/pkg/provider/marathon/label_test.go deleted file mode 100644 index 472b91d23..000000000 --- a/pkg/provider/marathon/label_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package marathon - -import ( - "math" - "testing" - - "github.com/gambol99/go-marathon" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGetConfiguration(t *testing.T) { - testCases := []struct { - desc string - app marathon.Application - p Provider - expected configuration - }{ - { - desc: "Empty labels", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{}, - }, - p: Provider{ - ExposedByDefault: false, - }, - expected: configuration{ - Enable: false, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - { - desc: "label enable", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{ - "traefik.enable": "true", - }, - }, - p: Provider{ - ExposedByDefault: false, - }, - expected: configuration{ - Enable: true, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - { - desc: "Use ip address index", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{ - "traefik.marathon.IPAddressIdx": "4", - }, - }, - p: Provider{ - ExposedByDefault: false, - }, - expected: configuration{ - Enable: false, - Marathon: specificConfiguration{ - IPAddressIdx: 4, - }, - }, - }, - { - desc: "Use marathon constraints", - app: marathon.Application{ - Constraints: &[][]string{ - {"key", "value"}, - }, - Labels: &map[string]string{}, - }, - p: Provider{ - ExposedByDefault: false, - }, - expected: configuration{ - Enable: false, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - { - desc: "ExposedByDefault and no enable label", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{}, - }, - p: Provider{ - ExposedByDefault: true, - }, - expected: configuration{ - Enable: true, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - { - desc: "ExposedByDefault and enable label false", - app: marathon.Application{ - Constraints: &[][]string{}, - Labels: &map[string]string{ - "traefik.enable": "false", - }, - }, - p: Provider{ - ExposedByDefault: true, - }, - expected: configuration{ - Enable: false, - Marathon: specificConfiguration{ - IPAddressIdx: math.MinInt32, - }, - }, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - extraConf, err := test.p.getConfiguration(test.app) - require.NoError(t, err) - - assert.Equal(t, test.expected, extraConf) - }) - } -} diff --git a/pkg/provider/marathon/marathon.go b/pkg/provider/marathon/marathon.go deleted file mode 100644 index d4e8cccd8..000000000 --- a/pkg/provider/marathon/marathon.go +++ /dev/null @@ -1,221 +0,0 @@ -package marathon - -import ( - "context" - "fmt" - "net" - "net/http" - "net/url" - "text/template" - "time" - - "github.com/cenkalti/backoff/v4" - "github.com/gambol99/go-marathon" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/logs" - "github.com/traefik/traefik/v2/pkg/provider" - "github.com/traefik/traefik/v2/pkg/safe" - "github.com/traefik/traefik/v2/pkg/types" -) - -const ( - // DefaultTemplateRule The default template for the default rule. - DefaultTemplateRule = "Host(`{{ normalize .Name }}`)" - marathonEventIDs = marathon.EventIDApplications | - marathon.EventIDAddHealthCheck | - marathon.EventIDDeploymentSuccess | - marathon.EventIDDeploymentFailed | - marathon.EventIDDeploymentInfo | - marathon.EventIDDeploymentStepSuccess | - marathon.EventIDDeploymentStepFailed -) - -// TaskState denotes the Mesos state a task can have. -type TaskState string - -const ( - taskStateRunning TaskState = "TASK_RUNNING" - taskStateStaging TaskState = "TASK_STAGING" -) - -var _ provider.Provider = (*Provider)(nil) - -// Provider holds configuration of the provider. -type Provider struct { - Constraints string `description:"Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application." json:"constraints,omitempty" toml:"constraints,omitempty" yaml:"constraints,omitempty" export:"true"` - Trace bool `description:"Display additional provider logs." json:"trace,omitempty" toml:"trace,omitempty" yaml:"trace,omitempty" export:"true"` - Watch bool `description:"Watch provider." json:"watch,omitempty" toml:"watch,omitempty" yaml:"watch,omitempty" export:"true"` - Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"` - DefaultRule string `description:"Default rule." json:"defaultRule,omitempty" toml:"defaultRule,omitempty" yaml:"defaultRule,omitempty"` - ExposedByDefault bool `description:"Expose Marathon apps by default." json:"exposedByDefault,omitempty" toml:"exposedByDefault,omitempty" yaml:"exposedByDefault,omitempty" export:"true"` - DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header." json:"dcosToken,omitempty" toml:"dcosToken,omitempty" yaml:"dcosToken,omitempty" loggable:"false"` - TLS *types.ClientTLS `description:"Enable TLS support." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` - DialerTimeout ptypes.Duration `description:"Set a dialer timeout for Marathon." json:"dialerTimeout,omitempty" toml:"dialerTimeout,omitempty" yaml:"dialerTimeout,omitempty" export:"true"` - ResponseHeaderTimeout ptypes.Duration `description:"Set a response header timeout for Marathon." json:"responseHeaderTimeout,omitempty" toml:"responseHeaderTimeout,omitempty" yaml:"responseHeaderTimeout,omitempty" export:"true"` - TLSHandshakeTimeout ptypes.Duration `description:"Set a TLS handshake timeout for Marathon." json:"tlsHandshakeTimeout,omitempty" toml:"tlsHandshakeTimeout,omitempty" yaml:"tlsHandshakeTimeout,omitempty" export:"true"` - KeepAlive ptypes.Duration `description:"Set a TCP Keep Alive time." json:"keepAlive,omitempty" toml:"keepAlive,omitempty" yaml:"keepAlive,omitempty" export:"true"` - ForceTaskHostname bool `description:"Force to use the task's hostname." json:"forceTaskHostname,omitempty" toml:"forceTaskHostname,omitempty" yaml:"forceTaskHostname,omitempty" export:"true"` - Basic *Basic `description:"Enable basic authentication." json:"basic,omitempty" toml:"basic,omitempty" yaml:"basic,omitempty" export:"true"` - RespectReadinessChecks bool `description:"Filter out tasks with non-successful readiness checks during deployments." json:"respectReadinessChecks,omitempty" toml:"respectReadinessChecks,omitempty" yaml:"respectReadinessChecks,omitempty" export:"true"` - readyChecker *readinessChecker - marathonClient marathon.Marathon - defaultRuleTpl *template.Template -} - -// SetDefaults sets the default values. -func (p *Provider) SetDefaults() { - p.Watch = true - p.Endpoint = "http://127.0.0.1:8080" - p.ExposedByDefault = true - p.DialerTimeout = ptypes.Duration(5 * time.Second) - p.ResponseHeaderTimeout = ptypes.Duration(60 * time.Second) - p.TLSHandshakeTimeout = ptypes.Duration(5 * time.Second) - p.KeepAlive = ptypes.Duration(10 * time.Second) - p.DefaultRule = DefaultTemplateRule -} - -// Basic holds basic authentication specific configurations. -type Basic struct { - HTTPBasicAuthUser string `description:"Basic authentication User." json:"httpBasicAuthUser,omitempty" toml:"httpBasicAuthUser,omitempty" yaml:"httpBasicAuthUser,omitempty" loggable:"false"` - HTTPBasicPassword string `description:"Basic authentication Password." json:"httpBasicPassword,omitempty" toml:"httpBasicPassword,omitempty" yaml:"httpBasicPassword,omitempty" loggable:"false"` -} - -// Init the provider. -func (p *Provider) Init() error { - fm := template.FuncMap{ - "strsToItfs": func(values []string) []interface{} { - var r []interface{} - for _, v := range values { - r = append(r, v) - } - return r - }, - } - - defaultRuleTpl, err := provider.MakeDefaultRuleTemplate(p.DefaultRule, fm) - if err != nil { - return fmt.Errorf("error while parsing default rule: %w", err) - } - - p.defaultRuleTpl = defaultRuleTpl - return nil -} - -// Provide allows the marathon provider to provide configurations to traefik -// using the given configuration channel. -func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - logger := log.With().Str(logs.ProviderName, "marathon").Logger() - ctx := logger.WithContext(context.Background()) - - operation := func() error { - confg := marathon.NewDefaultConfig() - confg.URL = p.Endpoint - confg.EventsTransport = marathon.EventsTransportSSE - - if p.Trace { - confg.LogOutput = logs.NoLevel(logger, zerolog.DebugLevel) - } - - if p.Basic != nil { - confg.HTTPBasicAuthUser = p.Basic.HTTPBasicAuthUser - confg.HTTPBasicPassword = p.Basic.HTTPBasicPassword - } - var rc *readinessChecker - if p.RespectReadinessChecks { - logger.Debug().Msg("Enabling Marathon readiness checker") - rc = defaultReadinessChecker(p.Trace) - } - p.readyChecker = rc - - if len(p.DCOSToken) > 0 { - confg.DCOSToken = p.DCOSToken - } - TLSConfig, err := p.TLS.CreateTLSConfig(ctx) - if err != nil { - return fmt.Errorf("unable to create client TLS configuration: %w", err) - } - confg.HTTPClient = &http.Client{ - Transport: &http.Transport{ - DialContext: (&net.Dialer{ - KeepAlive: time.Duration(p.KeepAlive), - Timeout: time.Duration(p.DialerTimeout), - }).DialContext, - ResponseHeaderTimeout: time.Duration(p.ResponseHeaderTimeout), - TLSHandshakeTimeout: time.Duration(p.TLSHandshakeTimeout), - TLSClientConfig: TLSConfig, - }, - } - client, err := marathon.NewClient(confg) - if err != nil { - logger.Error().Err(err).Msg("Failed to create a client for marathon") - return err - } - p.marathonClient = client - - if p.Watch { - update, err := client.AddEventsListener(marathonEventIDs) - if err != nil { - logger.Error().Err(err).Msg("Failed to register for events") - return err - } - pool.GoCtx(func(ctxPool context.Context) { - defer close(update) - for { - select { - case <-ctxPool.Done(): - return - case event := <-update: - logger.Debug().Msgf("Received provider event %s", event) - - conf := p.getConfigurations(ctx) - if conf != nil { - configurationChan <- dynamic.Message{ - ProviderName: "marathon", - Configuration: conf, - } - } - } - } - }) - } - - configuration := p.getConfigurations(ctx) - configurationChan <- dynamic.Message{ - ProviderName: "marathon", - Configuration: configuration, - } - return nil - } - - notify := func(err error, time time.Duration) { - logger.Error().Err(err).Msgf("Provider error, retrying in %s", time) - } - err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctx), notify) - if err != nil { - logger.Error().Err(err).Msg("Cannot retrieve data") - } - return nil -} - -func (p *Provider) getConfigurations(ctx context.Context) *dynamic.Configuration { - applications, err := p.getApplications() - if err != nil { - log.Ctx(ctx).Error().Err(err).Msg("Failed to retrieve Marathon applications") - return nil - } - - return p.buildConfiguration(ctx, applications) -} - -func (p *Provider) getApplications() (*marathon.Applications, error) { - v := url.Values{} - v.Add("embed", "apps.tasks") - v.Add("embed", "apps.deployments") - v.Add("embed", "apps.readiness") - - return p.marathonClient.Applications(v) -} diff --git a/pkg/provider/marathon/mocks/Marathon.go b/pkg/provider/marathon/mocks/Marathon.go deleted file mode 100644 index d2506bc79..000000000 --- a/pkg/provider/marathon/mocks/Marathon.go +++ /dev/null @@ -1,1286 +0,0 @@ -// Package mocks Code generated by mockery v1.0.0. DO NOT EDIT. -// mockery -recursive -dir=vendor/github.com/gambol99/ -name=Marathon -output=provider/marathon/mocks -package mocks - -import ( - "net/url" - "time" - - "github.com/gambol99/go-marathon" - "github.com/stretchr/testify/mock" -) - -// Marathon is an autogenerated mock type for the Marathon type -type Marathon struct { - mock.Mock -} - -// AbdicateLeader provides a mock function with given fields: -func (_m *Marathon) AbdicateLeader() (string, error) { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// AddEventsListener provides a mock function with given fields: filter -func (_m *Marathon) AddEventsListener(filter int) (marathon.EventsChannel, error) { - ret := _m.Called(filter) - - var r0 marathon.EventsChannel - if rf, ok := ret.Get(0).(func(int) marathon.EventsChannel); ok { - r0 = rf(filter) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(marathon.EventsChannel) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(int) error); ok { - r1 = rf(filter) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// AllTasks provides a mock function with given fields: opts -func (_m *Marathon) AllTasks(opts *marathon.AllTasksOpts) (*marathon.Tasks, error) { - ret := _m.Called(opts) - - var r0 *marathon.Tasks - if rf, ok := ret.Get(0).(func(*marathon.AllTasksOpts) *marathon.Tasks); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Tasks) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.AllTasksOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Application provides a mock function with given fields: name -func (_m *Marathon) Application(name string) (*marathon.Application, error) { - ret := _m.Called(name) - - var r0 *marathon.Application - if rf, ok := ret.Get(0).(func(string) *marathon.Application); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Application) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationBy provides a mock function with given fields: name, opts -func (_m *Marathon) ApplicationBy(name string, opts *marathon.GetAppOpts) (*marathon.Application, error) { - ret := _m.Called(name, opts) - - var r0 *marathon.Application - if rf, ok := ret.Get(0).(func(string, *marathon.GetAppOpts) *marathon.Application); ok { - r0 = rf(name, opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Application) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.GetAppOpts) error); ok { - r1 = rf(name, opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationByVersion provides a mock function with given fields: name, version -func (_m *Marathon) ApplicationByVersion(name, version string) (*marathon.Application, error) { - ret := _m.Called(name, version) - - var r0 *marathon.Application - if rf, ok := ret.Get(0).(func(string, string) *marathon.Application); ok { - r0 = rf(name, version) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Application) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(name, version) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationDeployments provides a mock function with given fields: name -func (_m *Marathon) ApplicationDeployments(name string) ([]*marathon.DeploymentID, error) { - ret := _m.Called(name) - - var r0 []*marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string) []*marathon.DeploymentID); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationOK provides a mock function with given fields: name -func (_m *Marathon) ApplicationOK(name string) (bool, error) { - ret := _m.Called(name) - - var r0 bool - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(name) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ApplicationVersions provides a mock function with given fields: name -func (_m *Marathon) ApplicationVersions(name string) (*marathon.ApplicationVersions, error) { - ret := _m.Called(name) - - var r0 *marathon.ApplicationVersions - if rf, ok := ret.Get(0).(func(string) *marathon.ApplicationVersions); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.ApplicationVersions) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Applications provides a mock function with given fields: _a0 -func (_m *Marathon) Applications(_a0 url.Values) (*marathon.Applications, error) { - ret := _m.Called(_a0) - - var r0 *marathon.Applications - if rf, ok := ret.Get(0).(func(url.Values) *marathon.Applications); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Applications) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(url.Values) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// CreateApplication provides a mock function with given fields: application -func (_m *Marathon) CreateApplication(application *marathon.Application) (*marathon.Application, error) { - ret := _m.Called(application) - - var r0 *marathon.Application - if rf, ok := ret.Get(0).(func(*marathon.Application) *marathon.Application); ok { - r0 = rf(application) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Application) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.Application) error); ok { - r1 = rf(application) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// CreateGroup provides a mock function with given fields: group -func (_m *Marathon) CreateGroup(group *marathon.Group) error { - ret := _m.Called(group) - - var r0 error - if rf, ok := ret.Get(0).(func(*marathon.Group) error); ok { - r0 = rf(group) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// CreatePod provides a mock function with given fields: pod -func (_m *Marathon) CreatePod(pod *marathon.Pod) (*marathon.Pod, error) { - ret := _m.Called(pod) - - var r0 *marathon.Pod - if rf, ok := ret.Get(0).(func(*marathon.Pod) *marathon.Pod); ok { - r0 = rf(pod) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.Pod) error); ok { - r1 = rf(pod) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteApplication provides a mock function with given fields: name, force -func (_m *Marathon) DeleteApplication(name string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(name, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(name, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteDeployment provides a mock function with given fields: id, force -func (_m *Marathon) DeleteDeployment(id string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(id, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(id, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(id, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteGroup provides a mock function with given fields: name, force -func (_m *Marathon) DeleteGroup(name string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(name, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(name, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeletePod provides a mock function with given fields: name, force -func (_m *Marathon) DeletePod(name string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(name, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(name, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeletePodInstance provides a mock function with given fields: name, instance -func (_m *Marathon) DeletePodInstance(name, instance string) (*marathon.PodInstance, error) { - ret := _m.Called(name, instance) - - var r0 *marathon.PodInstance - if rf, ok := ret.Get(0).(func(string, string) *marathon.PodInstance); ok { - r0 = rf(name, instance) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.PodInstance) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(name, instance) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeletePodInstances provides a mock function with given fields: name, instances -func (_m *Marathon) DeletePodInstances(name string, instances []string) ([]*marathon.PodInstance, error) { - ret := _m.Called(name, instances) - - var r0 []*marathon.PodInstance - if rf, ok := ret.Get(0).(func(string, []string) []*marathon.PodInstance); ok { - r0 = rf(name, instances) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*marathon.PodInstance) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, []string) error); ok { - r1 = rf(name, instances) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DeleteQueueDelay provides a mock function with given fields: appID -func (_m *Marathon) DeleteQueueDelay(appID string) error { - ret := _m.Called(appID) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(appID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Deployments provides a mock function with given fields: -func (_m *Marathon) Deployments() ([]*marathon.Deployment, error) { - ret := _m.Called() - - var r0 []*marathon.Deployment - if rf, ok := ret.Get(0).(func() []*marathon.Deployment); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*marathon.Deployment) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetMarathonURL provides a mock function with given fields: -func (_m *Marathon) GetMarathonURL() string { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// Group provides a mock function with given fields: name -func (_m *Marathon) Group(name string) (*marathon.Group, error) { - ret := _m.Called(name) - - var r0 *marathon.Group - if rf, ok := ret.Get(0).(func(string) *marathon.Group); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Group) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GroupBy provides a mock function with given fields: name, opts -func (_m *Marathon) GroupBy(name string, opts *marathon.GetGroupOpts) (*marathon.Group, error) { - ret := _m.Called(name, opts) - - var r0 *marathon.Group - if rf, ok := ret.Get(0).(func(string, *marathon.GetGroupOpts) *marathon.Group); ok { - r0 = rf(name, opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Group) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.GetGroupOpts) error); ok { - r1 = rf(name, opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Groups provides a mock function with given fields: -func (_m *Marathon) Groups() (*marathon.Groups, error) { - ret := _m.Called() - - var r0 *marathon.Groups - if rf, ok := ret.Get(0).(func() *marathon.Groups); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Groups) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GroupsBy provides a mock function with given fields: opts -func (_m *Marathon) GroupsBy(opts *marathon.GetGroupOpts) (*marathon.Groups, error) { - ret := _m.Called(opts) - - var r0 *marathon.Groups - if rf, ok := ret.Get(0).(func(*marathon.GetGroupOpts) *marathon.Groups); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Groups) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.GetGroupOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// HasApplicationVersion provides a mock function with given fields: name, version -func (_m *Marathon) HasApplicationVersion(name, version string) (bool, error) { - ret := _m.Called(name, version) - - var r0 bool - if rf, ok := ret.Get(0).(func(string, string) bool); ok { - r0 = rf(name, version) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(name, version) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// HasDeployment provides a mock function with given fields: id -func (_m *Marathon) HasDeployment(id string) (bool, error) { - ret := _m.Called(id) - - var r0 bool - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(id) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// HasGroup provides a mock function with given fields: name -func (_m *Marathon) HasGroup(name string) (bool, error) { - ret := _m.Called(name) - - var r0 bool - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(name) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Info provides a mock function with given fields: -func (_m *Marathon) Info() (*marathon.Info, error) { - ret := _m.Called() - - var r0 *marathon.Info - if rf, ok := ret.Get(0).(func() *marathon.Info); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Info) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// KillApplicationTasks provides a mock function with given fields: applicationID, opts -func (_m *Marathon) KillApplicationTasks(applicationID string, opts *marathon.KillApplicationTasksOpts) (*marathon.Tasks, error) { - ret := _m.Called(applicationID, opts) - - var r0 *marathon.Tasks - if rf, ok := ret.Get(0).(func(string, *marathon.KillApplicationTasksOpts) *marathon.Tasks); ok { - r0 = rf(applicationID, opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Tasks) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.KillApplicationTasksOpts) error); ok { - r1 = rf(applicationID, opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// KillTask provides a mock function with given fields: taskID, opts -func (_m *Marathon) KillTask(taskID string, opts *marathon.KillTaskOpts) (*marathon.Task, error) { - ret := _m.Called(taskID, opts) - - var r0 *marathon.Task - if rf, ok := ret.Get(0).(func(string, *marathon.KillTaskOpts) *marathon.Task); ok { - r0 = rf(taskID, opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Task) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.KillTaskOpts) error); ok { - r1 = rf(taskID, opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// KillTasks provides a mock function with given fields: taskIDs, opts -func (_m *Marathon) KillTasks(taskIDs []string, opts *marathon.KillTaskOpts) error { - ret := _m.Called(taskIDs, opts) - - var r0 error - if rf, ok := ret.Get(0).(func([]string, *marathon.KillTaskOpts) error); ok { - r0 = rf(taskIDs, opts) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Leader provides a mock function with given fields: -func (_m *Marathon) Leader() (string, error) { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ListApplications provides a mock function with given fields: _a0 -func (_m *Marathon) ListApplications(_a0 url.Values) ([]string, error) { - ret := _m.Called(_a0) - - var r0 []string - if rf, ok := ret.Get(0).(func(url.Values) []string); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(url.Values) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Ping provides a mock function with given fields: -func (_m *Marathon) Ping() (bool, error) { - ret := _m.Called() - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Pod provides a mock function with given fields: name -func (_m *Marathon) Pod(name string) (*marathon.Pod, error) { - ret := _m.Called(name) - - var r0 *marathon.Pod - if rf, ok := ret.Get(0).(func(string) *marathon.Pod); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PodByVersion provides a mock function with given fields: name, version -func (_m *Marathon) PodByVersion(name, version string) (*marathon.Pod, error) { - ret := _m.Called(name, version) - - var r0 *marathon.Pod - if rf, ok := ret.Get(0).(func(string, string) *marathon.Pod); ok { - r0 = rf(name, version) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(name, version) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PodIsRunning provides a mock function with given fields: name -func (_m *Marathon) PodIsRunning(name string) bool { - ret := _m.Called(name) - - var r0 bool - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(name) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// PodStatus provides a mock function with given fields: name -func (_m *Marathon) PodStatus(name string) (*marathon.PodStatus, error) { - ret := _m.Called(name) - - var r0 *marathon.PodStatus - if rf, ok := ret.Get(0).(func(string) *marathon.PodStatus); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.PodStatus) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PodStatuses provides a mock function with given fields: -func (_m *Marathon) PodStatuses() ([]*marathon.PodStatus, error) { - ret := _m.Called() - - var r0 []*marathon.PodStatus - if rf, ok := ret.Get(0).(func() []*marathon.PodStatus); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*marathon.PodStatus) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PodVersions provides a mock function with given fields: name -func (_m *Marathon) PodVersions(name string) ([]string, error) { - ret := _m.Called(name) - - var r0 []string - if rf, ok := ret.Get(0).(func(string) []string); ok { - r0 = rf(name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Pods provides a mock function with given fields: -func (_m *Marathon) Pods() ([]marathon.Pod, error) { - ret := _m.Called() - - var r0 []marathon.Pod - if rf, ok := ret.Get(0).(func() []marathon.Pod); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Queue provides a mock function with given fields: -func (_m *Marathon) Queue() (*marathon.Queue, error) { - ret := _m.Called() - - var r0 *marathon.Queue - if rf, ok := ret.Get(0).(func() *marathon.Queue); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Queue) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RemoveEventsListener provides a mock function with given fields: channel -func (_m *Marathon) RemoveEventsListener(channel marathon.EventsChannel) { - _m.Called(channel) -} - -// RestartApplication provides a mock function with given fields: name, force -func (_m *Marathon) RestartApplication(name string, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok { - r0 = rf(name, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = rf(name, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ScaleApplicationInstances provides a mock function with given fields: name, instances, force -func (_m *Marathon) ScaleApplicationInstances(name string, instances int, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(name, instances, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, int, bool) *marathon.DeploymentID); ok { - r0 = rf(name, instances, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, int, bool) error); ok { - r1 = rf(name, instances, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// SetApplicationVersion provides a mock function with given fields: name, version -func (_m *Marathon) SetApplicationVersion(name string, version *marathon.ApplicationVersion) (*marathon.DeploymentID, error) { - ret := _m.Called(name, version) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, *marathon.ApplicationVersion) *marathon.DeploymentID); ok { - r0 = rf(name, version) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.ApplicationVersion) error); ok { - r1 = rf(name, version) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Subscribe provides a mock function with given fields: _a0 -func (_m *Marathon) Subscribe(_a0 string) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Subscriptions provides a mock function with given fields: -func (_m *Marathon) Subscriptions() (*marathon.Subscriptions, error) { - ret := _m.Called() - - var r0 *marathon.Subscriptions - if rf, ok := ret.Get(0).(func() *marathon.Subscriptions); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Subscriptions) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// SupportsPods provides a mock function with given fields: -func (_m *Marathon) SupportsPods() (bool, error) { - ret := _m.Called() - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// TaskEndpoints provides a mock function with given fields: name, port, healthCheck -func (_m *Marathon) TaskEndpoints(name string, port int, healthCheck bool) ([]string, error) { - ret := _m.Called(name, port, healthCheck) - - var r0 []string - if rf, ok := ret.Get(0).(func(string, int, bool) []string); ok { - r0 = rf(name, port, healthCheck) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, int, bool) error); ok { - r1 = rf(name, port, healthCheck) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Tasks provides a mock function with given fields: application -func (_m *Marathon) Tasks(application string) (*marathon.Tasks, error) { - ret := _m.Called(application) - - var r0 *marathon.Tasks - if rf, ok := ret.Get(0).(func(string) *marathon.Tasks); ok { - r0 = rf(application) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Tasks) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(application) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Unsubscribe provides a mock function with given fields: _a0 -func (_m *Marathon) Unsubscribe(_a0 string) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// UpdateApplication provides a mock function with given fields: application, force -func (_m *Marathon) UpdateApplication(application *marathon.Application, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(application, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(*marathon.Application, bool) *marathon.DeploymentID); ok { - r0 = rf(application, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.Application, bool) error); ok { - r1 = rf(application, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// UpdateGroup provides a mock function with given fields: id, group, force -func (_m *Marathon) UpdateGroup(id string, group *marathon.Group, force bool) (*marathon.DeploymentID, error) { - ret := _m.Called(id, group, force) - - var r0 *marathon.DeploymentID - if rf, ok := ret.Get(0).(func(string, *marathon.Group, bool) *marathon.DeploymentID); ok { - r0 = rf(id, group, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.DeploymentID) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, *marathon.Group, bool) error); ok { - r1 = rf(id, group, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// UpdatePod provides a mock function with given fields: pod, force -func (_m *Marathon) UpdatePod(pod *marathon.Pod, force bool) (*marathon.Pod, error) { - ret := _m.Called(pod, force) - - var r0 *marathon.Pod - if rf, ok := ret.Get(0).(func(*marathon.Pod, bool) *marathon.Pod); ok { - r0 = rf(pod, force) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*marathon.Pod) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(*marathon.Pod, bool) error); ok { - r1 = rf(pod, force) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// WaitOnApplication provides a mock function with given fields: name, timeout -func (_m *Marathon) WaitOnApplication(name string, timeout time.Duration) error { - ret := _m.Called(name, timeout) - - var r0 error - if rf, ok := ret.Get(0).(func(string, time.Duration) error); ok { - r0 = rf(name, timeout) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// WaitOnDeployment provides a mock function with given fields: id, timeout -func (_m *Marathon) WaitOnDeployment(id string, timeout time.Duration) error { - ret := _m.Called(id, timeout) - - var r0 error - if rf, ok := ret.Get(0).(func(string, time.Duration) error); ok { - r0 = rf(id, timeout) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// WaitOnGroup provides a mock function with given fields: name, timeout -func (_m *Marathon) WaitOnGroup(name string, timeout time.Duration) error { - ret := _m.Called(name, timeout) - - var r0 error - if rf, ok := ret.Get(0).(func(string, time.Duration) error); ok { - r0 = rf(name, timeout) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// WaitOnPod provides a mock function with given fields: name, timeout -func (_m *Marathon) WaitOnPod(name string, timeout time.Duration) error { - ret := _m.Called(name, timeout) - - var r0 error - if rf, ok := ret.Get(0).(func(string, time.Duration) error); ok { - r0 = rf(name, timeout) - } else { - r0 = ret.Error(0) - } - - return r0 -} diff --git a/pkg/provider/marathon/readiness.go b/pkg/provider/marathon/readiness.go deleted file mode 100644 index 76785df13..000000000 --- a/pkg/provider/marathon/readiness.go +++ /dev/null @@ -1,122 +0,0 @@ -package marathon - -import ( - "time" - - "github.com/gambol99/go-marathon" - "github.com/rs/zerolog/log" -) - -const ( - // readinessCheckDefaultTimeout is the default timeout for a readiness - // check if no check timeout is specified on the application spec. This - // should really never be the case, but better be safe than sorry. - readinessCheckDefaultTimeout = 10 * time.Second - // readinessCheckSafetyMargin is some buffer duration to account for - // small offsets in readiness check execution. - readinessCheckSafetyMargin = 5 * time.Second - readinessLogHeader = "Marathon readiness check: " -) - -type readinessChecker struct { - checkDefaultTimeout time.Duration - checkSafetyMargin time.Duration - traceLogging bool -} - -func defaultReadinessChecker(isTraceLogging bool) *readinessChecker { - return &readinessChecker{ - checkDefaultTimeout: readinessCheckDefaultTimeout, - checkSafetyMargin: readinessCheckSafetyMargin, - traceLogging: isTraceLogging, - } -} - -func (rc *readinessChecker) Do(task marathon.Task, app marathon.Application) bool { - if rc == nil { - // Readiness checker disabled. - return true - } - - switch { - case len(app.Deployments) == 0: - // We only care about readiness during deployments; post-deployment readiness - // can be covered by a periodic post-deployment probe (i.e., Traefik health checks). - rc.tracef("task %s app %s: ready = true [no deployment ongoing]", task.ID, app.ID) - return true - - case app.ReadinessChecks == nil || len(*app.ReadinessChecks) == 0: - // Applications without configured readiness checks are always considered - // ready. - rc.tracef("task %s app %s: ready = true [no readiness checks on app]", task.ID, app.ID) - return true - } - - // Loop through all readiness check results and return the results for - // matching task IDs. - if app.ReadinessCheckResults != nil { - for _, readinessCheckResult := range *app.ReadinessCheckResults { - if readinessCheckResult.TaskID == task.ID { - rc.tracef("task %s app %s: ready = %t [evaluating readiness check ready state]", task.ID, app.ID, readinessCheckResult.Ready) - return readinessCheckResult.Ready - } - } - } - - // There's a corner case sometimes hit where the first new task of a - // deployment goes from TASK_STAGING to TASK_RUNNING without a corresponding - // readiness check result being included in the API response. This only happens - // in a very short (yet unlucky) time frame and does not repeat for subsequent - // tasks of the same deployment. - // Complicating matters, the situation may occur for both initially deploying - // applications as well as rolling-upgraded ones where one or more tasks from - // a previous deployment exist already and are joined by new tasks from a - // subsequent deployment. We must always make sure that pre-existing tasks - // maintain their ready state while newly launched tasks must be considered - // unready until a check result appears. - // We distinguish the two cases by comparing the current time with the start - // time of the task: It should take Marathon at most one readiness check timeout - // interval (plus some safety margin to account for the delayed nature of - // distributed systems) for readiness check results to be returned along the API - // response. Once the task turns old enough, we assume it to be part of a - // pre-existing deployment and mark it as ready. Note that it is okay to err - // on the side of caution and consider a task unready until the safety time - // window has elapsed because a newly created task should be readiness-checked - // and be given a result fairly shortly after its creation (i.e., on the scale - // of seconds). - readinessCheckTimeoutSecs := (*app.ReadinessChecks)[0].TimeoutSeconds - readinessCheckTimeout := time.Duration(readinessCheckTimeoutSecs) * time.Second - if readinessCheckTimeout == 0 { - rc.tracef("task %s app %s: readiness check timeout not set, using default value %s", task.ID, app.ID, rc.checkDefaultTimeout) - readinessCheckTimeout = rc.checkDefaultTimeout - } else { - readinessCheckTimeout += rc.checkSafetyMargin - } - - startTime, err := time.Parse(time.RFC3339, task.StartedAt) - if err != nil { - // An unparseable start time should never occur; if it does, we assume the - // problem should be surfaced as quickly as possible, which is easiest if - // we shun the task from rotation. - log.Warn().Err(err).Msgf("Failed to parse start-time %s of task %s from application %s (assuming unready)", task.StartedAt, task.ID, app.ID) - return false - } - - since := time.Since(startTime) - if since < readinessCheckTimeout { - rc.tracef("task %s app %s: ready = false [task with start-time %s not within assumed check timeout window of %s (elapsed time since task start: %s)]", task.ID, app.ID, startTime.Format(time.RFC3339), readinessCheckTimeout, since) - return false - } - - // Finally, we can be certain this task is not part of the deployment (i.e., - // it's an old task that's going to transition into the TASK_KILLING and/or - // TASK_KILLED state as new tasks' readiness checks gradually turn green.) - rc.tracef("task %s app %s: ready = true [task with start-time %s not involved in deployment (elapsed time since task start: %s)]", task.ID, app.ID, startTime.Format(time.RFC3339), since) - return true -} - -func (rc *readinessChecker) tracef(format string, args ...interface{}) { - if rc.traceLogging { - log.Debug().Msgf(readinessLogHeader+format, args...) - } -} diff --git a/pkg/provider/marathon/readiness_test.go b/pkg/provider/marathon/readiness_test.go deleted file mode 100644 index 8d61c01c4..000000000 --- a/pkg/provider/marathon/readiness_test.go +++ /dev/null @@ -1,134 +0,0 @@ -package marathon - -import ( - "testing" - "time" - - "github.com/gambol99/go-marathon" -) - -func testReadinessChecker() *readinessChecker { - return defaultReadinessChecker(false) -} - -func TestDisabledReadinessChecker(t *testing.T) { - var rc *readinessChecker - tsk := task() - app := application( - deployments("deploymentId"), - readinessCheck(0), - readinessCheckResult(testTaskName, false), - ) - - if ready := rc.Do(tsk, app); !ready { - t.Error("expected ready = true") - } -} - -func TestEnabledReadinessChecker(t *testing.T) { - tests := []struct { - desc string - task marathon.Task - app marathon.Application - rc readinessChecker - expectedReady bool - }{ - { - desc: "no deployment running", - task: task(), - app: application(), - expectedReady: true, - }, - { - desc: "no readiness checks defined", - task: task(), - app: application(deployments("deploymentId")), - expectedReady: true, - }, - { - desc: "readiness check result negative", - task: task(), - app: application( - deployments("deploymentId"), - readinessCheck(0), - readinessCheckResult("otherTaskID", true), - readinessCheckResult(testTaskName, false), - ), - expectedReady: false, - }, - { - desc: "readiness check result positive", - task: task(), - app: application( - deployments("deploymentId"), - readinessCheck(0), - readinessCheckResult("otherTaskID", false), - readinessCheckResult(testTaskName, true), - ), - expectedReady: true, - }, - { - desc: "no readiness check result with default timeout", - task: task(startedAtFromNow(3 * time.Minute)), - app: application( - deployments("deploymentId"), - readinessCheck(0), - ), - rc: readinessChecker{ - checkDefaultTimeout: 5 * time.Minute, - }, - expectedReady: false, - }, - { - desc: "no readiness check result with readiness check timeout", - task: task(startedAtFromNow(4 * time.Minute)), - app: application( - deployments("deploymentId"), - readinessCheck(3*time.Minute), - ), - rc: readinessChecker{ - checkSafetyMargin: 3 * time.Minute, - }, - expectedReady: false, - }, - { - desc: "invalid task start time", - task: task(startedAt("invalid")), - app: application( - deployments("deploymentId"), - readinessCheck(0), - ), - expectedReady: false, - }, - { - desc: "task not involved in deployment", - task: task(startedAtFromNow(1 * time.Hour)), - app: application( - deployments("deploymentId"), - readinessCheck(0), - ), - rc: readinessChecker{ - checkDefaultTimeout: 10 * time.Second, - }, - expectedReady: true, - }, - } - - for _, test := range tests { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - rc := testReadinessChecker() - if test.rc.checkDefaultTimeout > 0 { - rc.checkDefaultTimeout = test.rc.checkDefaultTimeout - } - if test.rc.checkSafetyMargin > 0 { - rc.checkSafetyMargin = test.rc.checkSafetyMargin - } - actualReady := test.rc.Do(test.task, test.app) - if actualReady != test.expectedReady { - t.Errorf("actual ready = %t, expected ready = %t", actualReady, test.expectedReady) - } - }) - } -} diff --git a/pkg/redactor/redactor_config_test.go b/pkg/redactor/redactor_config_test.go index 3c564c7a3..468b34251 100644 --- a/pkg/redactor/redactor_config_test.go +++ b/pkg/redactor/redactor_config_test.go @@ -28,7 +28,6 @@ import ( "github.com/traefik/traefik/v2/pkg/provider/kv/etcd" "github.com/traefik/traefik/v2/pkg/provider/kv/redis" "github.com/traefik/traefik/v2/pkg/provider/kv/zk" - "github.com/traefik/traefik/v2/pkg/provider/marathon" "github.com/traefik/traefik/v2/pkg/provider/rest" traefiktls "github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/tracing/datadog" @@ -610,32 +609,6 @@ func TestDo_staticConfiguration(t *testing.T) { HTTPClientTimeout: 42, } - config.Providers.Marathon = &marathon.Provider{ - Constraints: `Label("foo", "bar")`, - Trace: true, - Watch: true, - Endpoint: "foobar", - DefaultRule: "PathPrefix(`/`)", - ExposedByDefault: true, - DCOSToken: "foobar", - TLS: &types.ClientTLS{ - CA: "myCa", - Cert: "mycert.pem", - Key: "mycert.key", - InsecureSkipVerify: true, - }, - DialerTimeout: 42, - ResponseHeaderTimeout: 42, - TLSHandshakeTimeout: 42, - KeepAlive: 42, - ForceTaskHostname: true, - Basic: &marathon.Basic{ - HTTPBasicAuthUser: "user", - HTTPBasicPassword: "password", - }, - RespectReadinessChecks: true, - } - config.Providers.KubernetesIngress = &ingress.Provider{ Endpoint: "MyEndpoint", Token: "MyToken", diff --git a/pkg/redactor/testdata/anonymized-static-config.json b/pkg/redactor/testdata/anonymized-static-config.json index 1b116aaaf..35a447ef4 100644 --- a/pkg/redactor/testdata/anonymized-static-config.json +++ b/pkg/redactor/testdata/anonymized-static-config.json @@ -112,31 +112,6 @@ "filename": "file Filename", "debugLogGeneratedTemplate": true }, - "marathon": { - "constraints": "Label(\"foo\", \"bar\")", - "trace": true, - "watch": true, - "endpoint": "xxxx", - "defaultRule": "xxxx", - "exposedByDefault": true, - "dcosToken": "xxxx", - "tls": { - "ca": "xxxx", - "cert": "xxxx", - "key": "xxxx", - "insecureSkipVerify": true - }, - "dialerTimeout": "42ns", - "responseHeaderTimeout": "42ns", - "tlsHandshakeTimeout": "42ns", - "keepAlive": "42ns", - "forceTaskHostname": true, - "basic": { - "httpBasicAuthUser": "xxxx", - "httpBasicPassword": "xxxx" - }, - "respectReadinessChecks": true - }, "kubernetesIngress": { "endpoint": "xxxx", "token": "xxxx", diff --git a/pkg/redactor/testdata/example.json b/pkg/redactor/testdata/example.json index 5e5aa7f0a..3dd94d238 100644 --- a/pkg/redactor/testdata/example.json +++ b/pkg/redactor/testdata/example.json @@ -65,7 +65,6 @@ "Docker": null, "File": null, "Web": null, - "Marathon": null, "Consul": null, "ConsulCatalog": null, "Etcd": null, @@ -73,7 +72,6 @@ "Boltdb": null, "KubernetesIngress": null, "KubernetesCRD": null, - "Mesos": null, "Eureka": null, "ECS": null, "DynamoDB": null, diff --git a/pkg/redactor/testdata/expected.json b/pkg/redactor/testdata/expected.json index 22305449a..5849375f8 100644 --- a/pkg/redactor/testdata/expected.json +++ b/pkg/redactor/testdata/expected.json @@ -65,7 +65,6 @@ "Docker": null, "File": null, "Web": null, - "Marathon": null, "Consul": null, "ConsulCatalog": null, "Etcd": null, @@ -73,7 +72,6 @@ "Boltdb": null, "KubernetesIngress": null, "KubernetesCRD": null, - "Mesos": null, "Eureka": null, "ECS": null, "DynamoDB": null,