Merge branch v2.1 into master
This commit is contained in:
commit
aa21351d0d
76 changed files with 392 additions and 395 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -1,3 +1,24 @@
|
|||
## [v2.1.4](https://github.com/containous/traefik/tree/v2.1.4) (2020-02-06)
|
||||
[All Commits](https://github.com/containous/traefik/compare/v2.1.3...v2.1.4)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[acme,logs]** Improvement of the certificates resolvers logs ([#6225](https://github.com/containous/traefik/pull/6225) by [ldez](https://github.com/ldez))
|
||||
- **[acme]** Fix kubernetes providers shutdown and clean safe.Pool ([#6244](https://github.com/containous/traefik/pull/6244) by [juliens](https://github.com/juliens))
|
||||
- **[authentication,middleware]** don't create http client for each request in forwardAuth middleware ([#6267](https://github.com/containous/traefik/pull/6267) by [juliens](https://github.com/juliens))
|
||||
- **[k8s,k8s/ingress]** Allow wildcard hosts in ingress provider ([#6251](https://github.com/containous/traefik/pull/6251) by [dtomcej](https://github.com/dtomcej))
|
||||
- **[logs,tls]** Properly purge default certificate from stores before logging ([#6281](https://github.com/containous/traefik/pull/6281) by [dtomcej](https://github.com/dtomcej))
|
||||
- **[middleware]** use provider-qualified name when recursing for chain ([#6233](https://github.com/containous/traefik/pull/6233) by [mpl](https://github.com/mpl))
|
||||
|
||||
**Documentation:**
|
||||
- **[acme,cli]** Documentation fix for acme.md CLI ([#6262](https://github.com/containous/traefik/pull/6262) by [altano](https://github.com/altano))
|
||||
- **[acme,k8s/crd]** Add missing certResolver in IngressRoute examples. ([#6265](https://github.com/containous/traefik/pull/6265) by [ldez](https://github.com/ldez))
|
||||
- **[k8s]** fix a typo ([#6279](https://github.com/containous/traefik/pull/6279) by [silenceshell](https://github.com/silenceshell))
|
||||
- **[middleware]** Minor documentation tweaks. ([#6218](https://github.com/containous/traefik/pull/6218) by [stevegroom](https://github.com/stevegroom))
|
||||
- Correct a trivial spelling mistake in the documentation. ([#6269](https://github.com/containous/traefik/pull/6269) by [nepella](https://github.com/nepella))
|
||||
- Update install-traefik.md ([#6260](https://github.com/containous/traefik/pull/6260) by [bitfactory-sander-lissenburg](https://github.com/bitfactory-sander-lissenburg))
|
||||
- doc: use the same entry point name everywhere ([#6219](https://github.com/containous/traefik/pull/6219) by [ldez](https://github.com/ldez))
|
||||
- readme: update links to use HTTPS ([#6274](https://github.com/containous/traefik/pull/6274) by [imba-tjd](https://github.com/imba-tjd))
|
||||
|
||||
## [v2.1.3](https://github.com/containous/traefik/tree/v2.1.3) (2020-01-21)
|
||||
[All Commits](https://github.com/containous/traefik/compare/v2.1.2...v2.1.3)
|
||||
|
||||
|
|
22
README.md
22
README.md
|
@ -5,7 +5,7 @@
|
|||
|
||||
[![Build Status SemaphoreCI](https://semaphoreci.com/api/v1/containous/traefik/branches/master/shields_badge.svg)](https://semaphoreci.com/containous/traefik)
|
||||
[![Docs](https://img.shields.io/badge/docs-current-brightgreen.svg)](https://docs.traefik.io)
|
||||
[![Go Report Card](https://goreportcard.com/badge/containous/traefik)](http://goreportcard.com/report/containous/traefik)
|
||||
[![Go Report Card](https://goreportcard.com/badge/containous/traefik)](https://goreportcard.com/report/containous/traefik)
|
||||
[![](https://images.microbadger.com/badges/image/traefik.svg)](https://microbadger.com/images/traefik)
|
||||
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/containous/traefik/blob/master/LICENSE.md)
|
||||
[![Join the community support forum at https://community.containo.us/](https://img.shields.io/badge/style-register-green.svg?style=social&label=Discourse)](https://community.containo.us/)
|
||||
|
@ -89,7 +89,7 @@ You can access the simple HTML frontend of Traefik.
|
|||
|
||||
You can find the complete documentation of Traefik v2 at [https://docs.traefik.io](https://docs.traefik.io).
|
||||
|
||||
If you are using Traefik v1, you can find the complete documentation at [https://docs.traefik.io/v1.7/](https://docs.traefik.io/v1.7/)
|
||||
If you are using Traefik v1, you can find the complete documentation at [https://docs.traefik.io/v1.7/](https://docs.traefik.io/v1.7/).
|
||||
|
||||
A collection of contributions around Traefik can be found at [https://awesome.traefik.io](https://awesome.traefik.io).
|
||||
|
||||
|
@ -122,7 +122,7 @@ git clone https://github.com/containous/traefik
|
|||
|
||||
## Introductory Videos
|
||||
|
||||
You can find high level and deep dive videos on [videos.containo.us](https://videos.containo.us)
|
||||
You can find high level and deep dive videos on [videos.containo.us](https://videos.containo.us).
|
||||
|
||||
## Maintainers
|
||||
|
||||
|
@ -138,16 +138,16 @@ By participating in this project, you agree to abide by its terms.
|
|||
## Release Cycle
|
||||
|
||||
- We release a new version (e.g. 1.1.0, 1.2.0, 1.3.0) every other month.
|
||||
- Release Candidates are available before the release (e.g. 1.1.0-rc1, 1.1.0-rc2, 1.1.0-rc3, 1.1.0-rc4, before 1.1.0)
|
||||
- Bug-fixes (e.g. 1.1.1, 1.1.2, 1.2.1, 1.2.3) are released as needed (no additional features are delivered in those versions, bug-fixes only)
|
||||
- Release Candidates are available before the release (e.g. 1.1.0-rc1, 1.1.0-rc2, 1.1.0-rc3, 1.1.0-rc4, before 1.1.0).
|
||||
- Bug-fixes (e.g. 1.1.1, 1.1.2, 1.2.1, 1.2.3) are released as needed (no additional features are delivered in those versions, bug-fixes only).
|
||||
|
||||
Each version is supported until the next one is released (e.g. 1.1.x will be supported until 1.2.0 is out)
|
||||
Each version is supported until the next one is released (e.g. 1.1.x will be supported until 1.2.0 is out).
|
||||
|
||||
We use [Semantic Versioning](http://semver.org/)
|
||||
We use [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## Mailing lists
|
||||
## Mailing Lists
|
||||
|
||||
- General announcements, new releases: mail at news+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/news)
|
||||
- General announcements, new releases: mail at news+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/news).
|
||||
- Security announcements: mail at security+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/security).
|
||||
|
||||
## Credits
|
||||
|
@ -156,5 +156,5 @@ Kudos to [Peka](http://peka.byethost11.com/photoblog/) for his awesome work on t
|
|||
|
||||
Traefik's logo is licensed under the Creative Commons 3.0 Attributions license.
|
||||
|
||||
Traefik's logo was inspired by the gopher stickers made by Takuya Ueda (https://twitter.com/tenntenn).
|
||||
The original Go gopher was designed by Renee French (http://reneefrench.blogspot.com/).
|
||||
Traefik's logo was inspired by the gopher stickers made by [Takuya Ueda](https://twitter.com/tenntenn).
|
||||
The original Go gopher was designed by [Renee French](https://reneefrench.blogspot.com/).
|
||||
|
|
|
@ -267,14 +267,18 @@ func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.Pr
|
|||
}
|
||||
|
||||
if err := providerAggregator.AddProvider(p); err != nil {
|
||||
log.WithoutContext().Errorf("Unable to add ACME provider to the providers list: %v", err)
|
||||
log.WithoutContext().Errorf("The ACME resolver %q is skipped from the resolvers list because: %v", name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
p.SetTLSManager(tlsManager)
|
||||
|
||||
if p.TLSChallenge != nil {
|
||||
tlsManager.TLSAlpnGetter = p.GetTLSALPNCertificate
|
||||
}
|
||||
|
||||
p.SetConfigListenerChan(make(chan dynamic.Configuration))
|
||||
|
||||
resolvers = append(resolvers, p)
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 289 KiB After Width: | Height: | Size: 284 KiB |
|
@ -3,11 +3,11 @@
|
|||
A Quick Guide for Efficient Contributions
|
||||
{: .subtitle }
|
||||
|
||||
So you've decide to improve Traefik?
|
||||
So you've decided to improve Traefik?
|
||||
Thank You!
|
||||
Now the last step is to submit your Pull Request in a way that makes sure it gets the attention it deserves.
|
||||
|
||||
Let's go though the classic pitfalls to make sure everything is right.
|
||||
Let's go through the classic pitfalls to make sure everything is right.
|
||||
|
||||
## Title
|
||||
|
||||
|
@ -36,7 +36,7 @@ Help the readers focus on what matters, and help them understand the structure o
|
|||
- Add tests.
|
||||
- Address review comments in terms of additional commits (and don't amend/squash existing ones unless the PR is trivial).
|
||||
|
||||
!!! note "third-party dependencies"
|
||||
!!! note "Third-Party Dependencies"
|
||||
|
||||
If a PR involves changes to third-party dependencies, the commits pertaining to the vendor folder and the manifest/lock file(s) should be committed separated.
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ For more details, go to the [Docker provider documentation](../providers/docker.
|
|||
* Prefer a fixed version than the latest that could be an unexpected version.
|
||||
ex: `traefik:v2.0.0`
|
||||
* Docker images are based from the [Alpine Linux Official image](https://hub.docker.com/_/alpine).
|
||||
* All the orchestrator using docker images could fetch the official Traefik docker image.
|
||||
* Any orchestrator using docker images can fetch the official Traefik docker image.
|
||||
|
||||
## Use the Helm Chart
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ Please check the [configuration examples below](#configuration-examples) for mor
|
|||
[entryPoints.web]
|
||||
address = ":80"
|
||||
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
|
||||
[certificatesResolvers.le.acme]
|
||||
|
@ -72,7 +72,7 @@ Please check the [configuration examples below](#configuration-examples) for mor
|
|||
web:
|
||||
address: ":80"
|
||||
|
||||
web-secure:
|
||||
websecure:
|
||||
address: ":443"
|
||||
|
||||
certificatesResolvers:
|
||||
|
@ -196,7 +196,7 @@ when using the `HTTP-01` challenge, `certificatesResolvers.le.acme.httpChallenge
|
|||
[entryPoints.web]
|
||||
address = ":80"
|
||||
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
|
||||
[certificatesResolvers.le.acme]
|
||||
|
@ -210,7 +210,7 @@ when using the `HTTP-01` challenge, `certificatesResolvers.le.acme.httpChallenge
|
|||
web:
|
||||
address: ":80"
|
||||
|
||||
web-secure:
|
||||
websecure:
|
||||
address: ":443"
|
||||
|
||||
certificatesResolvers:
|
||||
|
@ -379,7 +379,7 @@ certificatesResolvers:
|
|||
|
||||
```bash tab="CLI"
|
||||
# ...
|
||||
--certificatesResolvers.le.acme.dnsChallenge.resolvers:=1.1.1.1:53,8.8.8.8:53
|
||||
--certificatesResolvers.le.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53
|
||||
```
|
||||
|
||||
#### Wildcard Domains
|
||||
|
|
|
@ -22,7 +22,6 @@ deploy:
|
|||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
|
|
|
@ -18,7 +18,6 @@ deploy:
|
|||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
|
@ -32,7 +31,8 @@ spec:
|
|||
services:
|
||||
- name: blog
|
||||
port: 8080
|
||||
tls: {}
|
||||
tls:
|
||||
certresolver: le
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
|
@ -58,7 +58,7 @@ labels:
|
|||
[http.routers.blog]
|
||||
rule = "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)"
|
||||
[http.routers.blog.tls]
|
||||
certResolver = "le" # From static configuration
|
||||
certResolver = "le"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
|
|
|
@ -18,7 +18,6 @@ deploy:
|
|||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
|
@ -32,7 +31,8 @@ spec:
|
|||
services:
|
||||
- name: blog
|
||||
port: 8080
|
||||
tls: {}
|
||||
tls:
|
||||
certresolver: le
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
|
@ -55,10 +55,10 @@ labels:
|
|||
```toml tab="Single Domain"
|
||||
## Dynamic configuration
|
||||
[http.routers]
|
||||
[http.routers.blog]
|
||||
rule = "Host(`company.com`) && Path(`/blog`)"
|
||||
[http.routers.blog.tls]
|
||||
certResolver = "le" # From static configuration
|
||||
[http.routers.blog]
|
||||
rule = "Host(`company.com`) && Path(`/blog`)"
|
||||
[http.routers.blog.tls]
|
||||
certResolver = "le"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
|
|
|
@ -20,4 +20,9 @@ Developing Traefik, our main goal is to make it simple to use, and we're sure yo
|
|||
|
||||
!!! info
|
||||
|
||||
If you're a business running critical services behind Traefik, know that [Containous](https://containo.us), the company that sponsors Traefik's development, can provide [commercial support](https://info.containo.us/commercial-services) and develops an [Enterprise Edition](https://containo.us/traefikee/) of Traefik.
|
||||
Join our user friendly and active [Community Forum](https://community.containo.us) to discuss, learn, and connect with the traefik community.
|
||||
|
||||
If you're a business running critical services behind Traefik,
|
||||
know that [Containous](https://containo.us), the company that sponsors Traefik's development,
|
||||
can provide [commercial support](https://info.containo.us/commercial-services)
|
||||
and develops an [Enterprise Edition](https://containo.us/traefikee/) of Traefik.
|
||||
|
|
|
@ -5,9 +5,9 @@ Tweaking the Request
|
|||
|
||||
![Overview](../assets/img/middleware/overview.png)
|
||||
|
||||
Attached to the routers, pieces of middleware are a mean of tweaking the requests before they are sent to your [service](../routing/services/index.md) (or before the answer from the services are sent to the clients).
|
||||
Attached to the routers, pieces of middleware are a means of tweaking the requests before they are sent to your [service](../routing/services/index.md) (or before the answer from the services are sent to the clients).
|
||||
|
||||
There are many different available middlewares in Traefik, some can modify the request, the headers, some are in charge of redirections, some add authentication, and so on.
|
||||
There are several available middleware in Traefik, some can modify the request, the headers, some are in charge of redirections, some add authentication, and so on.
|
||||
|
||||
Pieces of middleware can be combined in chains to fit every scenario.
|
||||
|
||||
|
@ -130,7 +130,7 @@ http:
|
|||
|
||||
## Provider Namespace
|
||||
|
||||
When you declare a middleware, it lives in its provider namespace.
|
||||
When you declare a middleware, it lives in its provider's namespace.
|
||||
For example, if you declare a middleware using a Docker label, under the hoods, it will reside in the docker provider namespace.
|
||||
|
||||
If you use multiple providers and wish to reference a middleware declared in another provider
|
||||
|
|
|
@ -190,17 +190,17 @@ TLS parameters used to be specified in the static configuration, as an entryPoin
|
|||
With Traefik v2, a new dynamic TLS section at the root contains all the desired TLS configurations.
|
||||
Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one of the [TLS configurations](../https/tls.md) defined at the root, hence defining the [TLS configuration](../https/tls.md) for that router.
|
||||
|
||||
!!! example "TLS on web-secure entryPoint becomes TLS option on Router-1"
|
||||
!!! example "TLS on websecure entryPoint becomes TLS option on Router-1"
|
||||
|
||||
!!! info "v1"
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# static configuration
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
|
||||
[entryPoints.web-secure.tls]
|
||||
[entryPoints.websecure.tls]
|
||||
minVersion = "VersionTLS12"
|
||||
cipherSuites = [
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
|
@ -210,13 +210,13 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o
|
|||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
]
|
||||
[[entryPoints.web-secure.tls.certificates]]
|
||||
[[entryPoints.websecure.tls.certificates]]
|
||||
certFile = "path/to/my.cert"
|
||||
keyFile = "path/to/my.key"
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--entryPoints='Name:web-secure Address::443 TLS:path/to/my.cert,path/to/my.key TLS.MinVersion:VersionTLS12 TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256'
|
||||
--entryPoints='Name:websecure Address::443 TLS:path/to/my.cert,path/to/my.key TLS.MinVersion:VersionTLS12 TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256'
|
||||
```
|
||||
|
||||
!!! info "v2"
|
||||
|
@ -818,32 +818,32 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo
|
|||
|
||||
```toml tab="File (TOML)"
|
||||
# static configuration
|
||||
defaultEntryPoints = ["web-secure","web"]
|
||||
defaultEntryPoints = ["websecure","web"]
|
||||
|
||||
[entryPoints.web]
|
||||
address = ":80"
|
||||
[entryPoints.web.redirect]
|
||||
entryPoint = "webs"
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
[entryPoints.https.tls]
|
||||
|
||||
[acme]
|
||||
email = "your-email-here@my-awesome-app.org"
|
||||
storage = "acme.json"
|
||||
entryPoint = "web-secure"
|
||||
entryPoint = "websecure"
|
||||
onHostRule = true
|
||||
[acme.httpChallenge]
|
||||
entryPoint = "web"
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--defaultentrypoints=web-secure,web
|
||||
--entryPoints=Name:web Address::80 Redirect.EntryPoint:web-secure
|
||||
--entryPoints=Name:web-secure Address::443 TLS
|
||||
--defaultentrypoints=websecure,web
|
||||
--entryPoints=Name:web Address::80 Redirect.EntryPoint:websecure
|
||||
--entryPoints=Name:websecure Address::443 TLS
|
||||
--acme.email=your-email-here@my-awesome-app.org
|
||||
--acme.storage=acme.json
|
||||
--acme.entryPoint=web-secure
|
||||
--acme.entryPoint=websecure
|
||||
--acme.onHostRule=true
|
||||
--acme.httpchallenge.entrypoint=http
|
||||
```
|
||||
|
@ -856,7 +856,7 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo
|
|||
[entryPoints.web]
|
||||
address = ":80"
|
||||
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
|
||||
[certificatesResolvers.sample.acme]
|
||||
|
@ -872,7 +872,7 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo
|
|||
web:
|
||||
address: ":80"
|
||||
|
||||
web-secure:
|
||||
websecure:
|
||||
address: ":443"
|
||||
|
||||
certificatesResolvers:
|
||||
|
@ -1069,7 +1069,7 @@ Each root item has been moved to a related section or removed.
|
|||
providersThrottleDuration = "2s"
|
||||
AllowMinWeightZero = true
|
||||
debug = true
|
||||
defaultEntryPoints = ["web", "web-secure"]
|
||||
defaultEntryPoints = ["web", "websecure"]
|
||||
keepTrailingSlash = false
|
||||
```
|
||||
|
||||
|
@ -1083,7 +1083,7 @@ Each root item has been moved to a related section or removed.
|
|||
--providersthrottleduration=2s
|
||||
--allowminweightzero=true
|
||||
--debug=true
|
||||
--defaultentrypoints=web,web-secure
|
||||
--defaultentrypoints=web,websecure
|
||||
--keeptrailingslash=true
|
||||
```
|
||||
|
||||
|
@ -1156,21 +1156,21 @@ As the dashboard access is now secured by default you can either:
|
|||
## static configuration
|
||||
# traefik.toml
|
||||
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
[entryPoints.web-secure.tls]
|
||||
[entryPoints.web-secure.auth]
|
||||
[entryPoints.web-secure.auth.basic]
|
||||
[entryPoints.websecure.tls]
|
||||
[entryPoints.websecure.auth]
|
||||
[entryPoints.websecure.auth.basic]
|
||||
users = [
|
||||
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
|
||||
]
|
||||
|
||||
[api]
|
||||
entryPoint = "web-secure"
|
||||
entryPoint = "websecure"
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--entryPoints='Name:web-secure Address::443 TLS Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/'
|
||||
--entryPoints='Name:websecure Address::443 TLS Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/'
|
||||
--api
|
||||
```
|
||||
|
||||
|
@ -1180,7 +1180,7 @@ As the dashboard access is now secured by default you can either:
|
|||
# dynamic configuration
|
||||
labels:
|
||||
- "traefik.http.routers.api.rule=Host(`traefik.docker.localhost`)"
|
||||
- "traefik.http.routers.api.entrypoints=web-secured"
|
||||
- "traefik.http.routers.api.entrypoints=websecured"
|
||||
- "traefik.http.routers.api.service=api@internal"
|
||||
- "traefik.http.routers.api.middlewares=myAuth"
|
||||
- "traefik.http.routers.api.tls"
|
||||
|
@ -1191,7 +1191,7 @@ As the dashboard access is now secured by default you can either:
|
|||
## static configuration
|
||||
# traefik.toml
|
||||
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
|
||||
[api]
|
||||
|
@ -1206,7 +1206,7 @@ As the dashboard access is now secured by default you can either:
|
|||
|
||||
[http.routers.api]
|
||||
rule = "Host(`traefik.docker.localhost`)"
|
||||
entrypoints = ["web-secure"]
|
||||
entrypoints = ["websecure"]
|
||||
service = "api@internal"
|
||||
middlewares = ["myAuth"]
|
||||
[http.routers.api.tls]
|
||||
|
@ -1222,7 +1222,7 @@ As the dashboard access is now secured by default you can either:
|
|||
# traefik.yaml
|
||||
|
||||
entryPoints:
|
||||
web-secure:
|
||||
websecure:
|
||||
address: ':443'
|
||||
|
||||
api: {}
|
||||
|
@ -1241,7 +1241,7 @@ As the dashboard access is now secured by default you can either:
|
|||
api:
|
||||
rule: Host(`traefik.docker.localhost`)
|
||||
entrypoints:
|
||||
- web-secure
|
||||
- websecure
|
||||
service: api@internal
|
||||
middlewares:
|
||||
- myAuth
|
||||
|
|
|
@ -60,7 +60,7 @@ If you require LetsEncrypt with HA in a kubernetes environment, we recommend usi
|
|||
If you are wanting to continue to run Traefik Community Edition, LetsEncrypt HA can be achieved by using a Certificate Controller such as [Cert-Manager](https://docs.cert-manager.io/en/latest/index.html).
|
||||
When using Cert-Manager to manage certificates, it will create secrets in your namespaces that can be referenced as TLS secrets in your [ingress objects](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls).
|
||||
When using the Traefik Kubernetes CRD Provider, unfortunately Cert-Manager cannot interface directly with the CRDs _yet_, but this is being worked on by our team.
|
||||
A workaround it to enable the [Kubernetes Ingress provider](./kubernetes-ingress.md) to allow Cert-Manager to create ingress objects to complete the challenges.
|
||||
A workaround is to enable the [Kubernetes Ingress provider](./kubernetes-ingress.md) to allow Cert-Manager to create ingress objects to complete the challenges.
|
||||
Please note that this still requires manual intervention to create the certificates through Cert-Manager, but once created, Cert-Manager will keep the certificate renewed.
|
||||
|
||||
## Provider Configuration
|
||||
|
|
|
@ -78,7 +78,7 @@ metadata:
|
|||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
- web-secure
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`foo.com`) && PathPrefix(`/bar`)
|
||||
kind: Rule
|
||||
|
|
|
@ -152,7 +152,7 @@ metadata:
|
|||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
- web-secure
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`foo.com`) && PathPrefix(`/bar`)
|
||||
kind: Rule
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = "{{ .PortHTTP }}"
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = "{{ .PortHTTPS }}"
|
||||
|
||||
{{range $name, $resolvers := .Acme }}
|
||||
|
@ -45,7 +45,7 @@
|
|||
|
||||
[http.routers]
|
||||
[http.routers.test]
|
||||
entryPoints = ["web-secure"]
|
||||
entryPoints = ["websecure"]
|
||||
rule = "Host(`traefik.acme.wtf`)"
|
||||
service = "test"
|
||||
[http.routers.test.tls]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = "{{ .PortHTTP }}"
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = "{{ .PortHTTPS }}"
|
||||
|
||||
{{range $name, $resolvers := .Acme }}
|
||||
|
@ -45,7 +45,7 @@
|
|||
|
||||
[http.routers]
|
||||
[http.routers.test]
|
||||
entryPoints = ["web-secure"]
|
||||
entryPoints = ["websecure"]
|
||||
rule = "PathPrefix(`/`)"
|
||||
service = "test"
|
||||
[http.routers.test.tls]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = "{{ .PortHTTP }}"
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = "{{ .PortHTTPS }}"
|
||||
|
||||
{{range $name, $resolvers := .Acme }}
|
||||
|
@ -45,14 +45,14 @@
|
|||
|
||||
[http.routers]
|
||||
[http.routers.test]
|
||||
entryPoints = ["web-secure"]
|
||||
entryPoints = ["websecure"]
|
||||
rule = "Host(`traefik.acme.wtf`)"
|
||||
service = "test"
|
||||
[http.routers.test.tls]
|
||||
certResolver = "default"
|
||||
|
||||
[http.routers.tchouk]
|
||||
entryPoints = ["web-secure"]
|
||||
entryPoints = ["websecure"]
|
||||
rule = "Host(`tchouk.acme.wtf`)"
|
||||
service = "test"
|
||||
[http.routers.tchouk.tls]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = "{{ .PortHTTP }}"
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = "{{ .PortHTTPS }}"
|
||||
|
||||
{{range $name, $resolvers := .Acme }}
|
||||
|
@ -45,7 +45,7 @@
|
|||
|
||||
[tcp.routers]
|
||||
[tcp.routers.test]
|
||||
entryPoints = ["web-secure"]
|
||||
entryPoints = ["websecure"]
|
||||
rule = "HostSNI(`traefik.acme.wtf`)"
|
||||
service = "test"
|
||||
[tcp.routers.test.tls]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = "{{ .PortHTTP }}"
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = "{{ .PortHTTPS }}"
|
||||
|
||||
{{range $name, $resolvers := .Acme }}
|
||||
|
@ -45,7 +45,7 @@
|
|||
|
||||
[http.routers]
|
||||
[http.routers.test]
|
||||
entryPoints = ["web-secure"]
|
||||
entryPoints = ["websecure"]
|
||||
rule = "Host(`traefik.acme.wtf`)"
|
||||
service = "test"
|
||||
[http.routers.test.tls]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = "{{ .PortHTTP }}"
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = "{{ .PortHTTPS }}"
|
||||
|
||||
{{range $name, $resolvers := .Acme }}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = "{{ .PortHTTP }}"
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = "{{ .PortHTTPS }}"
|
||||
|
||||
[entryPoints.traefik]
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
[http.routers]
|
||||
[http.routers.test]
|
||||
entryPoints = ["web-secure"]
|
||||
entryPoints = ["websecure"]
|
||||
rule = "Host(`traefik.acme.wtf`)"
|
||||
service = "test"
|
||||
[http.routers.test.tls]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
rootCAs = [ """{{ .CertContent }}""" ]
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
insecureSkipVerify = true
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
rootCAs = [ """{{ .CertContent }}""" ]
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[entryPoints.https02]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[entryPoints.web]
|
||||
address = ":8888"
|
||||
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":8443"
|
||||
|
||||
[api]
|
||||
|
@ -28,7 +28,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router1TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`example.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router1TLS.tls]
|
||||
|
@ -40,7 +40,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router2TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`example2.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router2TLS.tls]
|
||||
|
@ -52,7 +52,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router3TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`test.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router3TLS.tls]
|
||||
|
@ -64,7 +64,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router4TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`test2.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router4TLS.tls]
|
||||
|
@ -76,7 +76,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router5TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`foo.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router5TLS.tls]
|
||||
|
@ -88,7 +88,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router6TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`foo2.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router6TLS.tls]
|
||||
|
@ -100,7 +100,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router7TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`bar.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router7TLS.tls]
|
||||
|
@ -112,7 +112,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router8TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`bar2.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router8TLS.tls]
|
||||
|
@ -124,7 +124,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router9TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`pow.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router9TLS.tls]
|
||||
|
@ -136,7 +136,7 @@
|
|||
service = "service1"
|
||||
|
||||
[http.routers.router10TLS]
|
||||
entryPoints = [ "web-secure" ]
|
||||
entryPoints = [ "websecure" ]
|
||||
rule = "Host(`pow2.com`)"
|
||||
service = "service1"
|
||||
[http.routers.router10TLS.tls]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":4443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
rootCAs = [ """{{ .RootCertContent }}""" ]
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web-secure]
|
||||
[entryPoints.websecure]
|
||||
address = ":8443"
|
||||
|
||||
[api]
|
||||
|
|
|
@ -67,7 +67,7 @@ func TestHandler_EntryPoints(t *testing.T) {
|
|||
TrustedIPs: []string{"192.168.1.3", "192.168.1.4"},
|
||||
},
|
||||
},
|
||||
"web-secure": {
|
||||
"websecure": {
|
||||
Address: ":443",
|
||||
Transport: &static.EntryPointsTransport{
|
||||
LifeCycle: &static.LifeCycle{
|
||||
|
|
2
pkg/api/testdata/entrypoints.json
vendored
2
pkg/api/testdata/entrypoints.json
vendored
|
@ -37,7 +37,7 @@
|
|||
"192.168.1.40"
|
||||
]
|
||||
},
|
||||
"name": "web-secure",
|
||||
"name": "websecure",
|
||||
"proxyProtocol": {
|
||||
"insecure": true,
|
||||
"trustedIPs": [
|
||||
|
|
|
@ -2,12 +2,12 @@ package auth
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
|
@ -29,7 +29,7 @@ type forwardAuth struct {
|
|||
authResponseHeaders []string
|
||||
next http.Handler
|
||||
name string
|
||||
tlsConfig *tls.Config
|
||||
client http.Client
|
||||
trustForwardHeader bool
|
||||
}
|
||||
|
||||
|
@ -45,13 +45,23 @@ func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAu
|
|||
trustForwardHeader: config.TrustForwardHeader,
|
||||
}
|
||||
|
||||
// Ensure our request client does not follow redirects
|
||||
fa.client = http.Client{
|
||||
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
Timeout: 30 * time.Second,
|
||||
}
|
||||
|
||||
if config.TLS != nil {
|
||||
tlsConfig, err := config.TLS.CreateTLSConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fa.tlsConfig = tlsConfig
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = tlsConfig
|
||||
fa.client.Transport = tr
|
||||
}
|
||||
|
||||
return fa, nil
|
||||
|
@ -64,19 +74,6 @@ func (fa *forwardAuth) GetTracingInformation() (string, ext.SpanKindEnum) {
|
|||
func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), fa.name, forwardedTypeName))
|
||||
|
||||
// Ensure our request client does not follow redirects
|
||||
httpClient := http.Client{
|
||||
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
|
||||
if fa.tlsConfig != nil {
|
||||
httpClient.Transport = &http.Transport{
|
||||
TLSClientConfig: fa.tlsConfig,
|
||||
}
|
||||
}
|
||||
|
||||
forwardReq, err := http.NewRequest(http.MethodGet, fa.address, nil)
|
||||
tracing.LogRequest(tracing.GetSpan(req), forwardReq)
|
||||
if err != nil {
|
||||
|
@ -94,7 +91,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||
|
||||
writeHeader(req, forwardReq, fa.trustForwardHeader)
|
||||
|
||||
forwardResponse, forwardErr := httpClient.Do(forwardReq)
|
||||
forwardResponse, forwardErr := fa.client.Do(forwardReq)
|
||||
if forwardErr != nil {
|
||||
logMessage := fmt.Sprintf("Error calling %s. Cause: %s", fa.address, forwardErr)
|
||||
logger.Debug(logMessage)
|
||||
|
|
|
@ -179,12 +179,12 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
|||
p.renewCertificates(ctx)
|
||||
|
||||
ticker := time.NewTicker(24 * time.Hour)
|
||||
pool.Go(func(stop chan bool) {
|
||||
pool.GoCtx(func(ctxPool context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
p.renewCertificates(ctx)
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
ticker.Stop()
|
||||
return
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ func (p *Provider) resolveDomains(ctx context.Context, domains []string, tlsStor
|
|||
}
|
||||
|
||||
func (p *Provider) watchNewDomains(ctx context.Context) {
|
||||
p.pool.Go(func(stop chan bool) {
|
||||
p.pool.GoCtx(func(ctxPool context.Context) {
|
||||
for {
|
||||
select {
|
||||
case config := <-p.configFromListenerChan:
|
||||
|
@ -415,7 +415,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
|
|||
p.resolveDomains(ctxRouter, domains, tlsStore)
|
||||
}
|
||||
}
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +556,7 @@ func deleteUnnecessaryDomains(ctx context.Context, domains []types.Domain) []typ
|
|||
func (p *Provider) watchCertificate(ctx context.Context) {
|
||||
p.certsChan = make(chan *CertAndStore)
|
||||
|
||||
p.pool.Go(func(stop chan bool) {
|
||||
p.pool.GoCtx(func(ctxPool context.Context) {
|
||||
for {
|
||||
select {
|
||||
case cert := <-p.certsChan:
|
||||
|
@ -576,7 +576,7 @@ func (p *Provider) watchCertificate(ctx context.Context) {
|
|||
if err != nil {
|
||||
log.FromContext(ctx).Error(err)
|
||||
}
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,11 +103,11 @@ func (p *Provider) addWatcher(pool *safe.Pool, directory string, configurationCh
|
|||
}
|
||||
|
||||
// Process events
|
||||
pool.Go(func(stop chan bool) {
|
||||
pool.GoCtx(func(ctx context.Context) {
|
||||
defer watcher.Close()
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case evt := <-watcher.Events:
|
||||
if p.Directory == "" {
|
||||
|
|
|
@ -66,7 +66,7 @@ metadata:
|
|||
|
||||
spec:
|
||||
ports:
|
||||
- name: web-secure
|
||||
- name: websecure
|
||||
port: 443
|
||||
targetPort: 8443
|
||||
selector:
|
||||
|
@ -85,7 +85,7 @@ subsets:
|
|||
- ip: 10.10.0.5
|
||||
- ip: 10.10.0.6
|
||||
ports:
|
||||
- name: web-secure
|
||||
- name: websecure
|
||||
port: 8443
|
||||
|
||||
---
|
||||
|
@ -97,7 +97,7 @@ metadata:
|
|||
|
||||
spec:
|
||||
ports:
|
||||
- name: web-secure2
|
||||
- name: websecure2
|
||||
port: 8443
|
||||
scheme: https
|
||||
selector:
|
||||
|
@ -116,5 +116,5 @@ subsets:
|
|||
- ip: 10.10.0.7
|
||||
- ip: 10.10.0.8
|
||||
ports:
|
||||
- name: web-secure2
|
||||
- name: websecure2
|
||||
port: 8443
|
||||
|
|
|
@ -66,7 +66,7 @@ metadata:
|
|||
|
||||
spec:
|
||||
ports:
|
||||
- name: web-secure
|
||||
- name: websecure
|
||||
port: 443
|
||||
selector:
|
||||
app: containous
|
||||
|
@ -84,7 +84,7 @@ subsets:
|
|||
- ip: 10.10.0.5
|
||||
- ip: 10.10.0.6
|
||||
ports:
|
||||
- name: web-secure
|
||||
- name: websecure
|
||||
port: 443
|
||||
|
||||
---
|
||||
|
|
|
@ -98,11 +98,9 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
|||
return err
|
||||
}
|
||||
|
||||
pool.Go(func(stop chan bool) {
|
||||
pool.GoCtx(func(ctxPool context.Context) {
|
||||
operation := func() error {
|
||||
stopWatch := make(chan struct{}, 1)
|
||||
defer close(stopWatch)
|
||||
eventsChan, err := k8sClient.WatchAll(p.Namespaces, stopWatch)
|
||||
eventsChan, err := k8sClient.WatchAll(p.Namespaces, ctxPool.Done())
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("Error watching kubernetes events: %v", err)
|
||||
|
@ -110,20 +108,20 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
|||
select {
|
||||
case <-timer.C:
|
||||
return err
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
throttleDuration := time.Duration(p.ThrottleDuration)
|
||||
throttledChan := throttleEvents(ctxLog, throttleDuration, stop, eventsChan)
|
||||
throttledChan := throttleEvents(ctxLog, throttleDuration, pool, eventsChan)
|
||||
if throttledChan != nil {
|
||||
eventsChan = throttledChan
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return nil
|
||||
case event := <-eventsChan:
|
||||
// Note that event is the *first* event that came in during this throttling interval -- if we're hitting our throttle, we may have dropped events.
|
||||
|
@ -156,7 +154,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
|||
notify := func(err error, time time.Duration) {
|
||||
logger.Errorf("Provider connection error: %v; retrying in %s", err, time)
|
||||
}
|
||||
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
|
||||
err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxPool), notify)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot connect to Provider: %v", err)
|
||||
}
|
||||
|
@ -625,7 +623,7 @@ func getCABlocks(secret *corev1.Secret, namespace, secretName string) (string, e
|
|||
return cert, nil
|
||||
}
|
||||
|
||||
func throttleEvents(ctx context.Context, throttleDuration time.Duration, stop chan bool, eventsChan <-chan interface{}) chan interface{} {
|
||||
func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *safe.Pool, eventsChan <-chan interface{}) chan interface{} {
|
||||
if throttleDuration == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -635,10 +633,10 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, stop ch
|
|||
// Run a goroutine that reads events from eventChan and does a non-blocking write to pendingEvent.
|
||||
// This guarantees that writing to eventChan will never block,
|
||||
// and that pendingEvent will have something in it if there's been an event since we read from that channel.
|
||||
go func() {
|
||||
pool.GoCtx(func(ctxPool context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return
|
||||
case nextEvent := <-eventsChan:
|
||||
select {
|
||||
|
@ -650,7 +648,7 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, stop ch
|
|||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
|
||||
return eventsChanBuffered
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
kind: Endpoints
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: service1
|
||||
namespace: testing
|
||||
|
||||
subsets:
|
||||
- addresses:
|
||||
- ip: 10.10.0.1
|
||||
ports:
|
||||
- port: 8080
|
|
@ -0,0 +1,15 @@
|
|||
kind: Ingress
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: ""
|
||||
namespace: testing
|
||||
|
||||
spec:
|
||||
rules:
|
||||
- host: "*.foobar.com"
|
||||
http:
|
||||
paths:
|
||||
- path: /bar
|
||||
backend:
|
||||
serviceName: service1
|
||||
servicePort: 80
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: service1
|
||||
namespace: testing
|
||||
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
clusterIp: 10.0.0.1
|
|
@ -105,32 +105,29 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
|||
return err
|
||||
}
|
||||
|
||||
pool.Go(func(stop chan bool) {
|
||||
pool.GoCtx(func(ctxPool context.Context) {
|
||||
operation := func() error {
|
||||
stopWatch := make(chan struct{}, 1)
|
||||
defer close(stopWatch)
|
||||
|
||||
eventsChan, err := k8sClient.WatchAll(p.Namespaces, stopWatch)
|
||||
eventsChan, err := k8sClient.WatchAll(p.Namespaces, ctxPool.Done())
|
||||
if err != nil {
|
||||
logger.Errorf("Error watching kubernetes events: %v", err)
|
||||
timer := time.NewTimer(1 * time.Second)
|
||||
select {
|
||||
case <-timer.C:
|
||||
return err
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
throttleDuration := time.Duration(p.ThrottleDuration)
|
||||
throttledChan := throttleEvents(ctxLog, throttleDuration, stop, eventsChan)
|
||||
throttledChan := throttleEvents(ctxLog, throttleDuration, pool, eventsChan)
|
||||
if throttledChan != nil {
|
||||
eventsChan = throttledChan
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return nil
|
||||
case event := <-eventsChan:
|
||||
// Note that event is the *first* event that came in during this
|
||||
|
@ -165,7 +162,8 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
|||
notify := func(err error, time time.Duration) {
|
||||
logger.Errorf("Provider connection error: %s; retrying in %s", err, time)
|
||||
}
|
||||
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
|
||||
|
||||
err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxPool), notify)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot connect to Provider: %s", err)
|
||||
}
|
||||
|
@ -267,6 +265,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
|||
|
||||
serviceName := provider.Normalize(ingress.Namespace + "-" + pa.Backend.ServiceName + "-" + pa.Backend.ServicePort.String())
|
||||
conf.HTTP.Services[serviceName] = service
|
||||
conf.HTTP.Services[serviceName] = service
|
||||
|
||||
routerKey := strings.TrimPrefix(provider.Normalize(rule.Host+pa.Path), "-")
|
||||
conf.HTTP.Routers[routerKey] = loadRouter(ingress, rule, pa, rtConfig, serviceName)
|
||||
|
@ -323,6 +322,14 @@ func (p *Provider) updateIngressStatus(ing *v1beta1.Ingress, k8sClient Client) e
|
|||
return k8sClient.UpdateIngressStatus(ing, service.Status.LoadBalancer.Ingress[0].IP, service.Status.LoadBalancer.Ingress[0].Hostname)
|
||||
}
|
||||
|
||||
func buildHostRule(host string) string {
|
||||
if strings.HasPrefix(host, "*.") {
|
||||
return "HostRegexp(`" + strings.Replace(host, "*.", "{subdomain:[a-zA-Z0-9-]+}.", 1) + "`)"
|
||||
}
|
||||
|
||||
return "Host(`" + host + "`)"
|
||||
}
|
||||
|
||||
func shouldProcessIngress(ingressClass string, ingressClassAnnotation string) bool {
|
||||
return ingressClass == ingressClassAnnotation ||
|
||||
(len(ingressClass) == 0 && ingressClassAnnotation == traefikDefaultIngressClass)
|
||||
|
@ -522,7 +529,7 @@ func getProtocol(portSpec corev1.ServicePort, portName string, svcConfig *Servic
|
|||
func loadRouter(ingress *v1beta1.Ingress, rule v1beta1.IngressRule, pa v1beta1.HTTPIngressPath, rtConfig *RouterConfig, serviceName string) *dynamic.Router {
|
||||
var rules []string
|
||||
if len(rule.Host) > 0 {
|
||||
rules = []string{"Host(`" + rule.Host + "`)"}
|
||||
rules = []string{buildHostRule(rule.Host)}
|
||||
}
|
||||
|
||||
if len(pa.Path) > 0 {
|
||||
|
@ -562,7 +569,7 @@ func checkStringQuoteValidity(value string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func throttleEvents(ctx context.Context, throttleDuration time.Duration, stop chan bool, eventsChan <-chan interface{}) chan interface{} {
|
||||
func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *safe.Pool, eventsChan <-chan interface{}) chan interface{} {
|
||||
if throttleDuration == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -573,10 +580,10 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, stop ch
|
|||
// non-blocking write to pendingEvent. This guarantees that writing to
|
||||
// eventChan will never block, and that pendingEvent will have
|
||||
// something in it if there's been an event since we read from that channel.
|
||||
go func() {
|
||||
pool.GoCtx(func(ctxPool context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return
|
||||
case nextEvent := <-eventsChan:
|
||||
select {
|
||||
|
@ -590,7 +597,7 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, stop ch
|
|||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
|
||||
return eventsChanBuffered
|
||||
}
|
||||
|
|
|
@ -980,6 +980,35 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Ingress with wildcard host",
|
||||
expected: &dynamic.Configuration{
|
||||
TCP: &dynamic.TCPConfiguration{},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"foobar-com-bar": {
|
||||
Rule: "HostRegexp(`{subdomain:[a-zA-Z0-9-]+}.foobar.com`) && PathPrefix(`/bar`)",
|
||||
Service: "testing-service1-80",
|
||||
},
|
||||
},
|
||||
Services: map[string]*dynamic.Service{
|
||||
"testing-service1-80": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
PassHostHeader: Bool(true),
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://10.10.0.1:8080",
|
||||
Scheme: "",
|
||||
Port: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
|
|
@ -61,7 +61,6 @@ func (p *Provider) Init(storeType store.Backend, name string) error {
|
|||
// Provide allows the docker provider to provide configurations to traefik using the given configuration channel.
|
||||
func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
||||
ctx := log.With(context.Background(), log.Str(log.ProviderName, p.name))
|
||||
|
||||
logger := log.FromContext(ctx)
|
||||
|
||||
operation := func() error {
|
||||
|
@ -89,8 +88,10 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
|||
}
|
||||
}
|
||||
|
||||
pool.Go(func(stop chan bool) {
|
||||
err := p.watchKv(ctx, configurationChan, p.RootKey, stop)
|
||||
pool.GoCtx(func(ctxPool context.Context) {
|
||||
ctxLog := log.With(ctxPool, log.Str(log.ProviderName, p.name))
|
||||
|
||||
err := p.watchKv(ctxLog, configurationChan)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot watch KV store: %v", err)
|
||||
}
|
||||
|
@ -99,16 +100,16 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) watchKv(ctx context.Context, configurationChan chan<- dynamic.Message, prefix string, stop chan bool) error {
|
||||
func (p *Provider) watchKv(ctx context.Context, configurationChan chan<- dynamic.Message) error {
|
||||
operation := func() error {
|
||||
events, err := p.kvClient.WatchTree(p.RootKey, make(chan struct{}), nil)
|
||||
events, err := p.kvClient.WatchTree(p.RootKey, ctx.Done(), nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to watch KV: %w", err)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case _, ok := <-events:
|
||||
if !ok {
|
||||
|
@ -133,7 +134,9 @@ func (p *Provider) watchKv(ctx context.Context, configurationChan chan<- dynamic
|
|||
notify := func(err error, time time.Duration) {
|
||||
log.FromContext(ctx).Errorf("KV connection error: %+v, retrying in %s", err, time)
|
||||
}
|
||||
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
|
||||
|
||||
err := backoff.RetryNotify(safe.OperationWithRecover(operation),
|
||||
backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctx), notify)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot connect to KV server: %w", err)
|
||||
}
|
||||
|
|
|
@ -857,7 +857,7 @@ func TestKvWatchTree(t *testing.T) {
|
|||
|
||||
configChan := make(chan dynamic.Message)
|
||||
go func() {
|
||||
err := provider.watchKv(context.Background(), configChan, "prefix", make(chan bool, 1))
|
||||
err := provider.watchKv(context.Background(), configChan)
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
|
|
|
@ -159,11 +159,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
|
|||
logger.Errorf("Failed to register for events, %s", err)
|
||||
return err
|
||||
}
|
||||
pool.Go(func(stop chan bool) {
|
||||
pool.GoCtx(func(ctxPool context.Context) {
|
||||
defer close(update)
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return
|
||||
case event := <-update:
|
||||
logger.Debugf("Received provider event %s", event)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
)
|
||||
|
||||
// NewBuilder creates a builder.
|
||||
|
@ -22,21 +23,28 @@ func (f *Builder) Build(ctx context.Context, names []string) func(*http.Response
|
|||
var modifiers []func(*http.Response) error
|
||||
|
||||
for _, middleName := range names {
|
||||
if conf, ok := f.configs[middleName]; ok {
|
||||
if conf == nil || conf.Middleware == nil {
|
||||
getLogger(ctx, middleName, "undefined").Error("Invalid Middleware configuration (ResponseModifier)")
|
||||
continue
|
||||
}
|
||||
|
||||
if conf.Headers != nil {
|
||||
getLogger(ctx, middleName, "Headers").Debug("Creating Middleware (ResponseModifier)")
|
||||
|
||||
modifiers = append(modifiers, buildHeaders(conf.Headers))
|
||||
} else if conf.Chain != nil {
|
||||
getLogger(ctx, middleName, "Chain").Debug("Creating Middleware (ResponseModifier)")
|
||||
|
||||
modifiers = append(modifiers, f.Build(ctx, conf.Chain.Middlewares))
|
||||
conf, ok := f.configs[middleName]
|
||||
if !ok {
|
||||
getLogger(ctx, middleName, "undefined").Debug("Middleware name not found in config (ResponseModifier)")
|
||||
continue
|
||||
}
|
||||
if conf == nil || conf.Middleware == nil {
|
||||
getLogger(ctx, middleName, "undefined").Error("Invalid Middleware configuration (ResponseModifier)")
|
||||
continue
|
||||
}
|
||||
|
||||
if conf.Headers != nil {
|
||||
getLogger(ctx, middleName, "Headers").Debug("Creating Middleware (ResponseModifier)")
|
||||
|
||||
modifiers = append(modifiers, buildHeaders(conf.Headers))
|
||||
} else if conf.Chain != nil {
|
||||
chainCtx := provider.AddInContext(ctx, middleName)
|
||||
getLogger(chainCtx, middleName, "Chain").Debug("Creating Middleware (ResponseModifier)")
|
||||
var qualifiedNames []string
|
||||
for _, name := range conf.Chain.Middlewares {
|
||||
qualifiedNames = append(qualifiedNames, provider.GetQualifiedName(chainCtx, name))
|
||||
}
|
||||
modifiers = append(modifiers, f.Build(ctx, qualifiedNames))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,88 +10,37 @@ import (
|
|||
"github.com/containous/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
type routine struct {
|
||||
goroutine func(chan bool)
|
||||
stop chan bool
|
||||
}
|
||||
|
||||
type routineCtx func(ctx context.Context)
|
||||
|
||||
// Pool is a pool of go routines
|
||||
type Pool struct {
|
||||
routines []routine
|
||||
waitGroup sync.WaitGroup
|
||||
lock sync.Mutex
|
||||
baseCtx context.Context
|
||||
baseCancel context.CancelFunc
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
waitGroup sync.WaitGroup
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
// NewPool creates a Pool
|
||||
func NewPool(parentCtx context.Context) *Pool {
|
||||
baseCtx, baseCancel := context.WithCancel(parentCtx)
|
||||
ctx, cancel := context.WithCancel(baseCtx)
|
||||
ctx, cancel := context.WithCancel(parentCtx)
|
||||
return &Pool{
|
||||
baseCtx: baseCtx,
|
||||
baseCancel: baseCancel,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
// Ctx returns main context
|
||||
func (p *Pool) Ctx() context.Context {
|
||||
return p.baseCtx
|
||||
}
|
||||
|
||||
// GoCtx starts a recoverable goroutine with a context
|
||||
func (p *Pool) GoCtx(goroutine routineCtx) {
|
||||
p.lock.Lock()
|
||||
p.waitGroup.Add(1)
|
||||
Go(func() {
|
||||
defer p.waitGroup.Done()
|
||||
goroutine(p.ctx)
|
||||
})
|
||||
p.lock.Unlock()
|
||||
}
|
||||
|
||||
// Go starts a recoverable goroutine, and can be stopped with stop chan
|
||||
func (p *Pool) Go(goroutine func(stop chan bool)) {
|
||||
p.lock.Lock()
|
||||
newRoutine := routine{
|
||||
goroutine: goroutine,
|
||||
stop: make(chan bool, 1),
|
||||
}
|
||||
p.routines = append(p.routines, newRoutine)
|
||||
p.waitGroup.Add(1)
|
||||
Go(func() {
|
||||
defer p.waitGroup.Done()
|
||||
goroutine(newRoutine.stop)
|
||||
})
|
||||
p.lock.Unlock()
|
||||
}
|
||||
|
||||
// Stop stops all started routines, waiting for their termination
|
||||
func (p *Pool) Stop() {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
p.cancel()
|
||||
for _, routine := range p.routines {
|
||||
routine.stop <- true
|
||||
}
|
||||
p.waitGroup.Wait()
|
||||
for _, routine := range p.routines {
|
||||
close(routine.stop)
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup releases resources used by the pool, and should be called when the pool will no longer be used
|
||||
func (p *Pool) Cleanup() {
|
||||
p.Stop()
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
p.baseCancel()
|
||||
}
|
||||
|
||||
// Go starts a recoverable goroutine
|
||||
|
|
|
@ -18,12 +18,13 @@ func TestNewPoolContext(t *testing.T) {
|
|||
ctx := context.WithValue(context.Background(), testKey, "test")
|
||||
p := NewPool(ctx)
|
||||
|
||||
retCtx := p.Ctx()
|
||||
|
||||
retCtxVal, ok := retCtx.Value(testKey).(string)
|
||||
if !ok || retCtxVal != "test" {
|
||||
t.Errorf("Pool.Ctx() did not return a derived context, got %#v, expected context with test value", retCtx)
|
||||
}
|
||||
p.GoCtx(func(ctx context.Context) {
|
||||
retCtxVal, ok := ctx.Value(testKey).(string)
|
||||
if !ok || retCtxVal != "test" {
|
||||
t.Errorf("Pool.Ctx() did not return a derived context, got %#v, expected context with test value", ctx)
|
||||
}
|
||||
})
|
||||
p.Stop()
|
||||
}
|
||||
|
||||
type fakeRoutine struct {
|
||||
|
@ -46,14 +47,6 @@ func (tr *fakeRoutine) routineCtx(ctx context.Context) {
|
|||
<-ctx.Done()
|
||||
}
|
||||
|
||||
func (tr *fakeRoutine) routine(stop chan bool) {
|
||||
tr.Lock()
|
||||
tr.started = true
|
||||
tr.Unlock()
|
||||
tr.startSig <- true
|
||||
<-stop
|
||||
}
|
||||
|
||||
func TestPoolWithCtx(t *testing.T) {
|
||||
testRoutine := newFakeRoutine()
|
||||
|
||||
|
@ -79,12 +72,12 @@ func TestPoolWithCtx(t *testing.T) {
|
|||
defer timer.Stop()
|
||||
|
||||
test.fn(p)
|
||||
defer p.Cleanup()
|
||||
defer p.Stop()
|
||||
|
||||
testDone := make(chan bool, 1)
|
||||
go func() {
|
||||
<-testRoutine.startSig
|
||||
p.Cleanup()
|
||||
p.Stop()
|
||||
testDone <- true
|
||||
}()
|
||||
|
||||
|
@ -100,89 +93,30 @@ func TestPoolWithCtx(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPoolWithStopChan(t *testing.T) {
|
||||
testRoutine := newFakeRoutine()
|
||||
|
||||
func TestPoolCleanupWithGoPanicking(t *testing.T) {
|
||||
p := NewPool(context.Background())
|
||||
|
||||
timer := time.NewTimer(500 * time.Millisecond)
|
||||
defer timer.Stop()
|
||||
|
||||
p.Go(testRoutine.routine)
|
||||
if len(p.routines) != 1 {
|
||||
t.Fatalf("After Pool.Go(func), Pool did have %d goroutines, expected 1", len(p.routines))
|
||||
}
|
||||
p.GoCtx(func(ctx context.Context) {
|
||||
panic("BOOM")
|
||||
})
|
||||
|
||||
testDone := make(chan bool, 1)
|
||||
go func() {
|
||||
<-testRoutine.startSig
|
||||
p.Cleanup()
|
||||
p.Stop()
|
||||
testDone <- true
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-timer.C:
|
||||
testRoutine.Lock()
|
||||
defer testRoutine.Unlock()
|
||||
t.Fatalf("Pool test did not complete in time, goroutine started equals '%t'", testRoutine.started)
|
||||
t.Fatalf("Pool.Cleanup() did not complete in time with a panicking goroutine")
|
||||
case <-testDone:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolCleanupWithGoPanicking(t *testing.T) {
|
||||
testRoutine := func(stop chan bool) {
|
||||
panic("BOOM")
|
||||
}
|
||||
|
||||
testCtxRoutine := func(ctx context.Context) {
|
||||
panic("BOOM")
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
fn func(*Pool)
|
||||
}{
|
||||
{
|
||||
desc: "Go()",
|
||||
fn: func(p *Pool) {
|
||||
p.Go(testRoutine)
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "GoCtx()",
|
||||
fn: func(p *Pool) {
|
||||
p.GoCtx(testCtxRoutine)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
p := NewPool(context.Background())
|
||||
|
||||
timer := time.NewTimer(500 * time.Millisecond)
|
||||
defer timer.Stop()
|
||||
|
||||
test.fn(p)
|
||||
|
||||
testDone := make(chan bool, 1)
|
||||
go func() {
|
||||
p.Cleanup()
|
||||
testDone <- true
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-timer.C:
|
||||
t.Fatalf("Pool.Cleanup() did not complete in time with a panicking goroutine")
|
||||
case <-testDone:
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoroutineRecover(t *testing.T) {
|
||||
// if recover fails the test will panic
|
||||
Go(func() {
|
||||
|
|
|
@ -3,7 +3,7 @@ package server
|
|||
import (
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
"github.com/containous/traefik/v2/pkg/server/internal"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
"github.com/containous/traefik/v2/pkg/tls"
|
||||
)
|
||||
|
||||
|
@ -25,25 +25,25 @@ func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configura
|
|||
}
|
||||
|
||||
var defaultTLSOptionProviders []string
|
||||
for provider, configuration := range configurations {
|
||||
for pvd, configuration := range configurations {
|
||||
if configuration.HTTP != nil {
|
||||
for routerName, router := range configuration.HTTP.Routers {
|
||||
conf.HTTP.Routers[internal.MakeQualifiedName(provider, routerName)] = router
|
||||
conf.HTTP.Routers[provider.MakeQualifiedName(pvd, routerName)] = router
|
||||
}
|
||||
for middlewareName, middleware := range configuration.HTTP.Middlewares {
|
||||
conf.HTTP.Middlewares[internal.MakeQualifiedName(provider, middlewareName)] = middleware
|
||||
conf.HTTP.Middlewares[provider.MakeQualifiedName(pvd, middlewareName)] = middleware
|
||||
}
|
||||
for serviceName, service := range configuration.HTTP.Services {
|
||||
conf.HTTP.Services[internal.MakeQualifiedName(provider, serviceName)] = service
|
||||
conf.HTTP.Services[provider.MakeQualifiedName(pvd, serviceName)] = service
|
||||
}
|
||||
}
|
||||
|
||||
if configuration.TCP != nil {
|
||||
for routerName, router := range configuration.TCP.Routers {
|
||||
conf.TCP.Routers[internal.MakeQualifiedName(provider, routerName)] = router
|
||||
conf.TCP.Routers[provider.MakeQualifiedName(pvd, routerName)] = router
|
||||
}
|
||||
for serviceName, service := range configuration.TCP.Services {
|
||||
conf.TCP.Services[internal.MakeQualifiedName(provider, serviceName)] = service
|
||||
conf.TCP.Services[provider.MakeQualifiedName(pvd, serviceName)] = service
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,9 +56,9 @@ func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configura
|
|||
|
||||
for tlsOptionsName, options := range configuration.TLS.Options {
|
||||
if tlsOptionsName != "default" {
|
||||
tlsOptionsName = internal.MakeQualifiedName(provider, tlsOptionsName)
|
||||
tlsOptionsName = provider.MakeQualifiedName(pvd, tlsOptionsName)
|
||||
} else {
|
||||
defaultTLSOptionProviders = append(defaultTLSOptionProviders, provider)
|
||||
defaultTLSOptionProviders = append(defaultTLSOptionProviders, pvd)
|
||||
}
|
||||
|
||||
conf.TLS.Options[tlsOptionsName] = options
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"time"
|
||||
|
@ -49,8 +50,8 @@ func NewConfigurationWatcher(routinesPool *safe.Pool, pvd provider.Provider, pro
|
|||
|
||||
// Start the configuration watcher.
|
||||
func (c *ConfigurationWatcher) Start() {
|
||||
c.routinesPool.Go(c.listenProviders)
|
||||
c.routinesPool.Go(c.listenConfigurations)
|
||||
c.routinesPool.GoCtx(c.listenProviders)
|
||||
c.routinesPool.GoCtx(c.listenConfigurations)
|
||||
c.startProvider()
|
||||
}
|
||||
|
||||
|
@ -90,10 +91,10 @@ func (c *ConfigurationWatcher) startProvider() {
|
|||
// listenProviders receives configuration changes from the providers.
|
||||
// The configuration message then gets passed along a series of check
|
||||
// to finally end up in a throttler that sends it to listenConfigurations (through c. configurationValidatedChan).
|
||||
func (c *ConfigurationWatcher) listenProviders(stop chan bool) {
|
||||
func (c *ConfigurationWatcher) listenProviders(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case configMsg, ok := <-c.configurationChan:
|
||||
if !ok {
|
||||
|
@ -111,10 +112,10 @@ func (c *ConfigurationWatcher) listenProviders(stop chan bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *ConfigurationWatcher) listenConfigurations(stop chan bool) {
|
||||
func (c *ConfigurationWatcher) listenConfigurations(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case configMsg, ok := <-c.configurationValidatedChan:
|
||||
if !ok || configMsg.Configuration == nil {
|
||||
|
@ -150,8 +151,10 @@ func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
|
|||
if copyConf.TLS != nil {
|
||||
copyConf.TLS.Certificates = nil
|
||||
|
||||
for _, v := range copyConf.TLS.Stores {
|
||||
v.DefaultCertificate = nil
|
||||
for k := range copyConf.TLS.Stores {
|
||||
st := copyConf.TLS.Stores[k]
|
||||
st.DefaultCertificate = nil
|
||||
copyConf.TLS.Stores[k] = st
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,8 +181,8 @@ func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
|
|||
if !ok {
|
||||
providerConfigUpdateCh = make(chan dynamic.Message)
|
||||
c.providerConfigUpdateMap[configMsg.ProviderName] = providerConfigUpdateCh
|
||||
c.routinesPool.Go(func(stop chan bool) {
|
||||
c.throttleProviderConfigReload(c.providersThrottleDuration, c.configurationValidatedChan, providerConfigUpdateCh, stop)
|
||||
c.routinesPool.GoCtx(func(ctxPool context.Context) {
|
||||
c.throttleProviderConfigReload(ctxPool, c.providersThrottleDuration, c.configurationValidatedChan, providerConfigUpdateCh)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -190,14 +193,14 @@ func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
|
|||
// It will immediately publish a new configuration and then only publish the next configuration after the throttle duration.
|
||||
// Note that in the case it receives N new configs in the timeframe of the throttle duration after publishing,
|
||||
// it will publish the last of the newly received configurations.
|
||||
func (c *ConfigurationWatcher) throttleProviderConfigReload(throttle time.Duration, publish chan<- dynamic.Message, in <-chan dynamic.Message, stop chan bool) {
|
||||
func (c *ConfigurationWatcher) throttleProviderConfigReload(ctx context.Context, throttle time.Duration, publish chan<- dynamic.Message, in <-chan dynamic.Message) {
|
||||
ring := channels.NewRingChannel(1)
|
||||
defer ring.Close()
|
||||
|
||||
c.routinesPool.Go(func(stop chan bool) {
|
||||
c.routinesPool.GoCtx(func(ctxPool context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctxPool.Done():
|
||||
return
|
||||
case nextConfig := <-ring.Out():
|
||||
if config, ok := nextConfig.(dynamic.Message); ok {
|
||||
|
@ -210,7 +213,7 @@ func (c *ConfigurationWatcher) throttleProviderConfigReload(throttle time.Durati
|
|||
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case nextConfig := <-in:
|
||||
ring.In() <- nextConfig
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
"github.com/containous/traefik/v2/pkg/middlewares/stripprefix"
|
||||
"github.com/containous/traefik/v2/pkg/middlewares/stripprefixregex"
|
||||
"github.com/containous/traefik/v2/pkg/middlewares/tracing"
|
||||
"github.com/containous/traefik/v2/pkg/server/internal"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
)
|
||||
|
||||
type middlewareStackType int
|
||||
|
@ -56,10 +56,10 @@ func NewBuilder(configs map[string]*runtime.MiddlewareInfo, serviceBuilder servi
|
|||
func (b *Builder) BuildChain(ctx context.Context, middlewares []string) *alice.Chain {
|
||||
chain := alice.New()
|
||||
for _, name := range middlewares {
|
||||
middlewareName := internal.GetQualifiedName(ctx, name)
|
||||
middlewareName := provider.GetQualifiedName(ctx, name)
|
||||
|
||||
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
|
||||
constructorContext := internal.AddProviderInContext(ctx, middlewareName)
|
||||
constructorContext := provider.AddInContext(ctx, middlewareName)
|
||||
if midInf, ok := b.configs[middlewareName]; !ok || midInf.Middleware == nil {
|
||||
return nil, fmt.Errorf("middleware %q does not exist", middlewareName)
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) (
|
|||
|
||||
var qualifiedNames []string
|
||||
for _, name := range config.Chain.Middlewares {
|
||||
qualifiedNames = append(qualifiedNames, internal.GetQualifiedName(ctx, name))
|
||||
qualifiedNames = append(qualifiedNames, provider.GetQualifiedName(ctx, name))
|
||||
}
|
||||
config.Chain.Middlewares = qualifiedNames
|
||||
middleware = func(next http.Handler) (http.Handler, error) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||
"github.com/containous/traefik/v2/pkg/server/internal"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -262,7 +262,7 @@ func TestBuilder_BuildChainWithContext(t *testing.T) {
|
|||
|
||||
ctx := context.Background()
|
||||
if len(test.contextProvider) > 0 {
|
||||
ctx = internal.AddProviderInContext(ctx, "foobar@"+test.contextProvider)
|
||||
ctx = provider.AddInContext(ctx, "foobar@"+test.contextProvider)
|
||||
}
|
||||
|
||||
rtConf := runtime.NewConfig(dynamic.Configuration{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package internal
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -10,29 +10,29 @@ import (
|
|||
type contextKey int
|
||||
|
||||
const (
|
||||
providerKey contextKey = iota
|
||||
key contextKey = iota
|
||||
)
|
||||
|
||||
// AddProviderInContext Adds the provider name in the context
|
||||
func AddProviderInContext(ctx context.Context, elementName string) context.Context {
|
||||
// AddInContext Adds the provider name in the context
|
||||
func AddInContext(ctx context.Context, elementName string) context.Context {
|
||||
parts := strings.Split(elementName, "@")
|
||||
if len(parts) == 1 {
|
||||
log.FromContext(ctx).Debugf("Could not find a provider for %s.", elementName)
|
||||
return ctx
|
||||
}
|
||||
|
||||
if name, ok := ctx.Value(providerKey).(string); ok && name == parts[1] {
|
||||
if name, ok := ctx.Value(key).(string); ok && name == parts[1] {
|
||||
return ctx
|
||||
}
|
||||
|
||||
return context.WithValue(ctx, providerKey, parts[1])
|
||||
return context.WithValue(ctx, key, parts[1])
|
||||
}
|
||||
|
||||
// GetQualifiedName Gets the fully qualified name.
|
||||
func GetQualifiedName(ctx context.Context, elementName string) string {
|
||||
parts := strings.Split(elementName, "@")
|
||||
if len(parts) == 1 {
|
||||
if providerName, ok := ctx.Value(providerKey).(string); ok {
|
||||
if providerName, ok := ctx.Value(key).(string); ok {
|
||||
return MakeQualifiedName(providerName, parts[0])
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package internal
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -28,19 +28,19 @@ func TestAddProviderInContext(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "provider name in context",
|
||||
ctx: context.WithValue(context.Background(), providerKey, "foo"),
|
||||
ctx: context.WithValue(context.Background(), key, "foo"),
|
||||
name: "test",
|
||||
expected: "foo",
|
||||
},
|
||||
{
|
||||
desc: "provider name in context and different provider name embedded in element name",
|
||||
ctx: context.WithValue(context.Background(), providerKey, "foo"),
|
||||
ctx: context.WithValue(context.Background(), key, "foo"),
|
||||
name: "test@fii",
|
||||
expected: "fii",
|
||||
},
|
||||
{
|
||||
desc: "provider name in context and same provider name embedded in element name",
|
||||
ctx: context.WithValue(context.Background(), providerKey, "foo"),
|
||||
ctx: context.WithValue(context.Background(), key, "foo"),
|
||||
name: "test@foo",
|
||||
expected: "foo",
|
||||
},
|
||||
|
@ -51,10 +51,10 @@ func TestAddProviderInContext(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
newCtx := AddProviderInContext(test.ctx, test.name)
|
||||
newCtx := AddInContext(test.ctx, test.name)
|
||||
|
||||
var providerName string
|
||||
if name, ok := newCtx.Value(providerKey).(string); ok {
|
||||
if name, ok := newCtx.Value(key).(string); ok {
|
||||
providerName = name
|
||||
}
|
||||
|
||||
|
@ -90,13 +90,13 @@ func TestGetQualifiedName(t *testing.T) {
|
|||
},
|
||||
{
|
||||
desc: "with provider in context",
|
||||
ctx: context.WithValue(context.Background(), providerKey, "foo"),
|
||||
ctx: context.WithValue(context.Background(), key, "foo"),
|
||||
name: "test",
|
||||
expected: "test@foo",
|
||||
},
|
||||
{
|
||||
desc: "with provider in context and explicit name",
|
||||
ctx: context.WithValue(context.Background(), providerKey, "foo"),
|
||||
ctx: context.WithValue(context.Background(), key, "foo"),
|
||||
name: "test@fii",
|
||||
expected: "test@fii",
|
||||
},
|
|
@ -12,8 +12,8 @@ import (
|
|||
"github.com/containous/traefik/v2/pkg/middlewares/recovery"
|
||||
"github.com/containous/traefik/v2/pkg/middlewares/tracing"
|
||||
"github.com/containous/traefik/v2/pkg/rules"
|
||||
"github.com/containous/traefik/v2/pkg/server/internal"
|
||||
"github.com/containous/traefik/v2/pkg/server/middleware"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -121,7 +121,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
}
|
||||
|
||||
for routerName, routerConfig := range configs {
|
||||
ctxRouter := log.With(internal.AddProviderInContext(ctx, routerName), log.Str(log.RouterName, routerName))
|
||||
ctxRouter := log.With(provider.AddInContext(ctx, routerName), log.Str(log.RouterName, routerName))
|
||||
logger := log.FromContext(ctxRouter)
|
||||
|
||||
handler, err := m.buildRouterHandler(ctxRouter, routerName, routerConfig)
|
||||
|
@ -175,7 +175,7 @@ func (m *Manager) buildRouterHandler(ctx context.Context, routerName string, rou
|
|||
func (m *Manager) buildHTTPHandler(ctx context.Context, router *runtime.RouterInfo, routerName string) (http.Handler, error) {
|
||||
var qualifiedNames []string
|
||||
for _, name := range router.Middlewares {
|
||||
qualifiedNames = append(qualifiedNames, internal.GetQualifiedName(ctx, name))
|
||||
qualifiedNames = append(qualifiedNames, provider.GetQualifiedName(ctx, name))
|
||||
}
|
||||
router.Middlewares = qualifiedNames
|
||||
rm := m.modifierBuilder.Build(ctx, qualifiedNames)
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
"github.com/containous/traefik/v2/pkg/rules"
|
||||
"github.com/containous/traefik/v2/pkg/server/internal"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
tcpservice "github.com/containous/traefik/v2/pkg/server/service/tcp"
|
||||
"github.com/containous/traefik/v2/pkg/tcp"
|
||||
traefiktls "github.com/containous/traefik/v2/pkg/tls"
|
||||
|
@ -112,7 +112,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
continue
|
||||
}
|
||||
|
||||
ctxRouter := log.With(internal.AddProviderInContext(ctx, routerHTTPName), log.Str(log.RouterName, routerHTTPName))
|
||||
ctxRouter := log.With(provider.AddInContext(ctx, routerHTTPName), log.Str(log.RouterName, routerHTTPName))
|
||||
logger := log.FromContext(ctxRouter)
|
||||
|
||||
domains, err := rules.ParseDomains(routerHTTPConfig.Rule)
|
||||
|
@ -131,7 +131,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
if routerHTTPConfig.TLS != nil {
|
||||
tlsOptionsName := routerHTTPConfig.TLS.Options
|
||||
if tlsOptionsName != defaultTLSConfigName {
|
||||
tlsOptionsName = internal.GetQualifiedName(ctxRouter, routerHTTPConfig.TLS.Options)
|
||||
tlsOptionsName = provider.GetQualifiedName(ctxRouter, routerHTTPConfig.TLS.Options)
|
||||
}
|
||||
|
||||
tlsConf, err := m.tlsManager.Get(defaultTLSStoreName, tlsOptionsName)
|
||||
|
@ -180,7 +180,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
}
|
||||
|
||||
for routerName, routerConfig := range configs {
|
||||
ctxRouter := log.With(internal.AddProviderInContext(ctx, routerName), log.Str(log.RouterName, routerName))
|
||||
ctxRouter := log.With(provider.AddInContext(ctx, routerName), log.Str(log.RouterName, routerName))
|
||||
logger := log.FromContext(ctxRouter)
|
||||
|
||||
if routerConfig.Service == "" {
|
||||
|
@ -226,7 +226,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
}
|
||||
|
||||
if tlsOptionsName != defaultTLSConfigName {
|
||||
tlsOptionsName = internal.GetQualifiedName(ctxRouter, tlsOptionsName)
|
||||
tlsOptionsName = provider.GetQualifiedName(ctxRouter, tlsOptionsName)
|
||||
}
|
||||
|
||||
tlsConf, err := m.tlsManager.Get(defaultTLSStoreName, tlsOptionsName)
|
||||
|
|
|
@ -58,7 +58,7 @@ func (s *Server) Start(ctx context.Context) {
|
|||
s.tcpEntryPoints.Start()
|
||||
s.watcher.Start()
|
||||
|
||||
s.routinesPool.Go(s.listenSignals)
|
||||
s.routinesPool.GoCtx(s.listenSignals)
|
||||
}
|
||||
|
||||
// Wait blocks until the server shutdown.
|
||||
|
@ -90,7 +90,7 @@ func (s *Server) Close() {
|
|||
|
||||
stopMetricsClients()
|
||||
|
||||
s.routinesPool.Cleanup()
|
||||
s.routinesPool.Stop()
|
||||
|
||||
signal.Stop(s.signals)
|
||||
close(s.signals)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
|
@ -13,10 +14,10 @@ func (s *Server) configureSignals() {
|
|||
signal.Notify(s.signals, syscall.SIGUSR1)
|
||||
}
|
||||
|
||||
func (s *Server) listenSignals(stop chan bool) {
|
||||
func (s *Server) listenSignals(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case sig := <-s.signals:
|
||||
if sig == syscall.SIGUSR1 {
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
package server
|
||||
|
||||
import "context"
|
||||
|
||||
func (s *Server) configureSignals() {}
|
||||
|
||||
func (s *Server) listenSignals(stop chan bool) {}
|
||||
func (s *Server) listenSignals(ctx context.Context) {}
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"github.com/containous/traefik/v2/pkg/middlewares/pipelining"
|
||||
"github.com/containous/traefik/v2/pkg/safe"
|
||||
"github.com/containous/traefik/v2/pkg/server/cookie"
|
||||
"github.com/containous/traefik/v2/pkg/server/internal"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
"github.com/containous/traefik/v2/pkg/server/service/loadbalancer/mirror"
|
||||
"github.com/containous/traefik/v2/pkg/server/service/loadbalancer/wrr"
|
||||
"github.com/vulcand/oxy/roundrobin"
|
||||
|
@ -63,8 +63,8 @@ type Manager struct {
|
|||
func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string, responseModifier func(*http.Response) error) (http.Handler, error) {
|
||||
ctx := log.With(rootCtx, log.Str(log.ServiceName, serviceName))
|
||||
|
||||
serviceName = internal.GetQualifiedName(ctx, serviceName)
|
||||
ctx = internal.AddProviderInContext(ctx, serviceName)
|
||||
serviceName = provider.GetQualifiedName(ctx, serviceName)
|
||||
ctx = provider.AddInContext(ctx, serviceName)
|
||||
|
||||
conf, ok := m.configs[serviceName]
|
||||
if !ok {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||
"github.com/containous/traefik/v2/pkg/server/internal"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
"github.com/containous/traefik/v2/pkg/testhelpers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -336,7 +336,7 @@ func TestManager_Build(t *testing.T) {
|
|||
|
||||
ctx := context.Background()
|
||||
if len(test.providerName) > 0 {
|
||||
ctx = internal.AddProviderInContext(ctx, "foobar@"+test.providerName)
|
||||
ctx = provider.AddInContext(ctx, "foobar@"+test.providerName)
|
||||
}
|
||||
|
||||
_, err := manager.BuildHTTP(ctx, test.serviceName, nil)
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
"github.com/containous/traefik/v2/pkg/server/internal"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
"github.com/containous/traefik/v2/pkg/tcp"
|
||||
)
|
||||
|
||||
|
@ -27,8 +27,8 @@ func NewManager(conf *runtime.Configuration) *Manager {
|
|||
|
||||
// BuildTCP Creates a tcp.Handler for a service configuration.
|
||||
func (m *Manager) BuildTCP(rootCtx context.Context, serviceName string) (tcp.Handler, error) {
|
||||
serviceQualifiedName := internal.GetQualifiedName(rootCtx, serviceName)
|
||||
ctx := internal.AddProviderInContext(rootCtx, serviceQualifiedName)
|
||||
serviceQualifiedName := provider.GetQualifiedName(rootCtx, serviceName)
|
||||
ctx := provider.AddInContext(rootCtx, serviceQualifiedName)
|
||||
ctx = log.With(ctx, log.Str(log.ServiceName, serviceName))
|
||||
|
||||
conf, ok := m.configs[serviceQualifiedName]
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||
"github.com/containous/traefik/v2/pkg/server/internal"
|
||||
"github.com/containous/traefik/v2/pkg/server/provider"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -184,7 +184,7 @@ func TestManager_BuildTCP(t *testing.T) {
|
|||
|
||||
ctx := context.Background()
|
||||
if len(test.providerName) > 0 {
|
||||
ctx = internal.AddProviderInContext(ctx, "foobar@"+test.providerName)
|
||||
ctx = provider.AddInContext(ctx, "foobar@"+test.providerName)
|
||||
}
|
||||
|
||||
handler, err := manager.BuildTCP(ctx, test.serviceName)
|
||||
|
|
Loading…
Reference in a new issue