diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c3ef84b1..f62889661 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 b82f3824b..ff090d6fb 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 acbd946de..201e68242 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 cb0b4c6d3..5ba423b65 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 4384b78ad..cd4ea8fbb 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 34fe943be..8ff1cb4b0 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 fd72b03b8..52f85d639 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 429432c8a..d9e8417bb 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 8e94ac52f..9a42491d8 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 017e07e44..d63b3dd3c 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 95316afaf..58defc529 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 3e83e0928..bf8825c29 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 552b840d3..cbfe51caa 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 2480bdaf8..298d27448 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 4137ca3eb..5cdc59a05 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 012a6386f..722fd4740 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 3ddc5b545..7287bc4b8 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 04ac1e9ad..3dae96e22 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 5e0bf50f6..3ac8fd161 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 a6600cf02..aea1066c7 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 e2daf1f38..ad3b4b599 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 ec0d8b850..4b9f09dea 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 85b91cfe5..d8e6e99aa 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 dcce0a2b2..d9d1201f8 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 d4caf4752..46d2da9b8 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 4b90de740..aaa0725fc 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 db354d72d..13e66e654 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 255850fe6..e52405edb 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, } }