diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c3ef84b16..f62889661d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # 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) [All Commits](https://github.com/containous/traefik/compare/v1.6.2...v1.6.3) diff --git a/README.md b/README.md index b82f3824ba..ff090d6fbc 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ _(But if you'd rather configure some of your routes manually, Træfik supports t - Websocket, HTTP/2, GRPC ready - Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB) - Keeps access logs (JSON, CLF) -- [Fast](https://docs.traefik.io/benchmarks) ... which is nice +- Fast - 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 diff --git a/acme/acme.go b/acme/acme.go index acbd946de8..201e682421 100644 --- a/acme/acme.go +++ b/acme/acme.go @@ -9,7 +9,6 @@ import ( fmtlog "log" "net" "net/http" - "os" "reflect" "strings" "time" @@ -27,6 +26,7 @@ import ( "github.com/containous/traefik/types" "github.com/containous/traefik/version" "github.com/eapache/channels" + "github.com/sirupsen/logrus" "github.com/xenolf/lego/acme" legolog "github.com/xenolf/lego/log" "github.com/xenolf/lego/providers/dns" @@ -67,16 +67,19 @@ type ACME struct { func (a *ACME) init() error { acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version) + if a.ACMELogging { - legolog.Logger = fmtlog.New(os.Stderr, "legolog: ", fmtlog.LstdFlags) + legolog.Logger = fmtlog.New(log.WriterLevel(logrus.DebugLevel), "legolog: ", 0) } else { legolog.Logger = fmtlog.New(ioutil.Discard, "", 0) } + // no certificates in TLS config, so we add a default one cert, err := generate.DefaultCertificate() if err != nil { return err } + a.defaultCertificate = cert a.jobs = channels.NewInfiniteChannel() diff --git a/docs/configuration/acme.md b/docs/configuration/acme.md index cb0b4c6d3f..5ba423b658 100644 --- a/docs/configuration/acme.md +++ b/docs/configuration/acme.md @@ -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 | | [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` | 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 | | [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 | diff --git a/docs/configuration/backends/kubernetes.md b/docs/configuration/backends/kubernetes.md index 4384b78adc..cd4ea8fbb7 100644 --- a/docs/configuration/backends/kubernetes.md +++ b/docs/configuration/backends/kubernetes.md @@ -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/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.| +| `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) | <1> `traefik.ingress.kubernetes.io/error-pages` example: diff --git a/docs/configuration/metrics.md b/docs/configuration/metrics.md index 34fe943be3..8ff1cb4b0a 100644 --- a/docs/configuration/metrics.md +++ b/docs/configuration/metrics.md @@ -81,7 +81,7 @@ # ... ``` -### InfluxDB +## InfluxDB ```toml [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 - - # ... -``` diff --git a/docs/index.md b/docs/index.md index fd72b03b84..52f85d6397 100644 --- a/docs/index.md +++ b/docs/index.md @@ -42,7 +42,7 @@ _(But if you'd rather configure some of your routes manually, Træfik supports t - Websocket, HTTP/2, GRPC ready - Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB) - Keeps access logs (JSON, CLF) -- [Fast](/benchmarks) ... which is nice +- Fast - 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 diff --git a/docs/user-guide/cluster-docker-consul.md b/docs/user-guide/cluster-docker-consul.md index 429432c8af..d9e8417bb9 100644 --- a/docs/user-guide/cluster-docker-consul.md +++ b/docs/user-guide/cluster-docker-consul.md @@ -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. 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. -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 diff --git a/docs/user-guide/kv-config.md b/docs/user-guide/kv-config.md index 8e94ac52f2..9a42491d8a 100644 --- a/docs/user-guide/kv-config.md +++ b/docs/user-guide/kv-config.md @@ -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/certificate/certfile` | `` | -| `/traefik/tls/2/certificate/certfile` | `` | +| `/traefik/tls/2/certificate/keyfile` | `` | ### Atomic configuration changes diff --git a/integration/fixtures/acme/acme_http01.toml b/integration/fixtures/acme/acme_http01.toml index 017e07e44e..d63b3dd3c7 100644 --- a/integration/fixtures/acme/acme_http01.toml +++ b/integration/fixtures/acme/acme_http01.toml @@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"] email = "test@traefik.io" storage = "/tmp/acme.json" entryPoint = "https" +acmeLogging = true onDemand = {{.OnDemand}} onHostRule = {{.OnHostRule}} caServer = "http://{{.BoulderHost}}:4001/directory" diff --git a/integration/fixtures/acme/acme_http01_web.toml b/integration/fixtures/acme/acme_http01_web.toml index 95316afaf6..58defc529a 100644 --- a/integration/fixtures/acme/acme_http01_web.toml +++ b/integration/fixtures/acme/acme_http01_web.toml @@ -13,6 +13,7 @@ defaultEntryPoints = ["http", "https"] email = "test@traefik.io" storage = "/tmp/acme.json" entryPoint = "https" +acmeLogging = true onDemand = {{.OnDemand}} onHostRule = {{.OnHostRule}} caServer = "http://{{.BoulderHost}}:4001/directory" diff --git a/integration/fixtures/acme/acme_provided.toml b/integration/fixtures/acme/acme_provided.toml index 3e83e09285..bf8825c293 100644 --- a/integration/fixtures/acme/acme_provided.toml +++ b/integration/fixtures/acme/acme_provided.toml @@ -16,6 +16,7 @@ defaultEntryPoints = ["http", "https"] email = "test@traefik.io" storage = "/tmp/acme.json" entryPoint = "https" +acmeLogging = true onDemand = {{.OnDemand}} onHostRule = {{.OnHostRule}} caServer = "http://{{.BoulderHost}}:4001/directory" diff --git a/integration/fixtures/acme/acme_provided_dynamic.toml b/integration/fixtures/acme/acme_provided_dynamic.toml index 552b840d36..cbfe51caa0 100644 --- a/integration/fixtures/acme/acme_provided_dynamic.toml +++ b/integration/fixtures/acme/acme_provided_dynamic.toml @@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"] email = "test@traefik.io" storage = "/tmp/acme.json" entryPoint = "https" +acmeLogging = true onDemand = {{.OnDemand}} onHostRule = {{.OnHostRule}} caServer = "http://{{.BoulderHost}}:4001/directory" diff --git a/integration/fixtures/acme/no_challenge_acme.toml b/integration/fixtures/acme/no_challenge_acme.toml index 2480bdaf8d..298d274482 100644 --- a/integration/fixtures/acme/no_challenge_acme.toml +++ b/integration/fixtures/acme/no_challenge_acme.toml @@ -17,6 +17,7 @@ email = "test@traefik.io" storage = "/tmp/acme.json" entryPoint = "https" onHostRule = true +acmeLogging = true caServer = "http://{{.BoulderHost}}:4001/directory" # No challenge defined diff --git a/integration/fixtures/acme/wrong_acme.toml b/integration/fixtures/acme/wrong_acme.toml index 4137ca3eb5..5cdc59a05a 100644 --- a/integration/fixtures/acme/wrong_acme.toml +++ b/integration/fixtures/acme/wrong_acme.toml @@ -16,6 +16,7 @@ defaultEntryPoints = ["http", "https"] email = "test@traefik.io" storage = "/tmp/acme.json" entryPoint = "https" +acmeLogging = true onHostRule = true caServer = "http://wrongurl:4001/directory" diff --git a/integration/fixtures/provideracme/acme.toml b/integration/fixtures/provideracme/acme.toml index 012a6386f8..722fd4740c 100644 --- a/integration/fixtures/provideracme/acme.toml +++ b/integration/fixtures/provideracme/acme.toml @@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"] email = "test@traefik.io" storage = "/tmp/acme.json" entryPoint = "https" + acmeLogging = true onDemand = {{.OnDemand}} onHostRule = {{.OnHostRule}} caServer = "http://{{.BoulderHost}}:4001/directory" diff --git a/integration/fixtures/provideracme/acme_insan.toml b/integration/fixtures/provideracme/acme_insan.toml index 3ddc5b5452..7287bc4b80 100644 --- a/integration/fixtures/provideracme/acme_insan.toml +++ b/integration/fixtures/provideracme/acme_insan.toml @@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"] email = "test@traefik.io" storage = "/tmp/acme.json" entryPoint = "https" + acmeLogging = true onDemand = false onHostRule = false caServer = "http://{{.BoulderHost}}:4001/directory" diff --git a/integration/fixtures/provideracme/acme_onhost.toml b/integration/fixtures/provideracme/acme_onhost.toml index 04ac1e9ada..3dae96e222 100644 --- a/integration/fixtures/provideracme/acme_onhost.toml +++ b/integration/fixtures/provideracme/acme_onhost.toml @@ -14,6 +14,7 @@ defaultEntryPoints = ["http", "https"] email = "test@traefik.io" storage = "/tmp/acme.json" entryPoint = "https" + acmeLogging = true onDemand = {{.OnDemand}} onHostRule = {{.OnHostRule}} caServer = "http://{{.BoulderHost}}:4001/directory" diff --git a/mkdocs.yml b/mkdocs.yml index 5e0bf50f67..3ac8fd1610 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -101,4 +101,3 @@ pages: - 'Clustering/HA': 'user-guide/cluster.md' - 'gRPC Example': 'user-guide/grpc.md' - 'Traefik cluster example with Swarm': 'user-guide/cluster-docker-consul.md' - - Benchmarks: benchmarks.md diff --git a/provider/acme/provider.go b/provider/acme/provider.go index a6600cf02c..aea1066c7c 100644 --- a/provider/acme/provider.go +++ b/provider/acme/provider.go @@ -8,7 +8,6 @@ import ( fmtlog "log" "net" "net/http" - "os" "reflect" "strings" "sync" @@ -24,6 +23,7 @@ import ( "github.com/containous/traefik/types" "github.com/containous/traefik/version" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/xenolf/lego/acme" legolog "github.com/xenolf/lego/log" "github.com/xenolf/lego/providers/dns" @@ -90,7 +90,7 @@ func (p *Provider) SetConfigListenerChan(configFromListenerChan chan types.Confi func (p *Provider) init() error { acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version) if p.ACMELogging { - legolog.Logger = fmtlog.New(os.Stderr, "legolog: ", fmtlog.LstdFlags) + legolog.Logger = fmtlog.New(log.WriterLevel(logrus.DebugLevel), "legolog: ", 0) } else { legolog.Logger = fmtlog.New(ioutil.Discard, "", 0) } diff --git a/provider/consulcatalog/config.go b/provider/consulcatalog/config.go index e2daf1f382..ad3b4b599f 100644 --- a/provider/consulcatalog/config.go +++ b/provider/consulcatalog/config.go @@ -5,6 +5,7 @@ import ( "crypto/sha1" "encoding/base64" "fmt" + "net" "sort" "strconv" "strings" @@ -116,7 +117,7 @@ func (p *Provider) getServer(node *api.ServiceEntry) types.Server { address := getBackendAddress(node) 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), } } diff --git a/provider/consulcatalog/config_test.go b/provider/consulcatalog/config_test.go index ec0d8b850a..4b9f09dea5 100644 --- a/provider/consulcatalog/config_test.go +++ b/provider/consulcatalog/config_test.go @@ -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 { diff --git a/provider/docker/config.go b/provider/docker/config.go index 85b91cfe5c..d8e6e99aa5 100644 --- a/provider/docker/config.go +++ b/provider/docker/config.go @@ -3,6 +3,7 @@ package docker import ( "context" "fmt" + "net" "strconv" "strings" "text/template" @@ -262,11 +263,16 @@ func isBackendLBSwarm(container dockerData) bool { } func getSegmentBackendName(container dockerData) string { - if value := label.GetStringValue(container.SegmentLabels, label.TraefikBackend, ""); len(value) > 0 { - return provider.Normalize(container.ServiceName + "-" + value) + serviceName := container.ServiceName + 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 { @@ -336,7 +342,7 @@ func (p *Provider) getServers(containers []dockerData) map[string]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), } } diff --git a/provider/docker/config_container_docker_test.go b/provider/docker/config_container_docker_test.go index dcce0a2b22..d9d1201f81 100644 --- a/provider/docker/config_container_docker_test.go +++ b/provider/docker/config_container_docker_test.go @@ -939,8 +939,9 @@ func TestDockerGetFrontendRule(t *testing.T) { func TestDockerGetBackendName(t *testing.T) { testCases := []struct { - container docker.ContainerJSON - expected string + container docker.ContainerJSON + segmentName string + expected string }{ { container: containerJSON(name("foo")), @@ -963,6 +964,15 @@ func TestDockerGetBackendName(t *testing.T) { })), 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 { @@ -972,7 +982,8 @@ func TestDockerGetBackendName(t *testing.T) { dData := parseContainer(test.container) segmentProperties := label.ExtractTraefikLabels(dData.Labels) - dData.SegmentLabels = segmentProperties[""] + dData.SegmentLabels = segmentProperties[test.segmentName] + dData.SegmentName = test.segmentName actual := getBackendName(dData) assert.Equal(t, test.expected, actual) diff --git a/provider/ecs/config.go b/provider/ecs/config.go index d4caf4752a..46d2da9b8f 100644 --- a/provider/ecs/config.go +++ b/provider/ecs/config.go @@ -2,6 +2,7 @@ package ecs import ( "fmt" + "net" "strconv" "strings" "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)) 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), } } diff --git a/provider/marathon/config.go b/provider/marathon/config.go index 4b90de7403..aaa0725fc9 100644 --- a/provider/marathon/config.go +++ b/provider/marathon/config.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math" + "net" "strconv" "strings" "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)) 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), }, nil } diff --git a/provider/mesos/config.go b/provider/mesos/config.go index db354d72df..13e66e6543 100644 --- a/provider/mesos/config.go +++ b/provider/mesos/config.go @@ -3,6 +3,7 @@ package mesos import ( "fmt" "math" + "net" "strconv" "strings" "text/template" @@ -237,7 +238,7 @@ func (p *Provider) getServers(tasks []taskData) map[string]types.Server { serverName := "server-" + getID(task) 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), } } diff --git a/provider/rancher/config.go b/provider/rancher/config.go index 255850fe6e..e52405edb2 100644 --- a/provider/rancher/config.go +++ b/provider/rancher/config.go @@ -2,6 +2,7 @@ package rancher import ( "fmt" + "net" "strconv" "strings" "text/template" @@ -181,7 +182,7 @@ func getServers(service rancherData) map[string]types.Server { serverName := "server-" + strconv.Itoa(index) 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, } }