Merge 'v1.5.0-rc2' into master
This commit is contained in:
commit
260ee980e0
8 changed files with 119 additions and 40 deletions
36
CHANGELOG.md
36
CHANGELOG.md
|
@ -1,5 +1,41 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## [v1.5.0-rc2](https://github.com/containous/traefik/tree/v1.5.0-rc2) (2017-12-06)
|
||||||
|
[All Commits](https://github.com/containous/traefik/compare/v1.5.0-rc1...v1.5.0-rc2)
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[acme]** Modify the ACME renewing logs level ([#2520](https://github.com/containous/traefik/pull/2520) by [nmengin](https://github.com/nmengin))
|
||||||
|
- **[api]** Fix pprof route order. ([#2523](https://github.com/containous/traefik/pull/2523) by [timoreimann](https://github.com/timoreimann))
|
||||||
|
- **[docker,k8s]** Change custom headers separator ([#2509](https://github.com/containous/traefik/pull/2509) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker,k8s]** Fix Labels/annotation logs and values. ([#2488](https://github.com/containous/traefik/pull/2488) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker]** Quote template strings ([#2496](https://github.com/containous/traefik/pull/2496) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[docker]** Fix empty IP for backend when dnsrr in Docker swarm mode ([#2490](https://github.com/containous/traefik/pull/2490) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[healthcheck]** Fix healthcheck when web is not specified ([#2529](https://github.com/containous/traefik/pull/2529) by [Juliens](https://github.com/Juliens))
|
||||||
|
- **[k8s]** Reduce logs with new Kubernetes security annotations ([#2506](https://github.com/containous/traefik/pull/2506) by [ldez](https://github.com/ldez))
|
||||||
|
- **[metrics]** Do not ignore web params when web.metrics.prometheus is set ([#2499](https://github.com/containous/traefik/pull/2499) by [Juliens](https://github.com/Juliens))
|
||||||
|
- **[metrics]** Fix metrics problem on multiple entrypoints ([#2492](https://github.com/containous/traefik/pull/2492) by [Juliens](https://github.com/Juliens))
|
||||||
|
- Close ring buffer used in throttling function. ([#2532](https://github.com/containous/traefik/pull/2532) by [timoreimann](https://github.com/timoreimann))
|
||||||
|
- Fix wrong default entrypoint and non-existing entrypoint issue ([#2501](https://github.com/containous/traefik/pull/2501) by [Juliens](https://github.com/Juliens))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- **[consul]** Improve Consul documentation ([#2485](https://github.com/containous/traefik/pull/2485) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[docker]** Fix Docker labels documentation render. ([#2505](https://github.com/containous/traefik/pull/2505) by [ldez](https://github.com/ldez))
|
||||||
|
- **[k8s]** Add note to Kubernetes RBAC docs about RoleBindings and namespaces ([#2498](https://github.com/containous/traefik/pull/2498) by [jmara](https://github.com/jmara))
|
||||||
|
|
||||||
|
**Misc:**
|
||||||
|
- Merge v1.4.5 into v1.5 ([#2530](https://github.com/containous/traefik/pull/2530) by [mmatur](https://github.com/mmatur))
|
||||||
|
|
||||||
|
## [v1.4.5](https://github.com/containous/traefik/tree/v1.4.5) (2017-12-05)
|
||||||
|
[All Commits](https://github.com/containous/traefik/compare/v1.4.4...v1.4.5)
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[docker]** Fix empty ip when container is stopped ([#2478](https://github.com/containous/traefik/pull/2478) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[k8s]** Fix kubernetes path prefix rule with rewrite-target ([#2461](https://github.com/containous/traefik/pull/2461) by [cheungpat](https://github.com/cheungpat))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- **[file]** Emphasize the necessity of enabling file backend ([#2483](https://github.com/containous/traefik/pull/2483) by [mvasin](https://github.com/mvasin))
|
||||||
|
- Add link to future 1.5 documentation. ([#2477](https://github.com/containous/traefik/pull/2477) by [ldez](https://github.com/ldez))
|
||||||
|
|
||||||
## [v1.5.0-rc1](https://github.com/containous/traefik/tree/v1.5.0-rc1) (2017-11-28)
|
## [v1.5.0-rc1](https://github.com/containous/traefik/tree/v1.5.0-rc1) (2017-11-28)
|
||||||
[All Commits](https://github.com/containous/traefik/compare/v1.4.0-rc1...v1.5.0-rc1)
|
[All Commits](https://github.com/containous/traefik/compare/v1.4.0-rc1...v1.5.0-rc1)
|
||||||
|
|
||||||
|
|
65
acme/acme.go
65
acme/acme.go
|
@ -394,11 +394,35 @@ func (a *ACME) retrieveCertificates() {
|
||||||
|
|
||||||
func (a *ACME) renewCertificates() {
|
func (a *ACME) renewCertificates() {
|
||||||
a.jobs.In() <- func() {
|
a.jobs.In() <- func() {
|
||||||
log.Debug("Testing certificate renew...")
|
log.Info("Testing certificate renew...")
|
||||||
account := a.store.Get().(*Account)
|
account := a.store.Get().(*Account)
|
||||||
for _, certificateResource := range account.DomainsCertificate.Certs {
|
for _, certificateResource := range account.DomainsCertificate.Certs {
|
||||||
if certificateResource.needRenew() {
|
if certificateResource.needRenew() {
|
||||||
log.Debugf("Renewing certificate %+v", certificateResource.Domains)
|
log.Infof("Renewing certificate from LE : %+v", certificateResource.Domains)
|
||||||
|
renewedACMECert, err := a.renewACMECertificate(certificateResource)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error renewing certificate from LE: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
operation := func() error {
|
||||||
|
return a.storeRenewedCertificate(account, certificateResource, renewedACMECert)
|
||||||
|
}
|
||||||
|
notify := func(err error, time time.Duration) {
|
||||||
|
log.Warnf("Renewed certificate storage error: %v, retrying in %s", err, time)
|
||||||
|
}
|
||||||
|
ebo := backoff.NewExponentialBackOff()
|
||||||
|
ebo.MaxElapsedTime = 60 * time.Second
|
||||||
|
err = backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Datastore cannot sync: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACME) renewACMECertificate(certificateResource *DomainsCertificate) (*Certificate, error) {
|
||||||
renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{
|
renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{
|
||||||
Domain: certificateResource.Certificate.Domain,
|
Domain: certificateResource.Certificate.Domain,
|
||||||
CertURL: certificateResource.Certificate.CertURL,
|
CertURL: certificateResource.Certificate.CertURL,
|
||||||
|
@ -407,36 +431,45 @@ func (a *ACME) renewCertificates() {
|
||||||
Certificate: certificateResource.Certificate.Certificate,
|
Certificate: certificateResource.Certificate.Certificate,
|
||||||
}, true, OSCPMustStaple)
|
}, true, OSCPMustStaple)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error renewing certificate: %v", err)
|
return nil, err
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
log.Debugf("Renewed certificate %+v", certificateResource.Domains)
|
log.Infof("Renewed certificate from LE: %+v", certificateResource.Domains)
|
||||||
renewedACMECert := &Certificate{
|
return &Certificate{
|
||||||
Domain: renewedCert.Domain,
|
Domain: renewedCert.Domain,
|
||||||
CertURL: renewedCert.CertURL,
|
CertURL: renewedCert.CertURL,
|
||||||
CertStableURL: renewedCert.CertStableURL,
|
CertStableURL: renewedCert.CertStableURL,
|
||||||
PrivateKey: renewedCert.PrivateKey,
|
PrivateKey: renewedCert.PrivateKey,
|
||||||
Certificate: renewedCert.Certificate,
|
Certificate: renewedCert.Certificate,
|
||||||
}
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACME) storeRenewedCertificate(account *Account, certificateResource *DomainsCertificate, renewedACMECert *Certificate) error {
|
||||||
transaction, object, err := a.store.Begin()
|
transaction, object, err := a.store.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error renewing certificate: %v", err)
|
return fmt.Errorf("error during transaction initialization for renewing certificate: %v", err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("Renewing certificate in data store : %+v ", certificateResource.Domains)
|
||||||
account = object.(*Account)
|
account = object.(*Account)
|
||||||
err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains)
|
err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error renewing certificate: %v", err)
|
return fmt.Errorf("error renewing certificate in datastore: %v ", err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("Commit certificate renewed in data store : %+v", certificateResource.Domains)
|
||||||
if err = transaction.Commit(account); err != nil {
|
if err = transaction.Commit(account); err != nil {
|
||||||
log.Errorf("Error Saving ACME account %+v: %s", account, err.Error())
|
return fmt.Errorf("error saving ACME account %+v: %v", account, err)
|
||||||
continue
|
}
|
||||||
}
|
|
||||||
}
|
oldAccount := a.store.Get().(*Account)
|
||||||
|
for _, oldCertificateResource := range oldAccount.DomainsCertificate.Certs {
|
||||||
|
if oldCertificateResource.Domains.Main == certificateResource.Domains.Main && strings.Join(oldCertificateResource.Domains.SANs, ",") == strings.Join(certificateResource.Domains.SANs, ",") && certificateResource.Certificate != renewedACMECert {
|
||||||
|
return fmt.Errorf("renewed certificate not stored: %+v", certificateResource.Domains)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("Certificate successfully renewed in data store: %+v", certificateResource.Domains)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func dnsOverrideDelay(delay int) error {
|
func dnsOverrideDelay(delay int) error {
|
||||||
|
@ -448,7 +481,7 @@ func dnsOverrideDelay(delay int) error {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
} else if delay < 0 {
|
} else if delay < 0 {
|
||||||
err = fmt.Errorf("Invalid negative DelayDontCheckDNS: %d", delay)
|
err = fmt.Errorf("invalid negative DelayDontCheckDNS: %d", delay)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,9 @@ func (g DebugHandler) AddRoutes(router *mux.Router) {
|
||||||
fmt.Fprint(w, "\n}\n")
|
fmt.Fprint(w, "\n}\n")
|
||||||
})
|
})
|
||||||
|
|
||||||
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
|
|
||||||
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/cmdline").HandlerFunc(pprof.Cmdline)
|
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/cmdline").HandlerFunc(pprof.Cmdline)
|
||||||
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/profile").HandlerFunc(pprof.Profile)
|
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/profile").HandlerFunc(pprof.Profile)
|
||||||
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/symbol").HandlerFunc(pprof.Symbol)
|
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/symbol").HandlerFunc(pprof.Symbol)
|
||||||
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/trace").HandlerFunc(pprof.Trace)
|
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/trace").HandlerFunc(pprof.Trace)
|
||||||
|
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,9 @@ func healthCheck(globalConfiguration configuration.GlobalConfiguration) (*http.R
|
||||||
}
|
}
|
||||||
client.Transport = tr
|
client.Transport = tr
|
||||||
}
|
}
|
||||||
|
path := "/"
|
||||||
return client.Head(protocol + "://" + pingEntryPoint.Address + globalConfiguration.Web.Path + "ping")
|
if globalConfiguration.Web != nil {
|
||||||
|
path = globalConfiguration.Web.Path
|
||||||
|
}
|
||||||
|
return client.Head(protocol + "://" + pingEntryPoint.Address + path + "ping")
|
||||||
}
|
}
|
||||||
|
|
|
@ -620,7 +620,7 @@ This command allows to check the health of Traefik. Its exit status is `0` if Tr
|
||||||
This can be used with Docker [HEALTHCHECK](https://docs.docker.com/engine/reference/builder/#healthcheck) instruction or any other health check orchestration mechanism.
|
This can be used with Docker [HEALTHCHECK](https://docs.docker.com/engine/reference/builder/#healthcheck) instruction or any other health check orchestration mechanism.
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
The [`web` provider](/configuration/backends/web) must be enabled to allow `/ping` calls by the `healthcheck` command.
|
The [`ping`](/configuration/ping) must be enabled to allow the `healthcheck` command to call `/ping`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
traefik healthcheck
|
traefik healthcheck
|
||||||
|
|
|
@ -8,6 +8,8 @@ You have three choices:
|
||||||
- [Rules in a Separate File](/configuration/backends/file/#rules-in-a-separate-file)
|
- [Rules in a Separate File](/configuration/backends/file/#rules-in-a-separate-file)
|
||||||
- [Multiple `.toml` Files](/configuration/backends/file/#multiple-toml-files)
|
- [Multiple `.toml` Files](/configuration/backends/file/#multiple-toml-files)
|
||||||
|
|
||||||
|
To enable the file backend, you must either pass the `--file` option to the Træfik binary or put the `[file]` section (with or without inner settings) in the configuration file.
|
||||||
|
|
||||||
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
|
||||||
|
@ -153,15 +155,16 @@ filename = "rules.toml"
|
||||||
entrypoints = ["http", "https"] # overrides defaultEntryPoints
|
entrypoints = ["http", "https"] # overrides defaultEntryPoints
|
||||||
backend = "backend2"
|
backend = "backend2"
|
||||||
rule = "Path:/test"
|
rule = "Path:/test"
|
||||||
|
|
||||||
# HTTPS certificate
|
# HTTPS certificate
|
||||||
[[tlsConfiguration]]
|
[[tlsConfiguration]]
|
||||||
entryPoints = ["https"]
|
entryPoints = ["https"]
|
||||||
[tlsConfiguration.certificate]
|
[tlsConfiguration.certificate]
|
||||||
certFile = "integration/fixtures/https/snitest.com.cert"
|
certFile = "integration/fixtures/https/snitest.com.cert"
|
||||||
keyFile = "integration/fixtures/https/snitest.com.key"
|
keyFile = "integration/fixtures/https/snitest.com.key"
|
||||||
|
|
||||||
[[tlsConfiguration]]
|
[[tlsConfiguration]]
|
||||||
entryPoints = ["https"]
|
entryPoints = ["https"]
|
||||||
[[tlsConfiguration.certificates]]
|
[[tlsConfiguration.certificates]]
|
||||||
certFile = "integration/fixtures/https/snitest.org.cert"
|
certFile = "integration/fixtures/https/snitest.org.cert"
|
||||||
keyFile = "integration/fixtures/https/snitest.org.key"
|
keyFile = "integration/fixtures/https/snitest.org.key"
|
||||||
|
|
|
@ -21,6 +21,9 @@ If your cluster is configured with RBAC, you will need to authorize Træfik to u
|
||||||
|
|
||||||
RoleBindings per namespace enable to restrict granted permissions to the very namespaces only that Træfik is watching over, thereby following the least-privileges principle. This is the preferred approach if Træfik is not supposed to watch all namespaces, and the set of namespaces does not change dynamically. Otherwise, a single ClusterRoleBinding must be employed.
|
RoleBindings per namespace enable to restrict granted permissions to the very namespaces only that Træfik is watching over, thereby following the least-privileges principle. This is the preferred approach if Træfik is not supposed to watch all namespaces, and the set of namespaces does not change dynamically. Otherwise, a single ClusterRoleBinding must be employed.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
RoleBindings per namespace are available in Træfik 1.5 and later. Please use ClusterRoleBindings for older versions.
|
||||||
|
|
||||||
For the sake of simplicity, this guide will use a ClusterRoleBinding:
|
For the sake of simplicity, this guide will use a ClusterRoleBinding:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|
|
@ -374,6 +374,7 @@ func (s *Server) preLoadConfiguration(configMsg types.ConfigMessage) {
|
||||||
// it will publish the last of the newly received configurations.
|
// it will publish the last of the newly received configurations.
|
||||||
func throttleProviderConfigReload(throttle time.Duration, publish chan<- types.ConfigMessage, in <-chan types.ConfigMessage, stop chan bool) {
|
func throttleProviderConfigReload(throttle time.Duration, publish chan<- types.ConfigMessage, in <-chan types.ConfigMessage, stop chan bool) {
|
||||||
ring := channels.NewRingChannel(1)
|
ring := channels.NewRingChannel(1)
|
||||||
|
defer ring.Close()
|
||||||
|
|
||||||
safe.Go(func() {
|
safe.Go(func() {
|
||||||
for {
|
for {
|
||||||
|
|
Loading…
Reference in a new issue