Compare commits

...

19 Commits

Author SHA1 Message Date
Ludovic Fernandez
b77bb690de Prepare release v2.0.0-rc2 2019-09-03 21:18:03 +02:00
Ludovic Fernandez
f843f260ee fix: stripPrefix and stripPrefixRegex. 2019-09-03 20:32:03 +02:00
Julien Salleyron
770b3739e0 The chain middleware in k8s use middlewareRef 2019-09-03 19:20:04 +02:00
Jean-Baptiste Doumenjou
261e7c1744 Fix some documentation issues 2019-09-03 18:02:05 +02:00
Ludovic Fernandez
10acbb8d92 Don't panic with undefined middleware 2019-09-03 15:22:05 +02:00
Ludovic Fernandez
a917115a85 fix buffering middleware 2019-09-03 15:02:05 +02:00
Michael
b8ed6f1588 Re enable ratelimit integration tests 2019-09-03 14:34:04 +02:00
Michael
3ed57e01a6 Update go version to go 1.13rc2 2019-09-03 12:18:03 +02:00
Bas van Beek
cb7c5a8ca1 Update Zipkin OpenTracing driver to latest 0.4.3 release 2019-09-03 11:52:04 +02:00
Ludovic Fernandez
07eb9c5970 Update restrictions in the documentation. 2019-09-02 03:26:04 -07:00
Ludovic Fernandez
306e5081d9 fix: Datadog case. 2019-09-02 03:18:04 -07:00
Ludovic Fernandez
259c7adc81 deep-copy for MirrorService 2019-09-02 02:54:04 -07:00
Ludovic Fernandez
af9762cf32 Improve API for the web UI 2019-09-02 02:38:04 -07:00
Ludovic Fernandez
17554202f6 fix: stripPrefixRegex documentation. 2019-09-02 01:52:04 -07:00
Jean-Baptiste Doumenjou
0d9cf697fa Base of the migration guide
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-08-31 00:28:04 -07:00
Julien Salleyron
df0dd2f5e6 Add errors about unknown entryPoint in runtime api 2019-08-29 03:38:04 -07:00
Julien Salleyron
38508f9a9c Fix recovered panic when websocket is mirrored 2019-08-29 01:28:05 -07:00
Michael
b113972bcf Fix trailing slash with check new version 2019-08-29 00:56:04 -07:00
Michael
72e67bf4e9 Rest provider icon in the webui 2019-08-28 05:52:05 -07:00
123 changed files with 2416 additions and 654 deletions

View File

@@ -21,7 +21,7 @@ if [ -n "$SHOULD_TEST" ]; then docker version; fi
export GO_VERSION=1.12
if [ -f "./go.mod" ]; then GO_VERSION="$(grep '^go .*' go.mod | awk '{print $2}')"; export GO_VERSION; fi
if [ "${GO_VERSION}" == '1.13' ]; then export GO_VERSION=1.13rc1; fi
if [ "${GO_VERSION}" == '1.13' ]; then export GO_VERSION=1.13rc2; fi
echo "Selected Go version: ${GO_VERSION}"
if [ -f "./.semaphoreci/golang.sh" ]; then ./.semaphoreci/golang.sh; fi

View File

@@ -1,5 +1,30 @@
# Change Log
## [v2.0.0-rc2](https://github.com/containous/traefik/tree/v2.0.0-rc2) (2019-09-03)
[All Commits](https://github.com/containous/traefik/compare/v2.0.0-rc1...v2.0.0-rc2)
**Enhancements:**
- **[api]** Improve API for the web UI ([#5267](https://github.com/containous/traefik/pull/5267) by [ldez](https://github.com/ldez))
- **[middleware,tracing]** Re enable ratelimit integration tests ([#5288](https://github.com/containous/traefik/pull/5288) by [mmatur](https://github.com/mmatur))
- **[tracing]** Update Zipkin OpenTracing driver to latest 0.4.3 release ([#5283](https://github.com/containous/traefik/pull/5283) by [basvanbeek](https://github.com/basvanbeek))
**Bug fixes:**
- **[api]** Add errors about unknown entryPoint in runtime api ([#5265](https://github.com/containous/traefik/pull/5265) by [juliens](https://github.com/juliens))
- **[metrics,tracing]** fix: Datadog case. ([#5272](https://github.com/containous/traefik/pull/5272) by [ldez](https://github.com/ldez))
- **[middleware,k8s,k8s/crd]** The chain middleware in k8s use middlewareRef ([#5290](https://github.com/containous/traefik/pull/5290) by [juliens](https://github.com/juliens))
- **[middleware]** Don&#39;t panic with undefined middleware ([#5289](https://github.com/containous/traefik/pull/5289) by [ldez](https://github.com/ldez))
- **[middleware]** fix buffering middleware ([#5281](https://github.com/containous/traefik/pull/5281) by [ldez](https://github.com/ldez))
- **[middleware]** fix: stripPrefix and stripPrefixRegex. ([#5291](https://github.com/containous/traefik/pull/5291) by [ldez](https://github.com/ldez))
- **[service,websocket]** Fix recovered panic when websocket is mirrored ([#5255](https://github.com/containous/traefik/pull/5255) by [juliens](https://github.com/juliens))
- **[webui]** Rest provider icon in the webui ([#5261](https://github.com/containous/traefik/pull/5261) by [mmatur](https://github.com/mmatur))
- Fix trailing slash with check new version ([#5266](https://github.com/containous/traefik/pull/5266) by [mmatur](https://github.com/mmatur))
**Documentation:**
- **[middleware]** fix: stripPrefixRegex documentation. ([#5273](https://github.com/containous/traefik/pull/5273) by [ldez](https://github.com/ldez))
- Fix some documentation issues ([#5286](https://github.com/containous/traefik/pull/5286) by [jbdoumenjou](https://github.com/jbdoumenjou))
- Update restrictions in the documentation. ([#5270](https://github.com/containous/traefik/pull/5270) by [ldez](https://github.com/ldez))
- Base of the migration guide ([#5263](https://github.com/containous/traefik/pull/5263) by [jbdoumenjou](https://github.com/jbdoumenjou))
## [v2.0.0-rc1](https://github.com/containous/traefik/tree/v2.0.0-rc1) (2019-08-26)
[All Commits](https://github.com/containous/traefik/compare/v2.0.0-beta1...v2.0.0-rc1)
@@ -217,7 +242,7 @@
- **[api,authentication]** Remove authentication hashes from API ([#4918](https://github.com/containous/traefik/pull/4918) by [ldez](https://github.com/ldez))
- **[consul]** Enhance KV logs. ([#4877](https://github.com/containous/traefik/pull/4877) by [ldez](https://github.com/ldez))
- **[k8s]** Fix kubernetes template for backend responseforwarding flushinterval setting ([#4901](https://github.com/containous/traefik/pull/4901) by [ravilr](https://github.com/ravilr))
- **[metrics]** Upgraded DataDog tracing library to 1.13.0 ([#4878](https://github.com/containous/traefik/pull/4878) by [aantono](https://github.com/aantono))
- **[metrics]** Upgraded Datadog tracing library to 1.13.0 ([#4878](https://github.com/containous/traefik/pull/4878) by [aantono](https://github.com/aantono))
- **[server]** Add missing callback on close of hijacked connections ([#4900](https://github.com/containous/traefik/pull/4900) by [ravilr](https://github.com/ravilr))
**Documentation:**
@@ -419,7 +444,7 @@
- **[k8s/ingress]** Loop through service ports for global backend ([#4486](https://github.com/containous/traefik/pull/4486) by [dtomcej](https://github.com/dtomcej))
- **[k8s]** Add entrypoints prefix in kubernetes frontend/backend id ([#4679](https://github.com/containous/traefik/pull/4679) by [juliens](https://github.com/juliens))
- **[websocket]** Exclude websocket connections from Average Response Time ([#4313](https://github.com/containous/traefik/pull/4313) by [siyu6974](https://github.com/siyu6974))
- **[middleware]** Added support for configuring trace headers for DataDog tracing ([#4516](https://github.com/containous/traefik/pull/4516) by [aantono](https://github.com/aantono))
- **[middleware]** Added support for configuring trace headers for Datadog tracing ([#4516](https://github.com/containous/traefik/pull/4516) by [aantono](https://github.com/aantono))
**Documentation:**
- **[acme]** Add _FILE Environment Variable Documentation ([#4643](https://github.com/containous/traefik/pull/4643) by [dargmuesli](https://github.com/dargmuesli))
@@ -670,7 +695,7 @@
- **[metrics]** Metrics: Add support for InfluxDB Database / RetentionPolicy and HTTP client ([#3391](https://github.com/containous/traefik/pull/3391) by [drewkerrigan](https://github.com/drewkerrigan))
- **[middleware,consulcatalog,docker,ecs,kv,marathon,mesos,rancher]** Pass the TLS Cert infos in headers ([#3826](https://github.com/containous/traefik/pull/3826) by [jbdoumenjou](https://github.com/jbdoumenjou))
- **[middleware,server]** Extreme Makeover: server refactoring ([#3461](https://github.com/containous/traefik/pull/3461) by [ldez](https://github.com/ldez))
- **[middleware,tracing]** Added integration support for DataDog APM Tracing ([#3517](https://github.com/containous/traefik/pull/3517) by [aantono](https://github.com/aantono))
- **[middleware,tracing]** Added integration support for Datadog APM Tracing ([#3517](https://github.com/containous/traefik/pull/3517) by [aantono](https://github.com/aantono))
- **[middleware,tracing]** Create a custom logger for jaeger ([#3541](https://github.com/containous/traefik/pull/3541) by [mmatur](https://github.com/mmatur))
- **[middleware]** Performance enhancements for the rules matchers. ([#3563](https://github.com/containous/traefik/pull/3563) by [ShaneSaww](https://github.com/ShaneSaww))
- **[middleware]** Extract internal router creation from server ([#3204](https://github.com/containous/traefik/pull/3204) by [Juliens](https://github.com/Juliens))
@@ -731,7 +756,7 @@
- **[oxy]** Handle Te header when http2 ([#3824](https://github.com/containous/traefik/pull/3824) by [Juliens](https://github.com/Juliens))
- **[server]** Avoid goroutine leak in server ([#3851](https://github.com/containous/traefik/pull/3851) by [nmengin](https://github.com/nmengin))
- **[server]** Avoid panic during stop ([#3898](https://github.com/containous/traefik/pull/3898) by [nmengin](https://github.com/nmengin))
- **[tracing]** Added default configuration for DataDog APM Tracer ([#3655](https://github.com/containous/traefik/pull/3655) by [aantono](https://github.com/aantono))
- **[tracing]** Added default configuration for Datadog APM Tracer ([#3655](https://github.com/containous/traefik/pull/3655) by [aantono](https://github.com/aantono))
- **[tracing]** Added support for Trace name truncation for traces ([#3689](https://github.com/containous/traefik/pull/3689) by [aantono](https://github.com/aantono))
- **[websocket]** Handle shutdown of Hijacked connections ([#3636](https://github.com/containous/traefik/pull/3636) by [Juliens](https://github.com/Juliens))
- **[webui]** Added Dashboard table item for Rate Limits ([#3893](https://github.com/containous/traefik/pull/3893) by [codecyclist](https://github.com/codecyclist))
@@ -868,7 +893,7 @@
- **[docker]** Uses both binded HostIP and HostPort when useBindPortIP=true ([#3638](https://github.com/containous/traefik/pull/3638) by [geraldcroes](https://github.com/geraldcroes))
- **[k8s]** Fix Rewrite-target regex ([#3699](https://github.com/containous/traefik/pull/3699) by [dtomcej](https://github.com/dtomcej))
- **[middleware]** Correct Entrypoint Redirect with Stripped or Added Path ([#3631](https://github.com/containous/traefik/pull/3631) by [dtomcej](https://github.com/dtomcej))
- **[tracing]** Added default configuration for DataDog APM Tracer ([#3655](https://github.com/containous/traefik/pull/3655) by [aantono](https://github.com/aantono))
- **[tracing]** Added default configuration for Datadog APM Tracer ([#3655](https://github.com/containous/traefik/pull/3655) by [aantono](https://github.com/aantono))
- **[tracing]** Added support for Trace name truncation for traces ([#3689](https://github.com/containous/traefik/pull/3689) by [aantono](https://github.com/aantono))
- **[websocket]** Handle shutdown of Hijacked connections ([#3636](https://github.com/containous/traefik/pull/3636) by [Juliens](https://github.com/Juliens))
- H2C: Remove buggy line in init to make verbose switch working ([#3701](https://github.com/containous/traefik/pull/3701) by [dduportal](https://github.com/dduportal))
@@ -964,7 +989,7 @@
- **[mesos]** Segments Labels: Mesos ([#3383](https://github.com/containous/traefik/pull/3383) by [drewkerrigan](https://github.com/drewkerrigan))
- **[metrics]** Metrics: Add support for InfluxDB Database / RetentionPolicy and HTTP client ([#3391](https://github.com/containous/traefik/pull/3391) by [drewkerrigan](https://github.com/drewkerrigan))
- **[middleware,server]** Extreme Makeover: server refactoring ([#3461](https://github.com/containous/traefik/pull/3461) by [ldez](https://github.com/ldez))
- **[middleware,tracing]** Added integration support for DataDog APM Tracing ([#3517](https://github.com/containous/traefik/pull/3517) by [aantono](https://github.com/aantono))
- **[middleware,tracing]** Added integration support for Datadog APM Tracing ([#3517](https://github.com/containous/traefik/pull/3517) by [aantono](https://github.com/aantono))
- **[middleware,tracing]** Create a custom logger for jaeger ([#3541](https://github.com/containous/traefik/pull/3541) by [mmatur](https://github.com/mmatur))
- **[middleware]** Performance enhancements for the rules matchers. ([#3563](https://github.com/containous/traefik/pull/3563) by [ShaneSaww](https://github.com/ShaneSaww))
- **[middleware]** Extract internal router creation from server ([#3204](https://github.com/containous/traefik/pull/3204) by [Juliens](https://github.com/Juliens))
@@ -1142,7 +1167,7 @@
- **[metrics]** Added entrypoint metrics to influxdb ([#2992](https://github.com/containous/traefik/pull/2992) by [adityacs](https://github.com/adityacs))
- **[metrics]** Remove unnecessary conversion ([#2850](https://github.com/containous/traefik/pull/2850) by [ferhatelmas](https://github.com/ferhatelmas))
- **[metrics]** Extend metrics and rebuild prometheus exporting logic ([#2567](https://github.com/containous/traefik/pull/2567) by [marco-jantke](https://github.com/marco-jantke))
- **[metrics]** Added missing metrics to registry for DataDog and StatsD ([#2890](https://github.com/containous/traefik/pull/2890) by [aantono](https://github.com/aantono))
- **[metrics]** Added missing metrics to registry for Datadog and StatsD ([#2890](https://github.com/containous/traefik/pull/2890) by [aantono](https://github.com/aantono))
- **[middleware,consul,consulcatalog,docker,ecs,k8s,marathon,mesos,rancher]** New option in secure middleware ([#2958](https://github.com/containous/traefik/pull/2958) by [mmatur](https://github.com/mmatur))
- **[middleware,consulcatalog,docker,ecs,k8s,kv,marathon,mesos,rancher]** Ability to use &#34;X-Forwarded-For&#34; as a source of IP for white list. ([#3070](https://github.com/containous/traefik/pull/3070) by [ldez](https://github.com/ldez))
- **[middleware,docker]** Use pointer of error pages ([#2607](https://github.com/containous/traefik/pull/2607) by [ldez](https://github.com/ldez))
@@ -1394,7 +1419,7 @@
- **[mesos]** Add all available labels to Mesos Backend ([#2687](https://github.com/containous/traefik/pull/2687) by [ldez](https://github.com/ldez))
- **[metrics]** Added entrypoint metrics to influxdb ([#2992](https://github.com/containous/traefik/pull/2992) by [adityacs](https://github.com/adityacs))
- **[metrics]** Extend metrics and rebuild prometheus exporting logic ([#2567](https://github.com/containous/traefik/pull/2567) by [marco-jantke](https://github.com/marco-jantke))
- **[metrics]** Added missing metrics to registry for DataDog and StatsD ([#2890](https://github.com/containous/traefik/pull/2890) by [aantono](https://github.com/aantono))
- **[metrics]** Added missing metrics to registry for Datadog and StatsD ([#2890](https://github.com/containous/traefik/pull/2890) by [aantono](https://github.com/aantono))
- **[metrics]** Remove unnecessary conversion ([#2850](https://github.com/containous/traefik/pull/2850) by [ferhatelmas](https://github.com/ferhatelmas))
- **[middleware,consul,consulcatalog,docker,ecs,k8s,marathon,mesos,rancher]** New option in secure middleware ([#2958](https://github.com/containous/traefik/pull/2958) by [mmatur](https://github.com/mmatur))
- **[middleware,consulcatalog,docker,ecs,k8s,kv,marathon,mesos,rancher]** Ability to use &#34;X-Forwarded-For&#34; as a source of IP for white list. ([#3070](https://github.com/containous/traefik/pull/3070) by [ldez](https://github.com/ldez))
@@ -2015,12 +2040,12 @@
- **[marathon]** Add support for readiness checks. ([#1883](https://github.com/containous/traefik/pull/1883) by [timoreimann](https://github.com/timoreimann))
- **[marathon]** Move marathon mock ([#1732](https://github.com/containous/traefik/pull/1732) by [ldez](https://github.com/ldez))
- **[marathon]** Use single API call to fetch Marathon resources. ([#1815](https://github.com/containous/traefik/pull/1815) by [timoreimann](https://github.com/timoreimann))
- **[metrics]** Added RetryMetrics to DataDog and StatsD providers ([#1884](https://github.com/containous/traefik/pull/1884) by [aantono](https://github.com/aantono))
- **[metrics]** Added RetryMetrics to Datadog and StatsD providers ([#1884](https://github.com/containous/traefik/pull/1884) by [aantono](https://github.com/aantono))
- **[metrics]** Extract metrics to own package and refactor implementations ([#1968](https://github.com/containous/traefik/pull/1968) by [marco-jantke](https://github.com/marco-jantke))
- **[metrics]** Add metrics for backend_retries_total ([#1504](https://github.com/containous/traefik/pull/1504) by [marco-jantke](https://github.com/marco-jantke))
- **[metrics]** Add status code to request duration metric ([#1755](https://github.com/containous/traefik/pull/1755) by [marco-jantke](https://github.com/marco-jantke))
- **[middleware]** Add trusted whitelist proxy protocol ([#2234](https://github.com/containous/traefik/pull/2234) by [emilevauge](https://github.com/emilevauge)))
- **[metrics]** DataDog and StatsD Metrics Support ([#1701](https://github.com/containous/traefik/pull/1701) by [aantono](https://github.com/aantono))
- **[metrics]** Datadog and StatsD Metrics Support ([#1701](https://github.com/containous/traefik/pull/1701) by [aantono](https://github.com/aantono))
- **[middleware]** Create Header Middleware ([#1236](https://github.com/containous/traefik/pull/1236) by [dtomcej](https://github.com/dtomcej))
- **[middleware]** Add configurable timeouts and curate default timeout settings ([#1873](https://github.com/containous/traefik/pull/1873) by [marco-jantke](https://github.com/marco-jantke))
- **[middleware]** Fix command bug content. ([#2002](https://github.com/containous/traefik/pull/2002) by [ldez](https://github.com/ldez))
@@ -2326,11 +2351,11 @@
- **[marathon]** Move marathon mock ([#1732](https://github.com/containous/traefik/pull/1732) by [ldez](https://github.com/ldez))
- **[marathon]** Support multi-port service routing for containers running on Marathon ([#1742](https://github.com/containous/traefik/pull/1742) by [aantono](https://github.com/aantono))
- **[marathon]** Use test builder. ([#1871](https://github.com/containous/traefik/pull/1871) by [timoreimann](https://github.com/timoreimann))
- **[metrics]** DataDog and StatsD Metrics Support ([#1701](https://github.com/containous/traefik/pull/1701) by [aantono](https://github.com/aantono))
- **[metrics]** Datadog and StatsD Metrics Support ([#1701](https://github.com/containous/traefik/pull/1701) by [aantono](https://github.com/aantono))
- **[metrics]** Add status code to request duration metric ([#1755](https://github.com/containous/traefik/pull/1755) by [marco-jantke](https://github.com/marco-jantke))
- **[metrics]** Add metrics for backend_retries_total ([#1504](https://github.com/containous/traefik/pull/1504) by [marco-jantke](https://github.com/marco-jantke))
- **[metrics]** Extract metrics to own package and refactor implementations ([#1968](https://github.com/containous/traefik/pull/1968) by [marco-jantke](https://github.com/marco-jantke))
- **[metrics]** Added RetryMetrics to DataDog and StatsD providers ([#1884](https://github.com/containous/traefik/pull/1884) by [aantono](https://github.com/aantono))
- **[metrics]** Added RetryMetrics to Datadog and StatsD providers ([#1884](https://github.com/containous/traefik/pull/1884) by [aantono](https://github.com/aantono))
- **[middleware]** Return 503 on empty backend ([#1748](https://github.com/containous/traefik/pull/1748) by [marco-jantke](https://github.com/marco-jantke))
- **[middleware]** Add configurable timeouts and curate default timeout settings ([#1873](https://github.com/containous/traefik/pull/1873) by [marco-jantke](https://github.com/marco-jantke))
- **[middleware]** Custom Error Pages ([#1675](https://github.com/containous/traefik/pull/1675) by [bparli](https://github.com/bparli))

View File

@@ -1,4 +1,4 @@
FROM golang:1.13rc1-alpine
FROM golang:1.13rc2-alpine
RUN apk --update upgrade \
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \

View File

@@ -299,14 +299,14 @@ You haven't specified the sendAnonymousUsage option, it will be enabled by defau
Stats collection is enabled.
Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.
Help us improve Traefik by leaving this feature on :)
More details on: https://docs.traefik.io/basics/#collected-data
More details on: https://docs.traefik.io/v2.0/contributing/data-collection/
`)
collect(staticConfiguration)
} else {
log.WithoutContext().Info(`
Stats collection is disabled.
Help us improve Traefik by turning this feature on :)
More details on: https://docs.traefik.io/basics/#collected-data
More details on: https://docs.traefik.io/v2.0/contributing/data-collection/
`)
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -28,7 +28,7 @@ Successfully tagged traefik-webui:latest
[...]
docker build -t "traefik-dev:4475--feature-documentation" -f build.Dockerfile .
Sending build context to Docker daemon 279MB
Step 1/10 : FROM golang:1.13rc1-alpine
Step 1/10 : FROM golang:1.13rc2-alpine
---> f4bfb3d22bda
[...]
Successfully built 5c3c1a911277

View File

@@ -9,7 +9,7 @@ Understanding how you use Traefik is very important to us: it helps us improve t
For this very reason, the sendAnonymousUsage option is mandatory: we want you to take time to consider whether or not you wish to share anonymous data with us so we can benefit from your experience and use cases.
!!! warning
During the beta stage only, leaving this option unset will not prevent Traefik from running but will generate an error log indicating that it enables data collection by default.
Before the GA, leaving this option unset will not prevent Traefik from running but will generate an error log indicating that it enables data collection by default.
!!! example "Enabling Data Collection"

View File

@@ -35,7 +35,7 @@ tls:
!!! important "File Provider Only"
In the above example, we've used the [file provider](../providers/file.md) to handle these definitions.
In its current beta version, it is the only available method to configure the certificates (as well as the options and the stores).
It is the only available method to configure the certificates (as well as the options and the stores).
## Certificates Stores
@@ -52,9 +52,9 @@ tls:
default: {}
```
!!! important "Beta restriction"
!!! important "Restriction"
During the beta version, any store definition other than the default one (named `default`) will be ignored,
Any store definition other than the default one (named `default`) will be ignored,
and there is thefore only one globally available TLS store.
In the `tls.certificates` section, a list of stores can then be specified to indicate where the certificates should be stored:
@@ -85,9 +85,9 @@ tls:
keyFile: /path/to/other-domain.key
```
!!! important "Beta restriction"
!!! important "Restriction"
During the beta version, the `stores` list will actually be ignored and automatically set to `["default"]`.
The `stores` list will actually be ignored and automatically set to `["default"]`.
### Default Certificate

View File

@@ -79,10 +79,6 @@ Passwords must be encoded using MD5, SHA1, or BCrypt.
The `users` option is an array of authorized users. Each user will be declared using the `name:encoded-password` format.
!!! Note
If both `users` and `usersFile` are provided, the two are merged. The content of `usersFile` has precedence over `users`.
### `usersFile`
The `usersFile` option is the path to an external file that contains the authorized users for the middleware.
@@ -106,7 +102,7 @@ You can customize the realm for the authentication with the `realm` option. The
### `headerField`
You can customize the header field for the authenticated user using the `headerField`option.
You can define a header field to store the authenticated user using the `headerField`option.
```yaml tab="Docker"
labels:

View File

@@ -51,9 +51,9 @@ metadata:
spec:
chain:
middlewares:
- https-only
- known-ips
- auth-users
- name: https-only
- name: known-ips
- name: auth-users
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware

View File

@@ -132,7 +132,7 @@ For example, the expression `LatencyAtQuantileMS(50.0) > 100` will trigger the c
!!! Note
You must provide a float number (with the leading .0) for the quantile value
You must provide a float number (with the trailing .0) for the quantile value
#### Using multiple metrics
@@ -153,7 +153,6 @@ Here is the list of supported operators:
- Greater or equal than (`>=`)
- Lesser than (`<`)
- Lesser or equal than (`<=`)
- Not (`!`)
- Equal (`==`)
- Not Equal (`!=`)

View File

@@ -55,6 +55,6 @@ http:
Responses are compressed when:
* The response body is larger than `512` bytes.
* The response body is larger than `1400` bytes.
* The `Accept-Encoding` request header contains `gzip`.
* The response is not already compressed, i.e. the `Content-Encoding` response header is not already set.

View File

@@ -77,7 +77,7 @@ http:
```
!!! note
In this example, the error page URL is based on the status code (`query=/{status}.html)`.
In this example, the error page URL is based on the status code (`query=/{status}.html`).
## Configuration Options

View File

@@ -70,7 +70,12 @@ http:
`X-Script-Name` header added to the proxied request, the `X-Custom-Request-Header` header removed from the request,
and the `X-Custom-Response-Header` header removed from the response.
Please note that is not possible to remove headers through the use of labels (Docker, Rancher, Marathon, ...) for now.
Please note that it is not possible to remove headers through the use of labels (Docker, Rancher, Marathon, ...) for now.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
@@ -86,17 +91,17 @@ spec:
X-Custom-Response-Header: "" # Removes
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test"
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test",
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.testHeader.headers]
@@ -121,7 +126,7 @@ http:
### Using Security Headers
Security related headers (HSTS headers, SSL redirection, Browser XSS filter, etc) can be added and configured per frontend in a similar manner to the custom headers above.
Security related headers (HSTS headers, SSL redirection, Browser XSS filter, etc) can be added and configured in a manner similar to the custom headers above.
This functionality allows for some easy security features to quickly be set.
```yaml tab="Docker"
@@ -141,12 +146,6 @@ spec:
sslRedirect: "true"
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.framedeny=true"
- "traefik.http.middlewares.testheader.headers.sslredirect=true"
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.testheader.headers.framedeny": "true",
@@ -154,6 +153,12 @@ labels:
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.framedeny=true"
- "traefik.http.middlewares.testheader.headers.sslredirect=true"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.testHeader.headers]
@@ -172,7 +177,7 @@ http:
### CORS Headers
CORS (Cross-Origin Resource Sharing) headers can be added and configured per frontend in a similar manner to the custom headers above.
CORS (Cross-Origin Resource Sharing) headers can be added and configured in a manner similar to the custom headers above.
This functionality allows for more advanced security features to quickly be set.
```yaml tab="Docker"
@@ -199,14 +204,6 @@ spec:
addVaryHeader: "true"
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
- "traefik.http.middlewares.testheader.headers.accesscontrolalloworigin=origin-list-or-null"
- "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.testheader.headers.addvaryheader=true"
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.testheader.headers.accesscontrolallowmethods": "GET,OPTIONS,PUT",
@@ -216,6 +213,14 @@ labels:
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
- "traefik.http.middlewares.testheader.headers.accesscontrolalloworigin=origin-list-or-null"
- "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.testheader.headers.addvaryheader=true"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.testHeader.headers]

View File

@@ -74,7 +74,7 @@ The `ipStrategy` option defines two parameters that sets how Traefik will determ
The `depth` option tells Traefik to use the `X-Forwarded-For` header and take the IP located at the `depth` position (starting from the right).
- If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty.
- `depth` is ignored if its value is is lesser than or equal to 0.
- `depth` is ignored if its value is lesser than or equal to 0.
!!! note "Example of Depth & X-Forwarded-For"

View File

@@ -144,7 +144,7 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th
!!! note
- If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty.
- `depth` is ignored if its value is is lesser than or equal to 0.
- `depth` is ignored if its value is lesser than or equal to 0.
#### `ipStrategy.excludedIPs`

View File

@@ -219,7 +219,7 @@ PassTLSClientCert can add two headers to the request:
!!! note
The headers are filled with escaped string so it can be safely placed inside a URL query.
In the following example, you can see a complete certificate. We will use each part of it to explains the middleware options.
In the following example, you can see a complete certificate. We will use each part of it to explain the middleware options.
??? example "A complete client tls certificate"

View File

@@ -3,8 +3,6 @@
To Control the Number of Requests Going to a Service
{: .subtitle }
![RateLimit](../assets/img/middleware/ratelimit.png)
The RateLimit middleware ensures that services will receive a _fair_ number of requests, and allows you define what is fair.
## Configuration Example
@@ -173,7 +171,7 @@ The `ipStrategy` option defines two parameters that sets how Traefik will determ
The `depth` option tells Traefik to use the `X-Forwarded-For` header and take the IP located at the `depth` position (starting from the right).
- If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty.
- `depth` is ignored if its value is is lesser than or equal to 0.
- `depth` is ignored if its value is lesser than or equal to 0.
!!! note "Example of Depth & X-Forwarded-For"

View File

@@ -3,55 +3,50 @@
Removing Prefixes From the Path Before Forwarding the Request (Using a Regex)
{: .subtitle }
`TODO: add schema`
Remove the matching prefixes from the URL path.
## Configuration Examples
```yaml tab="Docker"
# Replace the path by /foo
labels:
- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=^/foo/(.*)",
- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/",
```
```yaml tab="Kubernetes"
# Replace the path by /foo
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-stripprefixregex
spec:
stripPrefixRegex:
regex: "^/foo/(.*)"
regex:
- "/foo/[a-z0-9]+/[0-9]+/"
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex": "^/foo/(.*)"
"traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex": "/foo/[a-z0-9]+/[0-9]+/"
}
```
```yaml tab="Rancher"
# Replace the path by /foo
labels:
- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=^/foo/(.*)",
- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/",
```
```toml tab="File (TOML)"
# Replace the path by /foo
[http.middlewares]
[http.middlewares.test-stripprefixregex.stripPrefixRegex]
regex = "^/foo/(.*)"
regex = ["/foo/[a-z0-9]+/[0-9]+/"]
```
```yaml tab="File (YAML)"
# Replace the path by /foo
http:
middlewares:
test-stripprefixregex:
stripPrefixRegex:
regex: "^/foo/(.*)"
regex:
- "/foo/[a-z0-9]+/[0-9]+/"
```
## Configuration Options

View File

@@ -0,0 +1,344 @@
# Migration Guide: From v1 to v2
How to Migrate from Traefik v1 to Traefik v2.
{: .subtitle }
The version 2 of Traefik introduces a number of breaking changes,
which require one to update their configuration when they migrate from v1 to v2.
The goal of this page is to recapitulate all of these changes, and in particular to give examples,
feature by feature, of how the configuration looked like in v1, and how it now looks like in v2.
## Frontends and Backends Are Dead... <br/>... Long Live Routers, Middlewares, and Services
During the transition from v1 to v2, a number of internal pieces and components of Traefik were rewritten and reorganized.
As such, the combination of core notions such as frontends and backends has been replaced with the combination of routers, services, and middlewares.
Typically, a router replaces a frontend, and a service assumes the role of a backend, with each router referring to a service.
However, even though a backend was in charge of applying any desired modification on the fly to the incoming request,
the router defers that responsibility to another component.
Instead, a dedicated middleware is now defined for each kind of such modification.
Then any router can refer to an instance of the wanted middleware.
!!! example "One frontend with basic auth and one backend, become one router, one service, and one basic auth middleware."
### v1
```yaml tab="Docker"
labels:
- "traefik.frontend.rule=Host:test.localhost;PathPrefix:/test"
- "traefik.frontend.auth.basic.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
```
```yaml tab="K8s Ingress"
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik
namespace: kube-system
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/rule-type: PathPrefix
spec:
rules:
- host: test.locahost
http:
paths:
- path: /test
backend:
serviceName: server0
servicePort: 80
- path: /test
backend:
serviceName: server1
servicePort: 80
```
```toml tab="File (TOML)"
[frontends]
[frontends.frontend1]
entryPoints = ["http"]
backend = "backend1"
[frontends.frontend1.routes]
[frontends.frontend1.routes.route0]
rule = "Host:test.localhost"
[frontends.frontend1.routes.route0]
rule = "PathPrefix:/test"
[frontends.frontend1.auth]
[frontends.frontend1.auth.basic]
users = [
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
]
[backends]
[backends.backend1]
[backends.backend1.servers.server0]
url = "http://10.10.10.1:80"
[backends.backend1.servers.server1]
url = "http://10.10.10.2:80"
[backends.backend1.loadBalancer]
method = "wrr"
```
### v2
```yaml tab="Docker"
labels:
- "traefik.http.routers.router0.rule=Host(`bar.com`) && PathPrefix(`/test`)"
- "traefik.http.routers.router0.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
```
```yaml tab="K8s IngressRoute"
# The definitions below require the definitions for the Middleware and IngressRoute kinds.
# https://docs.traefik.io/v2.0/providers/kubernetes-crd/#traefik-ingressroute-definition
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: basicauth
namespace: foo
spec:
basicAuth:
users:
- test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/
- test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutebar
spec:
entryPoints:
- http
routes:
- match: Host(`test.localhost`) && PathPrefix(`/test`)
kind: Rule
services:
- name: server0
port: 80
- name: server1
port: 80
middlewares:
- name: basicauth
namespace: foo
```
```toml tab="File (TOML)"
[http.routers]
[http.routers.router0]
rule = "Host(`test.localhost`) && PathPrefix(`/test`)"
middlewares = ["auth"]
service = "my-service"
[http.services]
[[http.services.my-service.loadBalancer.servers]]
url = "http://10.10.10.1:80"
[[http.services.my-service.loadBalancer.servers]]
url = "http://10.10.10.2:80"
[http.middlewares]
[http.middlewares.auth.basicAuth]
users = [
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
]
```
```yaml tab="File (YAML)"
http:
routers:
router0:
rule: "Host(`test.localhost`) && PathPrefix(`/test`)"
service: my-service
middlewares:
- auth
services:
my-service:
loadBalancer:
servers:
- url: http://10.10.10.1:80
- url: http://10.10.10.2:80
middlewares:
auth:
basicAuth:
users:
- "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
- "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
```
## TLS configuration is now dynamic, per router.
TLS parameters used to be specified in the static configuration, as an entryPoint field.
With Traefik v2, a new dynamic TLS section at the root contains all the desired TLS configurations.
Then, a router's TLS field can refer to one of the TLS configurations defined at the root, hence defining the TLS configuration for that router.
!!! example "TLS on web-secure entryPoint becomes TLS option on Router-1"
### v1
```toml tab="File (TOML)"
# static configuration
[entryPoints]
[entryPoints.web-secure]
address = ":443"
[entryPoints.web-secure.tls]
minVersion = "VersionTLS12"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384"
]
[[entryPoints.web-secure.tls.certificates]]
certFile = "path/to/my.cert"
keyFile = "path/to/my.key"
```
```bash tab="CLI"
--entryPoints='Name:web-secure Address::443 TLS:path/to/my.cert,path/to/my.key TLS.MinVersion:VersionTLS12 TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384'
```
### v2
```toml tab="File (TOML)"
# dynamic configuration
[http.routers]
[http.routers.Router-1]
rule = "Host(`bar.com`)"
service = "service-id"
# will terminate the TLS request
[http.routers.Router-1.tls]
options = "myTLSOptions"
[[tls.certificates]]
certFile = "/path/to/domain.cert"
keyFile = "/path/to/domain.key"
[tls.options]
[tls.options.default]
minVersion = "VersionTLS12"
[tls.options.myTLSOptions]
minVersion = "VersionTLS13"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384"
]
```
```yaml tab="File (YAML)"
http:
routers:
Router-1:
rule: "Host(`bar.com`)"
service: service-id
# will terminate the TLS request
tls:
options: myTLSOptions
tls:
certificates:
- certFile: /path/to/domain.cert
keyFile: /path/to/domain.key
options:
myTLSOptions:
minVersion: VersionTLS13
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384
```
```yaml tab="K8s IngressRoute"
# The definitions below require the definitions for the TLSOption and IngressRoute kinds.
# https://docs.traefik.io/v2.0/providers/kubernetes-crd/#traefik-ingressroute-definition
apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
name: mytlsoption
namespace: default
spec:
minVersion: VersionTLS13
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutebar
spec:
entryPoints:
- web
routes:
- match: Host(`bar.com`)
kind: Rule
services:
- name: whoami
port: 80
tls:
options:
name: mytlsoption
namespace: default
```
```yaml tab="Docker"
labels:
# myTLSOptions must be defined by another provider, in this instance in the File Provider.
# see the cross provider section
- "traefik.http.routers.router0.tls.options=myTLSOptions@file"
```
## HTTP -> HTTPS Redirection
TODO
## ACME (let's encrypt)
TODO
## Traefik Logs
TODO
## Tracing
TODO
## Metrics
TODO
## No more root level key/values
TODO
## Providers
Supported providers, for now:
- [ ] Azure Service Fabric
- [ ] BoltDB
- [ ] Consul
- [ ] Consul Catalog
- [x] Docker
- [ ] DynamoDB
- [ ] ECS
- [ ] Etcd
- [ ] Eureka
- [x] File
- [x] Kubernetes Ingress (without annotations)
- [x] Kubernetes IngressRoute
- [x] Marathon
- [ ] Mesos
- [x] Rest
- [ ] Zookeeper

View File

@@ -1,15 +1,15 @@
# DataDog
# Datadog
To enable the DataDog:
To enable the Datadog:
```toml tab="File (TOML)"
[metrics]
[metrics.dataDog]
[metrics.datadog]
```
```yaml tab="File (YAML)"
metrics:
dataDog: {}
datadog: {}
```
```bash tab="CLI"
@@ -24,13 +24,13 @@ Address instructs exporter to send metrics to datadog-agent at this address.
```toml tab="File (TOML)"
[metrics]
[metrics.dataDog]
[metrics.datadog]
address = "127.0.0.1:8125"
```
```yaml tab="File (YAML)"
metrics:
dataDog:
datadog:
address: 127.0.0.1:8125
```
@@ -46,13 +46,13 @@ Enable metrics on entry points.
```toml tab="File (TOML)"
[metrics]
[metrics.dataDog]
[metrics.datadog]
addEntryPointsLabels = true
```
```yaml tab="File (YAML)"
metrics:
dataDog:
datadog:
addEntryPointsLabels: true
```
@@ -68,13 +68,13 @@ Enable metrics on services.
```toml tab="File (TOML)"
[metrics]
[metrics.dataDog]
[metrics.datadog]
addServicesLabels = true
```
```yaml tab="File (YAML)"
metrics:
dataDog:
datadog:
addServicesLabels: true
```
@@ -90,13 +90,13 @@ The interval used by the exporter to push metrics to datadog-agent.
```toml tab="File (TOML)"
[metrics]
[metrics.dataDog]
[metrics.datadog]
pushInterval = 10s
```
```yaml tab="File (YAML)"
metrics:
dataDog:
datadog:
pushInterval: 10s
```

View File

@@ -4,7 +4,7 @@ Metrics system
Traefik supports 4 metrics backends:
- [DataDog](./datadog.md)
- [Datadog](./datadog.md)
- [InfluxDB](./influxdb.md)
- [Prometheus](./prometheus.md)
- [StatsD](./statsd.md)

View File

@@ -1,15 +1,15 @@
# DataDog
# Datadog
To enable the DataDog:
To enable the Datadog:
```toml tab="File (TOML)"
[tracing]
[tracing.dataDog]
[tracing.datadog]
```
```yaml tab="File (YAML)"
tracing:
dataDog: {}
datadog: {}
```
```bash tab="CLI"
@@ -24,13 +24,13 @@ Local Agent Host Port instructs reporter to send spans to datadog-tracing-agent
```toml tab="File (TOML)"
[tracing]
[tracing.dataDog]
[tracing.datadog]
localAgentHostPort = "127.0.0.1:8126"
```
```yaml tab="File (YAML)"
tracing:
dataDog:
datadog:
localAgentHostPort: 127.0.0.1:8126
```
@@ -42,17 +42,17 @@ tracing:
_Optional, Default=false_
Enable DataDog debug.
Enable Datadog debug.
```toml tab="File (TOML)"
[tracing]
[tracing.dataDog]
[tracing.datadog]
debug = true
```
```yaml tab="File (YAML)"
tracing:
dataDog:
datadog:
debug: true
```
@@ -68,13 +68,13 @@ Apply shared tag in a form of Key:Value to all the traces.
```toml tab="File (TOML)"
[tracing]
[tracing.dataDog]
[tracing.datadog]
globalTag = "sample"
```
```yaml tab="File (YAML)"
tracing:
dataDog:
datadog:
globalTag: sample
```
@@ -91,13 +91,13 @@ this option must be enabled in order to get all the parts of a distributed trace
```toml tab="File (TOML)"
[tracing]
[tracing.dataDog]
[tracing.datadog]
prioritySampling = true
```
```yaml tab="File (YAML)"
tracing:
dataDog:
datadog:
prioritySampling: true
```

View File

@@ -11,7 +11,7 @@ Traefik supports five tracing backends:
- [Jaeger](./jaeger.md)
- [Zipkin](./zipkin.md)
- [DataDog](./datadog.md)
- [Datadog](./datadog.md)
- [Instana](./instana.md)
- [Haystack](./haystack.md)

View File

@@ -18,46 +18,24 @@ tracing:
#### `httpEndpoint`
_Required, Default="http://localhost:9411/api/v1/spans"_
_Required, Default="http://localhost:9411/api/v2/spans"_
Zipkin HTTP endpoint used to send data.
```toml tab="File (TOML)"
[tracing]
[tracing.zipkin]
httpEndpoint = "http://localhost:9411/api/v1/spans"
httpEndpoint = "http://localhost:9411/api/v2/spans"
```
```yaml tab="File (YAML)"
tracing:
zipkin:
httpEndpoint: http://localhost:9411/api/v1/spans
httpEndpoint: http://localhost:9411/api/v2/spans
```
```bash tab="CLI"
--tracing.zipkin.httpEndpoint="http://localhost:9411/api/v1/spans"
```
#### `debug`
_Optional, Default=false_
Enable Zipkin debug.
```toml tab="File (TOML)"
[tracing]
[tracing.zipkin]
debug = true
```
```yaml tab="File (YAML)"
tracing:
zipkin:
debug: true
```
```bash tab="CLI"
--tracing.zipkin.debug=true
--tracing.zipkin.httpEndpoint="http://localhost:9411/api/v2/spans"
```
#### `sameSpan`
@@ -86,7 +64,7 @@ tracing:
_Optional, Default=true_
Use Zipkin 128 bit root span IDs.
Use Zipkin 128 bit trace IDs.
```toml tab="File (TOML)"
[tracing]
@@ -124,4 +102,4 @@ tracing:
```bash tab="CLI"
--tracing.zipkin.sampleRate="0.2"
```
```

View File

@@ -1,7 +1,7 @@
# API
!!! important
In the beta version, you can't configure middlewares (basic authentication or white listing) anymore, but as security is important, this will change before the RC version.
In the RC version, you can't configure middlewares (basic authentication or white listing) anymore, but as security is important, this will change before the GA version.
Traefik exposes a number of information through an API handler, such as the configuration of all routers, services, middlewares, etc.

View File

@@ -477,7 +477,7 @@ You can declare TCP Routers and/or Services using labels.
# ...
labels:
- traefik.tcp.routers.my-router.rule="HostSNI(`my-host.com`)"
- traefik.tcp.routers.my-router.rule.tls="true"
- traefik.tcp.routers.my-router.tls="true"
- traefik.tcp.services.my-service.loadbalancer.server.port="4123"
```

View File

@@ -46,7 +46,7 @@ You can write these configuration elements:
entryPoints = ["web"]
middlewares = ["my-basic-auth"]
service = "service-foo"
rule = "Path(`foo`)"
rule = "Path(`/foo`)"
# Add the middleware
[http.middlewares]
@@ -75,7 +75,7 @@ You can write these configuration elements:
middlewares:
- my-basic-auth
service: service-foo
rule: Path(`foo`)
rule: Path(`/foo`)
# Add the middleware
middlewares:

View File

@@ -45,13 +45,13 @@
- "traefik.http.middlewares.middleware09.headers.customrequestheaders.name1=foobar"
- "traefik.http.middlewares.middleware09.headers.customresponseheaders.name0=foobar"
- "traefik.http.middlewares.middleware09.headers.customresponseheaders.name1=foobar"
- "traefik.http.middlewares.middleware09.headers.featurepolicy=foobar"
- "traefik.http.middlewares.middleware09.headers.forcestsheader=true"
- "traefik.http.middlewares.middleware09.headers.framedeny=true"
- "traefik.http.middlewares.middleware09.headers.hostsproxyheaders=foobar, foobar"
- "traefik.http.middlewares.middleware09.headers.isdevelopment=true"
- "traefik.http.middlewares.middleware09.headers.publickey=foobar"
- "traefik.http.middlewares.middleware09.headers.referrerpolicy=foobar"
- "traefik.http.middlewares.middleware09.headers.featurepolicy=foobar"
- "traefik.http.middlewares.middleware09.headers.sslforcehost=true"
- "traefik.http.middlewares.middleware09.headers.sslhost=foobar"
- "traefik.http.middlewares.middleware09.headers.sslproxyheaders.name0=foobar"
@@ -65,10 +65,9 @@
- "traefik.http.middlewares.middleware10.ipwhitelist.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware10.ipwhitelist.sourcerange=foobar, foobar"
- "traefik.http.middlewares.middleware11.inflightreq.amount=42"
- "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requestheadername=foobar"
- "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requesthost=true"
- "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requestheadername=foobar"
- "traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requesthost=true"
- "traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.commonname=true"
- "traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.country=true"
@@ -88,18 +87,24 @@
- "traefik.http.middlewares.middleware12.passtlsclientcert.info.subject.province=true"
- "traefik.http.middlewares.middleware12.passtlsclientcert.info.subject.serialnumber=true"
- "traefik.http.middlewares.middleware12.passtlsclientcert.pem=true"
- "traefik.http.middlewares.middleware13.redirectregex.permanent=true"
- "traefik.http.middlewares.middleware13.redirectregex.regex=foobar"
- "traefik.http.middlewares.middleware13.redirectregex.replacement=foobar"
- "traefik.http.middlewares.middleware14.redirectscheme.permanent=true"
- "traefik.http.middlewares.middleware14.redirectscheme.port=foobar"
- "traefik.http.middlewares.middleware14.redirectscheme.scheme=foobar"
- "traefik.http.middlewares.middleware15.replacepath.path=foobar"
- "traefik.http.middlewares.middleware16.replacepathregex.regex=foobar"
- "traefik.http.middlewares.middleware16.replacepathregex.replacement=foobar"
- "traefik.http.middlewares.middleware17.retry.attempts=42"
- "traefik.http.middlewares.middleware18.stripprefix.prefixes=foobar, foobar"
- "traefik.http.middlewares.middleware19.stripprefixregex.regex=foobar, foobar"
- "traefik.http.middlewares.middleware13.ratelimit.average=42"
- "traefik.http.middlewares.middleware13.ratelimit.burst=42"
- "traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.requestheadername=foobar"
- "traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.requesthost=true"
- "traefik.http.middlewares.middleware14.redirectregex.permanent=true"
- "traefik.http.middlewares.middleware14.redirectregex.regex=foobar"
- "traefik.http.middlewares.middleware14.redirectregex.replacement=foobar"
- "traefik.http.middlewares.middleware15.redirectscheme.permanent=true"
- "traefik.http.middlewares.middleware15.redirectscheme.port=foobar"
- "traefik.http.middlewares.middleware15.redirectscheme.scheme=foobar"
- "traefik.http.middlewares.middleware16.replacepath.path=foobar"
- "traefik.http.middlewares.middleware17.replacepathregex.regex=foobar"
- "traefik.http.middlewares.middleware17.replacepathregex.replacement=foobar"
- "traefik.http.middlewares.middleware18.retry.attempts=42"
- "traefik.http.middlewares.middleware19.stripprefix.prefixes=foobar, foobar"
- "traefik.http.middlewares.middleware20.stripprefixregex.regex=foobar, foobar"
- "traefik.http.routers.router0.entrypoints=foobar, foobar"
- "traefik.http.routers.router0.middlewares=foobar, foobar"
- "traefik.http.routers.router0.priority=42"
@@ -135,8 +140,8 @@
- "traefik.http.services.service0.loadbalancer.passhostheader=true"
- "traefik.http.services.service0.loadbalancer.responseforwarding.flushinterval=foobar"
- "traefik.http.services.service0.loadbalancer.sticky=true"
- "traefik.http.services.service0.loadbalancer.sticky.cookie.name=foobar"
- "traefik.http.services.service0.loadbalancer.sticky.cookie.httponly=true"
- "traefik.http.services.service0.loadbalancer.sticky.cookie.name=foobar"
- "traefik.http.services.service0.loadbalancer.sticky.cookie.secure=true"
- "traefik.http.services.service0.loadbalancer.server.port=foobar"
- "traefik.http.services.service0.loadbalancer.server.scheme=foobar"
@@ -151,8 +156,8 @@
- "traefik.http.services.service1.loadbalancer.passhostheader=true"
- "traefik.http.services.service1.loadbalancer.responseforwarding.flushinterval=foobar"
- "traefik.http.services.service1.loadbalancer.sticky=true"
- "traefik.http.services.service1.loadbalancer.sticky.cookie.name=foobar"
- "traefik.http.services.service1.loadbalancer.sticky.cookie.httponly=true"
- "traefik.http.services.service1.loadbalancer.sticky.cookie.name=foobar"
- "traefik.http.services.service1.loadbalancer.sticky.cookie.secure=true"
- "traefik.http.services.service1.loadbalancer.server.port=foobar"
- "traefik.http.services.service1.loadbalancer.server.scheme=foobar"

View File

@@ -62,17 +62,28 @@
[http.services.Service01.loadBalancer.responseForwarding]
flushInterval = "foobar"
[http.services.Service02]
[http.services.Service02.weighted]
[http.services.Service02.mirroring]
service = "foobar"
[[http.services.Service02.weighted.services]]
[[http.services.Service02.mirroring.mirrors]]
name = "foobar"
percent = 42
[[http.services.Service02.mirroring.mirrors]]
name = "foobar"
percent = 42
[http.services.Service03]
[http.services.Service03.weighted]
[[http.services.Service03.weighted.services]]
name = "foobar"
weight = 42
[[http.services.Service02.weighted.services]]
[[http.services.Service03.weighted.services]]
name = "foobar"
weight = 42
[http.services.Service02.weighted.sticky]
[http.services.Service02.weighted.sticky.cookie]
[http.services.Service03.weighted.sticky]
[http.services.Service03.weighted.sticky.cookie]
name = "foobar"
secure = true
httpOnly = true
@@ -202,30 +213,40 @@
serialNumber = true
domainComponent = true
[http.middlewares.Middleware13]
[http.middlewares.Middleware13.redirectRegex]
[http.middlewares.Middleware13.rateLimit]
average = 42
burst = 42
[http.middlewares.Middleware13.rateLimit.sourceCriterion]
requestHeaderName = "foobar"
requestHost = true
[http.middlewares.Middleware13.rateLimit.sourceCriterion.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware14]
[http.middlewares.Middleware14.redirectRegex]
regex = "foobar"
replacement = "foobar"
permanent = true
[http.middlewares.Middleware14]
[http.middlewares.Middleware14.redirectScheme]
[http.middlewares.Middleware15]
[http.middlewares.Middleware15.redirectScheme]
scheme = "foobar"
port = "foobar"
permanent = true
[http.middlewares.Middleware15]
[http.middlewares.Middleware15.replacePath]
path = "foobar"
[http.middlewares.Middleware16]
[http.middlewares.Middleware16.replacePathRegex]
[http.middlewares.Middleware16.replacePath]
path = "foobar"
[http.middlewares.Middleware17]
[http.middlewares.Middleware17.replacePathRegex]
regex = "foobar"
replacement = "foobar"
[http.middlewares.Middleware17]
[http.middlewares.Middleware17.retry]
attempts = 42
[http.middlewares.Middleware18]
[http.middlewares.Middleware18.stripPrefix]
prefixes = ["foobar", "foobar"]
[http.middlewares.Middleware18.retry]
attempts = 42
[http.middlewares.Middleware19]
[http.middlewares.Middleware19.stripPrefixRegex]
[http.middlewares.Middleware19.stripPrefix]
prefixes = ["foobar", "foobar"]
[http.middlewares.Middleware20]
[http.middlewares.Middleware20.stripPrefixRegex]
regex = ["foobar", "foobar"]
[tcp]

View File

@@ -69,6 +69,14 @@ http:
responseForwarding:
flushInterval: foobar
Service02:
mirroring:
service: foobar
mirrors:
- name: foobar
percent: 42
- name: foobar
percent: 42
Service03:
weighted:
services:
- name: foobar
@@ -201,9 +209,11 @@ http:
inFlightReq:
amount: 42
sourceCriterion:
ipStrategy:
ipstrategy:
depth: 42
excludedIPs: [ foobar, foobar ]
excludedIPs:
- foobar
- foobar
requestHeaderName: foobar
requestHost: true
Middleware12:
@@ -230,45 +240,47 @@ http:
serialNumber: true
domainComponent: true
Middleware13:
redirectRegex:
regex: foobar
replacement: foobar
permanent: true
Middleware14:
redirectScheme:
scheme: foobar
port: foobar
permanent: true
Middleware15:
replacePath:
path: foobar
Middleware16:
replacePathRegex:
regex: foobar
replacement: foobar
Middleware17:
retry:
attempts: 42
Middleware18:
stripPrefix:
prefixes:
- foobar
- foobar
Middleware19:
stripPrefixRegex:
regex:
- foobar
- foobar
Middleware20:
rateLimit:
average: 42
burst: 42
sourceCriterion:
ipStrategy:
ipstrategy:
depth: 42
excludedIPs: [ foobar, foobar ]
excludedIPs:
- foobar
- foobar
requestHeaderName: foobar
requestHost: true
Middleware14:
redirectRegex:
regex: foobar
replacement: foobar
permanent: true
Middleware15:
redirectScheme:
scheme: foobar
port: foobar
permanent: true
Middleware16:
replacePath:
path: foobar
Middleware17:
replacePathRegex:
regex: foobar
replacement: foobar
Middleware18:
retry:
attempts: 42
Middleware19:
stripPrefix:
prefixes:
- foobar
- foobar
Middleware20:
stripPrefixRegex:
regex:
- foobar
- foobar
tcp:
routers:
TCPRouter0:

View File

@@ -45,13 +45,13 @@
"traefik.http.middlewares.middleware09.headers.customrequestheaders.name1": "foobar",
"traefik.http.middlewares.middleware09.headers.customresponseheaders.name0": "foobar",
"traefik.http.middlewares.middleware09.headers.customresponseheaders.name1": "foobar",
"traefik.http.middlewares.middleware09.headers.featurepolicy": "foobar",
"traefik.http.middlewares.middleware09.headers.forcestsheader": "true",
"traefik.http.middlewares.middleware09.headers.framedeny": "true",
"traefik.http.middlewares.middleware09.headers.hostsproxyheaders": "foobar, foobar",
"traefik.http.middlewares.middleware09.headers.isdevelopment": "true",
"traefik.http.middlewares.middleware09.headers.publickey": "foobar",
"traefik.http.middlewares.middleware09.headers.referrerpolicy": "foobar",
"traefik.http.middlewares.middleware09.headers.featurepolicy": "foobar",
"traefik.http.middlewares.middleware09.headers.sslforcehost": "true",
"traefik.http.middlewares.middleware09.headers.sslhost": "foobar",
"traefik.http.middlewares.middleware09.headers.sslproxyheaders.name0": "foobar",
@@ -64,11 +64,11 @@
"traefik.http.middlewares.middleware10.ipwhitelist.ipstrategy.depth": "42",
"traefik.http.middlewares.middleware10.ipwhitelist.ipstrategy.excludedips": "foobar, foobar",
"traefik.http.middlewares.middleware10.ipwhitelist.sourcerange": "foobar, foobar",
"traefik.http.middlewares.Middleware11.inflightreq.amount": "42",
"traefik.http.middlewares.Middleware11.inflightreq.sourcecriterion.ipstrategy.depth": "42",
"traefik.http.middlewares.Middleware11.inflightreq.sourcecriterion.ipstrategy.excludedips": "foobar, fiibar",
"traefik.http.middlewares.Middleware11.inflightreq.sourcecriterion.requestheadername": "foobar",
"traefik.http.middlewares.Middleware11.inflightreq.sourcecriterion.requesthost": "true",
"traefik.http.middlewares.middleware11.inflightreq.amount": "42",
"traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.ipstrategy.depth": "42",
"traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.ipstrategy.excludedips": "foobar, foobar",
"traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requestheadername": "foobar",
"traefik.http.middlewares.middleware11.inflightreq.sourcecriterion.requesthost": "true",
"traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.commonname": "true",
"traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.country": "true",
"traefik.http.middlewares.middleware12.passtlsclientcert.info.issuer.domaincomponent": "true",
@@ -87,24 +87,24 @@
"traefik.http.middlewares.middleware12.passtlsclientcert.info.subject.province": "true",
"traefik.http.middlewares.middleware12.passtlsclientcert.info.subject.serialnumber": "true",
"traefik.http.middlewares.middleware12.passtlsclientcert.pem": "true",
"traefik.http.middlewares.middleware13.redirectregex.permanent": "true",
"traefik.http.middlewares.middleware13.redirectregex.regex": "foobar",
"traefik.http.middlewares.middleware13.redirectregex.replacement": "foobar",
"traefik.http.middlewares.middleware14.redirectscheme.permanent": "true",
"traefik.http.middlewares.middleware14.redirectscheme.port": "foobar",
"traefik.http.middlewares.middleware14.redirectscheme.scheme": "foobar",
"traefik.http.middlewares.middleware15.replacepath.path": "foobar",
"traefik.http.middlewares.middleware16.replacepathregex.regex": "foobar",
"traefik.http.middlewares.middleware16.replacepathregex.replacement": "foobar",
"traefik.http.middlewares.middleware17.retry.attempts": "42",
"traefik.http.middlewares.middleware18.stripprefix.prefixes": "foobar, foobar",
"traefik.http.middlewares.middleware19.stripprefixregex.regex": "foobar, foobar",
"traefik.http.middlewares.Middleware20.ratelimit.average": "42",
"traefik.http.middlewares.Middleware20.ratelimit.burst": "42",
"traefik.http.middlewares.Middleware20.ratelimit.sourcecriterion.requestheadername": "foobar",
"traefik.http.middlewares.Middleware20.ratelimit.sourcecriterion.requesthost": "true",
"traefik.http.middlewares.Middleware20.ratelimit.sourcecriterion.ipstrategy.depth": "42",
"traefik.http.middlewares.Middleware20.ratelimit.sourcecriterion.ipstrategy.excludedips": "foobar, foobar",
"traefik.http.middlewares.middleware13.ratelimit.average": "42",
"traefik.http.middlewares.middleware13.ratelimit.burst": "42",
"traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.ipstrategy.depth": "42",
"traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.ipstrategy.excludedips": "foobar, foobar",
"traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.requestheadername": "foobar",
"traefik.http.middlewares.middleware13.ratelimit.sourcecriterion.requesthost": "true",
"traefik.http.middlewares.middleware14.redirectregex.permanent": "true",
"traefik.http.middlewares.middleware14.redirectregex.regex": "foobar",
"traefik.http.middlewares.middleware14.redirectregex.replacement": "foobar",
"traefik.http.middlewares.middleware15.redirectscheme.permanent": "true",
"traefik.http.middlewares.middleware15.redirectscheme.port": "foobar",
"traefik.http.middlewares.middleware15.redirectscheme.scheme": "foobar",
"traefik.http.middlewares.middleware16.replacepath.path": "foobar",
"traefik.http.middlewares.middleware17.replacepathregex.regex": "foobar",
"traefik.http.middlewares.middleware17.replacepathregex.replacement": "foobar",
"traefik.http.middlewares.middleware18.retry.attempts": "42",
"traefik.http.middlewares.middleware19.stripprefix.prefixes": "foobar, foobar",
"traefik.http.middlewares.middleware20.stripprefixregex.regex": "foobar, foobar",
"traefik.http.routers.router0.entrypoints": "foobar, foobar",
"traefik.http.routers.router0.middlewares": "foobar, foobar",
"traefik.http.routers.router0.priority": "42",
@@ -140,8 +140,8 @@
"traefik.http.services.service0.loadbalancer.passhostheader": "true",
"traefik.http.services.service0.loadbalancer.responseforwarding.flushinterval": "foobar",
"traefik.http.services.service0.loadbalancer.sticky": "true",
"traefik.http.services.service0.loadbalancer.sticky.cookie.name": "foobar",
"traefik.http.services.service0.loadbalancer.sticky.cookie.httponly": "true",
"traefik.http.services.service0.loadbalancer.sticky.cookie.name": "foobar",
"traefik.http.services.service0.loadbalancer.sticky.cookie.secure": "true",
"traefik.http.services.service0.loadbalancer.server.port": "foobar",
"traefik.http.services.service0.loadbalancer.server.scheme": "foobar",
@@ -156,9 +156,9 @@
"traefik.http.services.service1.loadbalancer.passhostheader": "true",
"traefik.http.services.service1.loadbalancer.responseforwarding.flushinterval": "foobar",
"traefik.http.services.service1.loadbalancer.sticky": "true",
"traefik.http.services.service1.loadbalancer.sticky.cookie.httponly": "true",
"traefik.http.services.service1.loadbalancer.sticky.cookie.name": "foobar",
"traefik.http.services.service1.loadbalancer.sticky.cookie.secure": "true",
"traefik.http.services.service1.loadbalancer.sticky.cookie.httponly": "true",
"traefik.http.services.service1.loadbalancer.server.port": "foobar",
"traefik.http.services.service1.loadbalancer.server.scheme": "foobar",
"traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar",

View File

@@ -151,19 +151,19 @@ Traefik log format: json | common (Default: ```common```)
Log level set to traefik logs. (Default: ```ERROR```)
`--metrics.datadog`:
DataDog metrics exporter type. (Default: ```false```)
Datadog metrics exporter type. (Default: ```false```)
`--metrics.datadog.addentrypointslabels`:
Enable metrics on entry points. (Default: ```true```)
`--metrics.datadog.address`:
DataDog's address. (Default: ```localhost:8125```)
Datadog's address. (Default: ```localhost:8125```)
`--metrics.datadog.addserviceslabels`:
Enable metrics on services. (Default: ```true```)
`--metrics.datadog.pushinterval`:
DataDog push interval. (Default: ```10```)
Datadog push interval. (Default: ```10```)
`--metrics.influxdb`:
InfluxDB metrics exporter type. (Default: ```false```)
@@ -457,13 +457,13 @@ Add cert file for self-signed certificate.
OpenTracing configuration. (Default: ```false```)
`--tracing.datadog`:
Settings for DataDog. (Default: ```false```)
Settings for Datadog. (Default: ```false```)
`--tracing.datadog.bagageprefixheadername`:
Specifies the header name prefix that will be used to store baggage items in a map.
`--tracing.datadog.debug`:
Enable DataDog debug. (Default: ```false```)
Enable Datadog debug. (Default: ```false```)
`--tracing.datadog.globaltag`:
Key:Value tag to be set on all the spans.
@@ -561,11 +561,8 @@ Set the maximum character limit for Span names (default 0 = no limit). (Default:
`--tracing.zipkin`:
Settings for Zipkin. (Default: ```false```)
`--tracing.zipkin.debug`:
Enable Zipkin debug. (Default: ```false```)
`--tracing.zipkin.httpendpoint`:
HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v1/spans```)
HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v2/spans```)
`--tracing.zipkin.id128bit`:
Use Zipkin 128 bit root span IDs. (Default: ```true```)

View File

@@ -151,19 +151,19 @@ Traefik log format: json | common (Default: ```common```)
Log level set to traefik logs. (Default: ```ERROR```)
`TRAEFIK_METRICS_DATADOG`:
DataDog metrics exporter type. (Default: ```false```)
Datadog metrics exporter type. (Default: ```false```)
`TRAEFIK_METRICS_DATADOG_ADDENTRYPOINTSLABELS`:
Enable metrics on entry points. (Default: ```true```)
`TRAEFIK_METRICS_DATADOG_ADDRESS`:
DataDog's address. (Default: ```localhost:8125```)
Datadog's address. (Default: ```localhost:8125```)
`TRAEFIK_METRICS_DATADOG_ADDSERVICESLABELS`:
Enable metrics on services. (Default: ```true```)
`TRAEFIK_METRICS_DATADOG_PUSHINTERVAL`:
DataDog push interval. (Default: ```10```)
Datadog push interval. (Default: ```10```)
`TRAEFIK_METRICS_INFLUXDB`:
InfluxDB metrics exporter type. (Default: ```false```)
@@ -457,13 +457,13 @@ Add cert file for self-signed certificate.
OpenTracing configuration. (Default: ```false```)
`TRAEFIK_TRACING_DATADOG`:
Settings for DataDog. (Default: ```false```)
Settings for Datadog. (Default: ```false```)
`TRAEFIK_TRACING_DATADOG_BAGAGEPREFIXHEADERNAME`:
Specifies the header name prefix that will be used to store baggage items in a map.
`TRAEFIK_TRACING_DATADOG_DEBUG`:
Enable DataDog debug. (Default: ```false```)
Enable Datadog debug. (Default: ```false```)
`TRAEFIK_TRACING_DATADOG_GLOBALTAG`:
Key:Value tag to be set on all the spans.
@@ -561,11 +561,8 @@ Set the maximum character limit for Span names (default 0 = no limit). (Default:
`TRAEFIK_TRACING_ZIPKIN`:
Settings for Zipkin. (Default: ```false```)
`TRAEFIK_TRACING_ZIPKIN_DEBUG`:
Enable Zipkin debug. (Default: ```false```)
`TRAEFIK_TRACING_ZIPKIN_HTTPENDPOINT`:
HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v1/spans```)
HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v2/spans```)
`TRAEFIK_TRACING_ZIPKIN_ID128BIT`:
Use Zipkin 128 bit root span IDs. (Default: ```true```)

View File

@@ -115,7 +115,7 @@
buckets = [42.0, 42.0]
addEntryPointsLabels = true
addServicesLabels = true
[metrics.dataDog]
[metrics.datadog]
address = "foobar"
pushInterval = "10s"
addEntryPointsLabels = true
@@ -181,9 +181,8 @@
httpEndpoint = "foobar"
sameSpan = true
id128Bit = true
debug = true
sampleRate = 42.0
[tracing.dataDog]
[tracing.datadog]
localAgentHostPort = "foobar"
globalTag = "foobar"
debug = true

View File

@@ -122,7 +122,7 @@ metrics:
- 42
addEntryPointsLabels: true
addServicesLabels: true
dataDog:
datadog:
address: foobar
pushInterval: 42
addEntryPointsLabels: true
@@ -186,9 +186,8 @@ tracing:
httpEndpoint: foobar
sameSpan: true
id128Bit: true
debug: true
sampleRate: 42
dataDog:
datadog:
localAgentHostPort: foobar
globalTag: foobar
debug: true

View File

@@ -216,7 +216,7 @@ The table below lists all the available matchers:
| ```Host(`domain-1`, ...)``` | Check if the request domain targets one of the given `domains`. |
| ```HostRegexp(`traefik.io`, `{subdomain:[a-z]+}.traefik.io`, ...)``` | Check if the request domain matches the given `regexp`. |
| ```Method(`GET`, ...)``` | Check if the request method is one of the given `methods` (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`) |
| ```Path(`path`, `/articles/{category}/{id:[0-9]+}`, ...)``` | Match exact request path. It accepts a sequence of literal and regular expression paths. |
| ```Path(`/path`, `/articles/{category}/{id:[0-9]+}`, ...)``` | Match exact request path. It accepts a sequence of literal and regular expression paths. |
| ```PathPrefix(`/products/`, `/articles/{category}/{id:[0-9]+}`)``` | Match request prefix path. It accepts a sequence of literal and regular expression prefix paths. |
| ```Query(`foo=bar`, `bar=baz`)``` | Match` Query String parameters. It accepts a sequence of key=value pairs. |

View File

@@ -98,7 +98,7 @@ The remaining section is going to explore them along with a benefit/cost trade-o
It may seem obvious to reuse the Marathon health checks as a signal to Traefik whether an application should be taken into load-balancing rotation or not.
Apart from the increased latency a failing health check may have, a major problem with this is is that Marathon does not persist the health check results.
Apart from the increased latency a failing health check may have, a major problem with this is that Marathon does not persist the health check results.
Consequently, if a master re-election occurs in the Marathon clusters, all health check results will revert to the _unknown_ state, effectively causing all applications inside the cluster to become unavailable and leading to a complete cluster failure.
Re-elections do not only happen during regular maintenance work (often requiring rolling upgrades of the Marathon nodes) but also when the Marathon leader fails spontaneously.
As such, there is no way to handle this situation deterministically.

View File

@@ -122,7 +122,7 @@ nav:
- 'Access Logs': 'observability/access-logs.md'
- 'Metrics':
- 'Overview': 'observability/metrics/overview.md'
- 'DataDog': 'observability/metrics/datadog.md'
- 'Datadog': 'observability/metrics/datadog.md'
- 'InfluxDB': 'observability/metrics/influxdb.md'
- 'Prometheus': 'observability/metrics/prometheus.md'
- 'StatsD': 'observability/metrics/statsd.md'
@@ -130,7 +130,7 @@ nav:
- 'Overview': 'observability/tracing/overview.md'
- 'Jaeger': 'observability/tracing/jaeger.md'
- 'Zipkin': 'observability/tracing/zipkin.md'
- 'DataDog': 'observability/tracing/datadog.md'
- 'Datadog': 'observability/tracing/datadog.md'
- 'Instana': 'observability/tracing/instana.md'
- 'Haystack': 'observability/tracing/haystack.md'
- 'User Guides':
@@ -143,6 +143,8 @@ nav:
- 'TLS Challenge': 'user-guides/docker-compose/acme-tls/index.md'
- 'HTTP Challenge': 'user-guides/docker-compose/acme-http/index.md'
- 'DNS Challenge': 'user-guides/docker-compose/acme-dns/index.md'
- 'Migration':
- 'Traefik v1 to v2': 'migration/v1-to-v2.md'
- 'Contributing':
- 'Thank You!': 'contributing/thank-you.md'
- 'Submitting Issues': 'contributing/submitting-issues.md'

View File

@@ -12,7 +12,7 @@ RUN yarn install
RUN npm run build
# BUILD
FROM golang:1.13rc1-alpine as gobuild
FROM golang:1.13rc2-alpine as gobuild
RUN apk --update upgrade \
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \

8
go.mod
View File

@@ -43,9 +43,9 @@ require (
github.com/go-check/check v0.0.0-00010101000000-000000000000
github.com/go-kit/kit v0.9.0
github.com/golang/protobuf v1.3.2
github.com/google/go-github/v27 v27.0.4
github.com/google/go-github/v28 v28.0.0
github.com/googleapis/gnostic v0.1.0 // indirect
github.com/gorilla/mux v1.6.2
github.com/gorilla/mux v1.7.3
github.com/gorilla/websocket v1.4.0
github.com/hashicorp/go-version v1.2.0
github.com/huandu/xstrings v1.2.0 // indirect
@@ -65,10 +65,10 @@ require (
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/opencontainers/runc v1.0.0-rc8 // indirect
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect
github.com/opentracing/basictracer-go v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.1.0
github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.3
github.com/openzipkin/zipkin-go v0.2.1
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/philhofer/fwd v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0

16
go.sum
View File

@@ -161,6 +161,7 @@ github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZi
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -193,6 +194,7 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
@@ -218,8 +220,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-github/v27 v27.0.4 h1:N/EEqsvJLgqTbepTiMBz+12KhwLovv6YvwpRezd+4Fg=
github.com/google/go-github/v27 v27.0.4/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0=
github.com/google/go-github/v28 v28.0.0 h1:+UjHI4+1W/vsXR4jJBWt0ZA74XHbvt5yBAvsf1M3bgM=
github.com/google/go-github/v28 v28.0.0/go.mod h1:+5GboIspo7F0NG2qsvfYh7en6F3EK37uyqv+c35AR3s=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
@@ -317,6 +319,7 @@ github.com/linode/linodego v0.10.0 h1:AMdb82HVgY8o3mjBXJcUv9B+fnJjfDMn2rNRGbX+jv
github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA=
github.com/looplab/fsm v0.1.0 h1:Qte7Zdn/5hBNbXzP7yxVU4OIFHWXBovyTT2LaBTyC20=
github.com/looplab/fsm v0.1.0/go.mod h1:m2VaOfDHxqXBBMgc26m6yUOwkFn8H2AlJDE+jd/uafI=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 h1:Kg/NPZLLC3aAFr1YToMs98dbCdhootQ1hZIvZU28hAQ=
@@ -383,9 +386,11 @@ github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7l
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5 h1:82Tnq9OJpn+h5xgGpss5/mOv3KXdjtkdorFSOUusjM8=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5/go.mod h1:uVHyebswE1cCXr2A73cRM2frx5ld1RJUCJkFNZ90ZiI=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.3 h1:XudIMByQMXJ6oDHy4SipNyo35LxjA69Z7v1nL0aAZvA=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.3/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1 h1:noL5/5Uf1HpVl3wNsfkZhIKbSWCVi5jgqkONNx8PXcA=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/oracle/oci-go-sdk v7.0.0+incompatible h1:oj5ESjXwwkFRdhZSnPlShvLWYdt/IZ65RQxveYM3maA=
github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014 h1:37VE5TYj2m/FLA9SNr4z0+A0JefvTmR60Zwf8XSEV7c=
@@ -396,6 +401,7 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -441,6 +447,7 @@ github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -604,6 +611,7 @@ google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM=

View File

@@ -309,8 +309,6 @@ func (s *AccessLogSuite) TestAccessLogFrontendRedirect(c *check.C) {
}
func (s *AccessLogSuite) TestAccessLogRateLimit(c *check.C) {
c.Skip("RateLimit is disable for now")
ensureWorkingDirectoryIsClean()
expected := []accessLogValue{

View File

@@ -150,9 +150,9 @@
[http.middlewares.foo-slash-add-prefix.addPrefix]
prefix = "/foo/"
[http.middlewares.id-strip-regex-prefix.stripPrefixRegex]
regex = ["/{id:[a-z]+}"]
regex = ["/[a-z]+"]
[http.middlewares.id-slash-strip-regex-prefix.stripPrefixRegex]
regex = ["/{id:[a-z]+}/"]
regex = ["/[a-z]+/"]
[http.middlewares.api-regex-replace.replacePathRegex]
regex = "/api"
replacement = "/"

View File

@@ -1,5 +1,17 @@
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: mychain
namespace: default
spec:
chain:
middlewares:
- name: stripprefix
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: stripprefix
namespace: default
@@ -26,4 +38,4 @@ spec:
- name: whoami
port: 80
middlewares:
- name: stripprefix
- name: mychain

View File

@@ -17,6 +17,11 @@
## dynamic configuration ##
[http.routers]
[http.routers.router3]
entrypoints=["unknown-entrypoint"]
service = "service1"
rule = "Host(`mydomain.com`)"
[http.routers.router4]
service = "service1"
rule = "Host(`snitest.net`)"

View File

@@ -28,7 +28,7 @@
[http.routers]
[http.routers.router1]
Service = "service1"
Middlewares = ["retry", "ratelimit"]
Middlewares = ["retry", "ratelimit-1"]
Rule = "Path(`/ratelimit`)"
[http.routers.router2]
Service = "service2"
@@ -44,16 +44,9 @@
attempts = 3
[http.middlewares.basic-auth.basicAuth]
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
[http.middlewares.ratelimit.rateLimit]
extractorfunc = "client.ip"
[http.middlewares.ratelimit.rateLimit.rateSet.rateset1]
period = "60s"
average = 4
burst = 5
[http.middlewares.ratelimit.rateLimit.rateSet.rateset2]
period = "3s"
average = 1
burst = 2
[http.middlewares.ratelimit-1.rateLimit]
average = 1
burst = 2
[http.services]

View File

@@ -27,7 +27,7 @@
[http.routers]
[http.routers.router1]
Service = "service1"
Middlewares = ["retry", "ratelimit"]
Middlewares = ["retry", "ratelimit-1"]
Rule = "Path(`/ratelimit`)"
[http.routers.router2]
Service = "service2"
@@ -43,17 +43,9 @@
attempts = 3
[http.middlewares.basic-auth.basicAuth]
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
[http.middlewares.ratelimit.rateLimit]
extractorfunc = "client.ip"
[http.middlewares.ratelimit.rateLimit.rateSet.rateset1]
period = "60s"
average = 4
burst = 5
[http.middlewares.ratelimit.rateLimit.rateSet.rateset2]
period = "3s"
average = 1
burst = 2
[http.middlewares.ratelimit-1.rateLimit]
average = 1
burst = 2
[http.services]
[http.services.service1]

View File

@@ -14,8 +14,7 @@
[tracing]
servicename = "tracing"
[tracing.zipkin]
httpEndpoint = "http://{{.IP}}:9411/api/v1/spans"
debug = true
httpEndpoint = "http://{{.IP}}:9411/api/v2/spans"
[providers.file]
filename = "{{ .SelfFilename }}"
@@ -25,7 +24,7 @@
[http.routers]
[http.routers.router1]
service = "service1"
middlewares = ["retry", "ratelimit"]
middlewares = ["retry", "ratelimit-1"]
rule = "Path(`/ratelimit`)"
[http.routers.router2]
service = "service2"
@@ -41,16 +40,9 @@
attempts = 3
[http.middlewares.basic-auth.basicAuth]
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
[http.middlewares.ratelimit.rateLimit]
extractorfunc = "client.ip"
[http.middlewares.ratelimit.rateLimit.rateSet.rateset1]
period = "60s"
average = 4
burst = 5
[http.middlewares.ratelimit.rateLimit.rateSet.rateset2]
period = "3s"
average = 1
burst = 2
[http.middlewares.ratelimit-1.rateLimit]
average = 1
burst = 2
[http.services]
[http.services.service1]

View File

@@ -55,19 +55,17 @@ frontendRedirect:
- traefik.http.middlewares.redirecthttp.redirectScheme.scheme=http
- traefik.http.middlewares.redirecthttp.redirectScheme.port=8000
- traefik.http.services.service3.loadbalancer.server.port=80
# TODO: disable temporarily (rateLimit)
#rateLimit:
# image: containous/whoami
# labels:
# - traefik.enable=true
# - traefik.http.routers.rt-rateLimit.entryPoints=httpRateLimit
# - traefik.http.routers.rt-rateLimit.rule=Host("ratelimit.docker.local")
# - traefik.http.routers.rt-rateLimit.middlewares=rate
# - traefik.http.middlewares.rate.ratelimit.extractorfunc=client.ip
# - traefik.http.middlewares.rate.ratelimit.rateset.Rate0.average=1
# - traefik.http.middlewares.rate.ratelimit.rateset.Rate0.burst=2
# - traefik.http.middlewares.rate.ratelimit.rateset.Rate0.period=10s
# - traefik.http.services.service3.loadbalancer.server.port=80
rateLimit:
image: containous/whoami
labels:
- traefik.enable=true
- traefik.http.routers.rt-rateLimit.entryPoints=httpRateLimit
- traefik.http.routers.rt-rateLimit.rule=Host("ratelimit.docker.local")
- traefik.http.routers.rt-rateLimit.middlewares=rate
- traefik.http.middlewares.rate.ratelimit
- traefik.http.middlewares.rate.ratelimit.average=1
- traefik.http.middlewares.rate.ratelimit.burst=2
- traefik.http.services.service3.loadbalancer.server.port=80
frontendWhitelist:
image: containous/whoami
labels:

View File

@@ -1,5 +1,5 @@
zipkin:
image: openzipkin/zipkin:2.12.6
image: openzipkin/zipkin:2.16.2
environment:
STORAGE_TYPE: mem
JAVA_OPTS: -Dlogging.level.zipkin=DEBUG

View File

@@ -546,6 +546,10 @@ func (s *SimpleSuite) TestRouterConfigErrors(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8080/api/http/routers", 1000*time.Millisecond, try.BodyContains(`["middleware \"unknown@file\" does not exist","found different TLS options for routers on the same host snitest.net, so using the default TLS options instead"]`))
c.Assert(err, checker.IsNil)
// router3 has an error because it uses an unknown entrypoint
err = try.GetRequest("http://127.0.0.1:8080/api/http/routers/router3@file", 1000*time.Millisecond, try.BodyContains(`entryPoint \"unknown-entrypoint\" doesn't exist`, "no valid entryPoint for this router"))
c.Assert(err, checker.IsNil)
// router4 is enabled, but in warning state because its tls options conf was messed up
err = try.GetRequest("http://127.0.0.1:8080/api/http/routers/router4@file", 1000*time.Millisecond, try.BodyContains(`"status":"warning"`))
c.Assert(err, checker.IsNil)

View File

@@ -10,31 +10,45 @@
"tls": {
"options": "default/mytlsoption"
},
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
},
"default/test2.route-23c7f4c450289ee29016@kubernetescrd": {
"entryPoints": [
"web"
],
"middlewares": [
"default/stripprefix"
"default/mychain"
],
"service": "default/test2.route-23c7f4c450289ee29016",
"rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/tobestripped`)",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
}
},
"middlewares": {
"default/stripprefix@kubernetescrd": {
"stripPrefix": {
"prefixes": [
"/tobestripped"
"default/mychain@kubernetescrd": {
"chain": {
"middlewares": [
"default/stripprefix"
]
},
"status": "enabled",
"usedBy": [
"default/test2.route-23c7f4c450289ee29016@kubernetescrd"
]
},
"default/stripprefix@kubernetescrd": {
"stripPrefix": {
"prefixes": [
"/tobestripped"
]
},
"status": "enabled"
}
},
"services": {
@@ -42,7 +56,7 @@
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.4:80"
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.5:80"
@@ -55,7 +69,7 @@
"default/test.route-6b204d94623b3df4370c@kubernetescrd"
],
"serverStatus": {
"http://10.42.0.4:80": "UP",
"http://10.42.0.3:80": "UP",
"http://10.42.0.5:80": "UP"
}
},
@@ -63,7 +77,7 @@
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.4:80"
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.5:80"
@@ -76,7 +90,7 @@
"default/test2.route-23c7f4c450289ee29016@kubernetescrd"
],
"serverStatus": {
"http://10.42.0.4:80": "UP",
"http://10.42.0.3:80": "UP",
"http://10.42.0.5:80": "UP"
}
}
@@ -92,7 +106,10 @@
"passthrough": false,
"options": "default/mytlsoption"
},
"status": "enabled"
"status": "enabled",
"using": [
"footcp"
]
}
},
"tcpServices": {
@@ -100,10 +117,10 @@
"loadBalancer": {
"servers": [
{
"address": "10.42.0.3:8080"
"address": "10.42.0.6:8080"
},
{
"address": "10.42.0.6:8080"
"address": "10.42.0.7:8080"
}
]
},

View File

@@ -4,17 +4,29 @@
"service": "default/whoami/http",
"rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)",
"tls": {},
"status": "enabled"
"status": "enabled",
"using": [
"traefik",
"web"
]
},
"whoami-test-https/whoami@kubernetes": {
"service": "default/whoami/http",
"rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)",
"status": "enabled"
"status": "enabled",
"using": [
"traefik",
"web"
]
},
"whoami-test/whoami@kubernetes": {
"service": "default/whoami/http",
"rule": "Host(`whoami.test`) \u0026\u0026 PathPrefix(`/whoami`)",
"status": "enabled"
"status": "enabled",
"using": [
"traefik",
"web"
]
}
},
"services": {
@@ -22,10 +34,10 @@
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.4:80"
"url": "http://10.42.0.2:80"
},
{
"url": "http://10.42.0.5:80"
"url": "http://10.42.0.4:80"
}
],
"passHostHeader": true
@@ -37,8 +49,8 @@
"whoami-test/whoami@kubernetes"
],
"serverStatus": {
"http://10.42.0.4:80": "UP",
"http://10.42.0.5:80": "UP"
"http://10.42.0.2:80": "UP",
"http://10.42.0.4:80": "UP"
}
}
}

View File

@@ -41,8 +41,6 @@ func (s *TracingSuite) startZipkin(c *check.C) {
}
func (s *TracingSuite) TestZipkinRateLimit(c *check.C) {
c.Skip("RateLimit is disable for now")
s.startZipkin(c)
defer s.composeProject.Stop(c, "zipkin")
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
@@ -88,7 +86,7 @@ func (s *TracingSuite) TestZipkinRateLimit(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit@file"))
err = try.GetRequest("http://"+s.IP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
c.Assert(err, checker.IsNil)
}
@@ -157,8 +155,6 @@ func (s *TracingSuite) startJaeger(c *check.C) {
}
func (s *TracingSuite) TestJaegerRateLimit(c *check.C) {
c.Skip("RateLimit is disable for now")
s.startJaeger(c)
defer s.composeProject.Stop(c, "jaeger")
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
@@ -200,13 +196,11 @@ func (s *TracingSuite) TestJaegerRateLimit(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
time.Sleep(3 * time.Second)
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://"+s.IP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit@file"))
err = try.GetRequest("http://"+s.IP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
c.Assert(err, checker.IsNil)
}
func (s *TracingSuite) TestJaegerRetry(c *check.C) {

View File

@@ -186,7 +186,7 @@ func TestDo_globalConfiguration(t *testing.T) {
Prometheus: &types.Prometheus{
Buckets: []float64{0.1, 0.3, 1.2, 5},
},
DataDog: &types.DataDog{
Datadog: &types.Datadog{
Address: "localhost:8181",
PushInterval: 12,
},
@@ -223,10 +223,9 @@ func TestDo_globalConfiguration(t *testing.T) {
HTTPEndpoint: "fff",
SameSpan: true,
ID128Bit: true,
Debug: true,
SampleRate: 53,
},
DataDog: &datadog.Config{
Datadog: &datadog.Config{
LocalAgentHostPort: "ggg",
GlobalTag: "eee",
Debug: true,

102
pkg/api/criterion.go Normal file
View File

@@ -0,0 +1,102 @@
package api
import (
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
)
const (
defaultPerPage = 100
defaultPage = 1
)
const nextPageHeader = "X-Next-Page"
type pageInfo struct {
startIndex int
endIndex int
nextPage int
}
type searchCriterion struct {
Search string `url:"search"`
Status string `url:"status"`
}
func newSearchCriterion(query url.Values) *searchCriterion {
if len(query) == 0 {
return nil
}
search := query.Get("search")
status := query.Get("status")
if status == "" && search == "" {
return nil
}
return &searchCriterion{Search: search, Status: status}
}
func (c *searchCriterion) withStatus(name string) bool {
return c.Status == "" || strings.EqualFold(name, c.Status)
}
func (c *searchCriterion) searchIn(values ...string) bool {
if c.Search == "" {
return true
}
for _, v := range values {
if strings.Contains(strings.ToLower(v), strings.ToLower(c.Search)) {
return true
}
}
return false
}
func pagination(request *http.Request, max int) (pageInfo, error) {
perPage, err := getIntParam(request, "per_page", defaultPerPage)
if err != nil {
return pageInfo{}, err
}
page, err := getIntParam(request, "page", defaultPage)
if err != nil {
return pageInfo{}, err
}
startIndex := (page - 1) * perPage
if startIndex != 0 && startIndex >= max {
return pageInfo{}, fmt.Errorf("invalid request: page: %d, per_page: %d", page, perPage)
}
endIndex := startIndex + perPage
if endIndex >= max {
endIndex = max
}
nextPage := 1
if page*perPage < max {
nextPage = page + 1
}
return pageInfo{startIndex: startIndex, endIndex: endIndex, nextPage: nextPage}, nil
}
func getIntParam(request *http.Request, key string, defaultValue int) (int, error) {
raw := request.URL.Query().Get(key)
if raw == "" {
return defaultValue, nil
}
value, err := strconv.Atoi(raw)
if err != nil || value <= 0 {
return 0, fmt.Errorf("invalid request: %s: %d", key, value)
}
return value, nil
}

View File

@@ -2,9 +2,8 @@ package api
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"reflect"
"strings"
"github.com/containous/traefik/v2/pkg/config/runtime"
@@ -15,12 +14,19 @@ import (
"github.com/gorilla/mux"
)
const (
defaultPerPage = 100
defaultPage = 1
)
type apiError struct {
Message string `json:"message"`
}
const nextPageHeader = "X-Next-Page"
func writeError(rw http.ResponseWriter, msg string, code int) {
data, err := json.Marshal(apiError{Message: msg})
if err != nil {
http.Error(rw, msg, code)
return
}
http.Error(rw, string(data), code)
}
type serviceInfoRepresentation struct {
*runtime.ServiceInfo
@@ -36,12 +42,6 @@ type RunTimeRepresentation struct {
TCPServices map[string]*runtime.TCPServiceInfo `json:"tcpServices,omitempty"`
}
type pageInfo struct {
startIndex int
endIndex int
nextPage int
}
// Handler serves the configuration and status of Traefik on API endpoints.
type Handler struct {
dashboard bool
@@ -136,48 +136,19 @@ func (h Handler) getRuntimeConfiguration(rw http.ResponseWriter, request *http.R
}
}
func pagination(request *http.Request, max int) (pageInfo, error) {
perPage, err := getIntParam(request, "per_page", defaultPerPage)
if err != nil {
return pageInfo{}, err
}
page, err := getIntParam(request, "page", defaultPage)
if err != nil {
return pageInfo{}, err
}
startIndex := (page - 1) * perPage
if startIndex != 0 && startIndex >= max {
return pageInfo{}, fmt.Errorf("invalid request: page: %d, per_page: %d", page, perPage)
}
endIndex := startIndex + perPage
if endIndex >= max {
endIndex = max
}
nextPage := 1
if page*perPage < max {
nextPage = page + 1
}
return pageInfo{startIndex: startIndex, endIndex: endIndex, nextPage: nextPage}, nil
}
func getIntParam(request *http.Request, key string, defaultValue int) (int, error) {
raw := request.URL.Query().Get(key)
if raw == "" {
return defaultValue, nil
}
value, err := strconv.Atoi(raw)
if err != nil || value <= 0 {
return 0, fmt.Errorf("invalid request: %s: %d", key, value)
}
return value, nil
}
func getProviderName(id string) string {
return strings.SplitN(id, "@", 2)[1]
}
func extractType(element interface{}) string {
v := reflect.ValueOf(element).Elem()
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
if field.Kind() == reflect.Ptr && field.Elem().Kind() == reflect.Struct {
if !field.IsNil() {
return v.Type().Field(i).Name
}
}
}
return ""
}

View File

@@ -2,6 +2,7 @@ package api
import (
"encoding/json"
"fmt"
"net/http"
"sort"
"strconv"
@@ -30,28 +31,31 @@ func (h Handler) getEntryPoints(rw http.ResponseWriter, request *http.Request) {
return results[i].Name < results[j].Name
})
rw.Header().Set("Content-Type", "application/json")
pageInfo, err := pagination(request, len(results))
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
writeError(rw, err.Error(), http.StatusBadRequest)
return
}
rw.Header().Set("Content-Type", "application/json")
rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage))
err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex])
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func (h Handler) getEntryPoint(rw http.ResponseWriter, request *http.Request) {
entryPointID := mux.Vars(request)["entryPointID"]
rw.Header().Set("Content-Type", "application/json")
ep, ok := h.staticConfig.EntryPoints[entryPointID]
if !ok {
http.NotFound(rw, request)
writeError(rw, fmt.Sprintf("entry point not found: %s", entryPointID), http.StatusNotFound)
return
}
@@ -60,11 +64,9 @@ func (h Handler) getEntryPoint(rw http.ResponseWriter, request *http.Request) {
Name: entryPointID,
}
rw.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(rw).Encode(result)
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}

View File

@@ -2,9 +2,11 @@ package api
import (
"encoding/json"
"fmt"
"net/http"
"sort"
"strconv"
"strings"
"github.com/containous/traefik/v2/pkg/config/runtime"
"github.com/containous/traefik/v2/pkg/log"
@@ -17,182 +19,224 @@ type routerRepresentation struct {
Provider string `json:"provider,omitempty"`
}
func newRouterRepresentation(name string, rt *runtime.RouterInfo) routerRepresentation {
return routerRepresentation{
RouterInfo: rt,
Name: name,
Provider: getProviderName(name),
}
}
type serviceRepresentation struct {
*runtime.ServiceInfo
ServerStatus map[string]string `json:"serverStatus,omitempty"`
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"`
}
func newServiceRepresentation(name string, si *runtime.ServiceInfo) serviceRepresentation {
return serviceRepresentation{
ServiceInfo: si,
Name: name,
Provider: getProviderName(name),
ServerStatus: si.GetAllStatus(),
Type: strings.ToLower(extractType(si.Service)),
}
}
type middlewareRepresentation struct {
*runtime.MiddlewareInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"`
}
func newMiddlewareRepresentation(name string, mi *runtime.MiddlewareInfo) middlewareRepresentation {
return middlewareRepresentation{
MiddlewareInfo: mi,
Name: name,
Provider: getProviderName(name),
Type: strings.ToLower(extractType(mi.Middleware)),
}
}
func (h Handler) getRouters(rw http.ResponseWriter, request *http.Request) {
results := make([]routerRepresentation, 0, len(h.runtimeConfiguration.Routers))
criterion := newSearchCriterion(request.URL.Query())
for name, rt := range h.runtimeConfiguration.Routers {
results = append(results, routerRepresentation{
RouterInfo: rt,
Name: name,
Provider: getProviderName(name),
})
if keepRouter(name, rt, criterion) {
results = append(results, newRouterRepresentation(name, rt))
}
}
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
rw.Header().Set("Content-Type", "application/json")
pageInfo, err := pagination(request, len(results))
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
writeError(rw, err.Error(), http.StatusBadRequest)
return
}
rw.Header().Set("Content-Type", "application/json")
rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage))
err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex])
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func (h Handler) getRouter(rw http.ResponseWriter, request *http.Request) {
routerID := mux.Vars(request)["routerID"]
rw.Header().Set("Content-Type", "application/json")
router, ok := h.runtimeConfiguration.Routers[routerID]
if !ok {
http.NotFound(rw, request)
writeError(rw, fmt.Sprintf("router not found: %s", routerID), http.StatusNotFound)
return
}
result := routerRepresentation{
RouterInfo: router,
Name: routerID,
Provider: getProviderName(routerID),
}
rw.Header().Set("Content-Type", "application/json")
result := newRouterRepresentation(routerID, router)
err := json.NewEncoder(rw).Encode(result)
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func (h Handler) getServices(rw http.ResponseWriter, request *http.Request) {
results := make([]serviceRepresentation, 0, len(h.runtimeConfiguration.Services))
criterion := newSearchCriterion(request.URL.Query())
for name, si := range h.runtimeConfiguration.Services {
results = append(results, serviceRepresentation{
ServiceInfo: si,
Name: name,
Provider: getProviderName(name),
ServerStatus: si.GetAllStatus(),
})
if keepService(name, si, criterion) {
results = append(results, newServiceRepresentation(name, si))
}
}
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
rw.Header().Set("Content-Type", "application/json")
pageInfo, err := pagination(request, len(results))
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
writeError(rw, err.Error(), http.StatusBadRequest)
return
}
rw.Header().Set("Content-Type", "application/json")
rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage))
err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex])
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func (h Handler) getService(rw http.ResponseWriter, request *http.Request) {
serviceID := mux.Vars(request)["serviceID"]
rw.Header().Add("Content-Type", "application/json")
service, ok := h.runtimeConfiguration.Services[serviceID]
if !ok {
http.NotFound(rw, request)
writeError(rw, fmt.Sprintf("service not found: %s", serviceID), http.StatusNotFound)
return
}
result := serviceRepresentation{
ServiceInfo: service,
Name: serviceID,
Provider: getProviderName(serviceID),
ServerStatus: service.GetAllStatus(),
}
rw.Header().Add("Content-Type", "application/json")
result := newServiceRepresentation(serviceID, service)
err := json.NewEncoder(rw).Encode(result)
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func (h Handler) getMiddlewares(rw http.ResponseWriter, request *http.Request) {
results := make([]middlewareRepresentation, 0, len(h.runtimeConfiguration.Middlewares))
criterion := newSearchCriterion(request.URL.Query())
for name, mi := range h.runtimeConfiguration.Middlewares {
results = append(results, middlewareRepresentation{
MiddlewareInfo: mi,
Name: name,
Provider: getProviderName(name),
})
if keepMiddleware(name, mi, criterion) {
results = append(results, newMiddlewareRepresentation(name, mi))
}
}
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
rw.Header().Set("Content-Type", "application/json")
pageInfo, err := pagination(request, len(results))
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
writeError(rw, err.Error(), http.StatusBadRequest)
return
}
rw.Header().Set("Content-Type", "application/json")
rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage))
err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex])
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func (h Handler) getMiddleware(rw http.ResponseWriter, request *http.Request) {
middlewareID := mux.Vars(request)["middlewareID"]
rw.Header().Set("Content-Type", "application/json")
middleware, ok := h.runtimeConfiguration.Middlewares[middlewareID]
if !ok {
http.NotFound(rw, request)
writeError(rw, fmt.Sprintf("middleware not found: %s", middlewareID), http.StatusNotFound)
return
}
result := middlewareRepresentation{
MiddlewareInfo: middleware,
Name: middlewareID,
Provider: getProviderName(middlewareID),
}
rw.Header().Set("Content-Type", "application/json")
result := newMiddlewareRepresentation(middlewareID, middleware)
err := json.NewEncoder(rw).Encode(result)
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func keepRouter(name string, item *runtime.RouterInfo, criterion *searchCriterion) bool {
if criterion == nil {
return true
}
return criterion.withStatus(item.Status) && criterion.searchIn(item.Rule, name)
}
func keepService(name string, item *runtime.ServiceInfo, criterion *searchCriterion) bool {
if criterion == nil {
return true
}
return criterion.withStatus(item.Status) && criterion.searchIn(name)
}
func keepMiddleware(name string, item *runtime.MiddlewareInfo, criterion *searchCriterion) bool {
if criterion == nil {
return true
}
return criterion.withStatus(item.Status) && criterion.searchIn(name)
}

View File

@@ -1,6 +1,7 @@
package api
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
@@ -137,6 +138,68 @@ func TestHandler_HTTP(t *testing.T) {
statusCode: http.StatusBadRequest,
},
},
{
desc: "routers filtered by status",
path: "/api/http/routers?status=enabled",
conf: runtime.Configuration{
Routers: map[string]*runtime.RouterInfo{
"test@myprovider": {
Router: &dynamic.Router{
EntryPoints: []string{"web"},
Service: "foo-service@myprovider",
Rule: "Host(`foo.bar.other`)",
Middlewares: []string{"addPrefixTest", "auth"},
},
Status: runtime.StatusEnabled,
},
"bar@myprovider": {
Router: &dynamic.Router{
EntryPoints: []string{"web"},
Service: "foo-service@myprovider",
Rule: "Host(`foo.bar`)",
Middlewares: []string{"auth", "addPrefixTest@anotherprovider"},
},
Status: runtime.StatusDisabled,
},
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/routers-filtered-status.json",
},
},
{
desc: "routers filtered by search",
path: "/api/http/routers?search=fii",
conf: runtime.Configuration{
Routers: map[string]*runtime.RouterInfo{
"test@myprovider": {
Router: &dynamic.Router{
EntryPoints: []string{"web"},
Service: "fii-service@myprovider",
Rule: "Host(`fii.bar.other`)",
Middlewares: []string{"addPrefixTest", "auth"},
},
Status: runtime.StatusEnabled,
},
"bar@myprovider": {
Router: &dynamic.Router{
EntryPoints: []string{"web"},
Service: "foo-service@myprovider",
Rule: "Host(`foo.bar`)",
Middlewares: []string{"auth", "addPrefixTest@anotherprovider"},
},
Status: runtime.StatusDisabled,
},
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/routers-filtered-search.json",
},
},
{
desc: "one router by id",
path: "/api/http/routers/bar@myprovider",
@@ -232,6 +295,45 @@ func TestHandler_HTTP(t *testing.T) {
si.UpdateServerStatus("http://127.0.0.2", "UP")
return si
}(),
"canary@myprovider": {
Service: &dynamic.Service{
Weighted: &dynamic.WeightedRoundRobin{
Services: nil,
Sticky: &dynamic.Sticky{
Cookie: &dynamic.Cookie{
Name: "chocolat",
Secure: true,
HTTPOnly: true,
},
},
},
},
Status: runtime.StatusEnabled,
UsedBy: []string{"foo@myprovider"},
},
"mirror@myprovider": {
Service: &dynamic.Service{
Mirroring: &dynamic.Mirroring{
Service: "one@myprovider",
Mirrors: []dynamic.MirrorService{
{
Name: "two@myprovider",
Percent: 10,
},
{
Name: "three@myprovider",
Percent: 15,
},
{
Name: "four@myprovider",
Percent: 80,
},
},
},
},
Status: runtime.StatusEnabled,
UsedBy: []string{"foo@myprovider"},
},
},
},
expected: expected{
@@ -301,6 +403,100 @@ func TestHandler_HTTP(t *testing.T) {
jsonFile: "testdata/services-page2.json",
},
},
{
desc: "services filtered by status",
path: "/api/http/services?status=enabled",
conf: runtime.Configuration{
Services: map[string]*runtime.ServiceInfo{
"bar@myprovider": func() *runtime.ServiceInfo {
si := &runtime.ServiceInfo{
Service: &dynamic.Service{
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://127.0.0.1",
},
},
},
},
UsedBy: []string{"foo@myprovider", "test@myprovider"},
Status: runtime.StatusEnabled,
}
si.UpdateServerStatus("http://127.0.0.1", "UP")
return si
}(),
"baz@myprovider": func() *runtime.ServiceInfo {
si := &runtime.ServiceInfo{
Service: &dynamic.Service{
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://127.0.0.2",
},
},
},
},
UsedBy: []string{"foo@myprovider"},
Status: runtime.StatusDisabled,
}
si.UpdateServerStatus("http://127.0.0.2", "UP")
return si
}(),
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/services-filtered-status.json",
},
},
{
desc: "services filtered by search",
path: "/api/http/services?search=baz",
conf: runtime.Configuration{
Services: map[string]*runtime.ServiceInfo{
"bar@myprovider": func() *runtime.ServiceInfo {
si := &runtime.ServiceInfo{
Service: &dynamic.Service{
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://127.0.0.1",
},
},
},
},
UsedBy: []string{"foo@myprovider", "test@myprovider"},
Status: runtime.StatusEnabled,
}
si.UpdateServerStatus("http://127.0.0.1", "UP")
return si
}(),
"baz@myprovider": func() *runtime.ServiceInfo {
si := &runtime.ServiceInfo{
Service: &dynamic.Service{
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://127.0.0.2",
},
},
},
},
UsedBy: []string{"foo@myprovider"},
Status: runtime.StatusDisabled,
}
si.UpdateServerStatus("http://127.0.0.2", "UP")
return si
}(),
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/services-filtered-search.json",
},
},
{
desc: "one service by id",
path: "/api/http/services/bar@myprovider",
@@ -411,6 +607,86 @@ func TestHandler_HTTP(t *testing.T) {
jsonFile: "testdata/middlewares.json",
},
},
{
desc: "middlewares filtered by status",
path: "/api/http/middlewares?status=enabled",
conf: runtime.Configuration{
Middlewares: map[string]*runtime.MiddlewareInfo{
"auth@myprovider": {
Middleware: &dynamic.Middleware{
BasicAuth: &dynamic.BasicAuth{
Users: []string{"admin:admin"},
},
},
UsedBy: []string{"bar@myprovider", "test@myprovider"},
Status: runtime.StatusEnabled,
},
"addPrefixTest@myprovider": {
Middleware: &dynamic.Middleware{
AddPrefix: &dynamic.AddPrefix{
Prefix: "/titi",
},
},
UsedBy: []string{"test@myprovider"},
Status: runtime.StatusDisabled,
},
"addPrefixTest@anotherprovider": {
Middleware: &dynamic.Middleware{
AddPrefix: &dynamic.AddPrefix{
Prefix: "/toto",
},
},
UsedBy: []string{"bar@myprovider"},
Status: runtime.StatusEnabled,
},
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/middlewares-filtered-status.json",
},
},
{
desc: "middlewares filtered by search",
path: "/api/http/middlewares?search=addprefixtest",
conf: runtime.Configuration{
Middlewares: map[string]*runtime.MiddlewareInfo{
"auth@myprovider": {
Middleware: &dynamic.Middleware{
BasicAuth: &dynamic.BasicAuth{
Users: []string{"admin:admin"},
},
},
UsedBy: []string{"bar@myprovider", "test@myprovider"},
Status: runtime.StatusEnabled,
},
"addPrefixTest@myprovider": {
Middleware: &dynamic.Middleware{
AddPrefix: &dynamic.AddPrefix{
Prefix: "/titi",
},
},
UsedBy: []string{"test@myprovider"},
Status: runtime.StatusDisabled,
},
"addPrefixTest@anotherprovider": {
Middleware: &dynamic.Middleware{
AddPrefix: &dynamic.AddPrefix{
Prefix: "/toto",
},
},
UsedBy: []string{"bar@myprovider"},
Status: runtime.StatusEnabled,
},
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/middlewares-filtered-search.json",
},
},
{
desc: "all middlewares, 1 res per page, want page 2",
path: "/api/http/middlewares?page=2&per_page=1",
@@ -521,6 +797,8 @@ func TestHandler_HTTP(t *testing.T) {
rtConf := &test.conf
// To lazily initialize the Statuses.
rtConf.PopulateUsedBy()
rtConf.GetRoutersByEntryPoints(context.Background(), []string{"web"}, false)
handler := New(static.Configuration{API: &static.API{}, Global: &static.Global{}}, rtConf)
router := mux.NewRouter()
handler.Append(router)

View File

@@ -56,7 +56,7 @@ func (h Handler) getOverview(rw http.ResponseWriter, request *http.Request) {
err := json.NewEncoder(rw).Encode(result)
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}

View File

@@ -2,9 +2,11 @@ package api
import (
"encoding/json"
"fmt"
"net/http"
"sort"
"strconv"
"strings"
"github.com/containous/traefik/v2/pkg/config/runtime"
"github.com/containous/traefik/v2/pkg/log"
@@ -17,118 +19,146 @@ type tcpRouterRepresentation struct {
Provider string `json:"provider,omitempty"`
}
func newTCPRouterRepresentation(name string, rt *runtime.TCPRouterInfo) tcpRouterRepresentation {
return tcpRouterRepresentation{
TCPRouterInfo: rt,
Name: name,
Provider: getProviderName(name),
}
}
type tcpServiceRepresentation struct {
*runtime.TCPServiceInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"`
}
func newTCPServiceRepresentation(name string, si *runtime.TCPServiceInfo) tcpServiceRepresentation {
return tcpServiceRepresentation{
TCPServiceInfo: si,
Name: name,
Provider: getProviderName(name),
Type: strings.ToLower(extractType(si.TCPService)),
}
}
func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) {
results := make([]tcpRouterRepresentation, 0, len(h.runtimeConfiguration.TCPRouters))
criterion := newSearchCriterion(request.URL.Query())
for name, rt := range h.runtimeConfiguration.TCPRouters {
results = append(results, tcpRouterRepresentation{
TCPRouterInfo: rt,
Name: name,
Provider: getProviderName(name),
})
if keepTCPRouter(name, rt, criterion) {
results = append(results, newTCPRouterRepresentation(name, rt))
}
}
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
rw.Header().Set("Content-Type", "application/json")
pageInfo, err := pagination(request, len(results))
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
writeError(rw, err.Error(), http.StatusBadRequest)
return
}
rw.Header().Set("Content-Type", "application/json")
rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage))
err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex])
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func (h Handler) getTCPRouter(rw http.ResponseWriter, request *http.Request) {
routerID := mux.Vars(request)["routerID"]
rw.Header().Set("Content-Type", "application/json")
router, ok := h.runtimeConfiguration.TCPRouters[routerID]
if !ok {
http.NotFound(rw, request)
writeError(rw, fmt.Sprintf("router not found: %s", routerID), http.StatusNotFound)
return
}
result := tcpRouterRepresentation{
TCPRouterInfo: router,
Name: routerID,
Provider: getProviderName(routerID),
}
rw.Header().Set("Content-Type", "application/json")
result := newTCPRouterRepresentation(routerID, router)
err := json.NewEncoder(rw).Encode(result)
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func (h Handler) getTCPServices(rw http.ResponseWriter, request *http.Request) {
results := make([]tcpServiceRepresentation, 0, len(h.runtimeConfiguration.TCPServices))
criterion := newSearchCriterion(request.URL.Query())
for name, si := range h.runtimeConfiguration.TCPServices {
results = append(results, tcpServiceRepresentation{
TCPServiceInfo: si,
Name: name,
Provider: getProviderName(name),
})
if keepTCPService(name, si, criterion) {
results = append(results, newTCPServiceRepresentation(name, si))
}
}
sort.Slice(results, func(i, j int) bool {
return results[i].Name < results[j].Name
})
rw.Header().Set("Content-Type", "application/json")
pageInfo, err := pagination(request, len(results))
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
writeError(rw, err.Error(), http.StatusBadRequest)
return
}
rw.Header().Set("Content-Type", "application/json")
rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage))
err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex])
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func (h Handler) getTCPService(rw http.ResponseWriter, request *http.Request) {
serviceID := mux.Vars(request)["serviceID"]
rw.Header().Set("Content-Type", "application/json")
service, ok := h.runtimeConfiguration.TCPServices[serviceID]
if !ok {
http.NotFound(rw, request)
writeError(rw, fmt.Sprintf("service not found: %s", serviceID), http.StatusNotFound)
return
}
result := tcpServiceRepresentation{
TCPServiceInfo: service,
Name: serviceID,
Provider: getProviderName(serviceID),
}
rw.Header().Set("Content-Type", "application/json")
result := newTCPServiceRepresentation(serviceID, service)
err := json.NewEncoder(rw).Encode(result)
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
writeError(rw, err.Error(), http.StatusInternalServerError)
}
}
func keepTCPRouter(name string, item *runtime.TCPRouterInfo, criterion *searchCriterion) bool {
if criterion == nil {
return true
}
return criterion.withStatus(item.Status) && criterion.searchIn(item.Rule, name)
}
func keepTCPService(name string, item *runtime.TCPServiceInfo, criterion *searchCriterion) bool {
if criterion == nil {
return true
}
return criterion.withStatus(item.Status) && criterion.searchIn(name)
}

View File

@@ -1,6 +1,7 @@
package api
import (
"context"
"encoding/json"
"io/ioutil"
"net/http"
@@ -112,6 +113,86 @@ func TestHandler_TCP(t *testing.T) {
jsonFile: "testdata/tcprouters-page2.json",
},
},
{
desc: "TCP routers filtered by status",
path: "/api/tcp/routers?status=enabled",
conf: runtime.Configuration{
TCPRouters: map[string]*runtime.TCPRouterInfo{
"test@myprovider": {
TCPRouter: &dynamic.TCPRouter{
EntryPoints: []string{"web"},
Service: "foo-service@myprovider",
Rule: "Host(`foo.bar.other`)",
TLS: &dynamic.RouterTCPTLSConfig{
Passthrough: false,
},
},
Status: runtime.StatusEnabled,
},
"bar@myprovider": {
TCPRouter: &dynamic.TCPRouter{
EntryPoints: []string{"web"},
Service: "foo-service@myprovider",
Rule: "Host(`foo.bar`)",
},
Status: runtime.StatusWarning,
},
"foo@myprovider": {
TCPRouter: &dynamic.TCPRouter{
EntryPoints: []string{"web"},
Service: "foo-service@myprovider",
Rule: "Host(`foo.bar`)",
},
Status: runtime.StatusDisabled,
},
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/tcprouters-filtered-status.json",
},
},
{
desc: "TCP routers filtered by search",
path: "/api/tcp/routers?search=bar@my",
conf: runtime.Configuration{
TCPRouters: map[string]*runtime.TCPRouterInfo{
"test@myprovider": {
TCPRouter: &dynamic.TCPRouter{
EntryPoints: []string{"web"},
Service: "foo-service@myprovider",
Rule: "Host(`foo.bar.other`)",
TLS: &dynamic.RouterTCPTLSConfig{
Passthrough: false,
},
},
Status: runtime.StatusEnabled,
},
"bar@myprovider": {
TCPRouter: &dynamic.TCPRouter{
EntryPoints: []string{"web"},
Service: "foo-service@myprovider",
Rule: "Host(`foo.bar`)",
},
Status: runtime.StatusWarning,
},
"foo@myprovider": {
TCPRouter: &dynamic.TCPRouter{
EntryPoints: []string{"web"},
Service: "foo-service@myprovider",
Rule: "Host(`foo.bar`)",
},
Status: runtime.StatusDisabled,
},
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/tcprouters-filtered-search.json",
},
},
{
desc: "one TCP router by id",
path: "/api/tcp/routers/bar@myprovider",
@@ -219,6 +300,110 @@ func TestHandler_TCP(t *testing.T) {
jsonFile: "testdata/tcpservices.json",
},
},
{
desc: "tcp services filtered by status",
path: "/api/tcp/services?status=enabled",
conf: runtime.Configuration{
TCPServices: map[string]*runtime.TCPServiceInfo{
"bar@myprovider": {
TCPService: &dynamic.TCPService{
LoadBalancer: &dynamic.TCPLoadBalancerService{
Servers: []dynamic.TCPServer{
{
Address: "127.0.0.1:2345",
},
},
},
},
UsedBy: []string{"foo@myprovider", "test@myprovider"},
Status: runtime.StatusEnabled,
},
"baz@myprovider": {
TCPService: &dynamic.TCPService{
LoadBalancer: &dynamic.TCPLoadBalancerService{
Servers: []dynamic.TCPServer{
{
Address: "127.0.0.2:2345",
},
},
},
},
UsedBy: []string{"foo@myprovider"},
Status: runtime.StatusWarning,
},
"foz@myprovider": {
TCPService: &dynamic.TCPService{
LoadBalancer: &dynamic.TCPLoadBalancerService{
Servers: []dynamic.TCPServer{
{
Address: "127.0.0.2:2345",
},
},
},
},
UsedBy: []string{"foo@myprovider"},
Status: runtime.StatusDisabled,
},
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/tcpservices-filtered-status.json",
},
},
{
desc: "tcp services filtered by search",
path: "/api/tcp/services?search=baz@my",
conf: runtime.Configuration{
TCPServices: map[string]*runtime.TCPServiceInfo{
"bar@myprovider": {
TCPService: &dynamic.TCPService{
LoadBalancer: &dynamic.TCPLoadBalancerService{
Servers: []dynamic.TCPServer{
{
Address: "127.0.0.1:2345",
},
},
},
},
UsedBy: []string{"foo@myprovider", "test@myprovider"},
Status: runtime.StatusEnabled,
},
"baz@myprovider": {
TCPService: &dynamic.TCPService{
LoadBalancer: &dynamic.TCPLoadBalancerService{
Servers: []dynamic.TCPServer{
{
Address: "127.0.0.2:2345",
},
},
},
},
UsedBy: []string{"foo@myprovider"},
Status: runtime.StatusWarning,
},
"foz@myprovider": {
TCPService: &dynamic.TCPService{
LoadBalancer: &dynamic.TCPLoadBalancerService{
Servers: []dynamic.TCPServer{
{
Address: "127.0.0.2:2345",
},
},
},
},
UsedBy: []string{"foo@myprovider"},
Status: runtime.StatusDisabled,
},
},
},
expected: expected{
statusCode: http.StatusOK,
nextPage: "1",
jsonFile: "testdata/tcpservices-filtered-search.json",
},
},
{
desc: "all tcp services, 1 res per page, want page 2",
path: "/api/tcp/services?page=2&per_page=1",
@@ -330,6 +515,10 @@ func TestHandler_TCP(t *testing.T) {
t.Parallel()
rtConf := &test.conf
// To lazily initialize the Statuses.
rtConf.PopulateUsedBy()
rtConf.GetTCPRoutersByEntryPoints(context.Background(), []string{"web"})
handler := New(static.Configuration{API: &static.API{}, Global: &static.Global{}}, rtConf)
router := mux.NewRouter()
handler.Append(router)

View File

@@ -7,6 +7,7 @@
"name": "auth@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "basicauth",
"usedBy": [
"bar@myprovider",
"test@myprovider"

View File

@@ -0,0 +1,26 @@
[
{
"addPrefix": {
"prefix": "/toto"
},
"name": "addPrefixTest@anotherprovider",
"provider": "anotherprovider",
"status": "enabled",
"type": "addprefix",
"usedBy": [
"bar@myprovider"
]
},
{
"addPrefix": {
"prefix": "/titi"
},
"name": "addPrefixTest@myprovider",
"provider": "myprovider",
"status": "disabled",
"type": "addprefix",
"usedBy": [
"test@myprovider"
]
}
]

View File

@@ -0,0 +1,29 @@
[
{
"addPrefix": {
"prefix": "/toto"
},
"name": "addPrefixTest@anotherprovider",
"provider": "anotherprovider",
"status": "enabled",
"type": "addprefix",
"usedBy": [
"bar@myprovider"
]
},
{
"basicAuth": {
"users": [
"admin:admin"
]
},
"name": "auth@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "basicauth",
"usedBy": [
"bar@myprovider",
"test@myprovider"
]
}
]

View File

@@ -6,6 +6,7 @@
"name": "addPrefixTest@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "addprefix",
"usedBy": [
"test@myprovider"
]

View File

@@ -6,6 +6,7 @@
"name": "addPrefixTest@anotherprovider",
"provider": "anotherprovider",
"status": "enabled",
"type": "addprefix",
"usedBy": [
"bar@myprovider"
]
@@ -17,6 +18,7 @@
"name": "addPrefixTest@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "addprefix",
"usedBy": [
"test@myprovider"
]
@@ -30,6 +32,7 @@
"name": "auth@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "basicauth",
"usedBy": [
"bar@myprovider",
"test@myprovider"

View File

@@ -10,5 +10,8 @@
"provider": "myprovider",
"rule": "Host(`foo.bar`)",
"service": "foo-service@myprovider",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
}

View File

@@ -0,0 +1,19 @@
[
{
"entryPoints": [
"web"
],
"middlewares": [
"addPrefixTest",
"auth"
],
"name": "test@myprovider",
"provider": "myprovider",
"rule": "Host(`fii.bar.other`)",
"service": "fii-service@myprovider",
"status": "enabled",
"using": [
"web"
]
}
]

View File

@@ -0,0 +1,19 @@
[
{
"entryPoints": [
"web"
],
"middlewares": [
"addPrefixTest",
"auth"
],
"name": "test@myprovider",
"provider": "myprovider",
"rule": "Host(`foo.bar.other`)",
"service": "foo-service@myprovider",
"status": "enabled",
"using": [
"web"
]
}
]

View File

@@ -7,7 +7,10 @@
"provider": "myprovider",
"rule": "Host(`foo.bar14`)",
"service": "foo-service@myprovider",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
},
{
"entryPoints": [
@@ -17,7 +20,10 @@
"provider": "myprovider",
"rule": "Host(`foo.bar15`)",
"service": "foo-service@myprovider",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
},
{
"entryPoints": [
@@ -27,7 +33,10 @@
"provider": "myprovider",
"rule": "Host(`foo.bar16`)",
"service": "foo-service@myprovider",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
},
{
"entryPoints": [
@@ -37,7 +46,10 @@
"provider": "myprovider",
"rule": "Host(`foo.bar17`)",
"service": "foo-service@myprovider",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
},
{
"entryPoints": [
@@ -47,6 +59,9 @@
"provider": "myprovider",
"rule": "Host(`foo.bar18`)",
"service": "foo-service@myprovider",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
}
]

View File

@@ -7,6 +7,9 @@
"provider": "myprovider",
"rule": "Host(`toto.bar`)",
"service": "foo-service@myprovider",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
}
]

View File

@@ -11,7 +11,10 @@
"provider": "myprovider",
"rule": "Host(`foo.bar`)",
"service": "foo-service@myprovider",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
},
{
"entryPoints": [
@@ -25,6 +28,9 @@
"provider": "myprovider",
"rule": "Host(`foo.bar.other`)",
"service": "foo-service@myprovider",
"status": "enabled"
"status": "enabled",
"using": [
"web"
]
}
]

View File

@@ -13,6 +13,7 @@
"http://127.0.0.1": "UP"
},
"status": "enabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider",
"test@myprovider"

View File

@@ -0,0 +1,22 @@
[
{
"loadBalancer": {
"passHostHeader": false,
"servers": [
{
"url": "http://127.0.0.2"
}
]
},
"name": "baz@myprovider",
"provider": "myprovider",
"serverStatus": {
"http://127.0.0.2": "UP"
},
"status": "disabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider"
]
}
]

View File

@@ -0,0 +1,23 @@
[
{
"loadBalancer": {
"passHostHeader": false,
"servers": [
{
"url": "http://127.0.0.1"
}
]
},
"name": "bar@myprovider",
"provider": "myprovider",
"serverStatus": {
"http://127.0.0.1": "UP"
},
"status": "enabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider",
"test@myprovider"
]
}
]

View File

@@ -14,6 +14,7 @@
"http://127.0.0.2": "UP"
},
"status": "enabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider"
]

View File

@@ -14,6 +14,7 @@
"http://127.0.0.1": "UP"
},
"status": "enabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider",
"test@myprovider"
@@ -34,6 +35,51 @@
"http://127.0.0.2": "UP"
},
"status": "enabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider"
]
},
{
"name": "canary@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "weighted",
"usedBy": [
"foo@myprovider"
],
"weighted": {
"sticky": {
"cookie": {
"httpOnly": true,
"name": "chocolat",
"secure": true
}
}
}
},
{
"mirroring": {
"mirrors": [
{
"name": "two@myprovider",
"percent": 10
},
{
"name": "three@myprovider",
"percent": 15
},
{
"name": "four@myprovider",
"percent": 80
}
],
"service": "one@myprovider"
},
"name": "mirror@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "mirroring",
"usedBy": [
"foo@myprovider"
]

View File

@@ -5,5 +5,9 @@
"name": "bar@myprovider",
"provider": "myprovider",
"rule": "Host(`foo.bar`)",
"service": "foo-service@myprovider"
"service": "foo-service@myprovider",
"status": "enabled",
"using": [
"web"
]
}

View File

@@ -0,0 +1,15 @@
[
{
"entryPoints": [
"web"
],
"name": "bar@myprovider",
"provider": "myprovider",
"rule": "Host(`foo.bar`)",
"service": "foo-service@myprovider",
"status": "warning",
"using": [
"web"
]
}
]

View File

@@ -0,0 +1,18 @@
[
{
"entryPoints": [
"web"
],
"name": "test@myprovider",
"provider": "myprovider",
"rule": "Host(`foo.bar.other`)",
"service": "foo-service@myprovider",
"status": "enabled",
"tls": {
"passthrough": false
},
"using": [
"web"
]
}
]

View File

@@ -6,6 +6,10 @@
"name": "baz@myprovider",
"provider": "myprovider",
"rule": "Host(`toto.bar`)",
"service": "foo-service@myprovider"
"service": "foo-service@myprovider",
"status": "enabled",
"using": [
"web"
]
}
]

View File

@@ -7,7 +7,10 @@
"provider": "myprovider",
"rule": "Host(`foo.bar`)",
"service": "foo-service@myprovider",
"status": "warning"
"status": "warning",
"using": [
"web"
]
},
{
"entryPoints": [
@@ -17,7 +20,10 @@
"provider": "myprovider",
"rule": "Host(`foo.bar`)",
"service": "foo-service@myprovider",
"status": "disabled"
"status": "disabled",
"using": [
"web"
]
},
{
"entryPoints": [
@@ -30,6 +36,9 @@
"status": "enabled",
"tls": {
"passthrough": false
}
},
"using": [
"web"
]
}
]

View File

@@ -8,6 +8,8 @@
},
"name": "bar@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider",
"test@myprovider"

View File

@@ -0,0 +1,18 @@
[
{
"loadBalancer": {
"servers": [
{
"address": "127.0.0.2:2345"
}
]
},
"name": "baz@myprovider",
"provider": "myprovider",
"status": "warning",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider"
]
}
]

View File

@@ -0,0 +1,19 @@
[
{
"loadBalancer": {
"servers": [
{
"address": "127.0.0.1:2345"
}
]
},
"name": "bar@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider",
"test@myprovider"
]
}
]

View File

@@ -9,6 +9,8 @@
},
"name": "baz@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider"
]

View File

@@ -10,6 +10,7 @@
"name": "bar@myprovider",
"provider": "myprovider",
"status": "enabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider",
"test@myprovider"
@@ -26,6 +27,7 @@
"name": "baz@myprovider",
"provider": "myprovider",
"status": "warning",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider"
]
@@ -41,6 +43,7 @@
"name": "foz@myprovider",
"provider": "myprovider",
"status": "disabled",
"type": "loadbalancer",
"usedBy": [
"foo@myprovider"
]

View File

@@ -119,7 +119,7 @@
buckets = [42.0, 42.0]
entryPoint = "foobar"
middlewares = ["foobar", "foobar"]
[metrics.dataDog]
[metrics.datadog]
address = "foobar"
pushInterval = "10s"
[metrics.statsD]
@@ -179,7 +179,7 @@
id128Bit = true
debug = true
sampleRate = 42.0
[tracing.dataDog]
[tracing.datadog]
localAgentHostPort = "foobar"
globalTag = "foobar"
debug = true
@@ -249,16 +249,14 @@
prefixes = ["foobar", "foobar"]
[http.middlewares.Middleware10]
[http.middlewares.Middleware10.rateLimit]
extractorFunc = "foobar"
[http.middlewares.Middleware10.rateLimit.rateSet]
[http.middlewares.Middleware10.rateLimit.rateSet.Rate0]
period = 42000000000
average = 42
burst = 42
[http.middlewares.Middleware10.rateLimit.rateSet.Rate1]
period = 42000000000
average = 42
burst = 42
average = 42
burst = 42
[http.middlewares.Middleware10.rateLimit.sourceCriterion]
requestHeaderName = "foobar"
requestHost = true
[http.middlewares.Middleware10.rateLimit.sourceCriterion.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware11]
[http.middlewares.Middleware11.redirectRegex]
regex = "foobar"

View File

@@ -687,6 +687,43 @@ func (in *Middleware) DeepCopy() *Middleware {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MirrorService) DeepCopyInto(out *MirrorService) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MirrorService.
func (in *MirrorService) DeepCopy() *MirrorService {
if in == nil {
return nil
}
out := new(MirrorService)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Mirroring) DeepCopyInto(out *Mirroring) {
*out = *in
if in.Mirrors != nil {
in, out := &in.Mirrors, &out.Mirrors
*out = make([]MirrorService, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Mirroring.
func (in *Mirroring) DeepCopy() *Mirroring {
if in == nil {
return nil
}
out := new(Mirroring)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PassTLSClientCert) DeepCopyInto(out *PassTLSClientCert) {
*out = *in
@@ -967,6 +1004,11 @@ func (in *Service) DeepCopyInto(out *Service) {
*out = new(WeightedRoundRobin)
(*in).DeepCopyInto(*out)
}
if in.Mirroring != nil {
in, out := &in.Mirroring, &out.Mirroring
*out = new(Mirroring)
(*in).DeepCopyInto(*out)
}
return
}

View File

@@ -143,7 +143,7 @@ func Test_decodeFileToNode_Toml(t *testing.T) {
{Name: "format", Value: "foobar"},
{Name: "level", Value: "foobar"}}},
{Name: "metrics", Children: []*parser.Node{
{Name: "dataDog", Children: []*parser.Node{
{Name: "datadog", Children: []*parser.Node{
{Name: "address", Value: "foobar"},
{Name: "pushInterval", Value: "10s"}}},
{Name: "influxDB", Children: []*parser.Node{
@@ -251,7 +251,7 @@ func Test_decodeFileToNode_Toml(t *testing.T) {
{Name: "maxIdleConnsPerHost", Value: "42"},
{Name: "rootCAs", Value: "foobar,foobar"}}},
{Name: "tracing", Children: []*parser.Node{
{Name: "dataDog", Children: []*parser.Node{
{Name: "datadog", Children: []*parser.Node{
{Name: "bagagePrefixHeaderName", Value: "foobar"},
{Name: "debug", Value: "true"},
{Name: "globalTag", Value: "foobar"},
@@ -282,7 +282,6 @@ func Test_decodeFileToNode_Toml(t *testing.T) {
{Name: "serviceName", Value: "foobar"},
{Name: "spanNameLimit", Value: "42"},
{Name: "zipkin", Children: []*parser.Node{
{Name: "debug", Value: "true"},
{Name: "httpEndpoint", Value: "foobar"},
{Name: "id128Bit", Value: "true"},
{Name: "sameSpan", Value: "true"},
@@ -378,7 +377,7 @@ func Test_decodeFileToNode_Yaml(t *testing.T) {
{Name: "format", Value: "foobar"},
{Name: "level", Value: "foobar"}}},
{Name: "metrics", Children: []*parser.Node{
{Name: "dataDog", Children: []*parser.Node{
{Name: "datadog", Children: []*parser.Node{
{Name: "address", Value: "foobar"},
{Name: "pushInterval", Value: "10s"}}},
{Name: "influxDB", Children: []*parser.Node{
@@ -486,7 +485,7 @@ func Test_decodeFileToNode_Yaml(t *testing.T) {
{Name: "maxIdleConnsPerHost", Value: "42"},
{Name: "rootCAs", Value: "foobar,foobar"}}},
{Name: "tracing", Children: []*parser.Node{
{Name: "dataDog", Children: []*parser.Node{
{Name: "datadog", Children: []*parser.Node{
{Name: "bagagePrefixHeaderName", Value: "foobar"},
{Name: "debug", Value: "true"},
{Name: "globalTag", Value: "foobar"},
@@ -517,7 +516,6 @@ func Test_decodeFileToNode_Yaml(t *testing.T) {
{Name: "serviceName", Value: "foobar"},
{Name: "spanNameLimit", Value: "42"},
{Name: "zipkin", Children: []*parser.Node{
{Name: "debug", Value: "true"},
{Name: "httpEndpoint", Value: "foobar"},
{Name: "id128Bit", Value: "true"},
{Name: "sameSpan", Value: "true"},

View File

@@ -119,7 +119,7 @@
buckets = [42.0, 42.0]
entryPoint = "foobar"
middlewares = ["foobar", "foobar"]
[metrics.dataDog]
[metrics.datadog]
address = "foobar"
pushInterval = "10s"
[metrics.statsD]
@@ -177,9 +177,8 @@
httpEndpoint = "foobar"
sameSpan = true
id128Bit = true
debug = true
sampleRate = 42.0
[tracing.dataDog]
[tracing.datadog]
localAgentHostPort = "foobar"
globalTag = "foobar"
debug = true
@@ -241,16 +240,14 @@
prefixes = ["foobar", "foobar"]
[http.middlewares.Middleware10]
[http.middlewares.Middleware10.rateLimit]
extractorFunc = "foobar"
[http.middlewares.Middleware10.rateLimit.rateSet]
[http.middlewares.Middleware10.rateLimit.rateSet.Rate0]
period = 42000000000
average = 42
burst = 42
[http.middlewares.Middleware10.rateLimit.rateSet.Rate1]
period = 42000000000
average = 42
burst = 42
average = 42
burst = 42
[http.middlewares.Middleware10.rateLimit.sourceCriterion]
requestHeaderName = "foobar"
requestHost = true
[http.middlewares.Middleware10.rateLimit.sourceCriterion.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware11]
[http.middlewares.Middleware11.redirectRegex]
regex = "foobar"

View File

@@ -130,7 +130,7 @@ metrics:
middlewares:
- foobar
- foobar
dataDog:
datadog:
address: foobar
pushInterval: 10s
statsD:
@@ -188,9 +188,8 @@ tracing:
httpEndpoint: foobar
sameSpan: true
id128Bit: true
debug: true
sampleRate: 42
dataDog:
datadog:
localAgentHostPort: foobar
globalTag: foobar
debug: true

View File

@@ -2,13 +2,15 @@ package runtime
import (
"context"
"fmt"
"sort"
"sync"
"github.com/containous/traefik/v2/pkg/config/dynamic"
"github.com/containous/traefik/v2/pkg/log"
)
// GetRoutersByEntryPoints returns all the http routers by entry points name and routers name
// GetRoutersByEntryPoints returns all the http routers by entry points name and routers name.
func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*RouterInfo {
entryPointsRouters := make(map[string]map[string]*RouterInfo)
@@ -17,13 +19,19 @@ func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints
continue
}
logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName)))
eps := rt.EntryPoints
if len(eps) == 0 {
logger.Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints)
eps = entryPoints
}
entryPointsCount := 0
for _, entryPointName := range eps {
if !contains(entryPoints, entryPointName) {
log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))).
rt.AddError(fmt.Errorf("entryPoint %q doesn't exist", entryPointName), false)
logger.WithField(log.EntryPointName, entryPointName).
Errorf("entryPoint %q doesn't exist", entryPointName)
continue
}
@@ -32,14 +40,40 @@ func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints
entryPointsRouters[entryPointName] = make(map[string]*RouterInfo)
}
entryPointsCount++
rt.Using = append(rt.Using, entryPointName)
entryPointsRouters[entryPointName][rtName] = rt
}
if entryPointsCount == 0 {
rt.AddError(fmt.Errorf("no valid entryPoint for this router"), true)
logger.Error("no valid entryPoint for this router")
}
rt.Using = unique(rt.Using)
}
return entryPointsRouters
}
// RouterInfo holds information about a currently running HTTP router
func unique(src []string) []string {
var uniq []string
set := make(map[string]struct{})
for _, v := range src {
if _, exist := set[v]; !exist {
set[v] = struct{}{}
uniq = append(uniq, v)
}
}
sort.Strings(uniq)
return uniq
}
// RouterInfo holds information about a currently running HTTP router.
type RouterInfo struct {
*dynamic.Router // dynamic configuration
// Err contains all the errors that occurred during router's creation.
@@ -47,7 +81,8 @@ type RouterInfo struct {
// Status reports whether the router is disabled, in a warning state, or all good (enabled).
// If not in "enabled" state, the reason for it should be in the list of Err.
// It is the caller's responsibility to set the initial status.
Status string `json:"status,omitempty"`
Status string `json:"status,omitempty"`
Using []string `json:"using,omitempty"` // Effective entry points used by that router.
}
// AddError adds err to r.Err, if it does not already exist.
@@ -71,13 +106,13 @@ func (r *RouterInfo) AddError(err error, critical bool) {
}
}
// MiddlewareInfo holds information about a currently running middleware
// MiddlewareInfo holds information about a currently running middleware.
type MiddlewareInfo struct {
*dynamic.Middleware // dynamic configuration
// Err contains all the errors that occurred during service creation.
Err []string `json:"error,omitempty"`
Status string `json:"status,omitempty"`
UsedBy []string `json:"usedBy,omitempty"` // list of routers and services using that middleware
UsedBy []string `json:"usedBy,omitempty"` // list of routers and services using that middleware.
}
// AddError adds err to s.Err, if it does not already exist.
@@ -101,7 +136,7 @@ func (m *MiddlewareInfo) AddError(err error, critical bool) {
}
}
// ServiceInfo holds information about a currently running service
// ServiceInfo holds information about a currently running service.
type ServiceInfo struct {
*dynamic.Service // dynamic configuration
// Err contains all the errors that occurred during service creation.

View File

@@ -104,6 +104,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) {
Rule: "Host(`bar.foo`)",
},
Status: "enabled",
Using: []string{"web"},
},
"foobar": {
Router: &dynamic.Router{
@@ -111,7 +112,9 @@ func TestGetRoutersByEntryPoints(t *testing.T) {
Service: "foobar-service@myprovider",
Rule: "Host(`bar.foobar`)",
},
Status: "enabled",
Status: "warning",
Err: []string{`entryPoint "webs" doesn't exist`},
Using: []string{"web"},
},
},
},
@@ -168,6 +171,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) {
Rule: "Host(`bar.foo`)",
},
Status: "enabled",
Using: []string{"web"},
},
"foobar": {
Router: &dynamic.Router{
@@ -176,6 +180,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) {
Rule: "Host(`bar.foobar`)",
},
Status: "enabled",
Using: []string{"web", "webs"},
},
},
"webs": {
@@ -187,6 +192,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) {
Rule: "Host(`foo.bar`)",
},
Status: "enabled",
Using: []string{"webs"},
},
"foobar": {
Router: &dynamic.Router{
@@ -195,6 +201,7 @@ func TestGetRoutersByEntryPoints(t *testing.T) {
Rule: "Host(`bar.foobar`)",
},
Status: "enabled",
Using: []string{"web", "webs"},
},
},
},

View File

@@ -2,24 +2,30 @@ package runtime
import (
"context"
"fmt"
"github.com/containous/traefik/v2/pkg/config/dynamic"
"github.com/containous/traefik/v2/pkg/log"
)
// GetTCPRoutersByEntryPoints returns all the tcp routers by entry points name and routers name
// GetTCPRoutersByEntryPoints returns all the tcp routers by entry points name and routers name.
func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoints []string) map[string]map[string]*TCPRouterInfo {
entryPointsRouters := make(map[string]map[string]*TCPRouterInfo)
for rtName, rt := range c.TCPRouters {
logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName)))
eps := rt.EntryPoints
if len(eps) == 0 {
logger.Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints)
eps = entryPoints
}
entryPointsCount := 0
for _, entryPointName := range eps {
if !contains(entryPoints, entryPointName) {
log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))).
rt.AddError(fmt.Errorf("entryPoint %q doesn't exist", entryPointName), false)
logger.WithField(log.EntryPointName, entryPointName).
Errorf("entryPoint %q doesn't exist", entryPointName)
continue
}
@@ -28,21 +34,30 @@ func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoi
entryPointsRouters[entryPointName] = make(map[string]*TCPRouterInfo)
}
entryPointsCount++
rt.Using = append(rt.Using, entryPointName)
entryPointsRouters[entryPointName][rtName] = rt
}
if entryPointsCount == 0 {
rt.AddError(fmt.Errorf("no valid entryPoint for this router"), true)
logger.Error("no valid entryPoint for this router")
}
}
return entryPointsRouters
}
// TCPRouterInfo holds information about a currently running TCP router
// TCPRouterInfo holds information about a currently running TCP router.
type TCPRouterInfo struct {
*dynamic.TCPRouter // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error
// Status reports whether the router is disabled, in a warning state, or all good (enabled).
// If not in "enabled" state, the reason for it should be in the list of Err.
// It is the caller's responsibility to set the initial status.
Status string `json:"status,omitempty"`
Status string `json:"status,omitempty"`
Using []string `json:"using,omitempty"` // Effective entry points used by that router.
}
// AddError adds err to r.Err, if it does not already exist.
@@ -66,7 +81,7 @@ func (r *TCPRouterInfo) AddError(err error, critical bool) {
}
}
// TCPServiceInfo holds information about a currently running TCP service
// TCPServiceInfo holds information about a currently running TCP service.
type TCPServiceInfo struct {
*dynamic.TCPService // dynamic configuration
Err []string `json:"error,omitempty"` // initialization error

View File

@@ -104,6 +104,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) {
Rule: "HostSNI(`bar.foo`)",
},
Status: "enabled",
Using: []string{"web"},
},
"foobar": {
TCPRouter: &dynamic.TCPRouter{
@@ -111,7 +112,9 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) {
Service: "foobar-service@myprovider",
Rule: "HostSNI(`bar.foobar`)",
},
Status: "enabled",
Status: "warning",
Err: []string{`entryPoint "webs" doesn't exist`},
Using: []string{"web"},
},
},
},
@@ -168,6 +171,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) {
Rule: "HostSNI(`bar.foo`)",
},
Status: "enabled",
Using: []string{"web"},
},
"foobar": {
TCPRouter: &dynamic.TCPRouter{
@@ -176,6 +180,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) {
Rule: "HostSNI(`bar.foobar`)",
},
Status: "enabled",
Using: []string{"web", "webs"},
},
},
"webs": {
@@ -187,6 +192,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) {
Rule: "HostSNI(`foo.bar`)",
},
Status: "enabled",
Using: []string{"webs"},
},
"foobar": {
TCPRouter: &dynamic.TCPRouter{
@@ -195,6 +201,7 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) {
Rule: "HostSNI(`bar.foobar`)",
},
Status: "enabled",
Using: []string{"web", "webs"},
},
},
},

View File

@@ -139,7 +139,7 @@ type Tracing struct {
SpanNameLimit int `description:"Set the maximum character limit for Span names (default 0 = no limit)." json:"spanNameLimit,omitempty" toml:"spanNameLimit,omitempty" yaml:"spanNameLimit,omitempty" export:"true"`
Jaeger *jaeger.Config `description:"Settings for Jaeger." json:"jaeger,omitempty" toml:"jaeger,omitempty" yaml:"jaeger,omitempty" export:"true" label:"allowEmpty"`
Zipkin *zipkin.Config `description:"Settings for Zipkin." json:"zipkin,omitempty" toml:"zipkin,omitempty" yaml:"zipkin,omitempty" export:"true" label:"allowEmpty"`
DataDog *datadog.Config `description:"Settings for DataDog." json:"dataDog,omitempty" toml:"dataDog,omitempty" yaml:"dataDog,omitempty" export:"true" label:"allowEmpty"`
Datadog *datadog.Config `description:"Settings for Datadog." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" export:"true" label:"allowEmpty"`
Instana *instana.Config `description:"Settings for Instana." json:"instana,omitempty" toml:"instana,omitempty" yaml:"instana,omitempty" export:"true" label:"allowEmpty"`
Haystack *haystack.Config `description:"Settings for Haystack." json:"haystack,omitempty" toml:"haystack,omitempty" yaml:"haystack,omitempty" export:"true" label:"allowEmpty"`
}

Some files were not shown because too many files have changed in this diff Show More