Merge v1.6.4 into master
This commit is contained in:
commit
586ba31120
28 changed files with 166 additions and 43 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -1,5 +1,22 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## [v1.6.4](https://github.com/containous/traefik/tree/v1.6.4) (2018-06-15)
|
||||||
|
[All Commits](https://github.com/containous/traefik/compare/v1.6.3...v1.6.4)
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[acme]** Use logrus writer instead of os.Stderr ([#3498](https://github.com/containous/traefik/pull/3498) by [ldez](https://github.com/ldez))
|
||||||
|
- **[consulcatalog]** Enclose IPv6 addresses in "[]" ([#3477](https://github.com/containous/traefik/pull/3477) by [herver](https://github.com/herver))
|
||||||
|
- **[docker,ecs,marathon,mesos,rancher]** Use net.JoinHostPort for servers URL ([#3484](https://github.com/containous/traefik/pull/3484) by [ldez](https://github.com/ldez))
|
||||||
|
- **[docker]** Backend name with docker-compose and segments. ([#3485](https://github.com/containous/traefik/pull/3485) by [ldez](https://github.com/ldez))
|
||||||
|
- **[oxy]** Handle buffer pool for oxy ([#3450](https://github.com/containous/traefik/pull/3450) by [Juliens](https://github.com/Juliens))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- **[acme]** The exoscale provider works with wildcard ([#3479](https://github.com/containous/traefik/pull/3479) by [greut](https://github.com/greut))
|
||||||
|
- **[consul,docker]** Edit wording ([#3438](https://github.com/containous/traefik/pull/3438) by [mayank23](https://github.com/mayank23))
|
||||||
|
- **[k8s]** Add missing annotation documentation. ([#3454](https://github.com/containous/traefik/pull/3454) by [ldez](https://github.com/ldez))
|
||||||
|
- **[kv]** Fix typo in kv user guide ([#3474](https://github.com/containous/traefik/pull/3474) by [shambarick](https://github.com/shambarick))
|
||||||
|
- Clean metrics documentation. ([#3488](https://github.com/containous/traefik/pull/3488) by [ldez](https://github.com/ldez))
|
||||||
|
|
||||||
## [v1.6.3](https://github.com/containous/traefik/tree/v1.6.3) (2018-06-05)
|
## [v1.6.3](https://github.com/containous/traefik/tree/v1.6.3) (2018-06-05)
|
||||||
[All Commits](https://github.com/containous/traefik/compare/v1.6.2...v1.6.3)
|
[All Commits](https://github.com/containous/traefik/compare/v1.6.2...v1.6.3)
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ _(But if you'd rather configure some of your routes manually, Træfik supports t
|
||||||
- Websocket, HTTP/2, GRPC ready
|
- Websocket, HTTP/2, GRPC ready
|
||||||
- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB)
|
- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB)
|
||||||
- Keeps access logs (JSON, CLF)
|
- Keeps access logs (JSON, CLF)
|
||||||
- [Fast](https://docs.traefik.io/benchmarks) ... which is nice
|
- Fast
|
||||||
- Exposes a Rest API
|
- Exposes a Rest API
|
||||||
- Packaged as a single binary file (made with :heart: with go) and available as a [tiny](https://microbadger.com/images/traefik) [official](https://hub.docker.com/r/_/traefik/) docker image
|
- Packaged as a single binary file (made with :heart: with go) and available as a [tiny](https://microbadger.com/images/traefik) [official](https://hub.docker.com/r/_/traefik/) docker image
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
fmtlog "log"
|
fmtlog "log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -27,6 +26,7 @@ import (
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/containous/traefik/version"
|
"github.com/containous/traefik/version"
|
||||||
"github.com/eapache/channels"
|
"github.com/eapache/channels"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
legolog "github.com/xenolf/lego/log"
|
legolog "github.com/xenolf/lego/log"
|
||||||
"github.com/xenolf/lego/providers/dns"
|
"github.com/xenolf/lego/providers/dns"
|
||||||
|
@ -67,16 +67,19 @@ type ACME struct {
|
||||||
|
|
||||||
func (a *ACME) init() error {
|
func (a *ACME) init() error {
|
||||||
acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version)
|
acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version)
|
||||||
|
|
||||||
if a.ACMELogging {
|
if a.ACMELogging {
|
||||||
legolog.Logger = fmtlog.New(os.Stderr, "legolog: ", fmtlog.LstdFlags)
|
legolog.Logger = fmtlog.New(log.WriterLevel(logrus.DebugLevel), "legolog: ", 0)
|
||||||
} else {
|
} else {
|
||||||
legolog.Logger = fmtlog.New(ioutil.Discard, "", 0)
|
legolog.Logger = fmtlog.New(ioutil.Discard, "", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// no certificates in TLS config, so we add a default one
|
// no certificates in TLS config, so we add a default one
|
||||||
cert, err := generate.DefaultCertificate()
|
cert, err := generate.DefaultCertificate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.defaultCertificate = cert
|
a.defaultCertificate = cert
|
||||||
|
|
||||||
a.jobs = channels.NewInfiniteChannel()
|
a.jobs = channels.NewInfiniteChannel()
|
||||||
|
|
|
@ -203,7 +203,7 @@ Here is a list of supported `provider`s, that can automate the DNS verification,
|
||||||
| [Duck DNS](https://www.duckdns.org/) | `duckdns` | `DUCKDNS_TOKEN` | Not tested yet |
|
| [Duck DNS](https://www.duckdns.org/) | `duckdns` | `DUCKDNS_TOKEN` | Not tested yet |
|
||||||
| [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` | Not tested yet |
|
| [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` | Not tested yet |
|
||||||
| External Program | `exec` | `EXEC_PATH` | Not tested yet |
|
| External Program | `exec` | `EXEC_PATH` | Not tested yet |
|
||||||
| [Exoscale](https://www.exoscale.ch) | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT` | Not tested yet |
|
| [Exoscale](https://www.exoscale.ch) | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT` | YES |
|
||||||
| [Fast DNS](https://www.akamai.com/) | `fastdns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | Not tested yet |
|
| [Fast DNS](https://www.akamai.com/) | `fastdns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | Not tested yet |
|
||||||
| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | Not tested yet |
|
| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | Not tested yet |
|
||||||
| [Gandi V5](http://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | Not tested yet |
|
| [Gandi V5](http://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | Not tested yet |
|
||||||
|
|
|
@ -158,6 +158,7 @@ The following general annotations are applicable on the Ingress object:
|
||||||
| `traefik.ingress.kubernetes.io/rewrite-target: /users` | Replaces each matched Ingress path with the specified one, and adds the old path to the `X-Replaced-Path` header. |
|
| `traefik.ingress.kubernetes.io/rewrite-target: /users` | Replaces each matched Ingress path with the specified one, and adds the old path to the `X-Replaced-Path` header. |
|
||||||
| `traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip` | Override the default frontend rule type. Default: `PathPrefix`. |
|
| `traefik.ingress.kubernetes.io/rule-type: PathPrefixStrip` | Override the default frontend rule type. Default: `PathPrefix`. |
|
||||||
| `traefik.ingress.kubernetes.io/whitelist-source-range: "1.2.3.0/24, fe80::/16"` | A comma-separated list of IP ranges permitted for access. all source IPs are permitted if the list is empty or a single range is ill-formatted. Please note, you may have to set `service.spec.externalTrafficPolicy` to the value `Local` to preserve the source IP of the request for filtering. Please see [this link](https://kubernetes.io/docs/tutorials/services/source-ip/) for more information.|
|
| `traefik.ingress.kubernetes.io/whitelist-source-range: "1.2.3.0/24, fe80::/16"` | A comma-separated list of IP ranges permitted for access. all source IPs are permitted if the list is empty or a single range is ill-formatted. Please note, you may have to set `service.spec.externalTrafficPolicy` to the value `Local` to preserve the source IP of the request for filtering. Please see [this link](https://kubernetes.io/docs/tutorials/services/source-ip/) for more information.|
|
||||||
|
| `ingress.kubernetes.io/whitelist-x-forwarded-for: "true"` | Use `X-Forwarded-For` header as valid source of IP for the white list. |
|
||||||
| `traefik.ingress.kubernetes.io/app-root: "/index.html"` | Redirects all requests for `/` to the defined path. (4) |
|
| `traefik.ingress.kubernetes.io/app-root: "/index.html"` | Redirects all requests for `/` to the defined path. (4) |
|
||||||
|
|
||||||
<1> `traefik.ingress.kubernetes.io/error-pages` example:
|
<1> `traefik.ingress.kubernetes.io/error-pages` example:
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
### InfluxDB
|
## InfluxDB
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[metrics]
|
[metrics]
|
||||||
|
@ -127,22 +127,3 @@
|
||||||
|
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Statistics
|
|
||||||
|
|
||||||
```toml
|
|
||||||
# Metrics definition
|
|
||||||
[metrics]
|
|
||||||
# ...
|
|
||||||
|
|
||||||
# Enable more detailed statistics.
|
|
||||||
[metrics.statistics]
|
|
||||||
|
|
||||||
# Number of recent errors logged.
|
|
||||||
#
|
|
||||||
# Default: 10
|
|
||||||
#
|
|
||||||
recentErrors = 10
|
|
||||||
|
|
||||||
# ...
|
|
||||||
```
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ _(But if you'd rather configure some of your routes manually, Træfik supports t
|
||||||
- Websocket, HTTP/2, GRPC ready
|
- Websocket, HTTP/2, GRPC ready
|
||||||
- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB)
|
- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB)
|
||||||
- Keeps access logs (JSON, CLF)
|
- Keeps access logs (JSON, CLF)
|
||||||
- [Fast](/benchmarks) ... which is nice
|
- Fast
|
||||||
- Exposes a Rest API
|
- Exposes a Rest API
|
||||||
- Packaged as a single binary file (made with :heart: with go) and available as a [tiny](https://microbadger.com/images/traefik) [official](https://hub.docker.com/r/_/traefik/) docker image
|
- Packaged as a single binary file (made with :heart: with go) and available as a [tiny](https://microbadger.com/images/traefik) [official](https://hub.docker.com/r/_/traefik/) docker image
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ If you want to use Let's Encrypt with Træfik, sharing configuration or TLS cert
|
||||||
Ok, could we mount a shared volume used by all my instances? Yes, you can, but it will not work.
|
Ok, could we mount a shared volume used by all my instances? Yes, you can, but it will not work.
|
||||||
When you use Let's Encrypt, you need to store certificates, but not only.
|
When you use Let's Encrypt, you need to store certificates, but not only.
|
||||||
When Træfik generates a new certificate, it configures a challenge and once Let's Encrypt will verify the ownership of the domain, it will ping back the challenge.
|
When Træfik generates a new certificate, it configures a challenge and once Let's Encrypt will verify the ownership of the domain, it will ping back the challenge.
|
||||||
If the challenge is not knowing by other Træfik instances, the validation will fail.
|
If the challenge is not known by other Træfik instances, the validation will fail.
|
||||||
|
|
||||||
For more information about challenge: [Automatic Certificate Management Environment (ACME)](https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#http-challenge)
|
For more information about the challenge: [Automatic Certificate Management Environment (ACME)](https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#http-challenge)
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
|
|
|
@ -355,7 +355,7 @@ And there, the same dynamic configuration in a KV Store (using `prefix = "traefi
|
||||||
|---------------------------------------|-----------------------|
|
|---------------------------------------|-----------------------|
|
||||||
| `/traefik/tls/2/entrypoints` | `https,other-https` |
|
| `/traefik/tls/2/entrypoints` | `https,other-https` |
|
||||||
| `/traefik/tls/2/certificate/certfile` | `<cert file content>` |
|
| `/traefik/tls/2/certificate/certfile` | `<cert file content>` |
|
||||||
| `/traefik/tls/2/certificate/certfile` | `<key file content>` |
|
| `/traefik/tls/2/certificate/keyfile` | `<key file content>` |
|
||||||
|
|
||||||
### Atomic configuration changes
|
### Atomic configuration changes
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"]
|
||||||
email = "test@traefik.io"
|
email = "test@traefik.io"
|
||||||
storage = "/tmp/acme.json"
|
storage = "/tmp/acme.json"
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
|
acmeLogging = true
|
||||||
onDemand = {{.OnDemand}}
|
onDemand = {{.OnDemand}}
|
||||||
onHostRule = {{.OnHostRule}}
|
onHostRule = {{.OnHostRule}}
|
||||||
caServer = "http://{{.BoulderHost}}:4001/directory"
|
caServer = "http://{{.BoulderHost}}:4001/directory"
|
||||||
|
|
|
@ -13,6 +13,7 @@ defaultEntryPoints = ["http", "https"]
|
||||||
email = "test@traefik.io"
|
email = "test@traefik.io"
|
||||||
storage = "/tmp/acme.json"
|
storage = "/tmp/acme.json"
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
|
acmeLogging = true
|
||||||
onDemand = {{.OnDemand}}
|
onDemand = {{.OnDemand}}
|
||||||
onHostRule = {{.OnHostRule}}
|
onHostRule = {{.OnHostRule}}
|
||||||
caServer = "http://{{.BoulderHost}}:4001/directory"
|
caServer = "http://{{.BoulderHost}}:4001/directory"
|
||||||
|
|
|
@ -16,6 +16,7 @@ defaultEntryPoints = ["http", "https"]
|
||||||
email = "test@traefik.io"
|
email = "test@traefik.io"
|
||||||
storage = "/tmp/acme.json"
|
storage = "/tmp/acme.json"
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
|
acmeLogging = true
|
||||||
onDemand = {{.OnDemand}}
|
onDemand = {{.OnDemand}}
|
||||||
onHostRule = {{.OnHostRule}}
|
onHostRule = {{.OnHostRule}}
|
||||||
caServer = "http://{{.BoulderHost}}:4001/directory"
|
caServer = "http://{{.BoulderHost}}:4001/directory"
|
||||||
|
|
|
@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"]
|
||||||
email = "test@traefik.io"
|
email = "test@traefik.io"
|
||||||
storage = "/tmp/acme.json"
|
storage = "/tmp/acme.json"
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
|
acmeLogging = true
|
||||||
onDemand = {{.OnDemand}}
|
onDemand = {{.OnDemand}}
|
||||||
onHostRule = {{.OnHostRule}}
|
onHostRule = {{.OnHostRule}}
|
||||||
caServer = "http://{{.BoulderHost}}:4001/directory"
|
caServer = "http://{{.BoulderHost}}:4001/directory"
|
||||||
|
|
|
@ -17,6 +17,7 @@ email = "test@traefik.io"
|
||||||
storage = "/tmp/acme.json"
|
storage = "/tmp/acme.json"
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
onHostRule = true
|
onHostRule = true
|
||||||
|
acmeLogging = true
|
||||||
caServer = "http://{{.BoulderHost}}:4001/directory"
|
caServer = "http://{{.BoulderHost}}:4001/directory"
|
||||||
# No challenge defined
|
# No challenge defined
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ defaultEntryPoints = ["http", "https"]
|
||||||
email = "test@traefik.io"
|
email = "test@traefik.io"
|
||||||
storage = "/tmp/acme.json"
|
storage = "/tmp/acme.json"
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
|
acmeLogging = true
|
||||||
onHostRule = true
|
onHostRule = true
|
||||||
caServer = "http://wrongurl:4001/directory"
|
caServer = "http://wrongurl:4001/directory"
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"]
|
||||||
email = "test@traefik.io"
|
email = "test@traefik.io"
|
||||||
storage = "/tmp/acme.json"
|
storage = "/tmp/acme.json"
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
|
acmeLogging = true
|
||||||
onDemand = {{.OnDemand}}
|
onDemand = {{.OnDemand}}
|
||||||
onHostRule = {{.OnHostRule}}
|
onHostRule = {{.OnHostRule}}
|
||||||
caServer = "http://{{.BoulderHost}}:4001/directory"
|
caServer = "http://{{.BoulderHost}}:4001/directory"
|
||||||
|
|
|
@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"]
|
||||||
email = "test@traefik.io"
|
email = "test@traefik.io"
|
||||||
storage = "/tmp/acme.json"
|
storage = "/tmp/acme.json"
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
|
acmeLogging = true
|
||||||
onDemand = false
|
onDemand = false
|
||||||
onHostRule = false
|
onHostRule = false
|
||||||
caServer = "http://{{.BoulderHost}}:4001/directory"
|
caServer = "http://{{.BoulderHost}}:4001/directory"
|
||||||
|
|
|
@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"]
|
||||||
email = "test@traefik.io"
|
email = "test@traefik.io"
|
||||||
storage = "/tmp/acme.json"
|
storage = "/tmp/acme.json"
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
|
acmeLogging = true
|
||||||
onDemand = {{.OnDemand}}
|
onDemand = {{.OnDemand}}
|
||||||
onHostRule = {{.OnHostRule}}
|
onHostRule = {{.OnHostRule}}
|
||||||
caServer = "http://{{.BoulderHost}}:4001/directory"
|
caServer = "http://{{.BoulderHost}}:4001/directory"
|
||||||
|
|
|
@ -101,4 +101,3 @@ pages:
|
||||||
- 'Clustering/HA': 'user-guide/cluster.md'
|
- 'Clustering/HA': 'user-guide/cluster.md'
|
||||||
- 'gRPC Example': 'user-guide/grpc.md'
|
- 'gRPC Example': 'user-guide/grpc.md'
|
||||||
- 'Traefik cluster example with Swarm': 'user-guide/cluster-docker-consul.md'
|
- 'Traefik cluster example with Swarm': 'user-guide/cluster-docker-consul.md'
|
||||||
- Benchmarks: benchmarks.md
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
fmtlog "log"
|
fmtlog "log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -24,6 +23,7 @@ import (
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/containous/traefik/version"
|
"github.com/containous/traefik/version"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
legolog "github.com/xenolf/lego/log"
|
legolog "github.com/xenolf/lego/log"
|
||||||
"github.com/xenolf/lego/providers/dns"
|
"github.com/xenolf/lego/providers/dns"
|
||||||
|
@ -90,7 +90,7 @@ func (p *Provider) SetConfigListenerChan(configFromListenerChan chan types.Confi
|
||||||
func (p *Provider) init() error {
|
func (p *Provider) init() error {
|
||||||
acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version)
|
acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version)
|
||||||
if p.ACMELogging {
|
if p.ACMELogging {
|
||||||
legolog.Logger = fmtlog.New(os.Stderr, "legolog: ", fmtlog.LstdFlags)
|
legolog.Logger = fmtlog.New(log.WriterLevel(logrus.DebugLevel), "legolog: ", 0)
|
||||||
} else {
|
} else {
|
||||||
legolog.Logger = fmtlog.New(ioutil.Discard, "", 0)
|
legolog.Logger = fmtlog.New(ioutil.Discard, "", 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -116,7 +117,7 @@ func (p *Provider) getServer(node *api.ServiceEntry) types.Server {
|
||||||
address := getBackendAddress(node)
|
address := getBackendAddress(node)
|
||||||
|
|
||||||
return types.Server{
|
return types.Server{
|
||||||
URL: fmt.Sprintf("%s://%s:%d", scheme, address, node.Service.Port),
|
URL: fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(address, strconv.Itoa(node.Service.Port))),
|
||||||
Weight: p.getWeight(node.Service.Tags),
|
Weight: p.getWeight(node.Service.Tags),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -377,6 +377,97 @@ func TestProviderBuildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Should build config containing one frontend, one IPv4 and one IPv6 backend",
|
||||||
|
nodes: []catalogUpdate{
|
||||||
|
{
|
||||||
|
Service: &serviceUpdate{
|
||||||
|
ServiceName: "test",
|
||||||
|
Attributes: []string{
|
||||||
|
"random.foo=bar",
|
||||||
|
label.TraefikBackendLoadBalancerMethod + "=drr",
|
||||||
|
label.TraefikBackendCircuitBreakerExpression + "=NetworkErrorRatio() > 0.5",
|
||||||
|
label.TraefikBackendMaxConnAmount + "=1000",
|
||||||
|
label.TraefikBackendMaxConnExtractorFunc + "=client.ip",
|
||||||
|
label.TraefikFrontendAuthBasic + "=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Nodes: []*api.ServiceEntry{
|
||||||
|
{
|
||||||
|
Service: &api.AgentService{
|
||||||
|
Service: "test",
|
||||||
|
Address: "127.0.0.1",
|
||||||
|
Port: 80,
|
||||||
|
Tags: []string{
|
||||||
|
"random.foo=bar",
|
||||||
|
label.Prefix + "backend.weight=42", // Deprecated label
|
||||||
|
label.TraefikFrontendPassHostHeader + "=true",
|
||||||
|
label.TraefikProtocol + "=https",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Node: &api.Node{
|
||||||
|
Node: "localhost",
|
||||||
|
Address: "127.0.0.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Service: &api.AgentService{
|
||||||
|
Service: "test",
|
||||||
|
Address: "::1",
|
||||||
|
Port: 80,
|
||||||
|
Tags: []string{
|
||||||
|
"random.foo=bar",
|
||||||
|
label.Prefix + "backend.weight=42", // Deprecated label
|
||||||
|
label.TraefikFrontendPassHostHeader + "=true",
|
||||||
|
label.TraefikProtocol + "=https",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Node: &api.Node{
|
||||||
|
Node: "localhost",
|
||||||
|
Address: "::1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFrontends: map[string]*types.Frontend{
|
||||||
|
"frontend-test": {
|
||||||
|
Backend: "backend-test",
|
||||||
|
PassHostHeader: true,
|
||||||
|
Routes: map[string]types.Route{
|
||||||
|
"route-host-test": {
|
||||||
|
Rule: "Host:test.localhost",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
EntryPoints: []string{},
|
||||||
|
BasicAuth: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedBackends: map[string]*types.Backend{
|
||||||
|
"backend-test": {
|
||||||
|
Servers: map[string]types.Server{
|
||||||
|
"test-0-us4-27hAOu2ARV7nNrmv6GoKlcA": {
|
||||||
|
URL: "https://127.0.0.1:80",
|
||||||
|
Weight: 42,
|
||||||
|
},
|
||||||
|
"test-1-Gh4zrXo5flAAz1A8LAEHm1-TSnE": {
|
||||||
|
URL: "https://[::1]:80",
|
||||||
|
Weight: 42,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
LoadBalancer: &types.LoadBalancer{
|
||||||
|
Method: "drr",
|
||||||
|
},
|
||||||
|
CircuitBreaker: &types.CircuitBreaker{
|
||||||
|
Expression: "NetworkErrorRatio() > 0.5",
|
||||||
|
},
|
||||||
|
MaxConn: &types.MaxConn{
|
||||||
|
Amount: 1000,
|
||||||
|
ExtractorFunc: "client.ip",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package docker
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
@ -262,11 +263,16 @@ func isBackendLBSwarm(container dockerData) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSegmentBackendName(container dockerData) string {
|
func getSegmentBackendName(container dockerData) string {
|
||||||
if value := label.GetStringValue(container.SegmentLabels, label.TraefikBackend, ""); len(value) > 0 {
|
serviceName := container.ServiceName
|
||||||
return provider.Normalize(container.ServiceName + "-" + value)
|
if values, err := label.GetStringMultipleStrict(container.Labels, labelDockerComposeProject, labelDockerComposeService); err == nil {
|
||||||
|
serviceName = provider.Normalize(values[labelDockerComposeService] + "_" + values[labelDockerComposeProject])
|
||||||
}
|
}
|
||||||
|
|
||||||
return provider.Normalize(container.ServiceName + "-" + getDefaultBackendName(container) + "-" + container.SegmentName)
|
if value := label.GetStringValue(container.SegmentLabels, label.TraefikBackend, ""); len(value) > 0 {
|
||||||
|
return provider.Normalize(serviceName + "-" + value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider.Normalize(serviceName + "-" + getDefaultBackendName(container) + "-" + container.SegmentName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultBackendName(container dockerData) string {
|
func getDefaultBackendName(container dockerData) string {
|
||||||
|
@ -336,7 +342,7 @@ func (p *Provider) getServers(containers []dockerData) map[string]types.Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
servers[provider.Normalize(serverName)] = types.Server{
|
servers[provider.Normalize(serverName)] = types.Server{
|
||||||
URL: fmt.Sprintf("%s://%s:%s", protocol, ip, port),
|
URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(ip, port)),
|
||||||
Weight: label.GetIntValue(container.SegmentLabels, label.TraefikWeight, label.DefaultWeight),
|
Weight: label.GetIntValue(container.SegmentLabels, label.TraefikWeight, label.DefaultWeight),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -940,6 +940,7 @@ func TestDockerGetFrontendRule(t *testing.T) {
|
||||||
func TestDockerGetBackendName(t *testing.T) {
|
func TestDockerGetBackendName(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
container docker.ContainerJSON
|
container docker.ContainerJSON
|
||||||
|
segmentName string
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
@ -963,6 +964,15 @@ func TestDockerGetBackendName(t *testing.T) {
|
||||||
})),
|
})),
|
||||||
expected: "bar-foo",
|
expected: "bar-foo",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
container: containerJSON(labels(map[string]string{
|
||||||
|
"com.docker.compose.project": "foo",
|
||||||
|
"com.docker.compose.service": "bar",
|
||||||
|
"traefik.sauternes.backend": "titi",
|
||||||
|
})),
|
||||||
|
segmentName: "sauternes",
|
||||||
|
expected: "bar-foo-titi",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for containerID, test := range testCases {
|
for containerID, test := range testCases {
|
||||||
|
@ -972,7 +982,8 @@ func TestDockerGetBackendName(t *testing.T) {
|
||||||
|
|
||||||
dData := parseContainer(test.container)
|
dData := parseContainer(test.container)
|
||||||
segmentProperties := label.ExtractTraefikLabels(dData.Labels)
|
segmentProperties := label.ExtractTraefikLabels(dData.Labels)
|
||||||
dData.SegmentLabels = segmentProperties[""]
|
dData.SegmentLabels = segmentProperties[test.segmentName]
|
||||||
|
dData.SegmentName = test.segmentName
|
||||||
|
|
||||||
actual := getBackendName(dData)
|
actual := getBackendName(dData)
|
||||||
assert.Equal(t, test.expected, actual)
|
assert.Equal(t, test.expected, actual)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ecs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
@ -133,7 +134,7 @@ func getServers(instances []ecsInstance) map[string]types.Server {
|
||||||
|
|
||||||
serverName := provider.Normalize(fmt.Sprintf("server-%s-%s", instance.Name, instance.ID))
|
serverName := provider.Normalize(fmt.Sprintf("server-%s-%s", instance.Name, instance.ID))
|
||||||
servers[serverName] = types.Server{
|
servers[serverName] = types.Server{
|
||||||
URL: fmt.Sprintf("%s://%s:%s", protocol, host, port),
|
URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(host, port)),
|
||||||
Weight: label.GetIntValue(instance.TraefikLabels, label.TraefikWeight, label.DefaultWeight),
|
Weight: label.GetIntValue(instance.TraefikLabels, label.TraefikWeight, label.DefaultWeight),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
@ -340,7 +341,7 @@ func (p *Provider) getServer(app appData, task marathon.Task) (string, *types.Se
|
||||||
serverName := provider.Normalize("server-" + app.ID + "-" + task.ID + getSegmentNameSuffix(app.SegmentName))
|
serverName := provider.Normalize("server-" + app.ID + "-" + task.ID + getSegmentNameSuffix(app.SegmentName))
|
||||||
|
|
||||||
return serverName, &types.Server{
|
return serverName, &types.Server{
|
||||||
URL: fmt.Sprintf("%s://%s:%v", protocol, host, port),
|
URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(host, port)),
|
||||||
Weight: label.GetIntValue(app.SegmentLabels, label.TraefikWeight, label.DefaultWeight),
|
Weight: label.GetIntValue(app.SegmentLabels, label.TraefikWeight, label.DefaultWeight),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package mesos
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
@ -237,7 +238,7 @@ func (p *Provider) getServers(tasks []taskData) map[string]types.Server {
|
||||||
|
|
||||||
serverName := "server-" + getID(task)
|
serverName := "server-" + getID(task)
|
||||||
servers[serverName] = types.Server{
|
servers[serverName] = types.Server{
|
||||||
URL: fmt.Sprintf("%s://%s:%s", protocol, host, port),
|
URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(host, port)),
|
||||||
Weight: getIntValue(task.TraefikLabels, label.TraefikWeight, label.DefaultWeight, math.MaxInt32),
|
Weight: getIntValue(task.TraefikLabels, label.TraefikWeight, label.DefaultWeight, math.MaxInt32),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package rancher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
@ -181,7 +182,7 @@ func getServers(service rancherData) map[string]types.Server {
|
||||||
|
|
||||||
serverName := "server-" + strconv.Itoa(index)
|
serverName := "server-" + strconv.Itoa(index)
|
||||||
servers[serverName] = types.Server{
|
servers[serverName] = types.Server{
|
||||||
URL: fmt.Sprintf("%s://%s:%s", protocol, ip, port),
|
URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(ip, port)),
|
||||||
Weight: weight,
|
Weight: weight,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue