Merge 'v1.5.1' into master

This commit is contained in:
Fernandez Ludovic 2018-01-29 16:50:16 +01:00
commit d426126a92
16 changed files with 319 additions and 343 deletions

View file

@ -24,9 +24,9 @@ before_deploy:
sudo -E apt-get -yq update; sudo -E apt-get -yq update;
sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-ce=${DOCKER_VERSION}*; sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-ce=${DOCKER_VERSION}*;
docker version; docker version;
make image;
if [ "$TRAVIS_TAG" ]; then if [ "$TRAVIS_TAG" ]; then
make -j${N_MAKE_JOBS} crossbinary-parallel; make -j${N_MAKE_JOBS} crossbinary-parallel;
make image-dirty;
tar cfz dist/traefik-${VERSION}.src.tar.gz --exclude-vcs --exclude dist .; tar cfz dist/traefik-${VERSION}.src.tar.gz --exclude-vcs --exclude dist .;
fi; fi;
curl -sI https://github.com/containous/structor/releases/latest | grep -Fi Location | tr -d '\r' | sed "s/tag/download/g" | awk -F " " '{ print $2 "/structor_linux-amd64"}' | wget --output-document=$GOPATH/bin/structor -i -; curl -sI https://github.com/containous/structor/releases/latest | grep -Fi Location | tr -d '\r' | sed "s/tag/download/g" | awk -F " " '{ print $2 "/structor_linux-amd64"}' | wget --output-document=$GOPATH/bin/structor -i -;

View file

@ -1,5 +1,18 @@
# Change Log # Change Log
## [v1.5.1](https://github.com/containous/traefik/tree/v1.5.1) (2018-01-29)
[All Commits](https://github.com/containous/traefik/compare/v1.5.0...v1.5.1)
**Bug fixes:**
- **[acme]** Handle undefined entrypoint on ACME config and frontend config ([#2756](https://github.com/containous/traefik/pull/2756) by [Juliens](https://github.com/Juliens))
- **[k8s]** Fix the k8s redirection template. ([#2748](https://github.com/containous/traefik/pull/2748) by [ldez](https://github.com/ldez))
- **[middleware]** Change gzipwriter receiver to implement CloseNotifier ([#2766](https://github.com/containous/traefik/pull/2766) by [Juliens](https://github.com/Juliens))
- **[tls]** Fix domain names in dynamic TLS configuration ([#2768](https://github.com/containous/traefik/pull/2768) by [nmengin](https://github.com/nmengin))
**Documentation:**
- **[acme]** Add note on redirect for ACME http challenge ([#2767](https://github.com/containous/traefik/pull/2767) by [Juliens](https://github.com/Juliens))
- **[file]** Enhance file provider documentation. ([#2777](https://github.com/containous/traefik/pull/2777) by [ldez](https://github.com/ldez))
## [v1.5.0](https://github.com/containous/traefik/tree/v1.5.0) (2018-01-23) ## [v1.5.0](https://github.com/containous/traefik/tree/v1.5.0) (2018-01-23)
[All Commits](https://github.com/containous/traefik/compare/v1.4.0-rc1...v1.5.0) [All Commits](https://github.com/containous/traefik/compare/v1.4.0-rc1...v1.5.0)

5
Gopkg.lock generated
View file

@ -89,7 +89,7 @@
branch = "master" branch = "master"
name = "github.com/NYTimes/gziphandler" name = "github.com/NYTimes/gziphandler"
packages = ["."] packages = ["."]
revision = "47ca22a0aeea4c9ceddfb935d818d636d934c312" revision = "289a3b81f5aedc99f8d6eb0f67827c142f1310d8"
[[projects]] [[projects]]
name = "github.com/Nvveen/Gotty" name = "github.com/Nvveen/Gotty"
@ -576,7 +576,6 @@
"metrics/internal/lv", "metrics/internal/lv",
"metrics/internal/ratemap", "metrics/internal/ratemap",
"metrics/multi", "metrics/multi",
"metrics/prometheus",
"metrics/statsd", "metrics/statsd",
"util/conn" "util/conn"
] ]
@ -1512,6 +1511,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "0d3d2cd01e06cfcc86cbd261395d59187d4d27d88398bd7aeb1298676becd3e7" inputs-digest = "b9fee5807e09b19baf3763abc285ea122d64d60dba42aaf47eaf9e96774b46bf"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -142,6 +142,7 @@ func run(globalConfiguration *configuration.GlobalConfiguration, configFile stri
http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment
globalConfiguration.SetEffectiveConfiguration(configFile) globalConfiguration.SetEffectiveConfiguration(configFile)
globalConfiguration.ValidateConfiguration()
jsonConf, _ := json.Marshal(globalConfiguration) jsonConf, _ := json.Marshal(globalConfiguration)
log.Infof("Traefik version %s built on %s", version.Version, version.BuildDate) log.Infof("Traefik version %s built on %s", version.Version, version.BuildDate)

View file

@ -262,6 +262,19 @@ func (gc *GlobalConfiguration) SetEffectiveConfiguration(configFile string) {
} }
} }
// ValidateConfiguration validate that configuration is coherent
func (gc *GlobalConfiguration) ValidateConfiguration() {
if gc.ACME != nil {
if _, ok := gc.EntryPoints[gc.ACME.EntryPoint]; !ok {
log.Fatalf("Unknown entrypoint %q for ACME configuration", gc.ACME.EntryPoint)
} else {
if gc.EntryPoints[gc.ACME.EntryPoint].TLS == nil {
log.Fatalf("Entrypoint without TLS %q for ACME configuration", gc.ACME.EntryPoint)
}
}
}
}
// DefaultEntryPoints holds default entry points // DefaultEntryPoints holds default entry points
type DefaultEntryPoints []string type DefaultEntryPoints []string

View file

@ -612,6 +612,7 @@ Those data help us prioritize our developments and focus on what's more importan
### What ? ### What ?
Once a day (the first call begins 10 minutes after the start of Træfik), we collect: Once a day (the first call begins 10 minutes after the start of Træfik), we collect:
- the Træfik version - the Træfik version
- a hash of the configuration - a hash of the configuration
- an **anonymous version** of the static configuration: - an **anonymous version** of the static configuration:

View file

@ -186,6 +186,9 @@ docker run -v "/my/host/acme:/etc/traefik/acme" traefik
Use `HTTP-01` challenge to generate/renew ACME certificates. Use `HTTP-01` challenge to generate/renew ACME certificates.
The redirection is fully compatible with the HTTP-01 challenge.
You can use redirection with HTTP-01 challenge without problem.
```toml ```toml
[acme] [acme]
# ... # ...

View file

@ -1,6 +1,140 @@
# File Backends # File Backends
Like any other reverse proxy, Træfik can be configured with a file. Træfik can be configured with a file.
## Reference
```toml
# Backends
[backends]
[backends.backend1]
[backends.backend1.servers]
[backends.backend1.servers.server0]
url = "http://10.10.10.1:80"
weight = 1
[backends.backend1.servers.server1]
url = "http://10.10.10.2:80"
weight = 2
# ...
[backends.backend1.circuitBreaker]
expression = "NetworkErrorRatio() > 0.5"
[backends.backend1.loadBalancer]
method = "drr"
[backends.backend1.loadBalancer.stickiness]
cookieName = "foobar"
[backends.backend1.maxConn]
amount = 10
extractorfunc = "request.host"
[backends.backend1.healthCheck]
path = "/health"
port = 88
interval = "30s"
[backends.backend2]
# ...
# Frontends
[frontends]
[frontends.frontend1]
entryPoints = ["http", "https"]
backend = "backend1"
passHostHeader = true
passTLSCert = true
priority = 42
basicAuth = [
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
]
whitelistSourceRange = ["10.42.0.0/16", "152.89.1.33/32", "afed:be44::/16"]
[frontends.frontend1.routes]
[frontends.frontend1.routes.route0]
rule = "Host:test.localhost"
[frontends.frontend1.routes.Route1]
rule = "Method:GET"
# ...
[frontends.frontend1.headers]
allowedHosts = ["foobar", "foobar"]
hostsProxyHeaders = ["foobar", "foobar"]
SSLRedirect = true
SSLTemporaryRedirect = true
SSLHost = "foobar"
STSSeconds = 42
STSIncludeSubdomains = true
STSPreload = true
forceSTSHeader = true
frameDeny = true
customFrameOptionsValue = "foobar"
contentTypeNosniff = true
browserXSSFilter = true
contentSecurityPolicy = "foobar"
publicKey = "foobar"
referrerPolicy = "foobar"
isDevelopment = true
[frontends.frontend1.headers.customRequestHeaders]
X-Foo-Bar-01 = "foobar"
X-Foo-Bar-02 = "foobar"
# ...
[frontends.frontend1.headers.customResponseHeaders]
X-Foo-Bar-03 = "foobar"
X-Foo-Bar-04 = "foobar"
# ...
[frontends.frontend1.headers.SSLProxyHeaders]
X-Foo-Bar-05 = "foobar"
X-Foo-Bar-06 = "foobar"
# ...
[frontends.frontend1.errors]
[frontends.frontend1.errors.errorPage0]
status = ["500-599"]
backend = "error"
query = "/{status}.html"
[frontends.frontend1.errors.errorPage1]
status = ["404", "403"]
backend = "error"
query = "/{status}.html"
# ...
[frontends.frontend1.ratelimit]
extractorfunc = "client.ip"
[frontends.frontend1.ratelimit.rateset.rateset1]
period = "10s"
average = 100
burst = 200
[frontends.frontend1.ratelimit.rateset.rateset2]
period = "3s"
average = 5
burst = 10
# ...
[frontends.frontend1.redirect]
entryPoint = "https"
regex = "^http://localhost/(.*)"
replacement = "http://mydomain/$1"
[frontends.frontend2]
# ...
# HTTPS certificates
[[tls]]
entryPoints = ["https"]
[tls.certificate]
certFile = "path/to/my.cert"
keyFile = "path/to/my.key"
[[tls]]
# ...
```
## Configuration mode
You have three choices: You have three choices:
@ -12,7 +146,7 @@ To enable the file backend, you must either pass the `--file` option to the Træ
The configuration file allows managing both backends/frontends and HTTPS certificates (which are not [Let's Encrypt](https://letsencrypt.org) certificates generated through Træfik). The configuration file allows managing both backends/frontends and HTTPS certificates (which are not [Let's Encrypt](https://letsencrypt.org) certificates generated through Træfik).
## Simple ### Simple
Add your configuration at the end of the global configuration file `traefik.toml`: Add your configuration at the end of the global configuration file `traefik.toml`:
@ -21,80 +155,33 @@ defaultEntryPoints = ["http", "https"]
[entryPoints] [entryPoints]
[entryPoints.http] [entryPoints.http]
address = ":80" # ...
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https] [entryPoints.https]
address = ":443" # ...
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "integration/fixtures/https/snitest.org.cert"
keyFile = "integration/fixtures/https/snitest.org.key"
[file] [file]
# rules # rules
[backends] [backends]
[backends.backend1] [backends.backend1]
[backends.backend1.circuitbreaker] # ...
expression = "NetworkErrorRatio() > 0.5"
[backends.backend1.servers.server1]
url = "http://172.17.0.2:80"
weight = 10
[backends.backend1.servers.server2]
url = "http://172.17.0.3:80"
weight = 1
[backends.backend2] [backends.backend2]
[backends.backend2.maxconn] # ...
amount = 10
extractorfunc = "request.host"
[backends.backend2.LoadBalancer]
method = "drr"
[backends.backend2.servers.server1]
url = "http://172.17.0.4:80"
weight = 1
[backends.backend2.servers.server2]
url = "http://172.17.0.5:80"
weight = 2
[frontends] [frontends]
[frontends.frontend1] [frontends.frontend1]
backend = "backend2" # ...
[frontends.frontend1.routes.test_1]
rule = "Host:test.localhost"
[frontends.frontend2] [frontends.frontend2]
backend = "backend1" # ...
passHostHeader = true
priority = 10
# restrict access to this frontend to the specified list of IPv4/IPv6 CIDR Nets
# an unset or empty list allows all Source-IPs to access
# if one of the Net-Specifications are invalid, the whole list is invalid
# and allows all Source-IPs to access.
whitelistSourceRange = ["10.42.0.0/16", "152.89.1.33/32", "afed:be44::/16"]
entrypoints = ["https"] # overrides defaultEntryPoints
[frontends.frontend2.routes.test_1]
rule = "Host:{subdomain:[a-z]+}.localhost"
[frontends.frontend3] [frontends.frontend3]
entrypoints = ["http", "https"] # overrides defaultEntryPoints # ...
backend = "backend2"
rule = "Path:/test"
# HTTPS certificate # HTTPS certificate
[[tls]] [[tls]]
entryPoints = ["https"] # ...
[tls.certificate]
certFile = "path/to/my.cert"
keyFile = "path/to/my.key"
[[tls]] [[tls]]
entryPoints = ["https"] # ...
[tls.certificate]
certFile = "path/to/my/other.cert"
keyFile = "path/to/my/other.key"
``` ```
!!! note !!! note
@ -104,92 +191,60 @@ defaultEntryPoints = ["http", "https"]
Adding certificates directly to the entryPoint is still maintained but certificates declared in this way cannot be managed dynamically. Adding certificates directly to the entryPoint is still maintained but certificates declared in this way cannot be managed dynamically.
It's recommended to use the file provider to declare certificates. It's recommended to use the file provider to declare certificates.
## Rules in a Separate File ### Rules in a Separate File
Put your rules in a separate file, for example `rules.toml`: Put your rules in a separate file, for example `rules.toml`:
```toml ```toml
# traefik.toml # traefik.toml
defaultEntryPoints = ["http", "https"]
[entryPoints] [entryPoints]
[entryPoints.http] [entryPoints.http]
address = ":80" # ...
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https] [entryPoints.https]
address = ":443" # ...
[entryPoints.https.tls]
[file] [file]
filename = "rules.toml" filename = "rules.toml"
``` ```
```toml ```toml
# rules.toml # rules.toml
[backends] [backends]
[backends.backend1] [backends.backend1]
[backends.backend1.circuitbreaker] # ...
expression = "NetworkErrorRatio() > 0.5"
[backends.backend1.servers.server1]
url = "http://172.17.0.2:80"
weight = 10
[backends.backend1.servers.server2]
url = "http://172.17.0.3:80"
weight = 1
[backends.backend2] [backends.backend2]
[backends.backend2.maxconn] # ...
amount = 10
extractorfunc = "request.host"
[backends.backend2.LoadBalancer]
method = "drr"
[backends.backend2.servers.server1]
url = "http://172.17.0.4:80"
weight = 1
[backends.backend2.servers.server2]
url = "http://172.17.0.5:80"
weight = 2
[frontends] [frontends]
[frontends.frontend1] [frontends.frontend1]
backend = "backend2" # ...
[frontends.frontend1.routes.test_1]
rule = "Host:test.localhost"
[frontends.frontend2] [frontends.frontend2]
backend = "backend1" # ...
passHostHeader = true
priority = 10
entrypoints = ["https"] # overrides defaultEntryPoints
[frontends.frontend2.routes.test_1]
rule = "Host:{subdomain:[a-z]+}.localhost"
[frontends.frontend3] [frontends.frontend3]
entrypoints = ["http", "https"] # overrides defaultEntryPoints # ...
backend = "backend2"
rule = "Path:/test"
# HTTPS certificate # HTTPS certificate
[[tls]] [[tls]]
entryPoints = ["https"] # ...
[tls.certificate]
certFile = "path/to/my.cert"
keyFile = "path/to/my.key"
[[tls]]
entryPoints = ["https"]
[tls.certificate]
certFile = "path/to/my/other.cert"
keyFile = "path/to/my/other.key"
## Multiple `.toml` Files [[tls]]
# ...
```
### Multiple `.toml` Files
You could have multiple `.toml` files in a directory (and recursively in its sub-directories): You could have multiple `.toml` files in a directory (and recursively in its sub-directories):
```toml ```toml
[file] [file]
directory = "/path/to/config/" directory = "/path/to/config/"
``` ```
If you want Træfik to watch file changes automatically, just add: If you want Træfik to watch file changes automatically, just add:
```toml ```toml
[file] [file]
watch = true watch = true
``` ```

View file

@ -150,7 +150,7 @@ The following security annotations are applicable on the Ingress object:
| `ingress.kubernetes.io/ssl-host:HOST` | This setting configures the hostname that redirects will be based on. Default is "", which is the same host as the request. | | `ingress.kubernetes.io/ssl-host:HOST` | This setting configures the hostname that redirects will be based on. Default is "", which is the same host as the request. |
| `ingress.kubernetes.io/ssl-proxy-headers:EXPR` | Header combinations that would signify a proper SSL Request (Such as `X-Forwarded-For:https`). Format: <code>HEADER:value&vert;&vert;HEADER2:value2</code> | | `ingress.kubernetes.io/ssl-proxy-headers:EXPR` | Header combinations that would signify a proper SSL Request (Such as `X-Forwarded-For:https`). Format: <code>HEADER:value&vert;&vert;HEADER2:value2</code> |
| `ingress.kubernetes.io/hsts-max-age:315360000` | Sets the max-age of the HSTS header. | | `ingress.kubernetes.io/hsts-max-age:315360000` | Sets the max-age of the HSTS header. |
| `ngress.kubernetes.io/hsts-include-subdomains:true` | Adds the IncludeSubdomains section of the STS header. | | `ingress.kubernetes.io/hsts-include-subdomains:true` | Adds the IncludeSubdomains section of the STS header. |
| `ingress.kubernetes.io/hsts-preload:true` | Adds the preload flag to the HSTS header. | | `ingress.kubernetes.io/hsts-preload:true` | Adds the preload flag to the HSTS header. |
| `ingress.kubernetes.io/force-hsts:false` | Adds the STS header to non-SSL requests. | | `ingress.kubernetes.io/force-hsts:false` | Adds the STS header to non-SSL requests. |
| `ingress.kubernetes.io/frame-deny:false` | Adds the `X-Frame-Options` header with the value of `DENY`. | | `ingress.kubernetes.io/frame-deny:false` | Adds the `X-Frame-Options` header with the value of `DENY`. |

View file

@ -282,21 +282,17 @@ Multiple sets of rates can be added to each frontend, but the time periods must
```toml ```toml
[frontends] [frontends]
[frontends.frontend1] [frontends.frontend1]
passHostHeader = true # ...
entrypoints = ["http"] [frontends.frontend1.ratelimit]
backend = "backend1" extractorfunc = "client.ip"
[frontends.frontend1.routes.test_1] [frontends.frontend1.ratelimit.rateset.rateset1]
rule = "Path:/" period = "10s"
[frontends.frontend1.ratelimit] average = 100
extractorfunc = "client.ip" burst = 200
[frontends.frontend1.ratelimit.rateset.rateset1] [frontends.frontend1.ratelimit.rateset.rateset2]
period = "10s" period = "3s"
average = 100 average = 5
burst = 200 burst = 10
[frontends.frontend1.ratelimit.rateset.rateset2]
period = "3s"
average = 5
burst = 10
``` ```
In the above example, frontend1 is configured to limit requests by the client's ip address. In the above example, frontend1 is configured to limit requests by the client's ip address.

View file

@ -1,5 +1,72 @@
# Entry Points Definition # Entry Points Definition
## Reference
```toml
[entryPoints]
[entryPoints.http]
address = ":80"
whitelistSourceRange = ["10.42.0.0/16", "152.89.1.33/32", "afed:be44::/16"]
compress = true
[entryPoints.http.tls]
minVersion = "VersionTLS12"
cipherSuites = ["TLS_RSA_WITH_AES_256_GCM_SHA384"]
[[entryPoints.http.tls.certificates]]
certFile = "path/to/my.cert"
keyFile = "path/to/my.key"
[[entryPoints.http.tls.certificates]]
certFile = "path/to/other.cert"
keyFile = "path/to/other.key"
# ...
[entryPoints.http.tls.clientCA]
files = ["path/to/ca1.crt", "path/to/ca2.crt"]
optional = false
[entryPoints.http.redirect]
entryPoint = "https"
regex = "^http://localhost/(.*)"
replacement = "http://mydomain/$1"
permanent = true
[entryPoints.http.auth]
headerField = "X-WebAuth-User"
[entryPoints.http.auth.basic]
users = [
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
]
usersFile = "/path/to/.htpasswd"
[entryPoints.http.auth.digest]
users = [
"test:traefik:a2688e031edb4be6a3797f3882655c05",
"test2:traefik:518845800f9e2bfb1f1f740ec24f074e",
]
usersFile = "/path/to/.htdigest"
[entryPoints.http.auth.forward]
address = "https://authserver.com/auth"
trustForwardHeader = true
[entryPoints.http.auth.forward.tls]
ca = [ "path/to/local.crt"]
caOptional = true
cert = "path/to/foo.cert"
key = "path/to/foo.key"
insecureSkipVerify = true
[entryPoints.http.proxyProtocol]
insecure = true
trustedIPs = ["10.10.10.1", "10.10.10.2"]
[entryPoints.http.forwardedHeaders]
trustedIPs = ["10.10.10.1", "10.10.10.2"]
[entryPoints.https]
# ...
```
## Basic
```toml ```toml
# Entrypoints definition # Entrypoints definition
# #
@ -71,7 +138,7 @@ Define an entrypoint with SNI support.
!!! note !!! note
If an empty TLS configuration is done, default self-signed certificates are generated. If an empty TLS configuration is done, default self-signed certificates are generated.
### Dynamic Certificates ### Dynamic Certificates
@ -162,7 +229,7 @@ Otherwise, the response from the auth server is returned.
# To enable forward auth on an entrypoint # To enable forward auth on an entrypoint
[entryPoints.http.auth.forward] [entryPoints.http.auth.forward]
address = "https://authserver.com/auth" address = "https://authserver.com/auth"
# Trust existing X-Forwarded-* headers. # Trust existing X-Forwarded-* headers.
# Useful with another reverse proxy in front of Traefik. # Useful with another reverse proxy in front of Traefik.
# #
@ -170,7 +237,7 @@ Otherwise, the response from the auth server is returned.
# Default: false # Default: false
# #
trustForwardHeader = true trustForwardHeader = true
# Enable forward auth TLS connection. # Enable forward auth TLS connection.
# #
# Optional # Optional
@ -234,7 +301,7 @@ Only IPs in `trustedIPs` will lead to remote client address replacement: you sho
!!! danger !!! danger
When queuing Træfik behind another load-balancer, be sure to carefully configure Proxy Protocol on both sides. When queuing Træfik behind another load-balancer, be sure to carefully configure Proxy Protocol on both sides.
Otherwise, it could introduce a security risk in your system by forging requests. Otherwise, it could introduce a security risk in your system by forging requests.
```toml ```toml
[entryPoints] [entryPoints]

View file

@ -28,14 +28,6 @@ echo $VERSION | git commit --file -
echo $VERSION | git tag -a $VERSION --file - echo $VERSION | git tag -a $VERSION --file -
git push -q --follow-tags -u origin master > /dev/null 2>&1 git push -q --follow-tags -u origin master > /dev/null 2>&1
# create docker image emilevauge/traefik (compatibility)
echo "Updating docker emilevauge/traefik image..."
docker login -u $DOCKER_USER -p $DOCKER_PASS
docker tag containous/traefik emilevauge/traefik:latest
docker push emilevauge/traefik:latest
docker tag emilevauge/traefik:latest emilevauge/traefik:${VERSION}
docker push emilevauge/traefik:${VERSION}
cd .. cd ..
rm -Rf traefik-library-image/ rm -Rf traefik-library-image/

View file

@ -635,31 +635,27 @@ func (s *Server) createTLSConfig(entryPointName string, tlsOption *traefikTls.TL
} }
if s.globalConfiguration.ACME != nil { if s.globalConfiguration.ACME != nil {
if _, ok := s.serverEntryPoints[s.globalConfiguration.ACME.EntryPoint]; ok { if entryPointName == s.globalConfiguration.ACME.EntryPoint {
if entryPointName == s.globalConfiguration.ACME.EntryPoint { checkOnDemandDomain := func(domain string) bool {
checkOnDemandDomain := func(domain string) bool { routeMatch := &mux.RouteMatch{}
routeMatch := &mux.RouteMatch{} router := router.GetHandler()
router := router.GetHandler() match := router.Match(&http.Request{URL: &url.URL{}, Host: domain}, routeMatch)
match := router.Match(&http.Request{URL: &url.URL{}, Host: domain}, routeMatch) if match && routeMatch.Route != nil {
if match && routeMatch.Route != nil { return true
return true
}
return false
} }
if s.leadership == nil { return false
err := s.globalConfiguration.ACME.CreateLocalConfig(config, &s.serverEntryPoints[entryPointName].certs, checkOnDemandDomain) }
if err != nil { if s.leadership == nil {
return nil, err err := s.globalConfiguration.ACME.CreateLocalConfig(config, &s.serverEntryPoints[entryPointName].certs, checkOnDemandDomain)
} if err != nil {
} else { return nil, err
err := s.globalConfiguration.ACME.CreateClusterConfig(s.leadership, config, &s.serverEntryPoints[entryPointName].certs, checkOnDemandDomain) }
if err != nil { } else {
return nil, err err := s.globalConfiguration.ACME.CreateClusterConfig(s.leadership, config, &s.serverEntryPoints[entryPointName].certs, checkOnDemandDomain)
} if err != nil {
return nil, err
} }
} }
} else {
return nil, errors.New("Unknown entrypoint " + s.globalConfiguration.ACME.EntryPoint + " for ACME configuration")
} }
} else { } else {
config.GetCertificate = s.serverEntryPoints[entryPointName].getCertificate config.GetCertificate = s.serverEntryPoints[entryPointName].getCertificate
@ -887,23 +883,23 @@ func (s *Server) loadConfig(configurations types.Configurations, globalConfigura
log.Debugf("Creating frontend %s", frontendName) log.Debugf("Creating frontend %s", frontendName)
var frontendEntryPoints []string
for _, entryPointName := range frontend.EntryPoints {
if _, ok := serverEntryPoints[entryPointName]; !ok {
log.Errorf("Undefined entrypoint '%s' for frontend %s", entryPointName, frontendName)
} else {
frontendEntryPoints = append(frontendEntryPoints, entryPointName)
}
}
frontend.EntryPoints = frontendEntryPoints
if len(frontend.EntryPoints) == 0 { if len(frontend.EntryPoints) == 0 {
log.Errorf("No entrypoint defined for frontend %s, defaultEntryPoints:%s", frontendName, globalConfiguration.DefaultEntryPoints) log.Errorf("No entrypoint defined for frontend %s", frontendName)
log.Errorf("Skipping frontend %s...", frontendName) log.Errorf("Skipping frontend %s...", frontendName)
continue frontend continue frontend
} }
var failedEntrypoints int
for _, entryPointName := range frontend.EntryPoints { for _, entryPointName := range frontend.EntryPoints {
log.Debugf("Wiring frontend %s to entryPoint %s", frontendName, entryPointName) log.Debugf("Wiring frontend %s to entryPoint %s", frontendName, entryPointName)
if _, ok := serverEntryPoints[entryPointName]; !ok {
log.Errorf("Undefined entrypoint '%s' for frontend %s", entryPointName, frontendName)
failedEntrypoints++
if failedEntrypoints == len(frontend.EntryPoints) {
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
continue
}
newServerRoute := &serverRoute{route: serverEntryPoints[entryPointName].httpRouter.GetHandler().NewRoute().Name(frontendName)} newServerRoute := &serverRoute{route: serverEntryPoints[entryPointName].httpRouter.GetHandler().NewRoute().Name(frontendName)}
for routeName, route := range frontend.Routes { for routeName, route := range frontend.Routes {

View file

@ -150,7 +150,12 @@ func (c *Certificate) AppendCertificates(certs map[string]*DomainsCertificates,
certKey := parsedCert.Subject.CommonName certKey := parsedCert.Subject.CommonName
if parsedCert.DNSNames != nil { if parsedCert.DNSNames != nil {
sort.Strings(parsedCert.DNSNames) sort.Strings(parsedCert.DNSNames)
certKey += fmt.Sprintf("%s,%s", parsedCert.Subject.CommonName, strings.Join(parsedCert.DNSNames, ",")) for _, dnsName := range parsedCert.DNSNames {
if dnsName != parsedCert.Subject.CommonName {
certKey += fmt.Sprintf(",%s", dnsName)
}
}
} }
certExists := false certExists := false

View file

@ -88,7 +88,7 @@ type GzipResponseWriterWithCloseNotify struct {
*GzipResponseWriter *GzipResponseWriter
} }
func (w *GzipResponseWriterWithCloseNotify) CloseNotify() <-chan bool { func (w GzipResponseWriterWithCloseNotify) CloseNotify() <-chan bool {
return w.ResponseWriter.(http.CloseNotifier).CloseNotify() return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
} }

View file

@ -1,165 +0,0 @@
// Package prometheus provides Prometheus implementations for metrics.
// Individual metrics are mapped to their Prometheus counterparts, and
// (depending on the constructor used) may be automatically registered in the
// global Prometheus metrics registry.
package prometheus
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/metrics/internal/lv"
)
// Counter implements Counter, via a Prometheus CounterVec.
type Counter struct {
cv *prometheus.CounterVec
lvs lv.LabelValues
}
// NewCounterFrom constructs and registers a Prometheus CounterVec,
// and returns a usable Counter object.
func NewCounterFrom(opts prometheus.CounterOpts, labelNames []string) *Counter {
cv := prometheus.NewCounterVec(opts, labelNames)
prometheus.MustRegister(cv)
return NewCounter(cv)
}
// NewCounter wraps the CounterVec and returns a usable Counter object.
func NewCounter(cv *prometheus.CounterVec) *Counter {
return &Counter{
cv: cv,
}
}
// With implements Counter.
func (c *Counter) With(labelValues ...string) metrics.Counter {
return &Counter{
cv: c.cv,
lvs: c.lvs.With(labelValues...),
}
}
// Add implements Counter.
func (c *Counter) Add(delta float64) {
c.cv.With(makeLabels(c.lvs...)).Add(delta)
}
// Gauge implements Gauge, via a Prometheus GaugeVec.
type Gauge struct {
gv *prometheus.GaugeVec
lvs lv.LabelValues
}
// NewGaugeFrom construts and registers a Prometheus GaugeVec,
// and returns a usable Gauge object.
func NewGaugeFrom(opts prometheus.GaugeOpts, labelNames []string) *Gauge {
gv := prometheus.NewGaugeVec(opts, labelNames)
prometheus.MustRegister(gv)
return NewGauge(gv)
}
// NewGauge wraps the GaugeVec and returns a usable Gauge object.
func NewGauge(gv *prometheus.GaugeVec) *Gauge {
return &Gauge{
gv: gv,
}
}
// With implements Gauge.
func (g *Gauge) With(labelValues ...string) metrics.Gauge {
return &Gauge{
gv: g.gv,
lvs: g.lvs.With(labelValues...),
}
}
// Set implements Gauge.
func (g *Gauge) Set(value float64) {
g.gv.With(makeLabels(g.lvs...)).Set(value)
}
// Add is supported by Prometheus GaugeVecs.
func (g *Gauge) Add(delta float64) {
g.gv.With(makeLabels(g.lvs...)).Add(delta)
}
// Summary implements Histogram, via a Prometheus SummaryVec. The difference
// between a Summary and a Histogram is that Summaries don't require predefined
// quantile buckets, but cannot be statistically aggregated.
type Summary struct {
sv *prometheus.SummaryVec
lvs lv.LabelValues
}
// NewSummaryFrom constructs and registers a Prometheus SummaryVec,
// and returns a usable Summary object.
func NewSummaryFrom(opts prometheus.SummaryOpts, labelNames []string) *Summary {
sv := prometheus.NewSummaryVec(opts, labelNames)
prometheus.MustRegister(sv)
return NewSummary(sv)
}
// NewSummary wraps the SummaryVec and returns a usable Summary object.
func NewSummary(sv *prometheus.SummaryVec) *Summary {
return &Summary{
sv: sv,
}
}
// With implements Histogram.
func (s *Summary) With(labelValues ...string) metrics.Histogram {
return &Summary{
sv: s.sv,
lvs: s.lvs.With(labelValues...),
}
}
// Observe implements Histogram.
func (s *Summary) Observe(value float64) {
s.sv.With(makeLabels(s.lvs...)).Observe(value)
}
// Histogram implements Histogram via a Prometheus HistogramVec. The difference
// between a Histogram and a Summary is that Histograms require predefined
// quantile buckets, and can be statistically aggregated.
type Histogram struct {
hv *prometheus.HistogramVec
lvs lv.LabelValues
}
// NewHistogramFrom constructs and registers a Prometheus HistogramVec,
// and returns a usable Histogram object.
func NewHistogramFrom(opts prometheus.HistogramOpts, labelNames []string) *Histogram {
hv := prometheus.NewHistogramVec(opts, labelNames)
prometheus.MustRegister(hv)
return NewHistogram(hv)
}
// NewHistogram wraps the HistogramVec and returns a usable Histogram object.
func NewHistogram(hv *prometheus.HistogramVec) *Histogram {
return &Histogram{
hv: hv,
}
}
// With implements Histogram.
func (h *Histogram) With(labelValues ...string) metrics.Histogram {
return &Histogram{
hv: h.hv,
lvs: h.lvs.With(labelValues...),
}
}
// Observe implements Histogram.
func (h *Histogram) Observe(value float64) {
h.hv.With(makeLabels(h.lvs...)).Observe(value)
}
func makeLabels(labelValues ...string) prometheus.Labels {
labels := prometheus.Labels{}
for i := 0; i < len(labelValues); i += 2 {
labels[labelValues[i]] = labelValues[i+1]
}
return labels
}