diff --git a/.travis.yml b/.travis.yml index a2d7ec008..5096a5c13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,9 +24,9 @@ before_deploy: sudo -E apt-get -yq update; sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-ce=${DOCKER_VERSION}*; docker version; + make image; if [ "$TRAVIS_TAG" ]; then make -j${N_MAKE_JOBS} crossbinary-parallel; - make image-dirty; tar cfz dist/traefik-${VERSION}.src.tar.gz --exclude-vcs --exclude dist .; 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 -; diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e571c270..c8cd4f640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # 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) [All Commits](https://github.com/containous/traefik/compare/v1.4.0-rc1...v1.5.0) diff --git a/Gopkg.lock b/Gopkg.lock index 6a3201050..5b43d80d1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -89,7 +89,7 @@ branch = "master" name = "github.com/NYTimes/gziphandler" packages = ["."] - revision = "47ca22a0aeea4c9ceddfb935d818d636d934c312" + revision = "289a3b81f5aedc99f8d6eb0f67827c142f1310d8" [[projects]] name = "github.com/Nvveen/Gotty" @@ -576,7 +576,6 @@ "metrics/internal/lv", "metrics/internal/ratemap", "metrics/multi", - "metrics/prometheus", "metrics/statsd", "util/conn" ] @@ -1512,6 +1511,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "0d3d2cd01e06cfcc86cbd261395d59187d4d27d88398bd7aeb1298676becd3e7" + inputs-digest = "b9fee5807e09b19baf3763abc285ea122d64d60dba42aaf47eaf9e96774b46bf" solver-name = "gps-cdcl" solver-version = 1 diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 0a40eeef4..a067cc810 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -142,6 +142,7 @@ func run(globalConfiguration *configuration.GlobalConfiguration, configFile stri http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment globalConfiguration.SetEffectiveConfiguration(configFile) + globalConfiguration.ValidateConfiguration() jsonConf, _ := json.Marshal(globalConfiguration) log.Infof("Traefik version %s built on %s", version.Version, version.BuildDate) diff --git a/configuration/configuration.go b/configuration/configuration.go index d78f926da..960690f4b 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -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 type DefaultEntryPoints []string diff --git a/docs/basics.md b/docs/basics.md index 5c30b78e4..fcfd36006 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -612,6 +612,7 @@ Those data help us prioritize our developments and focus on what's more importan ### What ? Once a day (the first call begins 10 minutes after the start of Træfik), we collect: + - the Træfik version - a hash of the configuration - an **anonymous version** of the static configuration: diff --git a/docs/configuration/acme.md b/docs/configuration/acme.md index 53cd3cae7..ffad21f29 100644 --- a/docs/configuration/acme.md +++ b/docs/configuration/acme.md @@ -186,6 +186,9 @@ docker run -v "/my/host/acme:/etc/traefik/acme" traefik 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 [acme] # ... diff --git a/docs/configuration/backends/file.md b/docs/configuration/backends/file.md index 3424bdbe4..cff38aba5 100644 --- a/docs/configuration/backends/file.md +++ b/docs/configuration/backends/file.md @@ -1,6 +1,140 @@ # 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: @@ -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). -## Simple +### Simple Add your configuration at the end of the global configuration file `traefik.toml`: @@ -21,80 +155,33 @@ defaultEntryPoints = ["http", "https"] [entryPoints] [entryPoints.http] - address = ":80" - [entryPoints.http.redirect] - entryPoint = "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] # rules [backends] [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.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.frontend1] - backend = "backend2" - [frontends.frontend1.routes.test_1] - rule = "Host:test.localhost" - + # ... [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] - entrypoints = ["http", "https"] # overrides defaultEntryPoints - backend = "backend2" - rule = "Path:/test" + # ... # HTTPS certificate [[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" + # ... ``` !!! 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. 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`: ```toml # traefik.toml +defaultEntryPoints = ["http", "https"] + [entryPoints] [entryPoints.http] - address = ":80" - [entryPoints.http.redirect] - entryPoint = "https" + # ... [entryPoints.https] - address = ":443" - [entryPoints.https.tls] + # ... [file] -filename = "rules.toml" + filename = "rules.toml" ``` ```toml # rules.toml [backends] [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.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.frontend1] - backend = "backend2" - [frontends.frontend1.routes.test_1] - rule = "Host:test.localhost" + # ... [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] - entrypoints = ["http", "https"] # overrides defaultEntryPoints - backend = "backend2" - rule = "Path:/test" - + # ... + # HTTPS certificate [[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): ```toml [file] -directory = "/path/to/config/" + directory = "/path/to/config/" ``` If you want Træfik to watch file changes automatically, just add: ```toml [file] -watch = true + watch = true ``` diff --git a/docs/configuration/backends/kubernetes.md b/docs/configuration/backends/kubernetes.md index 6093a9a80..632af9600 100644 --- a/docs/configuration/backends/kubernetes.md +++ b/docs/configuration/backends/kubernetes.md @@ -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-proxy-headers:EXPR` | Header combinations that would signify a proper SSL Request (Such as `X-Forwarded-For:https`). Format: HEADER:value||HEADER2:value2 | | `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/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`. | diff --git a/docs/configuration/commons.md b/docs/configuration/commons.md index 2aa9415ec..acf87a4f6 100644 --- a/docs/configuration/commons.md +++ b/docs/configuration/commons.md @@ -282,21 +282,17 @@ Multiple sets of rates can be added to each frontend, but the time periods must ```toml [frontends] [frontends.frontend1] - passHostHeader = true - entrypoints = ["http"] - backend = "backend1" - [frontends.frontend1.routes.test_1] - rule = "Path:/" - [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.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 ``` In the above example, frontend1 is configured to limit requests by the client's ip address. diff --git a/docs/configuration/entrypoints.md b/docs/configuration/entrypoints.md index 878e34ee4..dc51f9616 100644 --- a/docs/configuration/entrypoints.md +++ b/docs/configuration/entrypoints.md @@ -1,5 +1,72 @@ # 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 # Entrypoints definition # @@ -71,7 +138,7 @@ Define an entrypoint with SNI support. !!! note If an empty TLS configuration is done, default self-signed certificates are generated. - + ### Dynamic Certificates @@ -162,7 +229,7 @@ Otherwise, the response from the auth server is returned. # To enable forward auth on an entrypoint [entryPoints.http.auth.forward] address = "https://authserver.com/auth" - + # Trust existing X-Forwarded-* headers. # Useful with another reverse proxy in front of Traefik. # @@ -170,7 +237,7 @@ Otherwise, the response from the auth server is returned. # Default: false # trustForwardHeader = true - + # Enable forward auth TLS connection. # # Optional @@ -234,7 +301,7 @@ Only IPs in `trustedIPs` will lead to remote client address replacement: you sho !!! danger 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 [entryPoints] diff --git a/script/deploy.sh b/script/deploy.sh index ef2ec4b2a..8504e4ffb 100755 --- a/script/deploy.sh +++ b/script/deploy.sh @@ -28,14 +28,6 @@ echo $VERSION | git commit --file - echo $VERSION | git tag -a $VERSION --file - 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 .. rm -Rf traefik-library-image/ diff --git a/server/server.go b/server/server.go index 0f735d19a..fbda4830e 100644 --- a/server/server.go +++ b/server/server.go @@ -635,31 +635,27 @@ func (s *Server) createTLSConfig(entryPointName string, tlsOption *traefikTls.TL } if s.globalConfiguration.ACME != nil { - if _, ok := s.serverEntryPoints[s.globalConfiguration.ACME.EntryPoint]; ok { - if entryPointName == s.globalConfiguration.ACME.EntryPoint { - checkOnDemandDomain := func(domain string) bool { - routeMatch := &mux.RouteMatch{} - router := router.GetHandler() - match := router.Match(&http.Request{URL: &url.URL{}, Host: domain}, routeMatch) - if match && routeMatch.Route != nil { - return true - } - return false + if entryPointName == s.globalConfiguration.ACME.EntryPoint { + checkOnDemandDomain := func(domain string) bool { + routeMatch := &mux.RouteMatch{} + router := router.GetHandler() + match := router.Match(&http.Request{URL: &url.URL{}, Host: domain}, routeMatch) + if match && routeMatch.Route != nil { + return true } - if s.leadership == nil { - err := s.globalConfiguration.ACME.CreateLocalConfig(config, &s.serverEntryPoints[entryPointName].certs, checkOnDemandDomain) - if err != nil { - return nil, err - } - } else { - err := s.globalConfiguration.ACME.CreateClusterConfig(s.leadership, config, &s.serverEntryPoints[entryPointName].certs, checkOnDemandDomain) - if err != nil { - return nil, err - } + return false + } + if s.leadership == nil { + err := s.globalConfiguration.ACME.CreateLocalConfig(config, &s.serverEntryPoints[entryPointName].certs, checkOnDemandDomain) + if err != nil { + return nil, err + } + } else { + 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 { config.GetCertificate = s.serverEntryPoints[entryPointName].getCertificate @@ -887,23 +883,23 @@ func (s *Server) loadConfig(configurations types.Configurations, globalConfigura 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 { - 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) continue frontend } - var failedEntrypoints int for _, entryPointName := range frontend.EntryPoints { 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)} for routeName, route := range frontend.Routes { diff --git a/tls/certificate.go b/tls/certificate.go index b0a7ef9e0..c293bedc2 100644 --- a/tls/certificate.go +++ b/tls/certificate.go @@ -150,7 +150,12 @@ func (c *Certificate) AppendCertificates(certs map[string]*DomainsCertificates, certKey := parsedCert.Subject.CommonName if parsedCert.DNSNames != nil { 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 diff --git a/vendor/github.com/NYTimes/gziphandler/gzip.go b/vendor/github.com/NYTimes/gziphandler/gzip.go index b3cb8315b..ae1ebe4bf 100644 --- a/vendor/github.com/NYTimes/gziphandler/gzip.go +++ b/vendor/github.com/NYTimes/gziphandler/gzip.go @@ -88,7 +88,7 @@ type GzipResponseWriterWithCloseNotify struct { *GzipResponseWriter } -func (w *GzipResponseWriterWithCloseNotify) CloseNotify() <-chan bool { +func (w GzipResponseWriterWithCloseNotify) CloseNotify() <-chan bool { return w.ResponseWriter.(http.CloseNotifier).CloseNotify() } diff --git a/vendor/github.com/go-kit/kit/metrics/prometheus/prometheus.go b/vendor/github.com/go-kit/kit/metrics/prometheus/prometheus.go deleted file mode 100644 index 7a364c316..000000000 --- a/vendor/github.com/go-kit/kit/metrics/prometheus/prometheus.go +++ /dev/null @@ -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 -}