Merge branch 'v2.0' into master
This commit is contained in:
commit
56e0580aa5
134 changed files with 2201 additions and 818 deletions
344
CHANGELOG.md
344
CHANGELOG.md
|
@ -1,4 +1,346 @@
|
||||||
# Change Log
|
## [v2.0.0](https://github.com/containous/traefik/tree/v2.0.0) (2019-09-16)
|
||||||
|
[All Commits](https://github.com/containous/traefik/compare/v2.0.0-alpha1...v2.0.0)
|
||||||
|
|
||||||
|
**Enhancements:**
|
||||||
|
- **[acme,api,tracing]** New API security ([#5311](https://github.com/containous/traefik/pull/5311) by [juliens](https://github.com/juliens))
|
||||||
|
- **[acme,k8s,k8s/crd]** Document the TLS with ACME case ([#4654](https://github.com/containous/traefik/pull/4654) by [mpl](https://github.com/mpl))
|
||||||
|
- **[acme,kv]** Remove Deprecated StorageFile ([#4252](https://github.com/containous/traefik/pull/4252) by [juliens](https://github.com/juliens))
|
||||||
|
- **[acme]** Remove timeout/interval from the ACME Provider ([#4842](https://github.com/containous/traefik/pull/4842) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[acme]** Certificate resolvers. ([#5116](https://github.com/containous/traefik/pull/5116) by [ldez](https://github.com/ldez))
|
||||||
|
- **[acme]** Improve acme logs. ([#5139](https://github.com/containous/traefik/pull/5139) by [ldez](https://github.com/ldez))
|
||||||
|
- **[acme]** Migrate to go-acme/lego. ([#4589](https://github.com/containous/traefik/pull/4589) by [ldez](https://github.com/ldez))
|
||||||
|
- **[api,provider]** Enhance REST provider ([#5072](https://github.com/containous/traefik/pull/5072) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[api]** Adding content-header to api endpoints ([#5019](https://github.com/containous/traefik/pull/5019) by [dalanmiller](https://github.com/dalanmiller))
|
||||||
|
- **[api]** Deal with multiple errors and their criticality ([#5070](https://github.com/containous/traefik/pull/5070) by [mpl](https://github.com/mpl))
|
||||||
|
- **[api]** API: remove configuration of Entrypoint and Middlewares ([#5119](https://github.com/containous/traefik/pull/5119) by [mpl](https://github.com/mpl))
|
||||||
|
- **[api]** Improve API endpoints ([#5080](https://github.com/containous/traefik/pull/5080) by [ldez](https://github.com/ldez))
|
||||||
|
- **[api]** API: new contract ([#4964](https://github.com/containous/traefik/pull/4964) by [mpl](https://github.com/mpl))
|
||||||
|
- **[api]** Improve API for the web UI ([#5267](https://github.com/containous/traefik/pull/5267) by [ldez](https://github.com/ldez))
|
||||||
|
- **[api]** Manage status for TCP element in the endpoint overview. ([#5108](https://github.com/containous/traefik/pull/5108) by [ldez](https://github.com/ldez))
|
||||||
|
- **[api]** API: expose runtime representation ([#4841](https://github.com/containous/traefik/pull/4841) by [mpl](https://github.com/mpl))
|
||||||
|
- **[authentication,middleware,k8s,k8s/crd]** Auth middlewares in kubernetes CRD use secrets ([#5299](https://github.com/containous/traefik/pull/5299) by [juliens](https://github.com/juliens))
|
||||||
|
- **[authentication,logs,etcd]** Remove deprecated elements ([#3715](https://github.com/containous/traefik/pull/3715) by [geraldcroes](https://github.com/geraldcroes))
|
||||||
|
- **[authentication,middleware]** Basic Auth custom realm ([#3917](https://github.com/containous/traefik/pull/3917) by [tcoupin](https://github.com/tcoupin))
|
||||||
|
- **[cli]** New static configuration loading system. ([#4935](https://github.com/containous/traefik/pull/4935) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker,k8s,k8s/crd,k8s/ingress]** chore: update docker and k8s ([#5174](https://github.com/containous/traefik/pull/5174) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker,k8s,k8s/crd,marathon,rancher,tcp]** Add weighted round robin load balancer on TCP ([#5380](https://github.com/containous/traefik/pull/5380) by [juliens](https://github.com/juliens))
|
||||||
|
- **[docker,tcp]** Add support for TCP labels in Docker provider ([#4621](https://github.com/containous/traefik/pull/4621) by [juliens](https://github.com/juliens))
|
||||||
|
- **[docker]** Adds default rule system on Docker provider. ([#4413](https://github.com/containous/traefik/pull/4413) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker]** Adds Docker provider support ([#4399](https://github.com/containous/traefik/pull/4399) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker]** Update to Go1.12. Support of TLS1.3 ([#4540](https://github.com/containous/traefik/pull/4540) by [ldez](https://github.com/ldez))
|
||||||
|
- **[etcd]** Remove etcd v2 ([#3739](https://github.com/containous/traefik/pull/3739) by [geraldcroes](https://github.com/geraldcroes))
|
||||||
|
- **[file]** Restrict traefik.toml to static configuration. ([#5090](https://github.com/containous/traefik/pull/5090) by [ldez](https://github.com/ldez))
|
||||||
|
- **[file]** Support YAML for the dynamic configuration. ([#5024](https://github.com/containous/traefik/pull/5024) by [ldez](https://github.com/ldez))
|
||||||
|
- **[k8s,k8s/crd,k8s/ingress]** Correct Kubernetes Ingress and IngressRoute port heuristic for choosing HTTPS ([#5167](https://github.com/containous/traefik/pull/5167) by [seh](https://github.com/seh))
|
||||||
|
- **[k8s,k8s/crd,k8s/ingress]** Fix kubernetes id name ([#5383](https://github.com/containous/traefik/pull/5383) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[k8s,k8s/crd,tcp]** Add support for TCP (in kubernetes CRD) ([#4885](https://github.com/containous/traefik/pull/4885) by [mpl](https://github.com/mpl))
|
||||||
|
- **[k8s,k8s/crd,tls]** Define TLS options on the Router configuration for Kubernetes ([#4973](https://github.com/containous/traefik/pull/4973) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[k8s,k8s/crd]** Add passHostHeader and responseForwarding in IngressRoute ([#5368](https://github.com/containous/traefik/pull/5368) by [juliens](https://github.com/juliens))
|
||||||
|
- **[k8s,k8s/crd]** Add scheme to IngressRoute. ([#5062](https://github.com/containous/traefik/pull/5062) by [ldez](https://github.com/ldez))
|
||||||
|
- **[k8s,k8s/ingress]** Renamed `kubernetes` provider in `kubernetesIngress` provider ([#5068](https://github.com/containous/traefik/pull/5068) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[k8s,k8s/ingress]** Add TLS-enabled Router ([#5162](https://github.com/containous/traefik/pull/5162) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[k8s/ingress]** Adds Kubernetes provider support ([#4476](https://github.com/containous/traefik/pull/4476) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[k8s/ingress]** Adds update ingress status ([#4603](https://github.com/containous/traefik/pull/4603) by [juliens](https://github.com/juliens))
|
||||||
|
- **[k8s/ingress]** k8s integration tests ([#4569](https://github.com/containous/traefik/pull/4569) by [juliens](https://github.com/juliens))
|
||||||
|
- **[k8s/ingress]** Custom resource definition ([#4591](https://github.com/containous/traefik/pull/4591) by [ldez](https://github.com/ldez))
|
||||||
|
- **[logs]** Improve error on router without service. ([#5126](https://github.com/containous/traefik/pull/5126) by [ldez](https://github.com/ldez))
|
||||||
|
- **[logs]** log.loglevel becomes log.level in configuration ([#4775](https://github.com/containous/traefik/pull/4775) by [juliens](https://github.com/juliens))
|
||||||
|
- **[logs]** Drop headers by default in access logs. ([#5034](https://github.com/containous/traefik/pull/5034) by [ldez](https://github.com/ldez))
|
||||||
|
- **[logs]** Default to CLF when accesslog format is unsupported ([#5314](https://github.com/containous/traefik/pull/5314) by [mpl](https://github.com/mpl))
|
||||||
|
- **[marathon,tcp]** Handle TCP in the marathon provider ([#4728](https://github.com/containous/traefik/pull/4728) by [juliens](https://github.com/juliens))
|
||||||
|
- **[marathon]** Adds Marathon support. ([#4415](https://github.com/containous/traefik/pull/4415) by [ldez](https://github.com/ldez))
|
||||||
|
- **[metrics]** Add Metrics ([#5111](https://github.com/containous/traefik/pull/5111) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[metrics]** Add HTTP authentication to influxdb metric backend ([#3600](https://github.com/containous/traefik/pull/3600) by [halfa](https://github.com/halfa))
|
||||||
|
- **[middleware,k8s,k8s/crd]** k8s ErrorPage middleware now uses k8s service ([#5339](https://github.com/containous/traefik/pull/5339) by [juliens](https://github.com/juliens))
|
||||||
|
- **[middleware,k8s/crd]** Handle cross-provider middleware in kubernetes CRD ([#5009](https://github.com/containous/traefik/pull/5009) by [mpl](https://github.com/mpl))
|
||||||
|
- **[middleware,provider]** Change the provider separator from . to @ ([#4982](https://github.com/containous/traefik/pull/4982) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware,provider]** Add Feature-Policy header support ([#5156](https://github.com/containous/traefik/pull/5156) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[middleware,tracing]** Re enable ratelimit integration tests ([#5288](https://github.com/containous/traefik/pull/5288) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[middleware,provider]** IPStrategy for selecting IP in whitelist ([#3778](https://github.com/containous/traefik/pull/3778) by [juliens](https://github.com/juliens))
|
||||||
|
- **[middleware,provider]** Enables the use of elements declared in other providers ([#4372](https://github.com/containous/traefik/pull/4372) by [geraldcroes](https://github.com/geraldcroes))
|
||||||
|
- **[middleware]** Migrates the pass client tls cert middleware ([#4373](https://github.com/containous/traefik/pull/4373) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[middleware]** Migrates Compress from bool to struct ([#3714](https://github.com/containous/traefik/pull/3714) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[middleware]** Updates for jaeger tracing client. ([#3688](https://github.com/containous/traefik/pull/3688) by [tcolgate](https://github.com/tcolgate))
|
||||||
|
- **[middleware]** Add forwarded headers on entry point configuration ([#4364](https://github.com/containous/traefik/pull/4364) by [juliens](https://github.com/juliens))
|
||||||
|
- **[middleware]** SchemeRedirect Middleware ([#4400](https://github.com/containous/traefik/pull/4400) by [geraldcroes](https://github.com/geraldcroes))
|
||||||
|
- **[middleware]** Add rate limiter, rename maxConn into inFlightReq ([#5246](https://github.com/containous/traefik/pull/5246) by [mpl](https://github.com/mpl))
|
||||||
|
- **[middleware]** Disable RateLimit temporarily ([#5123](https://github.com/containous/traefik/pull/5123) by [juliens](https://github.com/juliens))
|
||||||
|
- **[middleware]** Enable CORS configuration ([#3809](https://github.com/containous/traefik/pull/3809) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[provider]** New constraints management. ([#4965](https://github.com/containous/traefik/pull/4965) by [ldez](https://github.com/ldez))
|
||||||
|
- **[provider]** Remove BaseProvider ([#4661](https://github.com/containous/traefik/pull/4661) by [ldez](https://github.com/ldez))
|
||||||
|
- **[provider]** Use name@provider instead of provider@name. ([#4990](https://github.com/containous/traefik/pull/4990) by [ldez](https://github.com/ldez))
|
||||||
|
- **[provider]** Add health check timeout parameter ([#3813](https://github.com/containous/traefik/pull/3813) by [jbiel](https://github.com/jbiel))
|
||||||
|
- **[provider]** Removes deprecated templates ([#3649](https://github.com/containous/traefik/pull/3649) by [geraldcroes](https://github.com/geraldcroes))
|
||||||
|
- **[provider]** Remove everything templates related ([#4595](https://github.com/containous/traefik/pull/4595) by [mpl](https://github.com/mpl))
|
||||||
|
- **[provider]** Small code enhancements on providers ([#3707](https://github.com/containous/traefik/pull/3707) by [vdemeester](https://github.com/vdemeester))
|
||||||
|
- **[provider]** Migrate rest provider ([#4253](https://github.com/containous/traefik/pull/4253) by [juliens](https://github.com/juliens))
|
||||||
|
- **[provider]** Labels parser. ([#4236](https://github.com/containous/traefik/pull/4236) by [ldez](https://github.com/ldez))
|
||||||
|
- **[rancher]** Add Rancher provider ([#4647](https://github.com/containous/traefik/pull/4647) by [SantoDE](https://github.com/SantoDE))
|
||||||
|
- **[rules]** New rule syntax ([#4437](https://github.com/containous/traefik/pull/4437) by [juliens](https://github.com/juliens))
|
||||||
|
- **[server]** Adds mirroring service ([#5251](https://github.com/containous/traefik/pull/5251) by [juliens](https://github.com/juliens))
|
||||||
|
- **[server]** Add support proxyprotocol v2 ([#4755](https://github.com/containous/traefik/pull/4755) by [c0va23](https://github.com/c0va23))
|
||||||
|
- **[server]** WeightedRoundRobin load balancer ([#5237](https://github.com/containous/traefik/pull/5237) by [juliens](https://github.com/juliens))
|
||||||
|
- **[server]** Make HTTP Keep-Alive timeout configurable for backend connections ([#4983](https://github.com/containous/traefik/pull/4983) by [mszabo-wikia](https://github.com/mszabo-wikia))
|
||||||
|
- **[server]** Rework loadbalancer support ([#4933](https://github.com/containous/traefik/pull/4933) by [juliens](https://github.com/juliens))
|
||||||
|
- **[server]** Use h2c from x/net to handle h2c requests ([#5045](https://github.com/containous/traefik/pull/5045) by [juliens](https://github.com/juliens))
|
||||||
|
- **[server]** Dynamic Configuration Refactoring ([#4168](https://github.com/containous/traefik/pull/4168) by [ldez](https://github.com/ldez))
|
||||||
|
- **[server]** Remove old global config and use new static config ([#4222](https://github.com/containous/traefik/pull/4222) by [juliens](https://github.com/juliens))
|
||||||
|
- **[sticky-session]** HttpOnly and Secure flags on the affinity cookie ([#4947](https://github.com/containous/traefik/pull/4947) by [gheibia](https://github.com/gheibia))
|
||||||
|
- **[tcp]** Adds TCP support ([#4587](https://github.com/containous/traefik/pull/4587) by [juliens](https://github.com/juliens))
|
||||||
|
- **[tls]** Define a TLS section to group TLS, TLSOptions, and TLSStores. ([#5031](https://github.com/containous/traefik/pull/5031) by [ldez](https://github.com/ldez))
|
||||||
|
- **[tls]** TLSOptions: handle conflict: same host name, different TLS options ([#5056](https://github.com/containous/traefik/pull/5056) by [mpl](https://github.com/mpl))
|
||||||
|
- **[tls]** Define TLS options on the Router configuration ([#4931](https://github.com/containous/traefik/pull/4931) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[tls]** Expand Client Auth Type configuration ([#5078](https://github.com/containous/traefik/pull/5078) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[tracing]** Improve tracing ([#5010](https://github.com/containous/traefik/pull/5010) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[tracing]** Add Jaeger collector endpoint ([#5082](https://github.com/containous/traefik/pull/5082) by [rmfitzpatrick](https://github.com/rmfitzpatrick))
|
||||||
|
- **[tracing]** Update tracing dependencies ([#4721](https://github.com/containous/traefik/pull/4721) by [ldez](https://github.com/ldez))
|
||||||
|
- **[tracing]** Added support for Haystack tracing ([#4555](https://github.com/containous/traefik/pull/4555) by [aantono](https://github.com/aantono))
|
||||||
|
- **[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))
|
||||||
|
- **[tracing]** Instana tracer implementation ([#4453](https://github.com/containous/traefik/pull/4453) by [notsureifkevin](https://github.com/notsureifkevin))
|
||||||
|
- **[tracing]** Make Zipkin trace rate configurable ([#3968](https://github.com/containous/traefik/pull/3968) by [negz](https://github.com/negz))
|
||||||
|
- **[webui]** refactor(webui): use @vue/cli to bootstrap new ui ([#5091](https://github.com/containous/traefik/pull/5091) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** Add a new dashboard page ([#5249](https://github.com/containous/traefik/pull/5249) by [Basgrani](https://github.com/Basgrani))
|
||||||
|
- **[webui]** Add doc and version in navbar ([#5137](https://github.com/containous/traefik/pull/5137) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** Use components to split Home concerns ([#5136](https://github.com/containous/traefik/pull/5136) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** Add more pages in the WebUI ([#5278](https://github.com/containous/traefik/pull/5278) by [Basgrani](https://github.com/Basgrani))
|
||||||
|
- **[webui]** feat(webui/dashboard): init new dashboard ([#5105](https://github.com/containous/traefik/pull/5105) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** Upgrade angular cli version ([#4450](https://github.com/containous/traefik/pull/4450) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** Update docker node version ([#4448](https://github.com/containous/traefik/pull/4448) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** Ignore target/dependencies in docker copy ([#4449](https://github.com/containous/traefik/pull/4449) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** Format code with prettier ([#4463](https://github.com/containous/traefik/pull/4463) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** No need for npm progress=false ([#3702](https://github.com/containous/traefik/pull/3702) by [vdemeester](https://github.com/vdemeester))
|
||||||
|
- **[webui]** Migrate to a work in progress webui ([#4568](https://github.com/containous/traefik/pull/4568) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** Include lint in build process ([#4462](https://github.com/containous/traefik/pull/4462) by [Slashgear](https://github.com/Slashgear))
|
||||||
|
- **[webui]** Dropping rxjs-compat in favor of pipe ([#4520](https://github.com/containous/traefik/pull/4520) by [imcotton](https://github.com/imcotton))
|
||||||
|
- Move dynamic config into a dedicated package. ([#5075](https://github.com/containous/traefik/pull/5075) by [ldez](https://github.com/ldez))
|
||||||
|
- Disable collect data by default. ([#5393](https://github.com/containous/traefik/pull/5393) by [ldez](https://github.com/ldez))
|
||||||
|
- Bump x/sys to support Risc-V architecture ([#5245](https://github.com/containous/traefik/pull/5245) by [carlosedp](https://github.com/carlosedp))
|
||||||
|
- New packaging system. ([#4593](https://github.com/containous/traefik/pull/4593) by [ldez](https://github.com/ldez))
|
||||||
|
- Updates Backoff ([#4457](https://github.com/containous/traefik/pull/4457) by [ldez](https://github.com/ldez))
|
||||||
|
- Remove the bug command ([#4556](https://github.com/containous/traefik/pull/4556) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Small code enhancements ([#3712](https://github.com/containous/traefik/pull/3712) by [mmatur](https://github.com/mmatur))
|
||||||
|
- Remove deprecated elements ([#3666](https://github.com/containous/traefik/pull/3666) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Clean old ([#4612](https://github.com/containous/traefik/pull/4612) by [ldez](https://github.com/ldez))
|
||||||
|
- Update anonymize/collect ([#4590](https://github.com/containous/traefik/pull/4590) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[api,webui]** Improve documentation about API and Dashboard. ([#5364](https://github.com/containous/traefik/pull/5364) by [ldez](https://github.com/ldez))
|
||||||
|
- **[api]** Add errors about unknown entryPoint in runtime api ([#5265](https://github.com/containous/traefik/pull/5265) by [juliens](https://github.com/juliens))
|
||||||
|
- **[api]** Add provider in middleware chain ([#5334](https://github.com/containous/traefik/pull/5334) by [juliens](https://github.com/juliens))
|
||||||
|
- **[cli]** fix: boolean flag parsing with map. ([#5372](https://github.com/containous/traefik/pull/5372) by [ldez](https://github.com/ldez))
|
||||||
|
- **[cli]** Return an error when help is called on a non existing command. ([#4977](https://github.com/containous/traefik/pull/4977) by [ldez](https://github.com/ldez))
|
||||||
|
- **[cli]** Filter env vars configuration ([#4985](https://github.com/containous/traefik/pull/4985) by [ldez](https://github.com/ldez))
|
||||||
|
- **[cli]** Fix some CLI bugs ([#4989](https://github.com/containous/traefik/pull/4989) by [ldez](https://github.com/ldez))
|
||||||
|
- **[cli]** Change the loading resource order ([#5007](https://github.com/containous/traefik/pull/5007) by [ldez](https://github.com/ldez))
|
||||||
|
- **[cli]** Apply the case of the CLI flags for the configuration ([#5153](https://github.com/containous/traefik/pull/5153) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[cli]** Don't allow non flag arguments by default. ([#4970](https://github.com/containous/traefik/pull/4970) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker]** Insensitive case for allow-empty value. ([#4745](https://github.com/containous/traefik/pull/4745) by [ldez](https://github.com/ldez))
|
||||||
|
- **[file]** fix: TLS configuration from directory. ([#5118](https://github.com/containous/traefik/pull/5118) by [ldez](https://github.com/ldez))
|
||||||
|
- **[k8s,k8s/crd]** Fix log messages about label selector ([#4629](https://github.com/containous/traefik/pull/4629) by [mpl](https://github.com/mpl))
|
||||||
|
- **[k8s,k8s/crd]** fix: TLS domains with IngressRoute. ([#5327](https://github.com/containous/traefik/pull/5327) by [ldez](https://github.com/ldez))
|
||||||
|
- **[k8s,k8s/crd]** Remove IngressEndpoint in CRD provider ([#4616](https://github.com/containous/traefik/pull/4616) by [juliens](https://github.com/juliens))
|
||||||
|
- **[logs]** fix: logger and context. ([#5370](https://github.com/containous/traefik/pull/5370) by [ldez](https://github.com/ldez))
|
||||||
|
- **[logs]** fix: error log message. ([#5020](https://github.com/containous/traefik/pull/5020) by [ldez](https://github.com/ldez))
|
||||||
|
- **[logs]** Fix typos in data collection message ([#4891](https://github.com/containous/traefik/pull/4891) by [mpl](https://github.com/mpl))
|
||||||
|
- **[logs]** Allow user to configure traefik log ([#4604](https://github.com/containous/traefik/pull/4604) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[metrics,tracing]** fix: Datadog case. ([#5272](https://github.com/containous/traefik/pull/5272) by [ldez](https://github.com/ldez))
|
||||||
|
- **[metrics]** Fix prometheus metrics ([#5152](https://github.com/containous/traefik/pull/5152) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[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]** Set X-Forwarded-* headers ([#4707](https://github.com/containous/traefik/pull/4707) by [mpl](https://github.com/mpl))
|
||||||
|
- **[middleware]** Fix `url.Parse` due to go1.12.8 changes. ([#5207](https://github.com/containous/traefik/pull/5207) 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))
|
||||||
|
- **[middleware]** Improve rate limiter tests ([#5310](https://github.com/containous/traefik/pull/5310) by [mpl](https://github.com/mpl))
|
||||||
|
- **[middleware]** Fix response modifier initial building ([#4719](https://github.com/containous/traefik/pull/4719) by [mpl](https://github.com/mpl))
|
||||||
|
- **[middleware]** Remove X-Forwarded-(Uri, Method, Tls-Client-Cert and Tls-Client-Cert-Info) from untrusted IP ([#5012](https://github.com/containous/traefik/pull/5012) by [stffabi](https://github.com/stffabi))
|
||||||
|
- **[middleware]** fix buffering middleware ([#5281](https://github.com/containous/traefik/pull/5281) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** Don't panic with undefined middleware ([#5289](https://github.com/containous/traefik/pull/5289) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** Properly add response headers for CORS ([#4857](https://github.com/containous/traefik/pull/4857) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[rules]** Allow matching with FQDN hosts with trailing periods ([#4763](https://github.com/containous/traefik/pull/4763) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[server]** Fix panic while server shutdown ([#4644](https://github.com/containous/traefik/pull/4644) by [juliens](https://github.com/juliens))
|
||||||
|
- **[server]** Write HTTP server logs into the global logger. ([#5329](https://github.com/containous/traefik/pull/5329) by [ldez](https://github.com/ldez))
|
||||||
|
- **[server]** Fix problem in aggregator provider ([#4625](https://github.com/containous/traefik/pull/4625) by [juliens](https://github.com/juliens))
|
||||||
|
- **[server]** Fix lock problem in server ([#4600](https://github.com/containous/traefik/pull/4600) by [juliens](https://github.com/juliens))
|
||||||
|
- **[service,websocket]** Fix recovered panic when websocket is mirrored ([#5255](https://github.com/containous/traefik/pull/5255) by [juliens](https://github.com/juliens))
|
||||||
|
- **[tcp]** Fix EOF error ([#4733](https://github.com/containous/traefik/pull/4733) by [juliens](https://github.com/juliens))
|
||||||
|
- **[tcp]** Don't add TCP proxy when error occurs during creation. ([#4858](https://github.com/containous/traefik/pull/4858) by [ldez](https://github.com/ldez))
|
||||||
|
- **[tcp]** Remove first byte wait when tcp catches all ([#4938](https://github.com/containous/traefik/pull/4938) by [juliens](https://github.com/juliens))
|
||||||
|
- **[tcp]** On client CloseWrite, do CloseWrite instead of Close for backend ([#5366](https://github.com/containous/traefik/pull/5366) by [juliens](https://github.com/juliens))
|
||||||
|
- **[tls]** Fix panic in TLS stores handling ([#4997](https://github.com/containous/traefik/pull/4997) 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))
|
||||||
|
- **[webui]** Web UI graph names. ([#5389](https://github.com/containous/traefik/pull/5389) by [ldez](https://github.com/ldez))
|
||||||
|
- **[webui]** fix: passHostHeader in the webUI. ([#5369](https://github.com/containous/traefik/pull/5369) by [ldez](https://github.com/ldez))
|
||||||
|
- Fix trailing slash with check new version ([#5266](https://github.com/containous/traefik/pull/5266) by [mmatur](https://github.com/mmatur))
|
||||||
|
- Ensure WaitGroup.Done() is always called ([#5026](https://github.com/containous/traefik/pull/5026) by [bsdelf](https://github.com/bsdelf))
|
||||||
|
- Clean files during tests. ([#4607](https://github.com/containous/traefik/pull/4607) by [ldez](https://github.com/ldez))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- **[acme,docker]** Removed extra colon before the 8080 docker port ([#5209](https://github.com/containous/traefik/pull/5209) by [fairwood136](https://github.com/fairwood136))
|
||||||
|
- **[acme,docker]** Add a docker-compose & let's encrypt user-guide ([#5121](https://github.com/containous/traefik/pull/5121) by [pbenefice](https://github.com/pbenefice))
|
||||||
|
- **[acme,docker]** Synchronize documentation ([#4571](https://github.com/containous/traefik/pull/4571) by [juliens](https://github.com/juliens))
|
||||||
|
- **[acme,k8s,k8s/crd]** Full ACME+CRD example ([#4652](https://github.com/containous/traefik/pull/4652) by [mpl](https://github.com/mpl))
|
||||||
|
- **[acme,k8s/crd]** Fix: CRD user guide ([#5244](https://github.com/containous/traefik/pull/5244) by [ldez](https://github.com/ldez))
|
||||||
|
- **[acme,tls]** docs: rewrite of the HTTPS and TLS section ([#4980](https://github.com/containous/traefik/pull/4980) by [mpl](https://github.com/mpl))
|
||||||
|
- **[acme]** Lets encrypt documentation typo ([#5127](https://github.com/containous/traefik/pull/5127) by [juliens](https://github.com/juliens))
|
||||||
|
- **[acme]** Use the same case every where for entryPoints. ([#4764](https://github.com/containous/traefik/pull/4764) by [ldez](https://github.com/ldez))
|
||||||
|
- **[acme]** doc/crd-acme: specify required kubectl version ([#5015](https://github.com/containous/traefik/pull/5015) by [mpl](https://github.com/mpl))
|
||||||
|
- **[acme]** Enhance manual dnsChallenge documentation ([#4636](https://github.com/containous/traefik/pull/4636) by [ntaranov](https://github.com/ntaranov))
|
||||||
|
- **[acme]** Fix error in the documentation for CLI configuration example ([#5392](https://github.com/containous/traefik/pull/5392) by [MycTl](https://github.com/MycTl))
|
||||||
|
- **[acme]** Add note about ACME renewal ([#4860](https://github.com/containous/traefik/pull/4860) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[acme]** Fix acme example ([#5130](https://github.com/containous/traefik/pull/5130) by [jamct](https://github.com/jamct))
|
||||||
|
- **[acme]** Rename Docker_Acme.md to Readme.md ([#4025](https://github.com/containous/traefik/pull/4025) by [vineetvermait](https://github.com/vineetvermait))
|
||||||
|
- **[acme]** Enhance acme page. ([#4611](https://github.com/containous/traefik/pull/4611) by [ldez](https://github.com/ldez))
|
||||||
|
- **[acme]** fix: some DNS provider link. ([#3637](https://github.com/containous/traefik/pull/3637) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker,marathon]** Update Dynamic Configuration Reference for both Docker and Marathon ([#5100](https://github.com/containous/traefik/pull/5100) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[docker]** Remove traefik.port from documentation ([#4886](https://github.com/containous/traefik/pull/4886) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker]** Fix two minor nits in Traefik 2.0 docs ([#4692](https://github.com/containous/traefik/pull/4692) by [cfra](https://github.com/cfra))
|
||||||
|
- **[docker]** Fix Getting started ([#4646](https://github.com/containous/traefik/pull/4646) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[docker]** docker-compose examples ([#4642](https://github.com/containous/traefik/pull/4642) by [karnthis](https://github.com/karnthis))
|
||||||
|
- **[docker]** Clarify docs with labels in Swarm Mode ([#4847](https://github.com/containous/traefik/pull/4847) by [mikesir87](https://github.com/mikesir87))
|
||||||
|
- **[file]** Update the file provider documentation ([#4588](https://github.com/containous/traefik/pull/4588) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[k8s,k8s/crd]** k8s static configuration explanation ([#4767](https://github.com/containous/traefik/pull/4767) by [ldez](https://github.com/ldez))
|
||||||
|
- **[k8s,k8s/crd]** doc: kubernetes CRD provider ([#4620](https://github.com/containous/traefik/pull/4620) by [mpl](https://github.com/mpl))
|
||||||
|
- **[k8s,k8s/ingress]** Add documentation about Kubernetes Ingress provider ([#5112](https://github.com/containous/traefik/pull/5112) by [mpl](https://github.com/mpl))
|
||||||
|
- **[k8s/crd]** user guide: fix a mistake in the deployment definition ([#5096](https://github.com/containous/traefik/pull/5096) by [ldez](https://github.com/ldez))
|
||||||
|
- **[k8s]** Fix typo in the CRD documentation ([#4902](https://github.com/containous/traefik/pull/4902) by [llussy](https://github.com/llussy))
|
||||||
|
- **[marathon]** Enhance Marathon documentation ([#4776](https://github.com/containous/traefik/pull/4776) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware,k8s,k8s/crd]** Fix typo: middleware -> middlewares. ([#4781](https://github.com/containous/traefik/pull/4781) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware,k8s/crd]** doc: fix middleware names for CRD. ([#4966](https://github.com/containous/traefik/pull/4966) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware,provider]** fix the documentation about middleware labels. ([#4888](https://github.com/containous/traefik/pull/4888) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** Fix Kubernetes Docs for Middlewares ([#4943](https://github.com/containous/traefik/pull/4943) by [HurricanKai](https://github.com/HurricanKai))
|
||||||
|
- **[middleware]** Adds a reference to the middleware overview. ([#4824](https://github.com/containous/traefik/pull/4824) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** docker-compose labels require $'s to be escaped ([#5225](https://github.com/containous/traefik/pull/5225) by [Makeshift](https://github.com/Makeshift))
|
||||||
|
- **[middleware]** Fix doc about removing headers ([#4708](https://github.com/containous/traefik/pull/4708) by [mpl](https://github.com/mpl))
|
||||||
|
- **[middleware]** Remove invalid commas. ([#4706](https://github.com/containous/traefik/pull/4706) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** Adds middlewares examples for k8s. ([#4713](https://github.com/containous/traefik/pull/4713) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** Update the middleware documentation ([#4729](https://github.com/containous/traefik/pull/4729) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[middleware]** fix: stripPrefixRegex documentation. ([#5273](https://github.com/containous/traefik/pull/5273) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** Correct typo in documentation on rate limiting ([#4939](https://github.com/containous/traefik/pull/4939) by [ableuler](https://github.com/ableuler))
|
||||||
|
- **[middleware]** Improve middleware documentation. ([#5003](https://github.com/containous/traefik/pull/5003) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** Enhance middleware examples. ([#4680](https://github.com/containous/traefik/pull/4680) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** docker-compose basic auth needs double dollar signs ([#4831](https://github.com/containous/traefik/pull/4831) by [muhlemmer](https://github.com/muhlemmer))
|
||||||
|
- **[middleware]** Fixed a typo in label. ([#5128](https://github.com/containous/traefik/pull/5128) by [jamct](https://github.com/jamct))
|
||||||
|
- **[middleware]** Review documentation ([#4798](https://github.com/containous/traefik/pull/4798) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware]** Kubernetes CRD documentation fixes ([#4971](https://github.com/containous/traefik/pull/4971) by [orhanhenrik](https://github.com/orhanhenrik))
|
||||||
|
- **[middleware]** compress link fixed ([#4817](https://github.com/containous/traefik/pull/4817) by [gato](https://github.com/gato))
|
||||||
|
- **[middleware]** Fix typo in forwardAuth middleware documentation ([#4638](https://github.com/containous/traefik/pull/4638) by [AkeemMcLennon](https://github.com/AkeemMcLennon))
|
||||||
|
- **[middleware]** change doc references to scheme[Rr]edirect -> redirect[Ss]cheme ([#4959](https://github.com/containous/traefik/pull/4959) by [topiaruss](https://github.com/topiaruss))
|
||||||
|
- **[middleware]** Update headers middleware docs for kubernetes crd ([#4955](https://github.com/containous/traefik/pull/4955) by [orhanhenrik](https://github.com/orhanhenrik))
|
||||||
|
- **[middleware]** Fix strip prefix documentation ([#4829](https://github.com/containous/traefik/pull/4829) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[provider]** Improve providers documentation. ([#5050](https://github.com/containous/traefik/pull/5050) by [ldez](https://github.com/ldez))
|
||||||
|
- **[rancher]** fix: Rancher documentation. ([#4818](https://github.com/containous/traefik/pull/4818) by [ldez](https://github.com/ldez))
|
||||||
|
- **[rancher]** Specify that Rancher provider is for 1.x only ([#4923](https://github.com/containous/traefik/pull/4923) by [bradjones1](https://github.com/bradjones1))
|
||||||
|
- **[server]** Add gRPC user guide ([#5042](https://github.com/containous/traefik/pull/5042) by [ldez](https://github.com/ldez))
|
||||||
|
- **[tcp]** Use rule HostSNI in documentation ([#4592](https://github.com/containous/traefik/pull/4592) by [bbinet](https://github.com/bbinet))
|
||||||
|
- **[tls]** fix: typo in routing example. ([#4849](https://github.com/containous/traefik/pull/4849) by [ldez](https://github.com/ldez))
|
||||||
|
- **[tracing]** Improve tracing documentation ([#5102](https://github.com/containous/traefik/pull/5102) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[tracing]** Fix typo in tracing docs ([#4737](https://github.com/containous/traefik/pull/4737) by [timoschwarzer](https://github.com/timoschwarzer))
|
||||||
|
- **[webui]** change docs and adjust dashboard for v2 alpha ([#4632](https://github.com/containous/traefik/pull/4632) by [SantoDE](https://github.com/SantoDE))
|
||||||
|
- doc: improve examples. ([#5132](https://github.com/containous/traefik/pull/5132) by [ldez](https://github.com/ldez))
|
||||||
|
- Fixed readme misspelling ([#4882](https://github.com/containous/traefik/pull/4882) by [antondalgren](https://github.com/antondalgren))
|
||||||
|
- Prepare release v2.0.0-rc2 ([#5293](https://github.com/containous/traefik/pull/5293) by [ldez](https://github.com/ldez))
|
||||||
|
- Fix typos in documentation ([#4884](https://github.com/containous/traefik/pull/4884) by [michael-k](https://github.com/michael-k))
|
||||||
|
- Fixed spelling typo ([#4848](https://github.com/containous/traefik/pull/4848) by [mikesir87](https://github.com/mikesir87))
|
||||||
|
- Enhance the Retry Middleware Documentation ([#5298](https://github.com/containous/traefik/pull/5298) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Clarification of the correct pronunciation of the word "Traefik" ([#4834](https://github.com/containous/traefik/pull/4834) by [ylamlum-g4m](https://github.com/ylamlum-g4m))
|
||||||
|
- Improve the "reading path" for new contributors ([#4908](https://github.com/containous/traefik/pull/4908) by [dduportal](https://github.com/dduportal))
|
||||||
|
- Fix some documentation issues ([#5286](https://github.com/containous/traefik/pull/5286) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Entry points CLI description. ([#4896](https://github.com/containous/traefik/pull/4896) by [ldez](https://github.com/ldez))
|
||||||
|
- Add Mathieu Lonjaret to maintainers ([#4950](https://github.com/containous/traefik/pull/4950) by [emilevauge](https://github.com/emilevauge))
|
||||||
|
- Prepare release v2.0.0-alpha5 ([#4967](https://github.com/containous/traefik/pull/4967) by [ldez](https://github.com/ldez))
|
||||||
|
- Minor fix in documentation ([#4811](https://github.com/containous/traefik/pull/4811) by [mmatur](https://github.com/mmatur))
|
||||||
|
- Prepare release v2.0.0-alpha6. ([#4975](https://github.com/containous/traefik/pull/4975) by [ldez](https://github.com/ldez))
|
||||||
|
- Fix a typo in documentation ([#4794](https://github.com/containous/traefik/pull/4794) by [groovytron](https://github.com/groovytron))
|
||||||
|
- Prepare release v2.0.0-alpha4. ([#4788](https://github.com/containous/traefik/pull/4788) by [ldez](https://github.com/ldez))
|
||||||
|
- Remove dumpcerts.sh ([#4783](https://github.com/containous/traefik/pull/4783) 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))
|
||||||
|
- Prepare release v2.0.0-alpha7 ([#5001](https://github.com/containous/traefik/pull/5001) by [ldez](https://github.com/ldez))
|
||||||
|
- misc documentation fixes ([#5302](https://github.com/containous/traefik/pull/5302) by [mpl](https://github.com/mpl))
|
||||||
|
- Fix some minors errors on the documentation ([#4664](https://github.com/containous/traefik/pull/4664) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Adds a note in traefik.sample.toml ([#4757](https://github.com/containous/traefik/pull/4757) by [ldez](https://github.com/ldez))
|
||||||
|
- Prepare release v2.0.0-rc1 ([#5252](https://github.com/containous/traefik/pull/5252) by [ldez](https://github.com/ldez))
|
||||||
|
- Use the same case everywhere ([#5043](https://github.com/containous/traefik/pull/5043) by [ldez](https://github.com/ldez))
|
||||||
|
- Improve the Documentation with a Reference Section ([#4714](https://github.com/containous/traefik/pull/4714) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Prepare release v2.0.0-alpha8 ([#5049](https://github.com/containous/traefik/pull/5049) by [ldez](https://github.com/ldez))
|
||||||
|
- Add a basic Traefik install guide ([#5117](https://github.com/containous/traefik/pull/5117) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- AML indent for domains under TLS documentation section ([#5173](https://github.com/containous/traefik/pull/5173) by [edvincent](https://github.com/edvincent))
|
||||||
|
- Update to v2.0 readme links ([#4700](https://github.com/containous/traefik/pull/4700) by [karnthis](https://github.com/karnthis))
|
||||||
|
- Prepare release v2.0.0-alpha3. ([#4693](https://github.com/containous/traefik/pull/4693) by [ldez](https://github.com/ldez))
|
||||||
|
- Misc documentation fixes ([#5307](https://github.com/containous/traefik/pull/5307) by [ldez](https://github.com/ldez))
|
||||||
|
- Update restrictions in the documentation. ([#5270](https://github.com/containous/traefik/pull/5270) by [ldez](https://github.com/ldez))
|
||||||
|
- Prepare release v2.0.0-rc3 ([#5343](https://github.com/containous/traefik/pull/5343) by [ldez](https://github.com/ldez))
|
||||||
|
- Fix typos in docs ([#4662](https://github.com/containous/traefik/pull/4662) by [SeMeKh](https://github.com/SeMeKh))
|
||||||
|
- Update traefik.sample.toml ([#4657](https://github.com/containous/traefik/pull/4657) by [ldez](https://github.com/ldez))
|
||||||
|
- fix: services configuration documentation. ([#5359](https://github.com/containous/traefik/pull/5359) by [ldez](https://github.com/ldez))
|
||||||
|
- Remove old links in readme ([#4651](https://github.com/containous/traefik/pull/4651) by [ldez](https://github.com/ldez))
|
||||||
|
- fix a service with one server .yaml example ([#5373](https://github.com/containous/traefik/pull/5373) by [zaverden](https://github.com/zaverden))
|
||||||
|
- Prepare release v2.0.0-rc4 ([#5384](https://github.com/containous/traefik/pull/5384) by [ldez](https://github.com/ldez))
|
||||||
|
- Fix dead maintainers link on the README.md ([#4639](https://github.com/containous/traefik/pull/4639) by [benjaminch](https://github.com/benjaminch))
|
||||||
|
- Prepare release v2.0.0-beta1 ([#5129](https://github.com/containous/traefik/pull/5129) by [ldez](https://github.com/ldez))
|
||||||
|
- Fix typo in documentation ([#5386](https://github.com/containous/traefik/pull/5386) by [adrienbrignon](https://github.com/adrienbrignon))
|
||||||
|
- Prepare release v2.0.0-alpha2 ([#4635](https://github.com/containous/traefik/pull/4635) by [ldez](https://github.com/ldez))
|
||||||
|
- Fix malformed rule ([#5133](https://github.com/containous/traefik/pull/5133) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- Improve various parts of the documentation. ([#4996](https://github.com/containous/traefik/pull/4996) by [ldez](https://github.com/ldez))
|
||||||
|
- Documentation Revamp ([#4475](https://github.com/containous/traefik/pull/4475) by [geraldcroes](https://github.com/geraldcroes))
|
||||||
|
- Adds a maintainer's page into the documentation. ([#4614](https://github.com/containous/traefik/pull/4614) by [ldez](https://github.com/ldez))
|
||||||
|
- Add Gerald, Jean-Baptiste and Damien to maintainers ([#3982](https://github.com/containous/traefik/pull/3982) by [emilevauge](https://github.com/emilevauge))
|
||||||
|
- fix broken links in readme.md ([#3967](https://github.com/containous/traefik/pull/3967) by [AndrewSav](https://github.com/AndrewSav))
|
||||||
|
- Add master overhaul notice ([#3961](https://github.com/containous/traefik/pull/3961) by [emilevauge](https://github.com/emilevauge))
|
||||||
|
- Complete maintainers processes ([#3696](https://github.com/containous/traefik/pull/3696) by [mmatur](https://github.com/mmatur))
|
||||||
|
- Complete maintainers processes ([#3681](https://github.com/containous/traefik/pull/3681) by [emilevauge](https://github.com/emilevauge))
|
||||||
|
- Prepare release v2.0.0-alpha1 ([#4617](https://github.com/containous/traefik/pull/4617) by [ldez](https://github.com/ldez))
|
||||||
|
|
||||||
|
**Misc:**
|
||||||
|
- Cherry pick v1.7 into v2.0 ([#5341](https://github.com/containous/traefik/pull/5341) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Cherry pick v1.7 into v2.0 ([#5192](https://github.com/containous/traefik/pull/5192) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into v2.0 ([#5115](https://github.com/containous/traefik/pull/5115) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Cherry pick v1.7 into v2.0 ([#4948](https://github.com/containous/traefik/pull/4948) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into v2.0 ([#4823](https://github.com/containous/traefik/pull/4823) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into v2.0 ([#4787](https://github.com/containous/traefik/pull/4787) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into v2.0 ([#4695](https://github.com/containous/traefik/pull/4695) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Merge v2.0.0-rc1 into master ([#5253](https://github.com/containous/traefik/pull/5253) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge branch v2.0 into master ([#5180](https://github.com/containous/traefik/pull/5180) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v2.0.0-alpha8 into master ([#5055](https://github.com/containous/traefik/pull/5055) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge current v2.0.0-alpha into master ([#5022](https://github.com/containous/traefik/pull/5022) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v2.0.0-alpha6 into master ([#4984](https://github.com/containous/traefik/pull/4984) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v2.0.0-alpha4 into master ([#4789](https://github.com/containous/traefik/pull/4789) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v2.0.0-alpha3 into master ([#4694](https://github.com/containous/traefik/pull/4694) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into master ([#4565](https://github.com/containous/traefik/pull/4565) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- Cherry pick v1.7 into master ([#4511](https://github.com/containous/traefik/pull/4511) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into master ([#4492](https://github.com/containous/traefik/pull/4492) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into master ([#4440](https://github.com/containous/traefik/pull/4440) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into master ([#4365](https://github.com/containous/traefik/pull/4365) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into master ([#4303](https://github.com/containous/traefik/pull/4303) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into master ([#4271](https://github.com/containous/traefik/pull/4271) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into master ([#4268](https://github.com/containous/traefik/pull/4268) by [ldez](https://github.com/ldez))
|
||||||
|
- Cherry pick v1.7 into master ([#4229](https://github.com/containous/traefik/pull/4229) by [juliens](https://github.com/juliens))
|
||||||
|
- Cherry pick v1.7 into master ([#4206](https://github.com/containous/traefik/pull/4206) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v1.7.4 into master ([#4137](https://github.com/containous/traefik/pull/4137) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v1.7.3 into master ([#4046](https://github.com/containous/traefik/pull/4046) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge current v1.7 into master ([#3992](https://github.com/containous/traefik/pull/3992) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v1.7.2 into master ([#3983](https://github.com/containous/traefik/pull/3983) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v1.7.0 into master ([#3925](https://github.com/containous/traefik/pull/3925) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v1.7.0-rc5 into master ([#3903](https://github.com/containous/traefik/pull/3903) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v1.7.0-rc4 into master ([#3867](https://github.com/containous/traefik/pull/3867) by [ldez](https://github.com/ldez))
|
||||||
|
- Merge v1.7.0-rc2 into master ([#3634](https://github.com/containous/traefik/pull/3634) by [ldez](https://github.com/ldez))
|
||||||
|
|
||||||
|
## [v2.0.0-rc4](https://github.com/containous/traefik/tree/v2.0.0-rc4) (2019-09-13)
|
||||||
|
[All Commits](https://github.com/containous/traefik/compare/v2.0.0-rc3...v2.0.0-rc4)
|
||||||
|
|
||||||
|
**Enhancements:**
|
||||||
|
- **[docker,k8s,k8s/crd,marathon,rancher,tcp]** Add weighted round robin load balancer on TCP ([#5380](https://github.com/containous/traefik/pull/5380) by [juliens](https://github.com/juliens))
|
||||||
|
- **[k8s,k8s/crd,k8s/ingress]** Fix kubernetes id name ([#5383](https://github.com/containous/traefik/pull/5383) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[k8s,k8s/crd]** Add passHostHeader and responseForwarding in IngressRoute ([#5368](https://github.com/containous/traefik/pull/5368) by [juliens](https://github.com/juliens))
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[api,webui]** Improve documentation about API and Dashboard. ([#5364](https://github.com/containous/traefik/pull/5364) by [ldez](https://github.com/ldez))
|
||||||
|
- **[cli]** fix: boolean flag parsing with map. ([#5372](https://github.com/containous/traefik/pull/5372) by [ldez](https://github.com/ldez))
|
||||||
|
- **[logs]** fix: logger and context. ([#5370](https://github.com/containous/traefik/pull/5370) by [ldez](https://github.com/ldez))
|
||||||
|
- **[tcp]** On client CloseWrite, do CloseWrite instead of Close for backend ([#5366](https://github.com/containous/traefik/pull/5366) by [juliens](https://github.com/juliens))
|
||||||
|
- **[webui]** fix: passHostHeader in the webUI. ([#5369](https://github.com/containous/traefik/pull/5369) by [ldez](https://github.com/ldez))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- fix a service with one server .yaml example ([#5373](https://github.com/containous/traefik/pull/5373) by [zaverden](https://github.com/zaverden))
|
||||||
|
- fix: services configuration documentation. ([#5359](https://github.com/containous/traefik/pull/5359) by [ldez](https://github.com/ldez))
|
||||||
|
|
||||||
## [v2.0.0-rc3](https://github.com/containous/traefik/tree/v2.0.0-rc3) (2019-09-10)
|
## [v2.0.0-rc3](https://github.com/containous/traefik/tree/v2.0.0-rc3) (2019-09-10)
|
||||||
[All Commits](https://github.com/containous/traefik/compare/v2.0.0-rc2...v2.0.0-rc3)
|
[All Commits](https://github.com/containous/traefik/compare/v2.0.0-rc2...v2.0.0-rc3)
|
||||||
|
|
|
@ -286,24 +286,16 @@ func checkNewVersion() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func stats(staticConfiguration *static.Configuration) {
|
func stats(staticConfiguration *static.Configuration) {
|
||||||
if staticConfiguration.Global.SendAnonymousUsage == nil {
|
logger := log.WithoutContext()
|
||||||
log.WithoutContext().Error(`
|
|
||||||
You haven't specified the sendAnonymousUsage option, it will be enabled by default.
|
|
||||||
`)
|
|
||||||
sendAnonymousUsage := true
|
|
||||||
staticConfiguration.Global.SendAnonymousUsage = &sendAnonymousUsage
|
|
||||||
}
|
|
||||||
|
|
||||||
if *staticConfiguration.Global.SendAnonymousUsage {
|
if staticConfiguration.Global.SendAnonymousUsage {
|
||||||
log.WithoutContext().Info(`
|
logger.Info(`Stats collection is enabled.`)
|
||||||
Stats collection is enabled.
|
logger.Info(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`)
|
||||||
Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.
|
logger.Info(`Help us improve Traefik by leaving this feature on :)`)
|
||||||
Help us improve Traefik by leaving this feature on :)
|
logger.Info(`More details on: https://docs.traefik.io/v2.0/contributing/data-collection/`)
|
||||||
More details on: https://docs.traefik.io/v2.0/contributing/data-collection/
|
|
||||||
`)
|
|
||||||
collect(staticConfiguration)
|
collect(staticConfiguration)
|
||||||
} else {
|
} else {
|
||||||
log.WithoutContext().Info(`
|
logger.Info(`
|
||||||
Stats collection is disabled.
|
Stats collection is disabled.
|
||||||
Help us improve Traefik by turning this feature on :)
|
Help us improve Traefik by turning this feature on :)
|
||||||
More details on: https://docs.traefik.io/v2.0/contributing/data-collection/
|
More details on: https://docs.traefik.io/v2.0/contributing/data-collection/
|
||||||
|
|
|
@ -8,9 +8,6 @@ Understanding How Traefik is Being Used
|
||||||
Understanding how you use Traefik is very important to us: it helps us improve the solution in many different ways.
|
Understanding how you use Traefik is very important to us: it helps us improve the solution in many different ways.
|
||||||
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.
|
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
|
|
||||||
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"
|
!!! example "Enabling Data Collection"
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
|
@ -71,14 +68,6 @@ Once a day (the first call begins 10 minutes after the start of Traefik), we col
|
||||||
cert = "dockerCert"
|
cert = "dockerCert"
|
||||||
key = "dockerKey"
|
key = "dockerKey"
|
||||||
insecureSkipVerify = true
|
insecureSkipVerify = true
|
||||||
|
|
||||||
[providers.ecs]
|
|
||||||
domain = "foo.bar"
|
|
||||||
exposedByDefault = true
|
|
||||||
clusters = ["foo-bar"]
|
|
||||||
region = "us-west-2"
|
|
||||||
accessKeyID = "AccessKeyID"
|
|
||||||
secretAccessKey = "SecretAccessKey"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
??? example "Resulting Obfuscated Configuration"
|
??? example "Resulting Obfuscated Configuration"
|
||||||
|
@ -92,7 +81,6 @@ Once a day (the first call begins 10 minutes after the start of Traefik), we col
|
||||||
|
|
||||||
[providers.docker]
|
[providers.docker]
|
||||||
endpoint = "xxxx"
|
endpoint = "xxxx"
|
||||||
domain = "xxxx"
|
|
||||||
exposedByDefault = true
|
exposedByDefault = true
|
||||||
swarmMode = true
|
swarmMode = true
|
||||||
|
|
||||||
|
@ -101,14 +89,6 @@ Once a day (the first call begins 10 minutes after the start of Traefik), we col
|
||||||
cert = "xxxx"
|
cert = "xxxx"
|
||||||
key = "xxxx"
|
key = "xxxx"
|
||||||
insecureSkipVerify = false
|
insecureSkipVerify = false
|
||||||
|
|
||||||
[providers.ecs]
|
|
||||||
domain = "xxxx"
|
|
||||||
exposedByDefault = true
|
|
||||||
clusters = []
|
|
||||||
region = "us-west-2"
|
|
||||||
accessKeyID = "xxxx"
|
|
||||||
secretAccessKey = "xxxx"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## The Code for Data Collection
|
## The Code for Data Collection
|
||||||
|
|
|
@ -17,11 +17,11 @@ services:
|
||||||
# The official v2.0 Traefik docker image
|
# The official v2.0 Traefik docker image
|
||||||
image: traefik:v2.0
|
image: traefik:v2.0
|
||||||
# Enables the web UI and tells Traefik to listen to docker
|
# Enables the web UI and tells Traefik to listen to docker
|
||||||
command: --api --providers.docker
|
command: --api.insecure=true --providers.docker
|
||||||
ports:
|
ports:
|
||||||
# The HTTP port
|
# The HTTP port
|
||||||
- "80:80"
|
- "80:80"
|
||||||
# The Web UI (enabled by --api)
|
# The Web UI (enabled by --api.insecure=true)
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
# So that Traefik can listen to the Docker events
|
# So that Traefik can listen to the Docker events
|
||||||
|
|
|
@ -50,10 +50,10 @@ You can configure Traefik to use an ACME provider (like Let's Encrypt) for autom
|
||||||
--entryPoints.web.address=":80"
|
--entryPoints.web.address=":80"
|
||||||
--entryPoints.websecure.address=":443"
|
--entryPoints.websecure.address=":443"
|
||||||
# ...
|
# ...
|
||||||
--certificatesResolvers.sample.acme.email: your-email@your-domain.org
|
--certificatesResolvers.sample.acme.email="your-email@your-domain.org"
|
||||||
--certificatesResolvers.sample.acme.storage: acme.json
|
--certificatesResolvers.sample.acme.storage="acme.json"
|
||||||
# used during the challenge
|
# used during the challenge
|
||||||
--certificatesResolvers.sample.acme.httpChallenge.entryPoint: web
|
--certificatesResolvers.sample.acme.httpChallenge.entryPoint=web
|
||||||
```
|
```
|
||||||
|
|
||||||
??? note "Configuration Reference"
|
??? note "Configuration Reference"
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "../../.markdownlint.json",
|
|
||||||
"MD041": false
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
To learn more about configuration options in the command line, refer to the [configuration overview](../getting-started/configuration-overview.md)
|
|
|
@ -1 +0,0 @@
|
||||||
To learn more about the configuration file, refer to [configuration overview](../getting-started/configuration-overview.md)
|
|
|
@ -1,2 +0,0 @@
|
||||||
!!! info "More On Entry Points"
|
|
||||||
Learn more about entry points and their configuration options in the dedicated section.
|
|
|
@ -1 +0,0 @@
|
||||||
To learn more about configuration in key-value stores, refer to the [configuration overview](../getting-started/configuration-overview.md)
|
|
|
@ -1,2 +0,0 @@
|
||||||
!!! info "More On Routers"
|
|
||||||
Learn more about routers and their configuration options in the [dedicated section](../routing/routers/index.md).
|
|
|
@ -97,8 +97,7 @@ metadata:
|
||||||
|
|
||||||
data:
|
data:
|
||||||
users: |2
|
users: |2
|
||||||
dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5
|
dGVzdDp0cmFlZmlrOmEyNjg4ZTAzMWVkYjRiZTZhMzc5N2YzODgyNjU1YzA1CnRlc3QyOnRyYWVmaWs6NTE4ODQ1ODAwZjllMmJmYjFmMWY3NDBlYzI0ZjA3NGUKCg==
|
||||||
aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```json tab="Marathon"
|
```json tab="Marathon"
|
||||||
|
|
|
@ -47,7 +47,7 @@ InfluxDB's address protocol (udp or http).
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[metrics]
|
[metrics]
|
||||||
[metrics.influxdb]
|
[metrics.influxdb]
|
||||||
protocol = "upd"
|
protocol = "udp"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
|
|
|
@ -12,13 +12,13 @@ The dashboard is the central place that shows you the current active routes hand
|
||||||
|
|
||||||
By default, the dashboard is available on `/` on port `:8080`.
|
By default, the dashboard is available on `/` on port `:8080`.
|
||||||
|
|
||||||
!!! tip "Did You Know?"
|
!!! note "Did You Know?"
|
||||||
It is possible to customize the dashboard endpoint.
|
It is possible to customize the dashboard endpoint.
|
||||||
To learn how, refer to the [API documentation](./api.md)
|
To learn how, refer to the [API documentation](./api.md)
|
||||||
|
|
||||||
## Enabling the Dashboard
|
## Enabling the Dashboard
|
||||||
|
|
||||||
To enable the dashboard, you need to enable Traefik's API.
|
To enable the dashboard, you need to enable [Traefik's API](./api.md).
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[api]
|
[api]
|
||||||
|
@ -49,10 +49,12 @@ api:
|
||||||
--api.dashboard=true
|
--api.dashboard=true
|
||||||
```
|
```
|
||||||
|
|
||||||
{!more-on-command-line.md!}
|
!!! important "API/Dashboard Security"
|
||||||
|
|
||||||
{!more-on-configuration-file.md!}
|
To secure your dashboard, the use of a `service` named `api@internal` is mandatory and requires the definition of a router using one or more security [middlewares](../middlewares/overview.md)
|
||||||
|
like authentication ([basicAuth](../middlewares/basicauth.md) , [digestAuth](../middlewares/digestauth.md), [forwardAuth](../middlewares/forwardauth.md)) or [whitelisting](../middlewares/ipwhitelist.md).
|
||||||
|
More information about `api@internal` can be found in the [API documentation](./api.md#configuration)
|
||||||
|
|
||||||
!!! tip "Did You Know?"
|
!!! note "Did You Know?"
|
||||||
The API provides more features than the Dashboard.
|
The API provides more features than the Dashboard.
|
||||||
To learn more about it, refer to the [API documentation](./api.md)
|
To learn more about it, refer to the [API documentation](./api.md)
|
||||||
|
|
|
@ -226,6 +226,13 @@ spec:
|
||||||
port: 80
|
port: 80
|
||||||
# (default 1) A weight used by the weighted round-robin strategy (WRR).
|
# (default 1) A weight used by the weighted round-robin strategy (WRR).
|
||||||
weight: 1
|
weight: 1
|
||||||
|
# (default true) PassHostHeader controls whether to leave the request's Host
|
||||||
|
# Header as it was before it reached the proxy, or whether to let the proxy set it
|
||||||
|
# to the destination (backend) host.
|
||||||
|
passHostHeader: true
|
||||||
|
responseForwarding:
|
||||||
|
# (default 100ms) Interval between flushes of the buffered response body to the client.
|
||||||
|
flushInterval: 100ms
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: traefik.containo.us/v1alpha1
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
|
|
@ -184,4 +184,6 @@
|
||||||
- "traefik.tcp.routers.tcprouter1.tls.options=foobar"
|
- "traefik.tcp.routers.tcprouter1.tls.options=foobar"
|
||||||
- "traefik.tcp.routers.tcprouter1.tls.passthrough=true"
|
- "traefik.tcp.routers.tcprouter1.tls.passthrough=true"
|
||||||
- "traefik.tcp.services.tcpservice0.loadbalancer.server.port=foobar"
|
- "traefik.tcp.services.tcpservice0.loadbalancer.server.port=foobar"
|
||||||
|
- "traefik.tcp.services.tcpservice0.loadbalancer.terminationdelay=100"
|
||||||
- "traefik.tcp.services.tcpservice1.loadbalancer.server.port=foobar"
|
- "traefik.tcp.services.tcpservice1.loadbalancer.server.port=foobar"
|
||||||
|
- "traefik.tcp.services.tcpservice1.loadbalancer.terminationdelay=100"
|
||||||
|
|
|
@ -286,14 +286,17 @@
|
||||||
[tcp.services]
|
[tcp.services]
|
||||||
[tcp.services.TCPService0]
|
[tcp.services.TCPService0]
|
||||||
[tcp.services.TCPService0.loadBalancer]
|
[tcp.services.TCPService0.loadBalancer]
|
||||||
|
terminationDelay = 100
|
||||||
|
|
||||||
[[tcp.services.TCPService0.loadBalancer.servers]]
|
[[tcp.services.TCPService0.loadBalancer.servers]]
|
||||||
address = "foobar"
|
address = "foobar"
|
||||||
|
|
||||||
[[tcp.services.TCPService0.loadBalancer.servers]]
|
[[tcp.services.TCPService0.loadBalancer.servers]]
|
||||||
address = "foobar"
|
address = "foobar"
|
||||||
|
|
||||||
[tcp.services.TCPService1]
|
[tcp.services.TCPService1]
|
||||||
[tcp.services.TCPService1.loadBalancer]
|
[tcp.services.TCPService1.loadBalancer]
|
||||||
|
terminationDelay = 100
|
||||||
|
|
||||||
[[tcp.services.TCPService1.loadBalancer.servers]]
|
[[tcp.services.TCPService1.loadBalancer.servers]]
|
||||||
address = "foobar"
|
address = "foobar"
|
||||||
|
|
|
@ -324,11 +324,13 @@ tcp:
|
||||||
services:
|
services:
|
||||||
TCPService0:
|
TCPService0:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
|
terminationDelay: 100
|
||||||
servers:
|
servers:
|
||||||
- address: foobar
|
- address: foobar
|
||||||
- address: foobar
|
- address: foobar
|
||||||
TCPService1:
|
TCPService1:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
|
terminationDelay: 100
|
||||||
servers:
|
servers:
|
||||||
- address: foobar
|
- address: foobar
|
||||||
- address: foobar
|
- address: foobar
|
||||||
|
|
|
@ -184,4 +184,6 @@
|
||||||
"traefik.tcp.routers.tcprouter1.tls.options": "foobar",
|
"traefik.tcp.routers.tcprouter1.tls.options": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.tls.passthrough": "true",
|
"traefik.tcp.routers.tcprouter1.tls.passthrough": "true",
|
||||||
"traefik.tcp.services.tcpservice0.loadbalancer.server.port": "foobar",
|
"traefik.tcp.services.tcpservice0.loadbalancer.server.port": "foobar",
|
||||||
|
"traefik.tcp.services.tcpservice0.loadbalancer.terminationDelay": "100",
|
||||||
"traefik.tcp.services.tcpservice1.loadbalancer.server.port": "foobar"
|
"traefik.tcp.services.tcpservice1.loadbalancer.server.port": "foobar"
|
||||||
|
"traefik.tcp.services.tcpservice1.loadbalancer.terminationDelay": "100",
|
||||||
|
|
|
@ -105,7 +105,7 @@ The `url` option point to a specific instance.
|
||||||
my-service:
|
my-service:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
servers:
|
servers:
|
||||||
url: "http://private-ip-server-1/"
|
- url: "http://private-ip-server-1/"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Load-balancing
|
#### Load-balancing
|
||||||
|
@ -312,11 +312,11 @@ This strategy can be defined only with [File](../../providers/file.md).
|
||||||
|
|
||||||
```toml tab="TOML"
|
```toml tab="TOML"
|
||||||
[http.services]
|
[http.services]
|
||||||
[http.services.canary]
|
[http.services.app]
|
||||||
[[http.services.canary.weighted.services]]
|
[[http.services.app.weighted.services]]
|
||||||
name = "appv1"
|
name = "appv1"
|
||||||
weight = 3
|
weight = 3
|
||||||
[[http.services.canary.weighted.services]]
|
[[http.services.app.weighted.services]]
|
||||||
name = "appv2"
|
name = "appv2"
|
||||||
weight = 1
|
weight = 1
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ This strategy can be defined only with [File](../../providers/file.md).
|
||||||
```yaml tab="YAML"
|
```yaml tab="YAML"
|
||||||
http:
|
http:
|
||||||
services:
|
services:
|
||||||
canary:
|
app:
|
||||||
weighted:
|
weighted:
|
||||||
services:
|
services:
|
||||||
- name: appv1
|
- name: appv1
|
||||||
|
@ -361,40 +361,40 @@ This strategy can be defined only with [File](../../providers/file.md).
|
||||||
|
|
||||||
```toml tab="TOML"
|
```toml tab="TOML"
|
||||||
[http.services]
|
[http.services]
|
||||||
[http.services.mirroring]
|
[http.services.mirrored-api]
|
||||||
[http.services.mirroring.mirroring]
|
[http.services.mirrored-api.mirroring]
|
||||||
service = "app"
|
service = "appv1"
|
||||||
[[http.services.mirroring.mirroring.mirrors]]
|
[[http.services.mirrored-api.mirroring.mirrors]]
|
||||||
name = "mirror"
|
name = "appv2"
|
||||||
percent = 10
|
percent = 10
|
||||||
|
|
||||||
[http.services.app]
|
[http.services.appv1]
|
||||||
[http.services.app.loadBalancer]
|
[http.services.appv1.loadBalancer]
|
||||||
[[http.services.appv1.loadBalancer.servers]]
|
[[http.services.appv1.loadBalancer.servers]]
|
||||||
url = "http://private-ip-server-1/"
|
url = "http://private-ip-server-1/"
|
||||||
|
|
||||||
[http.services.mirror]
|
[http.services.appv2]
|
||||||
[http.services.mirror.loadBalancer]
|
[http.services.appv2.loadBalancer]
|
||||||
[[http.services.mirror.loadBalancer.servers]]
|
[[http.services.appv2.loadBalancer.servers]]
|
||||||
url = "http://private-ip-server-2/"
|
url = "http://private-ip-server-2/"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="YAML"
|
```yaml tab="YAML"
|
||||||
http:
|
http:
|
||||||
services:
|
services:
|
||||||
|
mirrored-api:
|
||||||
mirroring:
|
mirroring:
|
||||||
mirroring:
|
service: appv1
|
||||||
service: app
|
|
||||||
mirrors:
|
mirrors:
|
||||||
- name: mirror
|
- name: appv2
|
||||||
percent: 10
|
percent: 10
|
||||||
|
|
||||||
app:
|
appv1:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
servers:
|
servers:
|
||||||
- url: "http://private-ip-server-1/"
|
- url: "http://private-ip-server-1/"
|
||||||
|
|
||||||
mirror:
|
appv2:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
servers:
|
servers:
|
||||||
- url: "http://private-ip-server-2/"
|
- url: "http://private-ip-server-2/"
|
||||||
|
@ -404,13 +404,14 @@ http:
|
||||||
|
|
||||||
### General
|
### General
|
||||||
|
|
||||||
Currently, `LoadBalancer` is the only supported kind of TCP `Service`.
|
Each of the fields of the service section represents a kind of service.
|
||||||
However, since Traefik is an ever evolving project, other kind of TCP Services will be available in the future,
|
Which means, that for each specified service, one of the fields, and only one,
|
||||||
reason why you have to specify it.
|
has to be enabled to define what kind of service is created.
|
||||||
|
Currently, the two available kinds are `LoadBalancer`, and `Weighted`.
|
||||||
|
|
||||||
### Load Balancer
|
### Servers Load Balancer
|
||||||
|
|
||||||
The load balancers are able to load balance the requests between multiple instances of your programs.
|
The servers load balancer is in charge of balancing the requests between the servers of the same service.
|
||||||
|
|
||||||
??? example "Declaring a Service with Two Servers -- Using the [File Provider](../../providers/file.md)"
|
??? example "Declaring a Service with Two Servers -- Using the [File Provider](../../providers/file.md)"
|
||||||
|
|
||||||
|
@ -455,3 +456,85 @@ The `address` option (IP:Port) point to a specific instance.
|
||||||
servers:
|
servers:
|
||||||
address: "xx.xx.xx.xx:xx"
|
address: "xx.xx.xx.xx:xx"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Termination Delay
|
||||||
|
|
||||||
|
As a proxy between a client and a server, it can happen that either side (e.g. client side) decides to terminate its writing capability on the connection (i.e. issuance of a FIN packet).
|
||||||
|
The proxy needs to propagate that intent to the other side, and so when that happens, it also does the same on its connection with the other side (e.g. backend side).
|
||||||
|
|
||||||
|
However, if for some reason (bad implementation, or malicious intent) the other side does not eventually do the same as well,
|
||||||
|
the connection would stay half-open, which would lock resources for however long.
|
||||||
|
|
||||||
|
To that end, as soon as the proxy enters this termination sequence, it sets a deadline on fully terminating the connections on both sides.
|
||||||
|
|
||||||
|
The termination delay controls that deadline.
|
||||||
|
It is a duration in milliseconds, defaulting to 100.
|
||||||
|
A negative value means an infinite deadline (i.e. the connection is never fully terminated by the proxy itself).
|
||||||
|
|
||||||
|
??? example "A Service with a termination delay -- Using the [File Provider](../../providers/file.md)"
|
||||||
|
|
||||||
|
```toml tab="TOML"
|
||||||
|
[tcp.services]
|
||||||
|
[tcp.services.my-service.loadBalancer]
|
||||||
|
[[tcp.services.my-service.loadBalancer]]
|
||||||
|
terminationDelay = 200
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="YAML"
|
||||||
|
tcp:
|
||||||
|
services:
|
||||||
|
my-service:
|
||||||
|
loadBalancer:
|
||||||
|
terminationDelay: 200
|
||||||
|
```
|
||||||
|
|
||||||
|
### Weighted
|
||||||
|
|
||||||
|
The Weighted Round Robin (alias `WRR`) load-balancer of services is in charge of balancing the requests between multiple services based on provided weights.
|
||||||
|
|
||||||
|
This strategy is only available to load balance between [services](./index.md) and not between [servers](./index.md#servers).
|
||||||
|
|
||||||
|
This strategy can only be defined with [File](../../providers/file.md).
|
||||||
|
|
||||||
|
```toml tab="TOML"
|
||||||
|
[tcp.services]
|
||||||
|
[tcp.services.app]
|
||||||
|
[[tcp.services.app.weighted.services]]
|
||||||
|
name = "appv1"
|
||||||
|
weight = 3
|
||||||
|
[[tcp.services.app.weighted.services]]
|
||||||
|
name = "appv2"
|
||||||
|
weight = 1
|
||||||
|
|
||||||
|
[tcp.services.appv1]
|
||||||
|
[tcp.services.appv1.loadBalancer]
|
||||||
|
[[tcp.services.appv1.loadBalancer.servers]]
|
||||||
|
address = "private-ip-server-1/:8080"
|
||||||
|
|
||||||
|
[tcp.services.appv2]
|
||||||
|
[tcp.services.appv2.loadBalancer]
|
||||||
|
[[tcp.services.appv2.loadBalancer.servers]]
|
||||||
|
address = "private-ip-server-2/:8080"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="YAML"
|
||||||
|
tcp:
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
weighted:
|
||||||
|
services:
|
||||||
|
- name: appv1
|
||||||
|
weight: 3
|
||||||
|
- name: appv2
|
||||||
|
weight: 1
|
||||||
|
|
||||||
|
appv1:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- address: "xxx.xxx.xxx.xxx:8080"
|
||||||
|
|
||||||
|
appv2:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- address: "xxx.xxx.xxx.xxx:8080"
|
||||||
|
```
|
||||||
|
|
|
@ -28,7 +28,7 @@ spec:
|
||||||
- name: traefik
|
- name: traefik
|
||||||
image: traefik:v2.0
|
image: traefik:v2.0
|
||||||
args:
|
args:
|
||||||
- --api
|
- --api.insecure
|
||||||
- --accesslog
|
- --accesslog
|
||||||
- --entrypoints.web.Address=:8000
|
- --entrypoints.web.Address=:8000
|
||||||
- --entrypoints.websecure.Address=:4443
|
- --entrypoints.websecure.Address=:4443
|
||||||
|
|
|
@ -3,11 +3,11 @@ version: "3.3"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-beta1"
|
image: "traefik:v2.0.0-rc3"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
- "--api=true"
|
- "--api.insecure=true"
|
||||||
- "--providers.docker=true"
|
- "--providers.docker=true"
|
||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.web.address=:80"
|
- "--entrypoints.web.address=:80"
|
||||||
|
|
|
@ -13,11 +13,11 @@ secrets:
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-beta1"
|
image: "traefik:v2.0.0-rc3"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
- "--api=true"
|
- "--api.insecure=true"
|
||||||
- "--providers.docker=true"
|
- "--providers.docker=true"
|
||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.web.address=:80"
|
- "--entrypoints.web.address=:80"
|
||||||
|
|
|
@ -3,11 +3,11 @@ version: "3.3"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-beta1"
|
image: "traefik:v2.0.0-rc3"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
- "--api=true"
|
- "--api.insecure=true"
|
||||||
- "--providers.docker=true"
|
- "--providers.docker=true"
|
||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.web.address=:80"
|
- "--entrypoints.web.address=:80"
|
||||||
|
|
|
@ -3,11 +3,11 @@ version: "3.3"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-beta1"
|
image: "traefik:v2.0.0-rc3"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
- "--api=true"
|
- "--api.insecure=true"
|
||||||
- "--providers.docker=true"
|
- "--providers.docker=true"
|
||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.websecure.address=:443"
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
|
|
@ -3,11 +3,11 @@ version: "3.3"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-beta1"
|
image: "traefik:v2.0.0-rc3"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
- "--api=true"
|
- "--api.insecure=true"
|
||||||
- "--providers.docker=true"
|
- "--providers.docker=true"
|
||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.web.address=:80"
|
- "--entrypoints.web.address=:80"
|
||||||
|
|
|
@ -53,7 +53,7 @@ ports:
|
||||||
```yaml
|
```yaml
|
||||||
command:
|
command:
|
||||||
# Traefik will listen on port 8080 by default for API request.
|
# Traefik will listen on port 8080 by default for API request.
|
||||||
- "--api=true"
|
- "--api.insecure=true"
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
|
|
|
@ -34,7 +34,7 @@ api: {}
|
||||||
```yaml tab="CLI"
|
```yaml tab="CLI"
|
||||||
--entryPoints.web.address=":80"
|
--entryPoints.web.address=":80"
|
||||||
--providers.file.filename=dynamic_conf.toml
|
--providers.file.filename=dynamic_conf.toml
|
||||||
--api=true
|
--api.insecure=true
|
||||||
```
|
```
|
||||||
|
|
||||||
`dynamic_conf.{toml,yml}`:
|
`dynamic_conf.{toml,yml}`:
|
||||||
|
@ -157,7 +157,7 @@ api: {}
|
||||||
# For secure connection on backend.local
|
# For secure connection on backend.local
|
||||||
--serversTransport.rootCAs=./backend.cert
|
--serversTransport.rootCAs=./backend.cert
|
||||||
--providers.file.filename=dynamic_conf.toml
|
--providers.file.filename=dynamic_conf.toml
|
||||||
--api=true
|
--api.insecure=true
|
||||||
```
|
```
|
||||||
|
|
||||||
`dynamic_conf.{toml,yml}`:
|
`dynamic_conf.{toml,yml}`:
|
||||||
|
|
|
@ -58,9 +58,9 @@ markdown_extensions:
|
||||||
- pymdownx.tasklist
|
- pymdownx.tasklist
|
||||||
- pymdownx.snippets:
|
- pymdownx.snippets:
|
||||||
check_paths: true
|
check_paths: true
|
||||||
- markdown_include.include:
|
# - markdown_include.include:
|
||||||
base_path: content/includes/
|
# base_path: content/includes/
|
||||||
encoding: utf-8
|
# encoding: utf-8
|
||||||
- toc:
|
- toc:
|
||||||
permalink: true
|
permalink: true
|
||||||
|
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -51,7 +51,7 @@ require (
|
||||||
github.com/huandu/xstrings v1.2.0 // indirect
|
github.com/huandu/xstrings v1.2.0 // indirect
|
||||||
github.com/influxdata/influxdb1-client v0.0.0-20190402204710-8ff2fc3824fc
|
github.com/influxdata/influxdb1-client v0.0.0-20190402204710-8ff2fc3824fc
|
||||||
github.com/instana/go-sensor v1.4.17-0.20190515112224-78c14625025a
|
github.com/instana/go-sensor v1.4.17-0.20190515112224-78c14625025a
|
||||||
github.com/labbsr0x/goh v0.0.0-20190610190554-60aa50bcbca7 // indirect
|
github.com/labbsr0x/goh v0.0.0-20190830205702-3d6988c73e10 // indirect
|
||||||
github.com/libkermit/compose v0.0.0-20171122111507-c04e39c026ad
|
github.com/libkermit/compose v0.0.0-20171122111507-c04e39c026ad
|
||||||
github.com/libkermit/docker v0.0.0-20171122101128-e6674d32b807
|
github.com/libkermit/docker v0.0.0-20171122101128-e6674d32b807
|
||||||
github.com/libkermit/docker-check v0.0.0-20171122104347-1113af38e591
|
github.com/libkermit/docker-check v0.0.0-20171122104347-1113af38e591
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -307,8 +307,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/labbsr0x/bindman-dns-webhook v1.0.0 h1:gooRvyQtVOCtV/l9ZCI4CManZeVN/kUWG/vugRqHqv4=
|
github.com/labbsr0x/bindman-dns-webhook v1.0.0 h1:gooRvyQtVOCtV/l9ZCI4CManZeVN/kUWG/vugRqHqv4=
|
||||||
github.com/labbsr0x/bindman-dns-webhook v1.0.0/go.mod h1:pn4jcNjxSywRWDPDyGkFzgSnwty18OFdiUFc6S6fpgc=
|
github.com/labbsr0x/bindman-dns-webhook v1.0.0/go.mod h1:pn4jcNjxSywRWDPDyGkFzgSnwty18OFdiUFc6S6fpgc=
|
||||||
github.com/labbsr0x/goh v0.0.0-20190417202808-8b16b4848295/go.mod h1:RBxeaayaaMmp7GxwHiKANjkg9e+rxjOm4mB5vD5rt/I=
|
github.com/labbsr0x/goh v0.0.0-20190417202808-8b16b4848295/go.mod h1:RBxeaayaaMmp7GxwHiKANjkg9e+rxjOm4mB5vD5rt/I=
|
||||||
github.com/labbsr0x/goh v0.0.0-20190610190554-60aa50bcbca7 h1:ocfbpesrzMqybD816LDEjourU4jiHj6gDGMieAcU8Io=
|
github.com/labbsr0x/goh v0.0.0-20190830205702-3d6988c73e10 h1:mrPTy7qNJPGHaUkkN301r8Y+13l2/vsiC8Lvi09e6sI=
|
||||||
github.com/labbsr0x/goh v0.0.0-20190610190554-60aa50bcbca7/go.mod h1:RBxeaayaaMmp7GxwHiKANjkg9e+rxjOm4mB5vD5rt/I=
|
github.com/labbsr0x/goh v0.0.0-20190830205702-3d6988c73e10/go.mod h1:RBxeaayaaMmp7GxwHiKANjkg9e+rxjOm4mB5vD5rt/I=
|
||||||
github.com/libkermit/compose v0.0.0-20171122111507-c04e39c026ad h1:nTyRWZ864mnHUnusBCVA628AZFgfGHwRUpbHqGhRQr8=
|
github.com/libkermit/compose v0.0.0-20171122111507-c04e39c026ad h1:nTyRWZ864mnHUnusBCVA628AZFgfGHwRUpbHqGhRQr8=
|
||||||
github.com/libkermit/compose v0.0.0-20171122111507-c04e39c026ad/go.mod h1:GyCk/ifDcqsU1tsRMMWqXANnTtxzcwEWscb7j5qmblM=
|
github.com/libkermit/compose v0.0.0-20171122111507-c04e39c026ad/go.mod h1:GyCk/ifDcqsU1tsRMMWqXANnTtxzcwEWscb7j5qmblM=
|
||||||
github.com/libkermit/docker v0.0.0-20171122101128-e6674d32b807 h1:/7J1WDQd6Xn1Pr8KtE2I/7/cKw66AV3hBUOyxqyXo84=
|
github.com/libkermit/docker v0.0.0-20171122101128-e6674d32b807 h1:/7J1WDQd6Xn1Pr8KtE2I/7/cKw66AV3hBUOyxqyXo84=
|
||||||
|
|
|
@ -46,7 +46,7 @@ func (s *AccessLogSuite) SetUpSuite(c *check.C) {
|
||||||
|
|
||||||
func (s *AccessLogSuite) TearDownTest(c *check.C) {
|
func (s *AccessLogSuite) TearDownTest(c *check.C) {
|
||||||
displayTraefikLogFile(c, traefikTestLogFile)
|
displayTraefikLogFile(c, traefikTestLogFile)
|
||||||
os.Remove(traefikTestAccessLogFile)
|
_ = os.Remove(traefikTestAccessLogFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AccessLogSuite) TestAccessLog(c *check.C) {
|
func (s *AccessLogSuite) TestAccessLog(c *check.C) {
|
||||||
|
@ -59,7 +59,7 @@ func (s *AccessLogSuite) TestAccessLog(c *check.C) {
|
||||||
defer func() {
|
defer func() {
|
||||||
traefikLog, err := ioutil.ReadFile(traefikTestLogFile)
|
traefikLog, err := ioutil.ReadFile(traefikTestLogFile)
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
log.Info(string(traefikLog))
|
log.WithoutContext().Info(string(traefikLog))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
|
@ -233,7 +233,7 @@ func digestParts(resp *http.Response) map[string]string {
|
||||||
func getMD5(data string) string {
|
func getMD5(data string) string {
|
||||||
digest := md5.New()
|
digest := md5.New()
|
||||||
if _, err := digest.Write([]byte(data)); err != nil {
|
if _, err := digest.Write([]byte(data)); err != nil {
|
||||||
log.Error(err)
|
log.WithoutContext().Error(err)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%x", digest.Sum(nil))
|
return fmt.Sprintf("%x", digest.Sum(nil))
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ func getMD5(data string) string {
|
||||||
func getCnonce() string {
|
func getCnonce() string {
|
||||||
b := make([]byte, 8)
|
b := make([]byte, 8)
|
||||||
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
||||||
log.Error(err)
|
log.WithoutContext().Error(err)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%x", b)[:16]
|
return fmt.Sprintf("%x", b)[:16]
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ type handler struct{}
|
||||||
// Simplified version of the Challenge Test Server from Boulder
|
// Simplified version of the Challenge Test Server from Boulder
|
||||||
// https://github.com/letsencrypt/boulder/blob/a6597b9f120207eff192c3e4107a7e49972a0250/test/challtestsrv/dnsone.go#L40
|
// https://github.com/letsencrypt/boulder/blob/a6597b9f120207eff192c3e4107a7e49972a0250/test/challtestsrv/dnsone.go#L40
|
||||||
func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
|
logger := log.WithoutContext()
|
||||||
|
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetReply(r)
|
m.SetReply(r)
|
||||||
m.Compress = false
|
m.Compress = false
|
||||||
|
@ -23,8 +25,9 @@ func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
if fakeDNS == "" {
|
if fakeDNS == "" {
|
||||||
fakeDNS = "127.0.0.1"
|
fakeDNS = "127.0.0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, q := range r.Question {
|
for _, q := range r.Question {
|
||||||
log.Infof("Query -- [%s] %s", q.Name, dns.TypeToString[q.Qtype])
|
logger.Infof("Query -- [%s] %s", q.Name, dns.TypeToString[q.Qtype])
|
||||||
|
|
||||||
switch q.Qtype {
|
switch q.Qtype {
|
||||||
case dns.TypeA:
|
case dns.TypeA:
|
||||||
|
@ -94,7 +97,7 @@ func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
m.Ns = append(m.Ns, auth)
|
m.Ns = append(m.Ns, auth)
|
||||||
|
|
||||||
if err := w.WriteMsg(m); err != nil {
|
if err := w.WriteMsg(m); err != nil {
|
||||||
log.Fatalf("Failed to write message %v", err)
|
logger.Fatalf("Failed to write message %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,9 +109,9 @@ func startFakeDNSServer() *dns.Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
log.Infof("Start a fake DNS server.")
|
log.WithoutContext().Infof("Start a fake DNS server.")
|
||||||
if err := srv.ListenAndServe(); err != nil {
|
if err := srv.ListenAndServe(); err != nil {
|
||||||
log.Fatalf("Failed to set udp listener %v", err)
|
log.WithoutContext().Fatalf("Failed to set udp listener %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
42
integration/fixtures/tcp/wrr.toml
Normal file
42
integration/fixtures/tcp/wrr.toml
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
[global]
|
||||||
|
checkNewVersion = false
|
||||||
|
sendAnonymousUsage = false
|
||||||
|
|
||||||
|
[log]
|
||||||
|
level = "DEBUG"
|
||||||
|
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.tcp]
|
||||||
|
address = ":8093"
|
||||||
|
|
||||||
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
|
[providers.file]
|
||||||
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
||||||
|
## dynamic configuration ##
|
||||||
|
[tcp]
|
||||||
|
[tcp.routers]
|
||||||
|
[tcp.routers.to-whoami-a]
|
||||||
|
rule = "HostSNI(`whoami-a.test`)"
|
||||||
|
service = "whoami"
|
||||||
|
entryPoints = [ "tcp" ]
|
||||||
|
[tcp.routers.to-whoami-a.tls]
|
||||||
|
passthrough=true
|
||||||
|
|
||||||
|
[[tcp.services.whoami.weighted.services]]
|
||||||
|
name="whoami-a"
|
||||||
|
weight=3
|
||||||
|
[[tcp.services.whoami.weighted.services]]
|
||||||
|
name="whoami-b"
|
||||||
|
weight=1
|
||||||
|
|
||||||
|
[tcp.services.whoami-a.loadBalancer]
|
||||||
|
[[tcp.services.whoami-a.loadBalancer.servers]]
|
||||||
|
address = "localhost:8081"
|
||||||
|
|
||||||
|
[tcp.services.whoami-b.loadBalancer]
|
||||||
|
[[tcp.services.whoami-b.loadBalancer.servers]]
|
||||||
|
address = "localhost:8082"
|
||||||
|
|
|
@ -50,7 +50,7 @@ func (s *myserver) StreamExample(in *helloworld.StreamExampleRequest, server hel
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := server.Send(&helloworld.StreamExampleReply{Data: string(data)}); err != nil {
|
if err := server.Send(&helloworld.StreamExampleReply{Data: string(data)}); err != nil {
|
||||||
log.Error(err)
|
log.WithoutContext().Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
<-s.stopStreamExample
|
<-s.stopStreamExample
|
||||||
|
|
|
@ -28,7 +28,7 @@ var showLog = flag.Bool("tlog", false, "always show Traefik logs")
|
||||||
|
|
||||||
func Test(t *testing.T) {
|
func Test(t *testing.T) {
|
||||||
if !*integration {
|
if !*integration {
|
||||||
log.Info("Integration tests disabled.")
|
log.WithoutContext().Info("Integration tests disabled.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ func (s *BaseSuite) createComposeProject(c *check.C, name string) {
|
||||||
ip, _, err := net.ParseCIDR(addr.String())
|
ip, _, err := net.ParseCIDR(addr.String())
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
if !ip.IsLoopback() && ip.To4() != nil {
|
if !ip.IsLoopback() && ip.To4() != nil {
|
||||||
os.Setenv("DOCKER_HOST_IP", ip.String())
|
_ = os.Setenv("DOCKER_HOST_IP", ip.String())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"service1": {
|
"service1": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
||||||
|
@ -183,7 +183,7 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"service1": {
|
"service1": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/integration/try"
|
"github.com/containous/traefik/v2/integration/try"
|
||||||
|
@ -266,3 +267,35 @@ func guessWhoTLSMaxVersion(addr, serverName string, tlsCall bool, tlsMaxVersion
|
||||||
|
|
||||||
return string(out[:n]), nil
|
return string(out[:n]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TCPSuite) TestWRR(c *check.C) {
|
||||||
|
file := s.adaptFile(c, "fixtures/tcp/wrr.toml", struct{}{})
|
||||||
|
defer os.Remove(file)
|
||||||
|
|
||||||
|
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||||
|
defer display(c)
|
||||||
|
|
||||||
|
err := cmd.Start()
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
defer cmd.Process.Kill()
|
||||||
|
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI"))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
call := map[string]int{}
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
// Traefik passes through, termination handled by whoami-a
|
||||||
|
out, err := guessWho("127.0.0.1:8093", "whoami-a.test", true)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
switch {
|
||||||
|
case strings.Contains(out, "whoami-a"):
|
||||||
|
call["whoami-a"]++
|
||||||
|
case strings.Contains(out, "whoami-b"):
|
||||||
|
call["whoami-b"]++
|
||||||
|
default:
|
||||||
|
call["unknown"]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Assert(call, checker.DeepEquals, map[string]int{"whoami-a": 3, "whoami-b": 1})
|
||||||
|
}
|
||||||
|
|
39
integration/testdata/rawdata-crd.json
vendored
39
integration/testdata/rawdata-crd.json
vendored
|
@ -1,28 +1,28 @@
|
||||||
{
|
{
|
||||||
"routers": {
|
"routers": {
|
||||||
"default/test.route-6b204d94623b3df4370c@kubernetescrd": {
|
"default-test.route-6b204d94623b3df4370c@kubernetescrd": {
|
||||||
"entryPoints": [
|
"entryPoints": [
|
||||||
"web"
|
"web"
|
||||||
],
|
],
|
||||||
"service": "default/test.route-6b204d94623b3df4370c",
|
"service": "default-test.route-6b204d94623b3df4370c",
|
||||||
"rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/bar`)",
|
"rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/bar`)",
|
||||||
"priority": 12,
|
"priority": 12,
|
||||||
"tls": {
|
"tls": {
|
||||||
"options": "default/mytlsoption"
|
"options": "default-mytlsoption"
|
||||||
},
|
},
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"using": [
|
"using": [
|
||||||
"web"
|
"web"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"default/test2.route-23c7f4c450289ee29016@kubernetescrd": {
|
"default-test2.route-23c7f4c450289ee29016@kubernetescrd": {
|
||||||
"entryPoints": [
|
"entryPoints": [
|
||||||
"web"
|
"web"
|
||||||
],
|
],
|
||||||
"middlewares": [
|
"middlewares": [
|
||||||
"default/mychain@kubernetescrd"
|
"default-mychain@kubernetescrd"
|
||||||
],
|
],
|
||||||
"service": "default/test2.route-23c7f4c450289ee29016",
|
"service": "default-test2.route-23c7f4c450289ee29016",
|
||||||
"rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/tobestripped`)",
|
"rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/tobestripped`)",
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"using": [
|
"using": [
|
||||||
|
@ -31,18 +31,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"middlewares": {
|
"middlewares": {
|
||||||
"default/mychain@kubernetescrd": {
|
"default-mychain@kubernetescrd": {
|
||||||
"chain": {
|
"chain": {
|
||||||
"middlewares": [
|
"middlewares": [
|
||||||
"default/stripprefix@kubernetescrd"
|
"default-stripprefix@kubernetescrd"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"usedBy": [
|
"usedBy": [
|
||||||
"default/test2.route-23c7f4c450289ee29016@kubernetescrd"
|
"default-test2.route-23c7f4c450289ee29016@kubernetescrd"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"default/stripprefix@kubernetescrd": {
|
"default-stripprefix@kubernetescrd": {
|
||||||
"stripPrefix": {
|
"stripPrefix": {
|
||||||
"prefixes": [
|
"prefixes": [
|
||||||
"/tobestripped"
|
"/tobestripped"
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"default/test.route-6b204d94623b3df4370c@kubernetescrd": {
|
"default-test.route-6b204d94623b3df4370c@kubernetescrd": {
|
||||||
"loadBalancer": {
|
"loadBalancer": {
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
|
@ -66,14 +66,14 @@
|
||||||
},
|
},
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"usedBy": [
|
"usedBy": [
|
||||||
"default/test.route-6b204d94623b3df4370c@kubernetescrd"
|
"default-test.route-6b204d94623b3df4370c@kubernetescrd"
|
||||||
],
|
],
|
||||||
"serverStatus": {
|
"serverStatus": {
|
||||||
"http://10.42.0.2:80": "UP",
|
"http://10.42.0.2:80": "UP",
|
||||||
"http://10.42.0.6:80": "UP"
|
"http://10.42.0.6:80": "UP"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"default/test2.route-23c7f4c450289ee29016@kubernetescrd": {
|
"default-test2.route-23c7f4c450289ee29016@kubernetescrd": {
|
||||||
"loadBalancer": {
|
"loadBalancer": {
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
},
|
},
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"usedBy": [
|
"usedBy": [
|
||||||
"default/test2.route-23c7f4c450289ee29016@kubernetescrd"
|
"default-test2.route-23c7f4c450289ee29016@kubernetescrd"
|
||||||
],
|
],
|
||||||
"serverStatus": {
|
"serverStatus": {
|
||||||
"http://10.42.0.2:80": "UP",
|
"http://10.42.0.2:80": "UP",
|
||||||
|
@ -96,15 +96,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tcpRouters": {
|
"tcpRouters": {
|
||||||
"default/test3.route-673acf455cb2dab0b43a@kubernetescrd": {
|
"default-test3.route-673acf455cb2dab0b43a@kubernetescrd": {
|
||||||
"entryPoints": [
|
"entryPoints": [
|
||||||
"footcp"
|
"footcp"
|
||||||
],
|
],
|
||||||
"service": "default/test3.route-673acf455cb2dab0b43a",
|
"service": "default-test3.route-673acf455cb2dab0b43a",
|
||||||
"rule": "HostSNI(`*`)",
|
"rule": "HostSNI(`*`)",
|
||||||
"tls": {
|
"tls": {
|
||||||
"passthrough": false,
|
"passthrough": false,
|
||||||
"options": "default/mytlsoption"
|
"options": "default-mytlsoption"
|
||||||
},
|
},
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"using": [
|
"using": [
|
||||||
|
@ -113,8 +113,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tcpServices": {
|
"tcpServices": {
|
||||||
"default/test3.route-673acf455cb2dab0b43a@kubernetescrd": {
|
"default-test3.route-673acf455cb2dab0b43a@kubernetescrd": {
|
||||||
"loadBalancer": {
|
"loadBalancer": {
|
||||||
|
"terminationDelay": 100,
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
"address": "10.42.0.4:8080"
|
"address": "10.42.0.4:8080"
|
||||||
|
@ -126,7 +127,7 @@
|
||||||
},
|
},
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"usedBy": [
|
"usedBy": [
|
||||||
"default/test3.route-673acf455cb2dab0b43a@kubernetescrd"
|
"default-test3.route-673acf455cb2dab0b43a@kubernetescrd"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
integration/testdata/rawdata-ingress.json
vendored
20
integration/testdata/rawdata-ingress.json
vendored
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"routers": {
|
"routers": {
|
||||||
"whoami-test-https/whoami-tls@kubernetes": {
|
"whoami-test-https-whoami-tls@kubernetes": {
|
||||||
"service": "default/whoami/http",
|
"service": "default-whoami-http",
|
||||||
"rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)",
|
"rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)",
|
||||||
"tls": {},
|
"tls": {},
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
|
@ -10,8 +10,8 @@
|
||||||
"web"
|
"web"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"whoami-test-https/whoami@kubernetes": {
|
"whoami-test-https-whoami@kubernetes": {
|
||||||
"service": "default/whoami/http",
|
"service": "default-whoami-http",
|
||||||
"rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)",
|
"rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)",
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"using": [
|
"using": [
|
||||||
|
@ -19,8 +19,8 @@
|
||||||
"web"
|
"web"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"whoami-test/whoami@kubernetes": {
|
"whoami-test-whoami@kubernetes": {
|
||||||
"service": "default/whoami/http",
|
"service": "default-whoami-http",
|
||||||
"rule": "Host(`whoami.test`) \u0026\u0026 PathPrefix(`/whoami`)",
|
"rule": "Host(`whoami.test`) \u0026\u0026 PathPrefix(`/whoami`)",
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"using": [
|
"using": [
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"default/whoami/http@kubernetes": {
|
"default-whoami-http@kubernetes": {
|
||||||
"loadBalancer": {
|
"loadBalancer": {
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
|
@ -44,9 +44,9 @@
|
||||||
},
|
},
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"usedBy": [
|
"usedBy": [
|
||||||
"whoami-test-https/whoami-tls@kubernetes",
|
"whoami-test-https-whoami-tls@kubernetes",
|
||||||
"whoami-test-https/whoami@kubernetes",
|
"whoami-test-https-whoami@kubernetes",
|
||||||
"whoami-test/whoami@kubernetes"
|
"whoami-test-whoami@kubernetes"
|
||||||
],
|
],
|
||||||
"serverStatus": {
|
"serverStatus": {
|
||||||
"http://10.42.0.2:80": "UP",
|
"http://10.42.0.2:80": "UP",
|
||||||
|
|
|
@ -26,10 +26,9 @@ import (
|
||||||
func TestDo_globalConfiguration(t *testing.T) {
|
func TestDo_globalConfiguration(t *testing.T) {
|
||||||
config := &static.Configuration{}
|
config := &static.Configuration{}
|
||||||
|
|
||||||
sendAnonymousUsage := true
|
|
||||||
config.Global = &static.Global{
|
config.Global = &static.Global{
|
||||||
CheckNewVersion: true,
|
CheckNewVersion: true,
|
||||||
SendAnonymousUsage: &sendAnonymousUsage,
|
SendAnonymousUsage: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
config.AccessLog = &types.AccessLog{
|
config.AccessLog = &types.AccessLog{
|
||||||
|
|
|
@ -136,7 +136,7 @@ func TestHandler_Overview(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"tcpfoo-service@myprovider": {
|
"tcpfoo-service@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
|
@ -148,7 +148,7 @@ func TestHandler_Overview(t *testing.T) {
|
||||||
},
|
},
|
||||||
"tcpbar-service@myprovider": {
|
"tcpbar-service@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.2",
|
Address: "127.0.0.2",
|
||||||
|
@ -160,7 +160,7 @@ func TestHandler_Overview(t *testing.T) {
|
||||||
},
|
},
|
||||||
"tcpfii-service@myprovider": {
|
"tcpfii-service@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.2",
|
Address: "127.0.0.2",
|
||||||
|
|
|
@ -255,7 +255,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"bar@myprovider": {
|
"bar@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:2345",
|
Address: "127.0.0.1:2345",
|
||||||
|
@ -268,7 +268,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
},
|
},
|
||||||
"baz@myprovider": {
|
"baz@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.2:2345",
|
Address: "127.0.0.2:2345",
|
||||||
|
@ -281,7 +281,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
},
|
},
|
||||||
"foz@myprovider": {
|
"foz@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.2:2345",
|
Address: "127.0.0.2:2345",
|
||||||
|
@ -307,7 +307,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"bar@myprovider": {
|
"bar@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:2345",
|
Address: "127.0.0.1:2345",
|
||||||
|
@ -320,7 +320,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
},
|
},
|
||||||
"baz@myprovider": {
|
"baz@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.2:2345",
|
Address: "127.0.0.2:2345",
|
||||||
|
@ -333,7 +333,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
},
|
},
|
||||||
"foz@myprovider": {
|
"foz@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.2:2345",
|
Address: "127.0.0.2:2345",
|
||||||
|
@ -359,7 +359,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"bar@myprovider": {
|
"bar@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:2345",
|
Address: "127.0.0.1:2345",
|
||||||
|
@ -372,7 +372,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
},
|
},
|
||||||
"baz@myprovider": {
|
"baz@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.2:2345",
|
Address: "127.0.0.2:2345",
|
||||||
|
@ -385,7 +385,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
},
|
},
|
||||||
"foz@myprovider": {
|
"foz@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.2:2345",
|
Address: "127.0.0.2:2345",
|
||||||
|
@ -411,7 +411,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"bar@myprovider": {
|
"bar@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:2345",
|
Address: "127.0.0.1:2345",
|
||||||
|
@ -423,7 +423,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
},
|
},
|
||||||
"baz@myprovider": {
|
"baz@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.2:2345",
|
Address: "127.0.0.2:2345",
|
||||||
|
@ -435,7 +435,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
},
|
},
|
||||||
"test@myprovider": {
|
"test@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.3:2345",
|
Address: "127.0.0.3:2345",
|
||||||
|
@ -459,7 +459,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"bar@myprovider": {
|
"bar@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:2345",
|
Address: "127.0.0.1:2345",
|
||||||
|
@ -483,7 +483,7 @@ func TestHandler_TCP(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"bar@myprovider": {
|
"bar@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:2345",
|
Address: "127.0.0.1:2345",
|
||||||
|
|
|
@ -91,7 +91,7 @@ func TestHandler_RawData(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"tcpfoo-service@myprovider": {
|
"tcpfoo-service@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
|
|
|
@ -35,7 +35,7 @@ func Collect(staticConfiguration *static.Configuration) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Anonymous stats sent to %s: %s", collectorURL, anonConfig)
|
log.WithoutContext().Infof("Anonymous stats sent to %s: %s", collectorURL, anonConfig)
|
||||||
|
|
||||||
hashConf, err := hashstructure.Hash(staticConfiguration, nil)
|
hashConf, err := hashstructure.Hash(staticConfiguration, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -77,7 +77,7 @@ type WRRService struct {
|
||||||
Weight *int `json:"weight,omitempty" toml:"weight,omitempty" yaml:"weight,omitempty"`
|
Weight *int `json:"weight,omitempty" toml:"weight,omitempty" yaml:"weight,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults Default values for a ServersLoadBalancer.
|
// SetDefaults Default values for a WRRService.
|
||||||
func (w *WRRService) SetDefaults() {
|
func (w *WRRService) SetDefaults() {
|
||||||
defaultWeight := 1
|
defaultWeight := 1
|
||||||
w.Weight = &defaultWeight
|
w.Weight = &defaultWeight
|
||||||
|
|
|
@ -18,7 +18,29 @@ type TCPConfiguration struct {
|
||||||
|
|
||||||
// TCPService holds a tcp service configuration (can only be of one type at the same time).
|
// TCPService holds a tcp service configuration (can only be of one type at the same time).
|
||||||
type TCPService struct {
|
type TCPService struct {
|
||||||
LoadBalancer *TCPLoadBalancerService `json:"loadBalancer,omitempty" toml:"loadBalancer,omitempty" yaml:"loadBalancer,omitempty"`
|
LoadBalancer *TCPServersLoadBalancer `json:"loadBalancer,omitempty" toml:"loadBalancer,omitempty" yaml:"loadBalancer,omitempty"`
|
||||||
|
Weighted *TCPWeightedRoundRobin `json:"weighted,omitempty" toml:"weighted,omitempty" yaml:"weighted,omitempty" label:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
|
// TCPWeightedRoundRobin is a weighted round robin tcp load-balancer of services.
|
||||||
|
type TCPWeightedRoundRobin struct {
|
||||||
|
Services []TCPWRRService `json:"services,omitempty" toml:"services,omitempty" yaml:"services,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
|
// TCPWRRService is a reference to a tcp service load-balanced with weighted round robin.
|
||||||
|
type TCPWRRService struct {
|
||||||
|
Name string `json:"name,omitempty" toml:"name,omitempty" yaml:"name,omitempty"`
|
||||||
|
Weight *int `json:"weight,omitempty" toml:"weight,omitempty" yaml:"weight,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDefaults Default values for a TCPWRRService.
|
||||||
|
func (w *TCPWRRService) SetDefaults() {
|
||||||
|
defaultWeight := 1
|
||||||
|
w.Weight = &defaultWeight
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
@ -43,13 +65,25 @@ type RouterTCPTLSConfig struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// TCPLoadBalancerService holds the LoadBalancerService configuration.
|
// TCPServersLoadBalancer holds the LoadBalancerService configuration.
|
||||||
type TCPLoadBalancerService struct {
|
type TCPServersLoadBalancer struct {
|
||||||
|
// TerminationDelay, corresponds to the deadline that the proxy sets, after one
|
||||||
|
// of its connected peers indicates it has closed the writing capability of its
|
||||||
|
// connection, to close the reading capability as well, hence fully terminating the
|
||||||
|
// connection. It is a duration in milliseconds, defaulting to 100. A negative value
|
||||||
|
// means an infinite deadline (i.e. the reading capability is never closed).
|
||||||
|
TerminationDelay *int `json:"terminationDelay,omitempty" toml:"terminationDelay,omitempty" yaml:"terminationDelay,omitempty"`
|
||||||
Servers []TCPServer `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server"`
|
Servers []TCPServer `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDefaults Default values for a TCPServersLoadBalancer
|
||||||
|
func (l *TCPServersLoadBalancer) SetDefaults() {
|
||||||
|
defaultTerminationDelay := 100 // in milliseconds
|
||||||
|
l.TerminationDelay = &defaultTerminationDelay
|
||||||
|
}
|
||||||
|
|
||||||
// Mergeable tells if the given service is mergeable.
|
// Mergeable tells if the given service is mergeable.
|
||||||
func (l *TCPLoadBalancerService) Mergeable(loadBalancer *TCPLoadBalancerService) bool {
|
func (l *TCPServersLoadBalancer) Mergeable(loadBalancer *TCPServersLoadBalancer) bool {
|
||||||
savedServers := l.Servers
|
savedServers := l.Servers
|
||||||
defer func() {
|
defer func() {
|
||||||
l.Servers = savedServers
|
l.Servers = savedServers
|
||||||
|
|
|
@ -1152,27 +1152,6 @@ func (in *TCPConfiguration) DeepCopy() *TCPConfiguration {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *TCPLoadBalancerService) DeepCopyInto(out *TCPLoadBalancerService) {
|
|
||||||
*out = *in
|
|
||||||
if in.Servers != nil {
|
|
||||||
in, out := &in.Servers, &out.Servers
|
|
||||||
*out = make([]TCPServer, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPLoadBalancerService.
|
|
||||||
func (in *TCPLoadBalancerService) DeepCopy() *TCPLoadBalancerService {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(TCPLoadBalancerService)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *TCPRouter) DeepCopyInto(out *TCPRouter) {
|
func (in *TCPRouter) DeepCopyInto(out *TCPRouter) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -1215,12 +1194,43 @@ func (in *TCPServer) DeepCopy() *TCPServer {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *TCPServersLoadBalancer) DeepCopyInto(out *TCPServersLoadBalancer) {
|
||||||
|
*out = *in
|
||||||
|
if in.TerminationDelay != nil {
|
||||||
|
in, out := &in.TerminationDelay, &out.TerminationDelay
|
||||||
|
*out = new(int)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.Servers != nil {
|
||||||
|
in, out := &in.Servers, &out.Servers
|
||||||
|
*out = make([]TCPServer, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPServersLoadBalancer.
|
||||||
|
func (in *TCPServersLoadBalancer) DeepCopy() *TCPServersLoadBalancer {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(TCPServersLoadBalancer)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *TCPService) DeepCopyInto(out *TCPService) {
|
func (in *TCPService) DeepCopyInto(out *TCPService) {
|
||||||
*out = *in
|
*out = *in
|
||||||
if in.LoadBalancer != nil {
|
if in.LoadBalancer != nil {
|
||||||
in, out := &in.LoadBalancer, &out.LoadBalancer
|
in, out := &in.LoadBalancer, &out.LoadBalancer
|
||||||
*out = new(TCPLoadBalancerService)
|
*out = new(TCPServersLoadBalancer)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
if in.Weighted != nil {
|
||||||
|
in, out := &in.Weighted, &out.Weighted
|
||||||
|
*out = new(TCPWeightedRoundRobin)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -1236,6 +1246,50 @@ func (in *TCPService) DeepCopy() *TCPService {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *TCPWRRService) DeepCopyInto(out *TCPWRRService) {
|
||||||
|
*out = *in
|
||||||
|
if in.Weight != nil {
|
||||||
|
in, out := &in.Weight, &out.Weight
|
||||||
|
*out = new(int)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPWRRService.
|
||||||
|
func (in *TCPWRRService) DeepCopy() *TCPWRRService {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(TCPWRRService)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *TCPWeightedRoundRobin) DeepCopyInto(out *TCPWeightedRoundRobin) {
|
||||||
|
*out = *in
|
||||||
|
if in.Services != nil {
|
||||||
|
in, out := &in.Services, &out.Services
|
||||||
|
*out = make([]TCPWRRService, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPWeightedRoundRobin.
|
||||||
|
func (in *TCPWeightedRoundRobin) DeepCopy() *TCPWeightedRoundRobin {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(TCPWeightedRoundRobin)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *TLSCLientCertificateDNInfo) DeepCopyInto(out *TLSCLientCertificateDNInfo) {
|
func (in *TLSCLientCertificateDNInfo) DeepCopyInto(out *TLSCLientCertificateDNInfo) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|
|
@ -3,6 +3,7 @@ package flag
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/parser"
|
"github.com/containous/traefik/v2/pkg/config/parser"
|
||||||
|
@ -80,8 +81,8 @@ func (f *flagSet) parseOne() (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
n := strings.ToLower(name)
|
flagType := f.getFlagType(name)
|
||||||
if f.flagTypes[n] == reflect.Bool || f.flagTypes[n] == reflect.Ptr {
|
if flagType == reflect.Bool || flagType == reflect.Ptr {
|
||||||
f.setValue(name, "true")
|
f.setValue(name, "true")
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
@ -111,10 +112,30 @@ func (f *flagSet) setValue(name string, value string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
v, ok := f.values[key]
|
v, ok := f.values[key]
|
||||||
if ok && f.flagTypes[strings.ToLower(name)] == reflect.Slice {
|
if ok && f.getFlagType(name) == reflect.Slice {
|
||||||
f.values[key] = v + "," + value
|
f.values[key] = v + "," + value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.values[key] = value
|
f.values[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *flagSet) getFlagType(name string) reflect.Kind {
|
||||||
|
neutral := strings.ToLower(name)
|
||||||
|
|
||||||
|
kind, ok := f.flagTypes[neutral]
|
||||||
|
if ok {
|
||||||
|
return kind
|
||||||
|
}
|
||||||
|
|
||||||
|
for n, k := range f.flagTypes {
|
||||||
|
if strings.Contains(n, parser.MapNamePlaceholder) {
|
||||||
|
p := strings.NewReplacer(".", `\.`, parser.MapNamePlaceholder, `([^.]+)`).Replace(n)
|
||||||
|
if regexp.MustCompile(p).MatchString(neutral) {
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.Invalid
|
||||||
|
}
|
||||||
|
|
|
@ -250,7 +250,7 @@ func TestParse(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "map struct with sub-map case senstitive",
|
desc: "map struct with sub-map case sensitive",
|
||||||
args: []string{"--foo.Name1.bar.name2.value=firstValue", "--foo.naMe1.bar.name2.value=secondValue"},
|
args: []string{"--foo.Name1.bar.name2.value=firstValue", "--foo.naMe1.bar.name2.value=secondValue"},
|
||||||
element: &struct {
|
element: &struct {
|
||||||
Foo map[string]struct {
|
Foo map[string]struct {
|
||||||
|
@ -273,6 +273,20 @@ func TestParse(t *testing.T) {
|
||||||
"traefik.foo.Name1.bar.name2.value": "secondValue",
|
"traefik.foo.Name1.bar.name2.value": "secondValue",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "pointer of struct and map without explicit value",
|
||||||
|
args: []string{"--foo.default.bar.fuu"},
|
||||||
|
element: &struct {
|
||||||
|
Foo map[string]struct {
|
||||||
|
Bar *struct {
|
||||||
|
Fuu *struct{ Value string }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}{},
|
||||||
|
expected: map[string]string{
|
||||||
|
"traefik.foo.default.bar.fuu": "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "slice with several flags 2 and different cases.",
|
desc: "slice with several flags 2 and different cases.",
|
||||||
args: []string{"--foo", "bar", "--Foo", "baz"},
|
args: []string{"--foo", "bar", "--Foo", "baz"},
|
||||||
|
|
|
@ -170,7 +170,9 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"traefik.tcp.routers.Router1.tls.options": "foo",
|
"traefik.tcp.routers.Router1.tls.options": "foo",
|
||||||
"traefik.tcp.routers.Router1.tls.passthrough": "false",
|
"traefik.tcp.routers.Router1.tls.passthrough": "false",
|
||||||
"traefik.tcp.services.Service0.loadbalancer.server.Port": "42",
|
"traefik.tcp.services.Service0.loadbalancer.server.Port": "42",
|
||||||
|
"traefik.tcp.services.Service0.loadbalancer.TerminationDelay": "42",
|
||||||
"traefik.tcp.services.Service1.loadbalancer.server.Port": "42",
|
"traefik.tcp.services.Service1.loadbalancer.server.Port": "42",
|
||||||
|
"traefik.tcp.services.Service1.loadbalancer.TerminationDelay": "42",
|
||||||
}
|
}
|
||||||
|
|
||||||
configuration, err := DecodeConfiguration(labels)
|
configuration, err := DecodeConfiguration(labels)
|
||||||
|
@ -206,21 +208,23 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"Service0": {
|
"Service0": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Port: "42",
|
Port: "42",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TerminationDelay: func(i int) *int { return &i }(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Service1": {
|
"Service1": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Port: "42",
|
Port: "42",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TerminationDelay: func(i int) *int { return &i }(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -610,7 +614,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"Service0": {
|
"Service0": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Port: "42",
|
Port: "42",
|
||||||
|
@ -619,7 +623,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Service1": {
|
"Service1": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Port: "42",
|
Port: "42",
|
||||||
|
|
|
@ -488,7 +488,7 @@ func TestPopulateUsedBy(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"foo-service@myprovider": {
|
"foo-service@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
|
@ -522,7 +522,7 @@ func TestPopulateUsedBy(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"foo-service@myprovider": {
|
"foo-service@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
|
@ -598,7 +598,7 @@ func TestPopulateUsedBy(t *testing.T) {
|
||||||
TCPServices: map[string]*runtime.TCPServiceInfo{
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
||||||
"foo-service@myprovider": {
|
"foo-service@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
|
@ -614,7 +614,7 @@ func TestPopulateUsedBy(t *testing.T) {
|
||||||
},
|
},
|
||||||
"bar-service@myprovider": {
|
"bar-service@myprovider": {
|
||||||
TCPService: &dynamic.TCPService{
|
TCPService: &dynamic.TCPService{
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
|
|
|
@ -72,7 +72,7 @@ type CertificateResolver struct {
|
||||||
// Global holds the global configuration.
|
// Global holds the global configuration.
|
||||||
type Global struct {
|
type Global struct {
|
||||||
CheckNewVersion bool `description:"Periodically check if a new version has been released." json:"checkNewVersion,omitempty" toml:"checkNewVersion,omitempty" yaml:"checkNewVersion,omitempty" label:"allowEmpty" export:"true"`
|
CheckNewVersion bool `description:"Periodically check if a new version has been released." json:"checkNewVersion,omitempty" toml:"checkNewVersion,omitempty" yaml:"checkNewVersion,omitempty" label:"allowEmpty" export:"true"`
|
||||||
SendAnonymousUsage *bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be enabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" export:"true"`
|
SendAnonymousUsage bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be enabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServersTransport options to configure communication between Traefik and the servers
|
// ServersTransport options to configure communication between Traefik and the servers
|
||||||
|
@ -238,13 +238,15 @@ func getSafeACMECAServer(caServerSrc string) string {
|
||||||
|
|
||||||
if strings.HasPrefix(caServerSrc, "https://acme-v01.api.letsencrypt.org") {
|
if strings.HasPrefix(caServerSrc, "https://acme-v01.api.letsencrypt.org") {
|
||||||
caServer := strings.Replace(caServerSrc, "v01", "v02", 1)
|
caServer := strings.Replace(caServerSrc, "v01", "v02", 1)
|
||||||
log.Warnf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer)
|
log.WithoutContext().
|
||||||
|
Warnf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer)
|
||||||
return caServer
|
return caServer
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(caServerSrc, "https://acme-staging.api.letsencrypt.org") {
|
if strings.HasPrefix(caServerSrc, "https://acme-staging.api.letsencrypt.org") {
|
||||||
caServer := strings.Replace(caServerSrc, "https://acme-staging.api.letsencrypt.org", "https://acme-staging-v02.api.letsencrypt.org", 1)
|
caServer := strings.Replace(caServerSrc, "https://acme-staging.api.letsencrypt.org", "https://acme-staging-v02.api.letsencrypt.org", 1)
|
||||||
log.Warnf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer)
|
log.WithoutContext().
|
||||||
|
Warnf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer)
|
||||||
return caServer
|
return caServer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,37 +122,41 @@ func (hc *HealthCheck) SetBackendsConfiguration(parentCtx context.Context, backe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hc *HealthCheck) execute(ctx context.Context, backend *BackendConfig) {
|
func (hc *HealthCheck) execute(ctx context.Context, backend *BackendConfig) {
|
||||||
log.Debugf("Initial health check for backend: %q", backend.name)
|
logger := log.FromContext(ctx)
|
||||||
hc.checkBackend(backend)
|
logger.Debugf("Initial health check for backend: %q", backend.name)
|
||||||
|
|
||||||
|
hc.checkBackend(ctx, backend)
|
||||||
ticker := time.NewTicker(backend.Interval)
|
ticker := time.NewTicker(backend.Interval)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
log.Debugf("Stopping current health check goroutines of backend: %s", backend.name)
|
logger.Debugf("Stopping current health check goroutines of backend: %s", backend.name)
|
||||||
return
|
return
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
log.Debugf("Refreshing health check for backend: %s", backend.name)
|
logger.Debugf("Refreshing health check for backend: %s", backend.name)
|
||||||
hc.checkBackend(backend)
|
hc.checkBackend(ctx, backend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hc *HealthCheck) checkBackend(backend *BackendConfig) {
|
func (hc *HealthCheck) checkBackend(ctx context.Context, backend *BackendConfig) {
|
||||||
|
logger := log.FromContext(ctx)
|
||||||
|
|
||||||
enabledURLs := backend.LB.Servers()
|
enabledURLs := backend.LB.Servers()
|
||||||
var newDisabledURLs []backendURL
|
var newDisabledURLs []backendURL
|
||||||
// FIXME re enable metrics
|
// FIXME re enable metrics
|
||||||
for _, disableURL := range backend.disabledURLs {
|
for _, disableURL := range backend.disabledURLs {
|
||||||
// FIXME serverUpMetricValue := float64(0)
|
// FIXME serverUpMetricValue := float64(0)
|
||||||
if err := checkHealth(disableURL.url, backend); err == nil {
|
if err := checkHealth(disableURL.url, backend); err == nil {
|
||||||
log.Warnf("Health check up: Returning to server list. Backend: %q URL: %q Weight: %d",
|
logger.Warnf("Health check up: Returning to server list. Backend: %q URL: %q Weight: %d",
|
||||||
backend.name, disableURL.url.String(), disableURL.weight)
|
backend.name, disableURL.url.String(), disableURL.weight)
|
||||||
if err = backend.LB.UpsertServer(disableURL.url, roundrobin.Weight(disableURL.weight)); err != nil {
|
if err = backend.LB.UpsertServer(disableURL.url, roundrobin.Weight(disableURL.weight)); err != nil {
|
||||||
log.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
// FIXME serverUpMetricValue = 1
|
// FIXME serverUpMetricValue = 1
|
||||||
} else {
|
} else {
|
||||||
log.Warnf("Health check still failing. Backend: %q URL: %q Reason: %s", backend.name, disableURL.url.String(), err)
|
logger.Warnf("Health check still failing. Backend: %q URL: %q Reason: %s", backend.name, disableURL.url.String(), err)
|
||||||
newDisabledURLs = append(newDisabledURLs, disableURL)
|
newDisabledURLs = append(newDisabledURLs, disableURL)
|
||||||
}
|
}
|
||||||
// FIXME labelValues := []string{"backend", backend.name, "url", backendurl.url.String()}
|
// FIXME labelValues := []string{"backend", backend.name, "url", backendurl.url.String()}
|
||||||
|
@ -173,9 +177,9 @@ func (hc *HealthCheck) checkBackend(backend *BackendConfig) {
|
||||||
weight = 1
|
weight = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Warnf("Health check failed: Remove from server list. Backend: %q URL: %q Weight: %d Reason: %s", backend.name, enableURL.String(), weight, err)
|
logger.Warnf("Health check failed: Remove from server list. Backend: %q URL: %q Weight: %d Reason: %s", backend.name, enableURL.String(), weight, err)
|
||||||
if err := backend.LB.RemoveServer(enableURL); err != nil {
|
if err := backend.LB.RemoveServer(enableURL); err != nil {
|
||||||
log.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
backend.disabledURLs = append(backend.disabledURLs, backendURL{enableURL, weight})
|
backend.disabledURLs = append(backend.disabledURLs, backendURL{enableURL, weight})
|
||||||
// FIXME serverUpMetricValue = 0
|
// FIXME serverUpMetricValue = 0
|
||||||
|
@ -244,10 +248,10 @@ func checkHealth(serverURL *url.URL, backend *BackendConfig) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLBStatusUpdater returns a new LbStatusUpdater
|
// NewLBStatusUpdater returns a new LbStatusUpdater
|
||||||
func NewLBStatusUpdater(bh BalancerHandler, svinfo *runtime.ServiceInfo) *LbStatusUpdater {
|
func NewLBStatusUpdater(bh BalancerHandler, info *runtime.ServiceInfo) *LbStatusUpdater {
|
||||||
return &LbStatusUpdater{
|
return &LbStatusUpdater{
|
||||||
BalancerHandler: bh,
|
BalancerHandler: bh,
|
||||||
serviceInfo: svinfo,
|
serviceInfo: info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,12 +62,6 @@ func Panic(args ...interface{}) {
|
||||||
mainLogger.Panic(args...)
|
mainLogger.Panic(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panicf logs a message at level Panic on the standard logger.
|
|
||||||
// Deprecated
|
|
||||||
func Panicf(format string, args ...interface{}) {
|
|
||||||
mainLogger.Panicf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatal logs a message at level Fatal on the standard logger.
|
// Fatal logs a message at level Fatal on the standard logger.
|
||||||
// Deprecated
|
// Deprecated
|
||||||
func Fatal(args ...interface{}) {
|
func Fatal(args ...interface{}) {
|
||||||
|
|
|
@ -12,4 +12,5 @@ const (
|
||||||
MetricsProviderName = "metricsProviderName"
|
MetricsProviderName = "metricsProviderName"
|
||||||
TracingProviderName = "tracingProviderName"
|
TracingProviderName = "tracingProviderName"
|
||||||
ServerName = "serverName"
|
ServerName = "serverName"
|
||||||
|
TLSStoreName = "tlsStoreName"
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
@ -24,7 +25,7 @@ type addPrefix struct {
|
||||||
|
|
||||||
// New creates a new handler.
|
// New creates a new handler.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.AddPrefix, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.AddPrefix, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
var result *addPrefix
|
var result *addPrefix
|
||||||
|
|
||||||
if len(config.Prefix) > 0 {
|
if len(config.Prefix) > 0 {
|
||||||
|
@ -45,7 +46,7 @@ func (ap *addPrefix) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ap *addPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (ap *addPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
logger := middlewares.GetLogger(req.Context(), ap.name, typeName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), ap.name, typeName))
|
||||||
|
|
||||||
oldURLPath := req.URL.Path
|
oldURLPath := req.URL.Path
|
||||||
req.URL.Path = ap.prefix + req.URL.Path
|
req.URL.Path = ap.prefix + req.URL.Path
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
goauth "github.com/abbot/go-http-auth"
|
goauth "github.com/abbot/go-http-auth"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares/accesslog"
|
"github.com/containous/traefik/v2/pkg/middlewares/accesslog"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
|
@ -30,7 +31,7 @@ type basicAuth struct {
|
||||||
|
|
||||||
// NewBasic creates a basicAuth middleware.
|
// NewBasic creates a basicAuth middleware.
|
||||||
func NewBasic(ctx context.Context, next http.Handler, authConfig dynamic.BasicAuth, name string) (http.Handler, error) {
|
func NewBasic(ctx context.Context, next http.Handler, authConfig dynamic.BasicAuth, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, basicTypeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, basicTypeName)).Debug("Creating middleware")
|
||||||
users, err := getUsers(authConfig.UsersFile, authConfig.Users, basicUserParser)
|
users, err := getUsers(authConfig.UsersFile, authConfig.Users, basicUserParser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -58,7 +59,7 @@ func (b *basicAuth) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *basicAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (b *basicAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
logger := middlewares.GetLogger(req.Context(), b.name, basicTypeName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), b.name, basicTypeName))
|
||||||
|
|
||||||
if username := b.auth.CheckAuth(req); username == "" {
|
if username := b.auth.CheckAuth(req); username == "" {
|
||||||
logger.Debug("Authentication failed")
|
logger.Debug("Authentication failed")
|
||||||
|
|
|
@ -210,9 +210,6 @@ func TestBasicAuthUsersFromFile(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
if test.desc != "Should skip comments" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
test := test
|
test := test
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
goauth "github.com/abbot/go-http-auth"
|
goauth "github.com/abbot/go-http-auth"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares/accesslog"
|
"github.com/containous/traefik/v2/pkg/middlewares/accesslog"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
|
@ -30,7 +31,7 @@ type digestAuth struct {
|
||||||
|
|
||||||
// NewDigest creates a digest auth middleware.
|
// NewDigest creates a digest auth middleware.
|
||||||
func NewDigest(ctx context.Context, next http.Handler, authConfig dynamic.DigestAuth, name string) (http.Handler, error) {
|
func NewDigest(ctx context.Context, next http.Handler, authConfig dynamic.DigestAuth, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, digestTypeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, digestTypeName)).Debug("Creating middleware")
|
||||||
users, err := getUsers(authConfig.UsersFile, authConfig.Users, digestUserParser)
|
users, err := getUsers(authConfig.UsersFile, authConfig.Users, digestUserParser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -58,7 +59,7 @@ func (d *digestAuth) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *digestAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (d *digestAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
logger := middlewares.GetLogger(req.Context(), d.name, digestTypeName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), d.name, digestTypeName))
|
||||||
|
|
||||||
if username, _ := d.auth.CheckAuth(req); username == "" {
|
if username, _ := d.auth.CheckAuth(req); username == "" {
|
||||||
logger.Debug("Digest authentication failed")
|
logger.Debug("Digest authentication failed")
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
@ -34,7 +35,7 @@ type forwardAuth struct {
|
||||||
|
|
||||||
// NewForward creates a forward auth middleware.
|
// NewForward creates a forward auth middleware.
|
||||||
func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAuth, name string) (http.Handler, error) {
|
func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAuth, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, forwardedTypeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, forwardedTypeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
fa := &forwardAuth{
|
fa := &forwardAuth{
|
||||||
address: config.Address,
|
address: config.Address,
|
||||||
|
@ -61,7 +62,7 @@ func (fa *forwardAuth) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
logger := middlewares.GetLogger(req.Context(), fa.name, forwardedTypeName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), fa.name, forwardedTypeName))
|
||||||
|
|
||||||
// Ensure our request client does not follow redirects
|
// Ensure our request client does not follow redirects
|
||||||
httpClient := http.Client{
|
httpClient := http.Client{
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
@ -22,7 +23,7 @@ type buffer struct {
|
||||||
|
|
||||||
// New creates a buffering middleware.
|
// New creates a buffering middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.Buffering, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.Buffering, name string) (http.Handler, error) {
|
||||||
logger := middlewares.GetLogger(ctx, name, typeName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName))
|
||||||
logger.Debug("Creating middleware")
|
logger.Debug("Creating middleware")
|
||||||
logger.Debugf("Setting up buffering: request limits: %d (mem), %d (max), response limits: %d (mem), %d (max) with retry: '%s'",
|
logger.Debugf("Setting up buffering: request limits: %d (mem), %d (max), response limits: %d (mem), %d (max) with retry: '%s'",
|
||||||
config.MemRequestBodyBytes, config.MaxRequestBodyBytes, config.MemResponseBodyBytes, config.MaxResponseBodyBytes, config.RetryExpression)
|
config.MemRequestBodyBytes, config.MaxRequestBodyBytes, config.MemResponseBodyBytes, config.MaxResponseBodyBytes, config.RetryExpression)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/containous/alice"
|
"github.com/containous/alice"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ type chainBuilder interface {
|
||||||
|
|
||||||
// New creates a chain middleware
|
// New creates a chain middleware
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.Chain, builder chainBuilder, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.Chain, builder chainBuilder, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
middlewareChain := builder.BuildChain(ctx, config.Middlewares)
|
middlewareChain := builder.BuildChain(ctx, config.Middlewares)
|
||||||
return middlewareChain.Then(next)
|
return middlewareChain.Then(next)
|
||||||
|
|
|
@ -25,7 +25,7 @@ type circuitBreaker struct {
|
||||||
func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.CircuitBreaker, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.CircuitBreaker, name string) (http.Handler, error) {
|
||||||
expression := confCircuitBreaker.Expression
|
expression := confCircuitBreaker.Expression
|
||||||
|
|
||||||
logger := middlewares.GetLogger(ctx, name, typeName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName))
|
||||||
logger.Debug("Creating middleware")
|
logger.Debug("Creating middleware")
|
||||||
logger.Debug("Setting up with expression: %s", expression)
|
logger.Debug("Setting up with expression: %s", expression)
|
||||||
|
|
||||||
|
@ -56,6 +56,5 @@ func (c *circuitBreaker) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *circuitBreaker) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (c *circuitBreaker) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
middlewares.GetLogger(req.Context(), c.name, typeName).Debug("Entering middleware")
|
|
||||||
c.circuitBreaker.ServeHTTP(rw, req)
|
c.circuitBreaker.ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/NYTimes/gziphandler"
|
"github.com/NYTimes/gziphandler"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -25,7 +25,7 @@ type compress struct {
|
||||||
|
|
||||||
// New creates a new compress middleware.
|
// New creates a new compress middleware.
|
||||||
func New(ctx context.Context, next http.Handler, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
return &compress{
|
return &compress{
|
||||||
next: next,
|
next: next,
|
||||||
|
@ -38,7 +38,8 @@ func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
if strings.HasPrefix(contentType, "application/grpc") {
|
if strings.HasPrefix(contentType, "application/grpc") {
|
||||||
c.next.ServeHTTP(rw, req)
|
c.next.ServeHTTP(rw, req)
|
||||||
} else {
|
} else {
|
||||||
gzipHandler(c.next, middlewares.GetLogger(req.Context(), c.name, typeName)).ServeHTTP(rw, req)
|
ctx := middlewares.GetLoggerCtx(req.Context(), c.name, typeName)
|
||||||
|
gzipHandler(ctx, c.next).ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,12 +47,12 @@ func (c *compress) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
return c.name, tracing.SpanKindNoneEnum
|
return c.name, tracing.SpanKindNoneEnum
|
||||||
}
|
}
|
||||||
|
|
||||||
func gzipHandler(h http.Handler, logger logrus.FieldLogger) http.Handler {
|
func gzipHandler(ctx context.Context, h http.Handler) http.Handler {
|
||||||
wrapper, err := gziphandler.GzipHandlerWithOpts(
|
wrapper, err := gziphandler.GzipHandlerWithOpts(
|
||||||
gziphandler.CompressionLevel(gzip.DefaultCompression),
|
gziphandler.CompressionLevel(gzip.DefaultCompression),
|
||||||
gziphandler.MinSize(gziphandler.DefaultMinSize))
|
gziphandler.MinSize(gziphandler.DefaultMinSize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err)
|
log.FromContext(ctx).Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper(h)
|
return wrapper(h)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/containous/traefik/v2/pkg/types"
|
"github.com/containous/traefik/v2/pkg/types"
|
||||||
|
@ -43,7 +44,7 @@ type customErrors struct {
|
||||||
|
|
||||||
// New creates a new custom error pages middleware.
|
// New creates a new custom error pages middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.ErrorPage, serviceBuilder serviceBuilder, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.ErrorPage, serviceBuilder serviceBuilder, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
httpCodeRanges, err := types.NewHTTPCodeRanges(config.Status)
|
httpCodeRanges, err := types.NewHTTPCodeRanges(config.Status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -69,7 +70,8 @@ func (c *customErrors) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
logger := middlewares.GetLogger(req.Context(), c.name, typeName)
|
ctx := middlewares.GetLoggerCtx(req.Context(), c.name, typeName)
|
||||||
|
logger := log.FromContext(ctx)
|
||||||
|
|
||||||
if c.backendHandler == nil {
|
if c.backendHandler == nil {
|
||||||
logger.Error("Error pages: no backend handler.")
|
logger.Error("Error pages: no backend handler.")
|
||||||
|
@ -78,7 +80,7 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder := newResponseRecorder(rw, middlewares.GetLogger(context.Background(), "test", typeName))
|
recorder := newResponseRecorder(ctx, rw)
|
||||||
c.next.ServeHTTP(recorder, req)
|
c.next.ServeHTTP(recorder, req)
|
||||||
|
|
||||||
// check the recorder code against the configured http status code ranges
|
// check the recorder code against the configured http status code ranges
|
||||||
|
@ -103,7 +105,7 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
recorderErrorPage := newResponseRecorder(rw, middlewares.GetLogger(context.Background(), "test", typeName))
|
recorderErrorPage := newResponseRecorder(ctx, rw)
|
||||||
utils.CopyHeaders(pageReq.Header, req.Header)
|
utils.CopyHeaders(pageReq.Header, req.Header)
|
||||||
|
|
||||||
c.backendHandler.ServeHTTP(recorderErrorPage, pageReq.WithContext(req.Context()))
|
c.backendHandler.ServeHTTP(recorderErrorPage, pageReq.WithContext(req.Context()))
|
||||||
|
@ -151,13 +153,13 @@ type responseRecorder interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newResponseRecorder returns an initialized responseRecorder.
|
// newResponseRecorder returns an initialized responseRecorder.
|
||||||
func newResponseRecorder(rw http.ResponseWriter, logger logrus.FieldLogger) responseRecorder {
|
func newResponseRecorder(ctx context.Context, rw http.ResponseWriter) responseRecorder {
|
||||||
recorder := &responseRecorderWithoutCloseNotify{
|
recorder := &responseRecorderWithoutCloseNotify{
|
||||||
HeaderMap: make(http.Header),
|
HeaderMap: make(http.Header),
|
||||||
Body: new(bytes.Buffer),
|
Body: new(bytes.Buffer),
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
responseWriter: rw,
|
responseWriter: rw,
|
||||||
logger: logger,
|
logger: log.FromContext(ctx),
|
||||||
}
|
}
|
||||||
if _, ok := rw.(http.CloseNotifier); ok {
|
if _, ok := rw.(http.CloseNotifier); ok {
|
||||||
return &responseRecorderWithCloseNotify{recorder}
|
return &responseRecorderWithCloseNotify{recorder}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
|
||||||
"github.com/containous/traefik/v2/pkg/testhelpers"
|
"github.com/containous/traefik/v2/pkg/testhelpers"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -151,7 +150,7 @@ func TestNewResponseRecorder(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
rec := newResponseRecorder(test.rw, middlewares.GetLogger(context.Background(), "test", typeName))
|
rec := newResponseRecorder(context.Background(), test.rw)
|
||||||
assert.IsType(t, rec, test.expected)
|
assert.IsType(t, rec, test.expected)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
@ -27,8 +28,9 @@ type headers struct {
|
||||||
// New creates a Headers middleware.
|
// New creates a Headers middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.Headers, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.Headers, name string) (http.Handler, error) {
|
||||||
// HeaderMiddleware -> SecureMiddleWare -> next
|
// HeaderMiddleware -> SecureMiddleWare -> next
|
||||||
logger := middlewares.GetLogger(ctx, name, typeName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName))
|
||||||
logger.Debug("Creating middleware")
|
logger.Debug("Creating middleware")
|
||||||
|
|
||||||
hasSecureHeaders := config.HasSecureHeadersDefined()
|
hasSecureHeaders := config.HasSecureHeadersDefined()
|
||||||
hasCustomHeaders := config.HasCustomHeadersDefined()
|
hasCustomHeaders := config.HasCustomHeadersDefined()
|
||||||
hasCorsHeaders := config.HasCorsHeadersDefined()
|
hasCorsHeaders := config.HasCorsHeadersDefined()
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/ip"
|
"github.com/containous/traefik/v2/pkg/ip"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -28,7 +28,7 @@ type ipWhiteLister struct {
|
||||||
|
|
||||||
// New builds a new IPWhiteLister given a list of CIDR-Strings to whitelist
|
// New builds a new IPWhiteLister given a list of CIDR-Strings to whitelist
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.IPWhiteList, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.IPWhiteList, name string) (http.Handler, error) {
|
||||||
logger := middlewares.GetLogger(ctx, name, typeName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName))
|
||||||
logger.Debug("Creating middleware")
|
logger.Debug("Creating middleware")
|
||||||
|
|
||||||
if len(config.SourceRange) == 0 {
|
if len(config.SourceRange) == 0 {
|
||||||
|
@ -46,6 +46,7 @@ func New(ctx context.Context, next http.Handler, config dynamic.IPWhiteList, nam
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debugf("Setting up IPWhiteLister with sourceRange: %s", config.SourceRange)
|
logger.Debugf("Setting up IPWhiteLister with sourceRange: %s", config.SourceRange)
|
||||||
|
|
||||||
return &ipWhiteLister{
|
return &ipWhiteLister{
|
||||||
strategy: strategy,
|
strategy: strategy,
|
||||||
whiteLister: checker,
|
whiteLister: checker,
|
||||||
|
@ -59,14 +60,15 @@ func (wl *ipWhiteLister) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wl *ipWhiteLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (wl *ipWhiteLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
logger := middlewares.GetLogger(req.Context(), wl.name, typeName)
|
ctx := middlewares.GetLoggerCtx(req.Context(), wl.name, typeName)
|
||||||
|
logger := log.FromContext(ctx)
|
||||||
|
|
||||||
err := wl.whiteLister.IsAuthorized(wl.strategy.GetIP(req))
|
err := wl.whiteLister.IsAuthorized(wl.strategy.GetIP(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logMessage := fmt.Sprintf("rejecting request %+v: %v", req, err)
|
logMessage := fmt.Sprintf("rejecting request %+v: %v", req, err)
|
||||||
logger.Debug(logMessage)
|
logger.Debug(logMessage)
|
||||||
tracing.SetErrorWithEvent(req, logMessage)
|
tracing.SetErrorWithEvent(req, logMessage)
|
||||||
reject(logger, rw)
|
reject(ctx, rw)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debugf("Accept %s: %+v", wl.strategy.GetIP(req), req)
|
logger.Debugf("Accept %s: %+v", wl.strategy.GetIP(req), req)
|
||||||
|
@ -74,12 +76,12 @@ func (wl *ipWhiteLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
wl.next.ServeHTTP(rw, req)
|
wl.next.ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reject(logger logrus.FieldLogger, rw http.ResponseWriter) {
|
func reject(ctx context.Context, rw http.ResponseWriter) {
|
||||||
statusCode := http.StatusForbidden
|
statusCode := http.StatusForbidden
|
||||||
|
|
||||||
rw.WriteHeader(statusCode)
|
rw.WriteHeader(statusCode)
|
||||||
_, err := rw.Write([]byte(http.StatusText(statusCode)))
|
_, err := rw.Write([]byte(http.StatusText(statusCode)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err)
|
log.FromContext(ctx).Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ type metricsMiddleware struct {
|
||||||
|
|
||||||
// NewEntryPointMiddleware creates a new metrics middleware for an Entrypoint.
|
// NewEntryPointMiddleware creates a new metrics middleware for an Entrypoint.
|
||||||
func NewEntryPointMiddleware(ctx context.Context, next http.Handler, registry metrics.Registry, entryPointName string) http.Handler {
|
func NewEntryPointMiddleware(ctx context.Context, next http.Handler, registry metrics.Registry, entryPointName string) http.Handler {
|
||||||
middlewares.GetLogger(ctx, nameEntrypoint, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, nameEntrypoint, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
return &metricsMiddleware{
|
return &metricsMiddleware{
|
||||||
next: next,
|
next: next,
|
||||||
|
@ -52,7 +52,7 @@ func NewEntryPointMiddleware(ctx context.Context, next http.Handler, registry me
|
||||||
|
|
||||||
// NewServiceMiddleware creates a new metrics middleware for a Service.
|
// NewServiceMiddleware creates a new metrics middleware for a Service.
|
||||||
func NewServiceMiddleware(ctx context.Context, next http.Handler, registry metrics.Registry, serviceName string) http.Handler {
|
func NewServiceMiddleware(ctx context.Context, next http.Handler, registry metrics.Registry, serviceName string) http.Handler {
|
||||||
middlewares.GetLogger(ctx, nameService, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, nameService, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
return &metricsMiddleware{
|
return &metricsMiddleware{
|
||||||
next: next,
|
next: next,
|
||||||
|
|
|
@ -4,10 +4,9 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetLogger creates a logger configured with the middleware fields.
|
// GetLoggerCtx creates a logger context with the middleware fields.
|
||||||
func GetLogger(ctx context.Context, middleware string, middlewareType string) logrus.FieldLogger {
|
func GetLoggerCtx(ctx context.Context, middleware string, middlewareType string) context.Context {
|
||||||
return log.FromContext(ctx).WithField(log.MiddlewareName, middleware).WithField(log.MiddlewareType, middlewareType)
|
return log.With(ctx, log.Str(log.MiddlewareName, middleware), log.Str(log.MiddlewareType, middlewareType))
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import (
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -66,7 +65,7 @@ type passTLSClientCert struct {
|
||||||
|
|
||||||
// New constructs a new PassTLSClientCert instance from supplied frontend header struct.
|
// New constructs a new PassTLSClientCert instance from supplied frontend header struct.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.PassTLSClientCert, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.PassTLSClientCert, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
return &passTLSClientCert{
|
return &passTLSClientCert{
|
||||||
next: next,
|
next: next,
|
||||||
|
@ -104,11 +103,13 @@ func (p *passTLSClientCert) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *passTLSClientCert) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (p *passTLSClientCert) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
logger := middlewares.GetLogger(req.Context(), p.name, typeName)
|
ctx := middlewares.GetLoggerCtx(req.Context(), p.name, typeName)
|
||||||
p.modifyRequestHeaders(logger, req)
|
|
||||||
|
p.modifyRequestHeaders(ctx, req)
|
||||||
p.next.ServeHTTP(rw, req)
|
p.next.ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
func getDNInfo(prefix string, options *DistinguishedNameOptions, cs *pkix.Name) string {
|
|
||||||
|
func getDNInfo(ctx context.Context, prefix string, options *DistinguishedNameOptions, cs *pkix.Name) string {
|
||||||
if options == nil {
|
if options == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -124,27 +125,27 @@ func getDNInfo(prefix string, options *DistinguishedNameOptions, cs *pkix.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.CountryName {
|
if options.CountryName {
|
||||||
writeParts(content, cs.Country, "C")
|
writeParts(ctx, content, cs.Country, "C")
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.StateOrProvinceName {
|
if options.StateOrProvinceName {
|
||||||
writeParts(content, cs.Province, "ST")
|
writeParts(ctx, content, cs.Province, "ST")
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.LocalityName {
|
if options.LocalityName {
|
||||||
writeParts(content, cs.Locality, "L")
|
writeParts(ctx, content, cs.Locality, "L")
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.OrganizationName {
|
if options.OrganizationName {
|
||||||
writeParts(content, cs.Organization, "O")
|
writeParts(ctx, content, cs.Organization, "O")
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.SerialNumber {
|
if options.SerialNumber {
|
||||||
writePart(content, cs.SerialNumber, "SN")
|
writePart(ctx, content, cs.SerialNumber, "SN")
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.CommonName {
|
if options.CommonName {
|
||||||
writePart(content, cs.CommonName, "CN")
|
writePart(ctx, content, cs.CommonName, "CN")
|
||||||
}
|
}
|
||||||
|
|
||||||
if content.Len() > 0 {
|
if content.Len() > 0 {
|
||||||
|
@ -154,24 +155,24 @@ func getDNInfo(prefix string, options *DistinguishedNameOptions, cs *pkix.Name)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeParts(content io.StringWriter, entries []string, prefix string) {
|
func writeParts(ctx context.Context, content io.StringWriter, entries []string, prefix string) {
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
writePart(content, entry, prefix)
|
writePart(ctx, content, entry, prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePart(content io.StringWriter, entry string, prefix string) {
|
func writePart(ctx context.Context, content io.StringWriter, entry string, prefix string) {
|
||||||
if len(entry) > 0 {
|
if len(entry) > 0 {
|
||||||
_, err := content.WriteString(fmt.Sprintf("%s=%s,", prefix, entry))
|
_, err := content.WriteString(fmt.Sprintf("%s=%s,", prefix, entry))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.FromContext(ctx).Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getXForwardedTLSClientCertInfo Build a string with the wanted client certificates information
|
// getXForwardedTLSClientCertInfo Build a string with the wanted client certificates information
|
||||||
// like Subject="C=%s,ST=%s,L=%s,O=%s,CN=%s",NB=%d,NA=%d,SAN=%s;
|
// like Subject="C=%s,ST=%s,L=%s,O=%s,CN=%s",NB=%d,NA=%d,SAN=%s;
|
||||||
func (p *passTLSClientCert) getXForwardedTLSClientCertInfo(certs []*x509.Certificate) string {
|
func (p *passTLSClientCert) getXForwardedTLSClientCertInfo(ctx context.Context, certs []*x509.Certificate) string {
|
||||||
var headerValues []string
|
var headerValues []string
|
||||||
|
|
||||||
for _, peerCert := range certs {
|
for _, peerCert := range certs {
|
||||||
|
@ -181,12 +182,12 @@ func (p *passTLSClientCert) getXForwardedTLSClientCertInfo(certs []*x509.Certifi
|
||||||
var na string
|
var na string
|
||||||
|
|
||||||
if p.info != nil {
|
if p.info != nil {
|
||||||
subject := getDNInfo("Subject", p.info.subject, &peerCert.Subject)
|
subject := getDNInfo(ctx, "Subject", p.info.subject, &peerCert.Subject)
|
||||||
if len(subject) > 0 {
|
if len(subject) > 0 {
|
||||||
values = append(values, subject)
|
values = append(values, subject)
|
||||||
}
|
}
|
||||||
|
|
||||||
issuer := getDNInfo("Issuer", p.info.issuer, &peerCert.Issuer)
|
issuer := getDNInfo(ctx, "Issuer", p.info.issuer, &peerCert.Issuer)
|
||||||
if len(issuer) > 0 {
|
if len(issuer) > 0 {
|
||||||
values = append(values, issuer)
|
values = append(values, issuer)
|
||||||
}
|
}
|
||||||
|
@ -217,10 +218,12 @@ func (p *passTLSClientCert) getXForwardedTLSClientCertInfo(certs []*x509.Certifi
|
||||||
}
|
}
|
||||||
|
|
||||||
// modifyRequestHeaders set the wanted headers with the certificates information.
|
// modifyRequestHeaders set the wanted headers with the certificates information.
|
||||||
func (p *passTLSClientCert) modifyRequestHeaders(logger logrus.FieldLogger, r *http.Request) {
|
func (p *passTLSClientCert) modifyRequestHeaders(ctx context.Context, r *http.Request) {
|
||||||
|
logger := log.FromContext(ctx)
|
||||||
|
|
||||||
if p.pem {
|
if p.pem {
|
||||||
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
|
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
|
||||||
r.Header.Set(xForwardedTLSClientCert, getXForwardedTLSClientCert(logger, r.TLS.PeerCertificates))
|
r.Header.Set(xForwardedTLSClientCert, getXForwardedTLSClientCert(ctx, r.TLS.PeerCertificates))
|
||||||
} else {
|
} else {
|
||||||
logger.Warn("Tried to extract a certificate on a request without mutual TLS")
|
logger.Warn("Tried to extract a certificate on a request without mutual TLS")
|
||||||
}
|
}
|
||||||
|
@ -228,7 +231,7 @@ func (p *passTLSClientCert) modifyRequestHeaders(logger logrus.FieldLogger, r *h
|
||||||
|
|
||||||
if p.info != nil {
|
if p.info != nil {
|
||||||
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
|
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
|
||||||
headerContent := p.getXForwardedTLSClientCertInfo(r.TLS.PeerCertificates)
|
headerContent := p.getXForwardedTLSClientCertInfo(ctx, r.TLS.PeerCertificates)
|
||||||
r.Header.Set(xForwardedTLSClientCertInfo, url.QueryEscape(headerContent))
|
r.Header.Set(xForwardedTLSClientCertInfo, url.QueryEscape(headerContent))
|
||||||
} else {
|
} else {
|
||||||
logger.Warn("Tried to extract a certificate on a request without mutual TLS")
|
logger.Warn("Tried to extract a certificate on a request without mutual TLS")
|
||||||
|
@ -248,22 +251,22 @@ func sanitize(cert []byte) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractCertificate extract the certificate from the request.
|
// extractCertificate extract the certificate from the request.
|
||||||
func extractCertificate(logger logrus.FieldLogger, cert *x509.Certificate) string {
|
func extractCertificate(ctx context.Context, cert *x509.Certificate) string {
|
||||||
b := pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}
|
b := pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}
|
||||||
certPEM := pem.EncodeToMemory(&b)
|
certPEM := pem.EncodeToMemory(&b)
|
||||||
if certPEM == nil {
|
if certPEM == nil {
|
||||||
logger.Error("Cannot extract the certificate content")
|
log.FromContext(ctx).Error("Cannot extract the certificate content")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return sanitize(certPEM)
|
return sanitize(certPEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getXForwardedTLSClientCert Build a string with the client certificates.
|
// getXForwardedTLSClientCert Build a string with the client certificates.
|
||||||
func getXForwardedTLSClientCert(logger logrus.FieldLogger, certs []*x509.Certificate) string {
|
func getXForwardedTLSClientCert(ctx context.Context, certs []*x509.Certificate) string {
|
||||||
var headerValues []string
|
var headerValues []string
|
||||||
|
|
||||||
for _, peerCert := range certs {
|
for _, peerCert := range certs {
|
||||||
headerValues = append(headerValues, extractCertificate(logger, peerCert))
|
headerValues = append(headerValues, extractCertificate(ctx, peerCert))
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.Join(headerValues, ",")
|
return strings.Join(headerValues, ",")
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ type pipelining struct {
|
||||||
|
|
||||||
// New returns a new pipelining instance
|
// New returns a new pipelining instance
|
||||||
func New(ctx context.Context, next http.Handler, name string) http.Handler {
|
func New(ctx context.Context, next http.Handler, name string) http.Handler {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
return &pipelining{
|
return &pipelining{
|
||||||
next: next,
|
next: next,
|
||||||
|
|
|
@ -90,7 +90,8 @@ func (rl *rateLimiter) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *rateLimiter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (rl *rateLimiter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
logger := middlewares.GetLogger(r.Context(), rl.name, typeName)
|
ctx := middlewares.GetLoggerCtx(r.Context(), rl.name, typeName)
|
||||||
|
logger := log.FromContext(ctx)
|
||||||
|
|
||||||
source, amount, err := rl.sourceMatcher.Extract(r)
|
source, amount, err := rl.sourceMatcher.Extract(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -127,7 +128,7 @@ func (rl *rateLimiter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
delay := res.Delay()
|
delay := res.Delay()
|
||||||
if delay > rl.maxDelay {
|
if delay > rl.maxDelay {
|
||||||
res.Cancel()
|
res.Cancel()
|
||||||
rl.serveDelayError(w, r, delay)
|
rl.serveDelayError(ctx, w, r, delay)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,12 +136,12 @@ func (rl *rateLimiter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
rl.next.ServeHTTP(w, r)
|
rl.next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *rateLimiter) serveDelayError(w http.ResponseWriter, r *http.Request, delay time.Duration) {
|
func (rl *rateLimiter) serveDelayError(ctx context.Context, w http.ResponseWriter, r *http.Request, delay time.Duration) {
|
||||||
w.Header().Set("Retry-After", fmt.Sprintf("%.0f", delay.Seconds()))
|
w.Header().Set("Retry-After", fmt.Sprintf("%.0f", delay.Seconds()))
|
||||||
w.Header().Set("X-Retry-In", delay.String())
|
w.Header().Set("X-Retry-In", delay.String())
|
||||||
w.WriteHeader(http.StatusTooManyRequests)
|
w.WriteHeader(http.StatusTooManyRequests)
|
||||||
|
|
||||||
if _, err := w.Write([]byte(http.StatusText(http.StatusTooManyRequests))); err != nil {
|
if _, err := w.Write([]byte(http.StatusText(http.StatusTooManyRequests))); err != nil {
|
||||||
middlewares.GetLogger(r.Context(), rl.name, typeName).Errorf("could not serve 429: %v", err)
|
log.FromContext(ctx).Errorf("could not serve 429: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,15 +127,16 @@ func TestRateLimit(t *testing.T) {
|
||||||
incomingLoad: 200,
|
incomingLoad: 200,
|
||||||
burst: 300,
|
burst: 300,
|
||||||
},
|
},
|
||||||
{
|
// TODO Try to disambiguate when it fails if it is because of too high a load.
|
||||||
desc: "Zero average ==> no rate limiting",
|
// {
|
||||||
config: dynamic.RateLimit{
|
// desc: "Zero average ==> no rate limiting",
|
||||||
Average: 0,
|
// config: dynamic.RateLimit{
|
||||||
Burst: 1,
|
// Average: 0,
|
||||||
},
|
// Burst: 1,
|
||||||
incomingLoad: 1000,
|
// },
|
||||||
loadDuration: time.Second,
|
// incomingLoad: 1000,
|
||||||
},
|
// loadDuration: time.Second,
|
||||||
|
// },
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -19,7 +19,7 @@ type recovery struct {
|
||||||
|
|
||||||
// New creates recovery middleware.
|
// New creates recovery middleware.
|
||||||
func New(ctx context.Context, next http.Handler, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
return &recovery{
|
return &recovery{
|
||||||
next: next,
|
next: next,
|
||||||
|
@ -28,13 +28,13 @@ func New(ctx context.Context, next http.Handler, name string) (http.Handler, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (re *recovery) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (re *recovery) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
defer recoverFunc(middlewares.GetLogger(req.Context(), re.name, typeName), rw)
|
defer recoverFunc(middlewares.GetLoggerCtx(req.Context(), re.name, typeName), rw)
|
||||||
re.next.ServeHTTP(rw, req)
|
re.next.ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func recoverFunc(logger logrus.FieldLogger, rw http.ResponseWriter) {
|
func recoverFunc(ctx context.Context, rw http.ResponseWriter) {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
logger.Errorf("Recovered from panic in http handler: %+v", err)
|
log.FromContext(ctx).Errorf("Recovered from panic in http handler: %+v", err)
|
||||||
http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package redirect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -25,7 +24,7 @@ type redirect struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a Redirect middleware.
|
// New creates a Redirect middleware.
|
||||||
func newRedirect(_ context.Context, next http.Handler, regex string, replacement string, permanent bool, name string) (http.Handler, error) {
|
func newRedirect(next http.Handler, regex string, replacement string, permanent bool, name string) (http.Handler, error) {
|
||||||
re, err := regexp.Compile(regex)
|
re, err := regexp.Compile(regex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,9 +15,9 @@ const (
|
||||||
|
|
||||||
// NewRedirectRegex creates a redirect middleware.
|
// NewRedirectRegex creates a redirect middleware.
|
||||||
func NewRedirectRegex(ctx context.Context, next http.Handler, conf dynamic.RedirectRegex, name string) (http.Handler, error) {
|
func NewRedirectRegex(ctx context.Context, next http.Handler, conf dynamic.RedirectRegex, name string) (http.Handler, error) {
|
||||||
logger := middlewares.GetLogger(ctx, name, typeRegexName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeRegexName))
|
||||||
logger.Debug("Creating middleware")
|
logger.Debug("Creating middleware")
|
||||||
logger.Debugf("Setting up redirection from %s to %s", conf.Regex, conf.Replacement)
|
logger.Debugf("Setting up redirection from %s to %s", conf.Regex, conf.Replacement)
|
||||||
|
|
||||||
return newRedirect(ctx, next, conf.Regex, conf.Replacement, conf.Permanent, name)
|
return newRedirect(next, conf.Regex, conf.Replacement, conf.Permanent, name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ const (
|
||||||
|
|
||||||
// NewRedirectScheme creates a new RedirectScheme middleware.
|
// NewRedirectScheme creates a new RedirectScheme middleware.
|
||||||
func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.RedirectScheme, name string) (http.Handler, error) {
|
func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.RedirectScheme, name string) (http.Handler, error) {
|
||||||
logger := middlewares.GetLogger(ctx, name, typeSchemeName)
|
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeSchemeName))
|
||||||
logger.Debug("Creating middleware")
|
logger.Debug("Creating middleware")
|
||||||
logger.Debugf("Setting up redirection to %s %s", conf.Scheme, conf.Port)
|
logger.Debugf("Setting up redirection to %s %s", conf.Scheme, conf.Port)
|
||||||
|
|
||||||
|
@ -29,5 +30,5 @@ func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.Redi
|
||||||
port = ":" + conf.Port
|
port = ":" + conf.Port
|
||||||
}
|
}
|
||||||
|
|
||||||
return newRedirect(ctx, next, schemeRedirectRegex, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, name)
|
return newRedirect(next, schemeRedirectRegex, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
@ -25,7 +26,7 @@ type replacePath struct {
|
||||||
|
|
||||||
// New creates a new replace path middleware.
|
// New creates a new replace path middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.ReplacePath, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.ReplacePath, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
return &replacePath{
|
return &replacePath{
|
||||||
next: next,
|
next: next,
|
||||||
|
@ -42,5 +43,6 @@ func (r *replacePath) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
req.Header.Add(ReplacedPathHeader, req.URL.Path)
|
req.Header.Add(ReplacedPathHeader, req.URL.Path)
|
||||||
req.URL.Path = r.path
|
req.URL.Path = r.path
|
||||||
req.RequestURI = req.URL.RequestURI()
|
req.RequestURI = req.URL.RequestURI()
|
||||||
|
|
||||||
r.next.ServeHTTP(rw, req)
|
r.next.ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares/replacepath"
|
"github.com/containous/traefik/v2/pkg/middlewares/replacepath"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
|
@ -28,7 +29,7 @@ type replacePathRegex struct {
|
||||||
|
|
||||||
// New creates a new replace path regex middleware.
|
// New creates a new replace path regex middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.ReplacePathRegex, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.ReplacePathRegex, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
exp, err := regexp.Compile(strings.TrimSpace(config.Regex))
|
exp, err := regexp.Compile(strings.TrimSpace(config.Regex))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"net/http/httptrace"
|
"net/http/httptrace"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
@ -43,8 +44,7 @@ type retry struct {
|
||||||
|
|
||||||
// New returns a new retry middleware.
|
// New returns a new retry middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.Retry, listener Listener, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.Retry, listener Listener, name string) (http.Handler, error) {
|
||||||
logger := middlewares.GetLogger(ctx, name, typeName)
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
logger.Debug("Creating middleware")
|
|
||||||
|
|
||||||
if config.Attempts <= 0 {
|
if config.Attempts <= 0 {
|
||||||
return nil, fmt.Errorf("incorrect (or empty) value for attempt (%d)", config.Attempts)
|
return nil, fmt.Errorf("incorrect (or empty) value for attempt (%d)", config.Attempts)
|
||||||
|
@ -94,8 +94,10 @@ func (r *retry) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
attempts++
|
attempts++
|
||||||
logger := middlewares.GetLogger(req.Context(), r.name, typeName)
|
|
||||||
logger.Debugf("New attempt %d for request: %v", attempts, req.URL)
|
log.FromContext(middlewares.GetLoggerCtx(req.Context(), r.name, typeName)).
|
||||||
|
Debugf("New attempt %d for request: %v", attempts, req.URL)
|
||||||
|
|
||||||
r.listener.Retried(req, attempts)
|
r.listener.Retried(req, attempts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
@ -26,7 +27,7 @@ type stripPrefix struct {
|
||||||
|
|
||||||
// New creates a new strip prefix middleware.
|
// New creates a new strip prefix middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.StripPrefix, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.StripPrefix, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
return &stripPrefix{
|
return &stripPrefix{
|
||||||
prefixes: config.Prefixes,
|
prefixes: config.Prefixes,
|
||||||
next: next,
|
next: next,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares/stripprefix"
|
"github.com/containous/traefik/v2/pkg/middlewares/stripprefix"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
|
@ -26,7 +27,7 @@ type stripPrefixRegex struct {
|
||||||
|
|
||||||
// New builds a new StripPrefixRegex middleware.
|
// New builds a new StripPrefixRegex middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.StripPrefixRegex, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.StripPrefixRegex, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
stripPrefix := stripPrefixRegex{
|
stripPrefix := stripPrefixRegex{
|
||||||
next: next,
|
next: next,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/containous/alice"
|
"github.com/containous/alice"
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go"
|
"github.com/opentracing/opentracing-go"
|
||||||
|
@ -17,7 +18,7 @@ const (
|
||||||
|
|
||||||
// NewEntryPoint creates a new middleware that the incoming request.
|
// NewEntryPoint creates a new middleware that the incoming request.
|
||||||
func NewEntryPoint(ctx context.Context, t *tracing.Tracing, entryPointName string, next http.Handler) http.Handler {
|
func NewEntryPoint(ctx context.Context, t *tracing.Tracing, entryPointName string, next http.Handler) http.Handler {
|
||||||
middlewares.GetLogger(ctx, "tracing", entryPointTypeName).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, "tracing", entryPointTypeName)).Debug("Creating middleware")
|
||||||
|
|
||||||
return &entryPointMiddleware{
|
return &entryPointMiddleware{
|
||||||
entryPoint: entryPointName,
|
entryPoint: entryPointName,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/middlewares"
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
@ -21,7 +22,7 @@ type forwarderMiddleware struct {
|
||||||
|
|
||||||
// NewForwarder creates a new forwarder middleware that traces the outgoing request.
|
// NewForwarder creates a new forwarder middleware that traces the outgoing request.
|
||||||
func NewForwarder(ctx context.Context, router, service string, next http.Handler) http.Handler {
|
func NewForwarder(ctx context.Context, router, service string, next http.Handler) http.Handler {
|
||||||
middlewares.GetLogger(ctx, "tracing", forwarderTypeName).
|
log.FromContext(middlewares.GetLoggerCtx(ctx, "tracing", forwarderTypeName)).
|
||||||
Debugf("Added outgoing tracing middleware %s", service)
|
Debugf("Added outgoing tracing middleware %s", service)
|
||||||
|
|
||||||
return &forwarderMiddleware{
|
return &forwarderMiddleware{
|
||||||
|
|
|
@ -350,17 +350,19 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
|
||||||
if route.TLS == nil || route.TLS.CertResolver != p.ResolverName {
|
if route.TLS == nil || route.TLS.CertResolver != p.ResolverName {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxRouter := log.With(ctx, log.Str(log.RouterName, routerName), log.Str(log.Rule, route.Rule))
|
ctxRouter := log.With(ctx, log.Str(log.RouterName, routerName), log.Str(log.Rule, route.Rule))
|
||||||
|
logger := log.FromContext(ctxRouter)
|
||||||
|
|
||||||
tlsStore := "default"
|
tlsStore := "default"
|
||||||
if len(route.TLS.Domains) > 0 {
|
if len(route.TLS.Domains) > 0 {
|
||||||
for _, domain := range route.TLS.Domains {
|
for _, domain := range route.TLS.Domains {
|
||||||
if domain.Main != dns01.UnFqdn(domain.Main) {
|
if domain.Main != dns01.UnFqdn(domain.Main) {
|
||||||
log.Warnf("FQDN detected, please remove the trailing dot: %s", domain.Main)
|
logger.Warnf("FQDN detected, please remove the trailing dot: %s", domain.Main)
|
||||||
}
|
}
|
||||||
for _, san := range domain.SANs {
|
for _, san := range domain.SANs {
|
||||||
if san != dns01.UnFqdn(san) {
|
if san != dns01.UnFqdn(san) {
|
||||||
log.Warnf("FQDN detected, please remove the trailing dot: %s", san)
|
logger.Warnf("FQDN detected, please remove the trailing dot: %s", san)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +380,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
|
||||||
} else {
|
} else {
|
||||||
domains, err := rules.ParseHostSNI(route.Rule)
|
domains, err := rules.ParseHostSNI(route.Rule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.FromContext(ctxRouter).Errorf("Error parsing domains in provider ACME: %v", err)
|
logger.Errorf("Error parsing domains in provider ACME: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
p.resolveDomains(ctxRouter, domains, tlsStore)
|
p.resolveDomains(ctxRouter, domains, tlsStore)
|
||||||
|
|
|
@ -78,14 +78,16 @@ func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, container d
|
||||||
|
|
||||||
if len(configuration.Services) == 0 {
|
if len(configuration.Services) == 0 {
|
||||||
configuration.Services = make(map[string]*dynamic.TCPService)
|
configuration.Services = make(map[string]*dynamic.TCPService)
|
||||||
lb := &dynamic.TCPLoadBalancerService{}
|
lb := &dynamic.TCPServersLoadBalancer{}
|
||||||
|
lb.SetDefaults()
|
||||||
configuration.Services[serviceName] = &dynamic.TCPService{
|
configuration.Services[serviceName] = &dynamic.TCPService{
|
||||||
LoadBalancer: lb,
|
LoadBalancer: lb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, service := range configuration.Services {
|
for name, service := range configuration.Services {
|
||||||
err := p.addServerTCP(ctx, container, service.LoadBalancer)
|
ctxSvc := log.With(ctx, log.Str(log.ServiceName, name))
|
||||||
|
err := p.addServerTCP(ctxSvc, container, service.LoadBalancer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -106,8 +108,9 @@ func (p *Provider) buildServiceConfiguration(ctx context.Context, container dock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, service := range configuration.Services {
|
for name, service := range configuration.Services {
|
||||||
err := p.addServer(ctx, container, service.LoadBalancer)
|
ctxSvc := log.With(ctx, log.Str(log.ServiceName, name))
|
||||||
|
err := p.addServer(ctxSvc, container, service.LoadBalancer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -142,7 +145,7 @@ func (p *Provider) keepContainer(ctx context.Context, container dockerData) bool
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) addServerTCP(ctx context.Context, container dockerData, loadBalancer *dynamic.TCPLoadBalancerService) error {
|
func (p *Provider) addServerTCP(ctx context.Context, container dockerData, loadBalancer *dynamic.TCPServersLoadBalancer) error {
|
||||||
serverPort := ""
|
serverPort := ""
|
||||||
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
|
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
|
||||||
serverPort = loadBalancer.Servers[0].Port
|
serverPort = loadBalancer.Servers[0].Port
|
||||||
|
|
|
@ -13,6 +13,8 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Int(v int) *int { return &v }
|
||||||
|
|
||||||
func TestDefaultRule(t *testing.T) {
|
func TestDefaultRule(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
@ -2086,12 +2088,13 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"Test": {
|
"Test": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:80",
|
Address: "127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TerminationDelay: Int(100),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2130,12 +2133,13 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
Routers: map[string]*dynamic.TCPRouter{},
|
Routers: map[string]*dynamic.TCPRouter{},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"Test": {
|
"Test": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:80",
|
Address: "127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TerminationDelay: Int(100),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2184,12 +2188,13 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"foo": {
|
"foo": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:8080",
|
Address: "127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TerminationDelay: Int(100),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2259,7 +2264,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"foo": {
|
"foo": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:8080",
|
Address: "127.0.0.1:8080",
|
||||||
|
@ -2268,6 +2273,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
Address: "127.0.0.2:8080",
|
Address: "127.0.0.2:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TerminationDelay: Int(100),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2325,12 +2331,59 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
Routers: map[string]*dynamic.TCPRouter{},
|
Routers: map[string]*dynamic.TCPRouter{},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"foo": {
|
"foo": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "127.0.0.1:8080",
|
Address: "127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TerminationDelay: Int(100),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.Router{},
|
||||||
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
|
Services: map[string]*dynamic.Service{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "tcp with label for tcp service, with termination delay",
|
||||||
|
containers: []dockerData{
|
||||||
|
{
|
||||||
|
ServiceName: "Test",
|
||||||
|
Name: "Test",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"traefik.tcp.services.foo.loadbalancer.server.port": "8080",
|
||||||
|
"traefik.tcp.services.foo.loadbalancer.terminationdelay": "200",
|
||||||
|
},
|
||||||
|
NetworkSettings: networkSettings{
|
||||||
|
Ports: nat.PortMap{
|
||||||
|
nat.Port("80/tcp"): []nat.PortBinding{},
|
||||||
|
},
|
||||||
|
Networks: map[string]*networkData{
|
||||||
|
"bridge": {
|
||||||
|
Name: "bridge",
|
||||||
|
Addr: "127.0.0.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: &dynamic.Configuration{
|
||||||
|
TCP: &dynamic.TCPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.TCPRouter{},
|
||||||
|
Services: map[string]*dynamic.TCPService{
|
||||||
|
"foo": {
|
||||||
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
|
Servers: []dynamic.TCPServer{
|
||||||
|
{
|
||||||
|
Address: "127.0.0.1:8080",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TerminationDelay: Int(200),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -85,7 +85,7 @@ func (p *Provider) BuildConfiguration() (*dynamic.Configuration, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p.Filename) > 0 {
|
if len(p.Filename) > 0 {
|
||||||
return p.loadFileConfig(p.Filename, true)
|
return p.loadFileConfig(ctx, p.Filename, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("error using file configuration provider, neither filename or directory defined")
|
return nil, errors.New("error using file configuration provider, neither filename or directory defined")
|
||||||
|
@ -156,11 +156,11 @@ func sendConfigToChannel(configurationChan chan<- dynamic.Message, configuration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) loadFileConfig(filename string, parseTemplate bool) (*dynamic.Configuration, error) {
|
func (p *Provider) loadFileConfig(ctx context.Context, filename string, parseTemplate bool) (*dynamic.Configuration, error) {
|
||||||
var err error
|
var err error
|
||||||
var configuration *dynamic.Configuration
|
var configuration *dynamic.Configuration
|
||||||
if parseTemplate {
|
if parseTemplate {
|
||||||
configuration, err = p.CreateConfiguration(filename, template.FuncMap{}, false)
|
configuration, err = p.CreateConfiguration(ctx, filename, template.FuncMap{}, false)
|
||||||
} else {
|
} else {
|
||||||
configuration, err = p.DecodeConfiguration(filename)
|
configuration, err = p.DecodeConfiguration(filename)
|
||||||
}
|
}
|
||||||
|
@ -169,25 +169,25 @@ func (p *Provider) loadFileConfig(filename string, parseTemplate bool) (*dynamic
|
||||||
}
|
}
|
||||||
|
|
||||||
if configuration.TLS != nil {
|
if configuration.TLS != nil {
|
||||||
configuration.TLS.Certificates = flattenCertificates(configuration.TLS)
|
configuration.TLS.Certificates = flattenCertificates(ctx, configuration.TLS)
|
||||||
}
|
}
|
||||||
|
|
||||||
return configuration, nil
|
return configuration, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func flattenCertificates(tlsConfig *dynamic.TLSConfiguration) []*tls.CertAndStores {
|
func flattenCertificates(ctx context.Context, tlsConfig *dynamic.TLSConfiguration) []*tls.CertAndStores {
|
||||||
var certs []*tls.CertAndStores
|
var certs []*tls.CertAndStores
|
||||||
for _, cert := range tlsConfig.Certificates {
|
for _, cert := range tlsConfig.Certificates {
|
||||||
content, err := cert.Certificate.CertFile.Read()
|
content, err := cert.Certificate.CertFile.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.FromContext(ctx).Error(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cert.Certificate.CertFile = tls.FileOrContent(string(content))
|
cert.Certificate.CertFile = tls.FileOrContent(string(content))
|
||||||
|
|
||||||
content, err = cert.Certificate.KeyFile.Read()
|
content, err = cert.Certificate.KeyFile.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.FromContext(ctx).Error(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cert.Certificate.KeyFile = tls.FileOrContent(string(content))
|
cert.Certificate.KeyFile = tls.FileOrContent(string(content))
|
||||||
|
@ -243,7 +243,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st
|
||||||
}
|
}
|
||||||
|
|
||||||
var c *dynamic.Configuration
|
var c *dynamic.Configuration
|
||||||
c, err = p.loadFileConfig(filepath.Join(directory, item.Name()), true)
|
c, err = p.loadFileConfig(ctx, filepath.Join(directory, item.Name()), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return configuration, err
|
return configuration, err
|
||||||
}
|
}
|
||||||
|
@ -331,7 +331,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateConfiguration creates a provider configuration from content using templating.
|
// CreateConfiguration creates a provider configuration from content using templating.
|
||||||
func (p *Provider) CreateConfiguration(filename string, funcMap template.FuncMap, templateObjects interface{}) (*dynamic.Configuration, error) {
|
func (p *Provider) CreateConfiguration(ctx context.Context, filename string, funcMap template.FuncMap, templateObjects interface{}) (*dynamic.Configuration, error) {
|
||||||
tmplContent, err := readFile(filename)
|
tmplContent, err := readFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading configuration file: %s - %s", filename, err)
|
return nil, fmt.Errorf("error reading configuration file: %s - %s", filename, err)
|
||||||
|
@ -359,7 +359,7 @@ func (p *Provider) CreateConfiguration(filename string, funcMap template.FuncMap
|
||||||
|
|
||||||
var renderedTemplate = buffer.String()
|
var renderedTemplate = buffer.String()
|
||||||
if p.DebugLogGeneratedTemplate {
|
if p.DebugLogGeneratedTemplate {
|
||||||
logger := log.WithoutContext().WithField(log.ProviderName, providerName)
|
logger := log.FromContext(ctx)
|
||||||
logger.Debugf("Template content: %s", tmplContent)
|
logger.Debugf("Template content: %s", tmplContent)
|
||||||
logger.Debugf("Rendering results: %s", renderedTemplate)
|
logger.Debugf("Rendering results: %s", renderedTemplate)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ func TestTLSContent(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
provider := &Provider{}
|
provider := &Provider{}
|
||||||
configuration, err := provider.loadFileConfig(fileConfig.Name(), true)
|
configuration, err := provider.loadFileConfig(context.Background(), fileConfig.Name(), true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, "CONTENT", configuration.TLS.Certificates[0].Certificate.CertFile.String())
|
require.Equal(t, "CONTENT", configuration.TLS.Certificates[0].Certificate.CertFile.String())
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: IngressRouteTCP
|
||||||
|
metadata:
|
||||||
|
name: test.route
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- foo
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- match: HostSNI(`foo.com`)
|
||||||
|
services:
|
||||||
|
- name: whoamitcp
|
||||||
|
port: 8000
|
||||||
|
terminationDelay: 500
|
|
@ -13,6 +13,7 @@ spec:
|
||||||
services:
|
services:
|
||||||
- name: whoamitcp
|
- name: whoamitcp
|
||||||
port: 8000
|
port: 8000
|
||||||
|
weight: 2
|
||||||
- name: whoamitcp2
|
- name: whoamitcp2
|
||||||
port: 8080
|
port: 8080
|
||||||
|
weight: 3
|
||||||
|
|
20
pkg/provider/kubernetes/crd/fixtures/with_options.yml
Normal file
20
pkg/provider/kubernetes/crd/fixtures/with_options.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: test.route
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- foo
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- match: Host(`foo.com`) && PathPrefix(`/bar`)
|
||||||
|
kind: Rule
|
||||||
|
priority: 12
|
||||||
|
services:
|
||||||
|
- name: whoami
|
||||||
|
port: 80
|
||||||
|
passHostHeader: false
|
||||||
|
responseForwarding:
|
||||||
|
flushInterval: 10s
|
|
@ -511,7 +511,7 @@ func makeID(namespace, name string) string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
return namespace + "/" + name
|
return namespace + "-" + name
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldProcessIngress(ingressClass string, ingressClassAnnotation string) bool {
|
func shouldProcessIngress(ingressClass string, ingressClassAnnotation string) bool {
|
||||||
|
|
|
@ -73,6 +73,8 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there is only one service defined, we skip the creation of the load balancer of services,
|
||||||
|
// i.e. the service on top is directly a load balancer of servers.
|
||||||
if len(route.Services) == 1 {
|
if len(route.Services) == 1 {
|
||||||
conf.Services[serviceName] = balancerServerHTTP
|
conf.Services[serviceName] = balancerServerHTTP
|
||||||
break
|
break
|
||||||
|
@ -157,12 +159,18 @@ func createLoadBalancerServerHTTP(client Client, namespace string, service v1alp
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &dynamic.Service{
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: servers,
|
|
||||||
// TODO: support other strategies.
|
// TODO: support other strategies.
|
||||||
PassHostHeader: true,
|
lb := &dynamic.ServersLoadBalancer{}
|
||||||
},
|
lb.SetDefaults()
|
||||||
|
|
||||||
|
lb.Servers = servers
|
||||||
|
if service.PassHostHeader != nil {
|
||||||
|
lb.PassHostHeader = *service.PassHostHeader
|
||||||
|
}
|
||||||
|
lb.ResponseForwarding = service.ResponseForwarding
|
||||||
|
|
||||||
|
return &dynamic.Service{
|
||||||
|
LoadBalancer: lb,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,16 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var allServers []dynamic.TCPServer
|
key, err := makeServiceKey(route.Match, ingressName)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceName := makeID(ingressRouteTCP.Namespace, key)
|
||||||
|
|
||||||
for _, service := range route.Services {
|
for _, service := range route.Services {
|
||||||
servers, err := loadTCPServers(client, ingressRouteTCP.Namespace, service)
|
balancerServerTCP, err := createLoadBalancerServerTCP(client, ingressRouteTCP.Namespace, service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.
|
logger.
|
||||||
WithField("serviceName", service.Name).
|
WithField("serviceName", service.Name).
|
||||||
|
@ -60,16 +67,28 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
allServers = append(allServers, servers...)
|
// If there is only one service defined, we skip the creation of the load balancer of services,
|
||||||
|
// i.e. the service on top is directly a load balancer of servers.
|
||||||
|
if len(route.Services) == 1 {
|
||||||
|
conf.Services[serviceName] = balancerServerTCP
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
key, e := makeServiceKey(route.Match, ingressName)
|
serviceKey := fmt.Sprintf("%s-%s-%d", serviceName, service.Name, service.Port)
|
||||||
if e != nil {
|
conf.Services[serviceKey] = balancerServerTCP
|
||||||
logger.Error(e)
|
|
||||||
continue
|
srv := dynamic.TCPWRRService{Name: serviceKey}
|
||||||
|
srv.SetDefaults()
|
||||||
|
if service.Weight != nil {
|
||||||
|
srv.Weight = service.Weight
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Services[serviceName] == nil {
|
||||||
|
conf.Services[serviceName] = &dynamic.TCPService{Weighted: &dynamic.TCPWeightedRoundRobin{}}
|
||||||
|
}
|
||||||
|
conf.Services[serviceName].Weighted.Services = append(conf.Services[serviceName].Weighted.Services, srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceName := makeID(ingressRouteTCP.Namespace, key)
|
|
||||||
conf.Routers[serviceName] = &dynamic.TCPRouter{
|
conf.Routers[serviceName] = &dynamic.TCPRouter{
|
||||||
EntryPoints: ingressRouteTCP.Spec.EntryPoints,
|
EntryPoints: ingressRouteTCP.Spec.EntryPoints,
|
||||||
Rule: route.Match,
|
Rule: route.Match,
|
||||||
|
@ -83,7 +102,10 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client
|
||||||
Domains: ingressRouteTCP.Spec.TLS.Domains,
|
Domains: ingressRouteTCP.Spec.TLS.Domains,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ingressRouteTCP.Spec.TLS.Options != nil && len(ingressRouteTCP.Spec.TLS.Options.Name) > 0 {
|
if ingressRouteTCP.Spec.TLS.Options == nil || len(ingressRouteTCP.Spec.TLS.Options.Name) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
tlsOptionsName := ingressRouteTCP.Spec.TLS.Options.Name
|
tlsOptionsName := ingressRouteTCP.Spec.TLS.Options.Name
|
||||||
// Is a Kubernetes CRD reference (i.e. not a cross-provider reference)
|
// Is a Kubernetes CRD reference (i.e. not a cross-provider reference)
|
||||||
ns := ingressRouteTCP.Spec.TLS.Options.Namespace
|
ns := ingressRouteTCP.Spec.TLS.Options.Namespace
|
||||||
|
@ -101,19 +123,32 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client
|
||||||
conf.Routers[serviceName].TLS.Options = tlsOptionsName
|
conf.Routers[serviceName].TLS.Options = tlsOptionsName
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
conf.Services[serviceName] = &dynamic.TCPService{
|
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
|
||||||
Servers: allServers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createLoadBalancerServerTCP(client Client, namespace string, service v1alpha1.ServiceTCP) (*dynamic.TCPService, error) {
|
||||||
|
servers, err := loadTCPServers(client, namespace, service)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tcpService := &dynamic.TCPService{
|
||||||
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
|
Servers: servers,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if service.TerminationDelay != nil {
|
||||||
|
tcpService.LoadBalancer.TerminationDelay = service.TerminationDelay
|
||||||
|
}
|
||||||
|
|
||||||
|
return tcpService, nil
|
||||||
|
}
|
||||||
|
|
||||||
func loadTCPServers(client Client, namespace string, svc v1alpha1.ServiceTCP) ([]dynamic.TCPServer, error) {
|
func loadTCPServers(client Client, namespace string, svc v1alpha1.ServiceTCP) ([]dynamic.TCPServer, error) {
|
||||||
service, exists, err := client.GetService(namespace, svc.Name)
|
service, exists, err := client.GetService(namespace, svc.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -47,15 +47,15 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
},
|
},
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -79,20 +79,20 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
},
|
},
|
||||||
"default/test.route-f44ce589164e656d231c": {
|
"default-test.route-f44ce589164e656d231c": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-f44ce589164e656d231c",
|
Service: "default-test.route-f44ce589164e656d231c",
|
||||||
Rule: "HostSNI(`bar.com`)",
|
Rule: "HostSNI(`bar.com`)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -105,8 +105,8 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default/test.route-f44ce589164e656d231c": {
|
"default-test.route-f44ce589164e656d231c": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -130,40 +130,57 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "One ingress Route with two different services, their servers will merge",
|
desc: "One ingress Route with two different services",
|
||||||
paths: []string{"tcp/services.yml", "tcp/with_two_services.yml"},
|
paths: []string{"tcp/services.yml", "tcp/with_two_services.yml"},
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
Weighted: &dynamic.TCPWeightedRoundRobin{
|
||||||
|
Services: []dynamic.TCPWRRService{
|
||||||
|
{
|
||||||
|
Name: "default-test.route-fdd3e9338e47a45efefc-whoamitcp-8000",
|
||||||
|
Weight: func(i int) *int { return &i }(2),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "default-test.route-fdd3e9338e47a45efefc-whoamitcp2-8080",
|
||||||
|
Weight: func(i int) *int { return &i }(3),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"default-test.route-fdd3e9338e47a45efefc-whoamitcp-8000": {
|
||||||
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
Port: "",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Address: "10.10.0.2:8000",
|
Address: "10.10.0.2:8000",
|
||||||
Port: "",
|
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"default-test.route-fdd3e9338e47a45efefc-whoamitcp2-8080": {
|
||||||
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.3:8080",
|
Address: "10.10.0.3:8080",
|
||||||
Port: "",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Address: "10.10.0.4:8080",
|
Address: "10.10.0.4:8080",
|
||||||
Port: "",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{},
|
Routers: map[string]*dynamic.Router{},
|
||||||
|
@ -238,16 +255,16 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
},
|
},
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
TLS: &dynamic.RouterTCPTLSConfig{},
|
TLS: &dynamic.RouterTCPTLSConfig{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -275,9 +292,9 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
TLS: &dynamic.RouterTCPTLSConfig{
|
TLS: &dynamic.RouterTCPTLSConfig{
|
||||||
Passthrough: true,
|
Passthrough: true,
|
||||||
|
@ -285,8 +302,8 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -315,7 +332,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
@ -334,18 +351,18 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
},
|
},
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
TLS: &dynamic.RouterTCPTLSConfig{
|
TLS: &dynamic.RouterTCPTLSConfig{
|
||||||
Options: "default/foo",
|
Options: "default-foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -373,7 +390,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"myns/foo": {
|
"myns-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
@ -392,18 +409,18 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
},
|
},
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
TLS: &dynamic.RouterTCPTLSConfig{
|
TLS: &dynamic.RouterTCPTLSConfig{
|
||||||
Options: "myns/foo",
|
Options: "myns-foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -431,7 +448,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
@ -449,18 +466,18 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
},
|
},
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
TLS: &dynamic.RouterTCPTLSConfig{
|
TLS: &dynamic.RouterTCPTLSConfig{
|
||||||
Options: "default/foo",
|
Options: "default-foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -488,25 +505,25 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
TLS: &dynamic.RouterTCPTLSConfig{
|
TLS: &dynamic.RouterTCPTLSConfig{
|
||||||
Options: "default/unknown",
|
Options: "default-unknown",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -534,25 +551,25 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
TLS: &dynamic.RouterTCPTLSConfig{
|
TLS: &dynamic.RouterTCPTLSConfig{
|
||||||
Options: "unknown/foo",
|
Options: "unknown-foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -580,16 +597,16 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-fdd3e9338e47a45efefc",
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
Rule: "HostSNI(`foo.com`)",
|
Rule: "HostSNI(`foo.com`)",
|
||||||
TLS: &dynamic.RouterTCPTLSConfig{},
|
TLS: &dynamic.RouterTCPTLSConfig{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default/test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -612,6 +629,44 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
TLS: &dynamic.TLSConfiguration{},
|
TLS: &dynamic.TLSConfiguration{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "TCP with terminationDelay",
|
||||||
|
paths: []string{"tcp/services.yml", "tcp/with_termination_delay.yml"},
|
||||||
|
expected: &dynamic.Configuration{
|
||||||
|
TLS: &dynamic.TLSConfiguration{},
|
||||||
|
TCP: &dynamic.TCPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.TCPRouter{
|
||||||
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
|
EntryPoints: []string{"foo"},
|
||||||
|
Service: "default-test.route-fdd3e9338e47a45efefc",
|
||||||
|
Rule: "HostSNI(`foo.com`)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Services: map[string]*dynamic.TCPService{
|
||||||
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
|
Servers: []dynamic.TCPServer{
|
||||||
|
{
|
||||||
|
Address: "10.10.0.1:8000",
|
||||||
|
Port: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: "10.10.0.2:8000",
|
||||||
|
Port: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TerminationDelay: Int(500),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.Router{},
|
||||||
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
|
Services: map[string]*dynamic.Service{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
@ -663,16 +718,16 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -700,28 +755,28 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test2.route-23c7f4c450289ee29016": {
|
"default-test2.route-23c7f4c450289ee29016": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test2.route-23c7f4c450289ee29016",
|
Service: "default-test2.route-23c7f4c450289ee29016",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/tobestripped`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/tobestripped`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
Middlewares: []string{"default/stripprefix", "foo/addprefix"},
|
Middlewares: []string{"default-stripprefix", "foo-addprefix"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{
|
Middlewares: map[string]*dynamic.Middleware{
|
||||||
"default/stripprefix": {
|
"default-stripprefix": {
|
||||||
StripPrefix: &dynamic.StripPrefix{
|
StripPrefix: &dynamic.StripPrefix{
|
||||||
Prefixes: []string{"/tobestripped"},
|
Prefixes: []string{"/tobestripped"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"foo/addprefix": {
|
"foo-addprefix": {
|
||||||
AddPrefix: &dynamic.AddPrefix{
|
AddPrefix: &dynamic.AddPrefix{
|
||||||
Prefix: "/tobeadded",
|
Prefix: "/tobeadded",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test2.route-23c7f4c450289ee29016": {
|
"default-test2.route-23c7f4c450289ee29016": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -750,28 +805,28 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test2.route-23c7f4c450289ee29016": {
|
"default-test2.route-23c7f4c450289ee29016": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test2.route-23c7f4c450289ee29016",
|
Service: "default-test2.route-23c7f4c450289ee29016",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/tobestripped`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/tobestripped`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
Middlewares: []string{"default/stripprefix", "foo/addprefix", "basicauth@file", "redirect@file"},
|
Middlewares: []string{"default-stripprefix", "foo-addprefix", "basicauth@file", "redirect@file"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{
|
Middlewares: map[string]*dynamic.Middleware{
|
||||||
"default/stripprefix": {
|
"default-stripprefix": {
|
||||||
StripPrefix: &dynamic.StripPrefix{
|
StripPrefix: &dynamic.StripPrefix{
|
||||||
Prefixes: []string{"/tobestripped"},
|
Prefixes: []string{"/tobestripped"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"foo/addprefix": {
|
"foo-addprefix": {
|
||||||
AddPrefix: &dynamic.AddPrefix{
|
AddPrefix: &dynamic.AddPrefix{
|
||||||
Prefix: "/tobeadded",
|
Prefix: "/tobeadded",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test2.route-23c7f4c450289ee29016": {
|
"default-test2.route-23c7f4c450289ee29016": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -798,22 +853,22 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Priority: 14,
|
Priority: 14,
|
||||||
},
|
},
|
||||||
"default/test.route-77c62dfe9517144aeeaa": {
|
"default-test.route-77c62dfe9517144aeeaa": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-77c62dfe9517144aeeaa",
|
Service: "default-test.route-77c62dfe9517144aeeaa",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/foo`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/foo`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -826,7 +881,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
PassHostHeader: true,
|
PassHostHeader: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default/test.route-77c62dfe9517144aeeaa": {
|
"default-test.route-77c62dfe9517144aeeaa": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -855,30 +910,30 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-77c62dfe9517144aeeaa": {
|
"default-test.route-77c62dfe9517144aeeaa": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-77c62dfe9517144aeeaa",
|
Service: "default-test.route-77c62dfe9517144aeeaa",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/foo`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/foo`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-77c62dfe9517144aeeaa": {
|
"default-test.route-77c62dfe9517144aeeaa": {
|
||||||
Weighted: &dynamic.WeightedRoundRobin{
|
Weighted: &dynamic.WeightedRoundRobin{
|
||||||
Services: []dynamic.WRRService{
|
Services: []dynamic.WRRService{
|
||||||
{
|
{
|
||||||
Name: "default/test.route-77c62dfe9517144aeeaa-whoami-80",
|
Name: "default-test.route-77c62dfe9517144aeeaa-whoami-80",
|
||||||
Weight: func(i int) *int { return &i }(1),
|
Weight: func(i int) *int { return &i }(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "default/test.route-77c62dfe9517144aeeaa-whoami2-8080",
|
Name: "default-test.route-77c62dfe9517144aeeaa-whoami2-8080",
|
||||||
Weight: func(i int) *int { return &i }(1),
|
Weight: func(i int) *int { return &i }(1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default/test.route-77c62dfe9517144aeeaa-whoami-80": {
|
"default-test.route-77c62dfe9517144aeeaa-whoami-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -891,7 +946,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
PassHostHeader: true,
|
PassHostHeader: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default/test.route-77c62dfe9517144aeeaa-whoami2-8080": {
|
"default-test.route-77c62dfe9517144aeeaa-whoami2-8080": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -919,30 +974,30 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-77c62dfe9517144aeeaa": {
|
"default-test.route-77c62dfe9517144aeeaa": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-77c62dfe9517144aeeaa",
|
Service: "default-test.route-77c62dfe9517144aeeaa",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/foo`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/foo`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-77c62dfe9517144aeeaa": {
|
"default-test.route-77c62dfe9517144aeeaa": {
|
||||||
Weighted: &dynamic.WeightedRoundRobin{
|
Weighted: &dynamic.WeightedRoundRobin{
|
||||||
Services: []dynamic.WRRService{
|
Services: []dynamic.WRRService{
|
||||||
{
|
{
|
||||||
Name: "default/test.route-77c62dfe9517144aeeaa-whoami-80",
|
Name: "default-test.route-77c62dfe9517144aeeaa-whoami-80",
|
||||||
Weight: Int(10),
|
Weight: Int(10),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "default/test.route-77c62dfe9517144aeeaa-whoami2-8080",
|
Name: "default-test.route-77c62dfe9517144aeeaa-whoami2-8080",
|
||||||
Weight: Int(0),
|
Weight: Int(0),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default/test.route-77c62dfe9517144aeeaa-whoami-80": {
|
"default-test.route-77c62dfe9517144aeeaa-whoami-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -955,7 +1010,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
PassHostHeader: true,
|
PassHostHeader: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default/test.route-77c62dfe9517144aeeaa-whoami2-8080": {
|
"default-test.route-77c62dfe9517144aeeaa-whoami2-8080": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1057,9 +1112,9 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
TLS: &dynamic.RouterTLSConfig{},
|
TLS: &dynamic.RouterTLSConfig{},
|
||||||
|
@ -1067,7 +1122,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1090,7 +1145,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
@ -1113,19 +1168,19 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
TLS: &dynamic.RouterTLSConfig{
|
TLS: &dynamic.RouterTLSConfig{
|
||||||
Options: "default/foo",
|
Options: "default-foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1148,7 +1203,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"myns/foo": {
|
"myns-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
@ -1171,19 +1226,19 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
TLS: &dynamic.RouterTLSConfig{
|
TLS: &dynamic.RouterTLSConfig{
|
||||||
Options: "myns/foo",
|
Options: "myns-foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1206,7 +1261,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
|
@ -1228,19 +1283,19 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
TLS: &dynamic.RouterTLSConfig{
|
TLS: &dynamic.RouterTLSConfig{
|
||||||
Options: "default/foo",
|
Options: "default-foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1263,7 +1318,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1274,19 +1329,19 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
TLS: &dynamic.RouterTLSConfig{
|
TLS: &dynamic.RouterTLSConfig{
|
||||||
Options: "default/unknown",
|
Options: "default-unknown",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1309,7 +1364,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
TLS: &dynamic.TLSConfiguration{
|
TLS: &dynamic.TLSConfiguration{
|
||||||
Options: map[string]tls.Options{
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default-foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1320,19 +1375,19 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
TLS: &dynamic.RouterTLSConfig{
|
TLS: &dynamic.RouterTLSConfig{
|
||||||
Options: "unknown/foo",
|
Options: "unknown-foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1360,9 +1415,9 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"web"},
|
EntryPoints: []string{"web"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
TLS: &dynamic.RouterTLSConfig{},
|
TLS: &dynamic.RouterTLSConfig{},
|
||||||
|
@ -1370,7 +1425,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1398,16 +1453,16 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1435,16 +1490,16 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{
|
Routers: map[string]*dynamic.Router{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
EntryPoints: []string{"foo"},
|
EntryPoints: []string{"foo"},
|
||||||
Service: "default/test.route-6b204d94623b3df4370c",
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/test.route-6b204d94623b3df4370c": {
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1473,17 +1528,17 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{},
|
Routers: map[string]*dynamic.Router{},
|
||||||
Middlewares: map[string]*dynamic.Middleware{
|
Middlewares: map[string]*dynamic.Middleware{
|
||||||
"default/basicauth": {
|
"default-basicauth": {
|
||||||
BasicAuth: &dynamic.BasicAuth{
|
BasicAuth: &dynamic.BasicAuth{
|
||||||
Users: dynamic.Users{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
Users: dynamic.Users{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default/digestauth": {
|
"default-digestauth": {
|
||||||
DigestAuth: &dynamic.DigestAuth{
|
DigestAuth: &dynamic.DigestAuth{
|
||||||
Users: dynamic.Users{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
Users: dynamic.Users{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"default/forwardauth": {
|
"default-forwardauth": {
|
||||||
ForwardAuth: &dynamic.ForwardAuth{
|
ForwardAuth: &dynamic.ForwardAuth{
|
||||||
Address: "test.com",
|
Address: "test.com",
|
||||||
TLS: &dynamic.ClientTLS{
|
TLS: &dynamic.ClientTLS{
|
||||||
|
@ -1510,16 +1565,16 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
Routers: map[string]*dynamic.Router{},
|
Routers: map[string]*dynamic.Router{},
|
||||||
Middlewares: map[string]*dynamic.Middleware{
|
Middlewares: map[string]*dynamic.Middleware{
|
||||||
"default/errorpage": {
|
"default-errorpage": {
|
||||||
Errors: &dynamic.ErrorPage{
|
Errors: &dynamic.ErrorPage{
|
||||||
Status: []string{"404", "500"},
|
Status: []string{"404", "500"},
|
||||||
Service: "default/errorpage-errorpage-service",
|
Service: "default-errorpage-errorpage-service",
|
||||||
Query: "query",
|
Query: "query",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default/errorpage-errorpage-service": {
|
"default-errorpage-errorpage-service": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -1536,6 +1591,44 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Simple Ingress Route, with options",
|
||||||
|
paths: []string{"services.yml", "with_options.yml"},
|
||||||
|
expected: &dynamic.Configuration{
|
||||||
|
TCP: &dynamic.TCPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.TCPRouter{},
|
||||||
|
Services: map[string]*dynamic.TCPService{},
|
||||||
|
},
|
||||||
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.Router{
|
||||||
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
|
EntryPoints: []string{"foo"},
|
||||||
|
Service: "default-test.route-6b204d94623b3df4370c",
|
||||||
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
|
Priority: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
|
Services: map[string]*dynamic.Service{
|
||||||
|
"default-test.route-6b204d94623b3df4370c": {
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
|
Servers: []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.1:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.2:80",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PassHostHeader: false,
|
||||||
|
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: "10s"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &dynamic.TLSConfiguration{},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "port selected by name (TODO)",
|
desc: "port selected by name (TODO)",
|
||||||
},
|
},
|
||||||
|
@ -1544,9 +1637,6 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
test := test
|
test := test
|
||||||
|
|
||||||
if test.desc != "Simple Ingress Route, with error page middleware" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/types"
|
"github.com/containous/traefik/v2/pkg/types"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
@ -51,6 +52,8 @@ type Service struct {
|
||||||
Scheme string `json:"scheme,omitempty"`
|
Scheme string `json:"scheme,omitempty"`
|
||||||
HealthCheck *HealthCheck `json:"healthCheck,omitempty"`
|
HealthCheck *HealthCheck `json:"healthCheck,omitempty"`
|
||||||
Strategy string `json:"strategy,omitempty"`
|
Strategy string `json:"strategy,omitempty"`
|
||||||
|
PassHostHeader *bool `json:"passHostHeader,omitempty"`
|
||||||
|
ResponseForwarding *dynamic.ResponseForwarding `json:"responseForwarding,omitempty"`
|
||||||
Weight *int `json:"weight,omitempty"`
|
Weight *int `json:"weight,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue