From 649cb548d0584db1ed6bbeaebe4bbf74ff0e0f8c Mon Sep 17 00:00:00 2001 From: Guilhem Lettron Date: Tue, 25 Oct 2016 17:59:39 +0200 Subject: [PATCH 01/35] Use sdnotify for systemd (#768) * Use sdnotify for systemd This is useful if a configuration is long to load. Systemd will continue dependency chain only when server have finish to start. https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type= * Extract the waiting behavior from Start() --- contrib/systemd/traefik.service | 1 + glide.lock | 10 +++++++--- glide.yaml | 4 ++++ server.go | 6 +++++- traefik.go | 7 +++++++ 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/contrib/systemd/traefik.service b/contrib/systemd/traefik.service index 846d22ee6..c93f8e27d 100644 --- a/contrib/systemd/traefik.service +++ b/contrib/systemd/traefik.service @@ -2,6 +2,7 @@ Description=Traefik [Service] +Type=notify ExecStart=/usr/bin/traefik --configFile=/etc/traefik.toml Restart=on-failure diff --git a/glide.lock b/glide.lock index 96ae7f6b0..bb904e3ec 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 39ff28cc1d13d5915a870b14491ece1849c4eaf5a56cecd50a7676ecee6c6143 -updated: 2016-10-06T14:06:39.455848971+02:00 +hash: 61a63d2dd37e5a9bf32c83fa520f54458c3fe6b520f89b9615d8b26f5d3f317f +updated: 2016-10-24T15:09:49.3944218+02:00 imports: - name: github.com/abbot/go-http-auth version: cb4372376e1e00e9f6ab9ec142e029302c9e7140 @@ -31,6 +31,10 @@ imports: - client - pkg/pathutil - pkg/types +- name: github.com/coreos/go-systemd + version: 43e4800a6165b4e02bb2a36673c54b230d6f7b26 + subpackages: + - daemon - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: @@ -340,7 +344,7 @@ testImports: - name: github.com/libkermit/docker-check version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3 - name: github.com/spf13/pflag - version: 08b1a584251b5b62f458943640fc8ebd4d50aaa5 + version: 5644820622454e71517561946e3d94b9f9db6842 - name: github.com/vbatts/tar-split version: bd4c5d64c3e9297f410025a3b1bd0c58f659e721 subpackages: diff --git a/glide.yaml b/glide.yaml index 6230825c3..9358b2efe 100644 --- a/glide.yaml +++ b/glide.yaml @@ -102,3 +102,7 @@ import: - package: github.com/docker/leadership - package: github.com/satori/go.uuid version: ^1.1.0 +- package: github.com/coreos/go-systemd + version: v12 + subpackages: + - daemon diff --git a/server.go b/server.go index 4846e1885..0cac574c9 100644 --- a/server.go +++ b/server.go @@ -91,7 +91,7 @@ func NewServer(globalConfiguration GlobalConfiguration) *Server { return server } -// Start starts the server and blocks until server is shutted down. +// Start starts the server. func (server *Server) Start() { server.startHTTPServers() server.startLeadership() @@ -104,6 +104,10 @@ func (server *Server) Start() { server.configureProviders() server.startProviders() go server.listenSignals() +} + +// Wait blocks until server is shutted down. +func (server *Server) Wait() { <-server.stopChan } diff --git a/traefik.go b/traefik.go index 5cdef2497..9f924b3b5 100644 --- a/traefik.go +++ b/traefik.go @@ -24,6 +24,8 @@ import ( "github.com/containous/traefik/version" "github.com/docker/libkv/store" "github.com/satori/go.uuid" + + "github.com/coreos/go-systemd/daemon" ) var versionTemplate = `Version: {{.Version}} @@ -268,6 +270,11 @@ func run(traefikConfiguration *TraefikConfiguration) { server := NewServer(globalConfiguration) server.Start() defer server.Close() + sent, err := daemon.SdNotify("READY=1") + if !sent && err != nil { + log.Error("Fail to notify", err) + } + server.Wait() log.Info("Shutting down") } From adcf58da68525a1d5ccfd62e9485a535a114778b Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Fri, 21 Oct 2016 16:02:18 +0200 Subject: [PATCH 02/35] Fix ProvidersThrottleDuration doc --- docs/toml.md | 6 +++--- server.go | 4 ++-- traefik.sample.toml | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/toml.md b/docs/toml.md index 25245c4bc..b58f911ca 100644 --- a/docs/toml.md +++ b/docs/toml.md @@ -31,14 +31,14 @@ # # logLevel = "ERROR" -# Backends throttle duration: minimum duration between 2 events from providers +# Backends throttle duration: minimum duration in seconds between 2 events from providers # before applying a new configuration. It avoids unnecessary reloads if multiples events # are sent in a short amount of time. # # Optional -# Default: "2s" +# Default: "2" # -# ProvidersThrottleDuration = "5s" +# ProvidersThrottleDuration = "5" # If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used. # If you encounter 'too many open files' errors, you can either change this value, or change `ulimit` value. diff --git a/server.go b/server.go index 0cac574c9..fe7d83142 100644 --- a/server.go +++ b/server.go @@ -212,11 +212,11 @@ func (server *Server) listenProviders(stop chan bool) { lastConfigs.Set(configMsg.ProviderName, &configMsg) lastReceivedConfigurationValue := lastReceivedConfiguration.Get().(time.Time) if time.Now().After(lastReceivedConfigurationValue.Add(time.Duration(server.globalConfiguration.ProvidersThrottleDuration))) { - log.Debugf("Last %s config received more than %s, OK", configMsg.ProviderName, server.globalConfiguration.ProvidersThrottleDuration) + log.Debugf("Last %s config received more than %s, OK", configMsg.ProviderName, server.globalConfiguration.ProvidersThrottleDuration.String()) // last config received more than n s ago server.configurationValidatedChan <- configMsg } else { - log.Debugf("Last %s config received less than %s, waiting...", configMsg.ProviderName, server.globalConfiguration.ProvidersThrottleDuration) + log.Debugf("Last %s config received less than %s, waiting...", configMsg.ProviderName, server.globalConfiguration.ProvidersThrottleDuration.String()) safe.Go(func() { <-time.After(server.globalConfiguration.ProvidersThrottleDuration) lastReceivedConfigurationValue := lastReceivedConfiguration.Get().(time.Time) diff --git a/traefik.sample.toml b/traefik.sample.toml index 754e6cc80..905e55579 100644 --- a/traefik.sample.toml +++ b/traefik.sample.toml @@ -30,14 +30,14 @@ # # logLevel = "ERROR" -# Backends throttle duration: minimum duration between 2 events from providers +# Backends throttle duration: minimum duration in seconds between 2 events from providers # before applying a new configuration. It avoids unnecessary reloads if multiples events # are sent in a short amount of time. # # Optional -# Default: "2s" +# Default: "2" # -# ProvidersThrottleDuration = "5s" +# ProvidersThrottleDuration = "5" # If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used. # If you encounter 'too many open files' errors, you can either change this value, or change `ulimit` value. From 22b0b8b750d894fb1ce90ec9dda765862b2b6433 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Fri, 21 Oct 2016 15:56:09 +0200 Subject: [PATCH 03/35] Fix mapstructure issue with anonymous slice Signed-off-by: Emile Vauge --- glide.lock | 6 +++--- glide.yaml | 4 +++- types/types.go | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/glide.lock b/glide.lock index bb904e3ec..bec1206d5 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 61a63d2dd37e5a9bf32c83fa520f54458c3fe6b520f89b9615d8b26f5d3f317f -updated: 2016-10-24T15:09:49.3944218+02:00 +hash: 45d9abd00276bba5aaeb92cd5f2464e404bba3cf90f37aa538d4866041626327 +updated: 2016-10-26T14:26:07.740582437+02:00 imports: - name: github.com/abbot/go-http-auth version: cb4372376e1e00e9f6ab9ec142e029302c9e7140 @@ -225,7 +225,7 @@ imports: - name: github.com/miekg/dns version: 5d001d020961ae1c184f9f8152fdc73810481677 - name: github.com/mitchellh/mapstructure - version: ca63d7c062ee3c9f34db231e352b60012b4fd0c1 + version: f3009df150dadf309fdee4a54ed65c124afad715 - name: github.com/moul/http2curl version: b1479103caacaa39319f75e7f57fc545287fca0d - name: github.com/NYTimes/gziphandler diff --git a/glide.yaml b/glide.yaml index 9358b2efe..1436021bc 100644 --- a/glide.yaml +++ b/glide.yaml @@ -102,7 +102,9 @@ import: - package: github.com/docker/leadership - package: github.com/satori/go.uuid version: ^1.1.0 +- package: github.com/mitchellh/mapstructure + version: f3009df150dadf309fdee4a54ed65c124afad715 - package: github.com/coreos/go-systemd version: v12 subpackages: - - daemon + - daemon \ No newline at end of file diff --git a/types/types.go b/types/types.go index 76fa96bd4..a8db1a6e3 100644 --- a/types/types.go +++ b/types/types.go @@ -216,12 +216,12 @@ type Users []string // Basic HTTP basic authentication type Basic struct { - Users + Users `mapstructure:","` } // Digest HTTP authentication type Digest struct { - Users + Users `mapstructure:","` } // CanonicalDomain returns a lower case domain with trim space From e5a8fb390e24a6bbca7bbf5ae060de9738e46661 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Fri, 21 Oct 2016 13:41:11 +0200 Subject: [PATCH 04/35] Fix multiple certificates using flags Signed-off-by: Emile Vauge --- configuration.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/configuration.go b/configuration.go index 20546e8b3..a677145da 100644 --- a/configuration.go +++ b/configuration.go @@ -28,7 +28,7 @@ type GlobalConfiguration struct { AccessLogsFile string `description:"Access logs file"` TraefikLogsFile string `description:"Traefik logs file"` LogLevel string `short:"l" description:"Log level"` - EntryPoints EntryPoints `description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key'"` + EntryPoints EntryPoints `description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key;prod/traefik.crt,prod/traefik.key'"` Cluster *types.Cluster `description:"Enable clustering"` Constraints types.Constraints `description:"Filter services by constraint, matching with service tags"` ACME *acme.ACME `description:"Enable ACME (Let's Encrypt): automatic SSL"` @@ -263,21 +263,28 @@ func (certs *Certificates) String() string { if len(*certs) == 0 { return "" } - return (*certs)[0].CertFile + "," + (*certs)[0].KeyFile + var result []string + for _, certificate := range *certs { + result = append(result, certificate.CertFile+","+certificate.KeyFile) + } + return strings.Join(result, ";") } // Set is the method to set the flag value, part of the flag.Value interface. // Set's argument is a string to be parsed to set the flag. // It's a comma-separated list, so we split it. func (certs *Certificates) Set(value string) error { - files := strings.Split(value, ",") - if len(files) != 2 { - return errors.New("Bad certificates format: " + value) + certificates := strings.Split(value, ";") + for _, certificate := range certificates { + files := strings.Split(certificate, ",") + if len(files) != 2 { + return errors.New("Bad certificates format: " + value) + } + *certs = append(*certs, Certificate{ + CertFile: files[0], + KeyFile: files[1], + }) } - *certs = append(*certs, Certificate{ - CertFile: files[0], - KeyFile: files[1], - }) return nil } From 7c375e8fd96d1df33bca6a340462d2db86ab3462 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 3 Aug 2016 14:50:52 +0200 Subject: [PATCH 05/35] Fix ResponseRecorder Flush Signed-off-by: Emile Vauge --- middlewares/retry.go | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/middlewares/retry.go b/middlewares/retry.go index 8577a1685..021306304 100644 --- a/middlewares/retry.go +++ b/middlewares/retry.go @@ -9,6 +9,13 @@ import ( "net/http" ) +var ( + _ http.ResponseWriter = &ResponseRecorder{} + _ http.Hijacker = &ResponseRecorder{} + _ http.Flusher = &ResponseRecorder{} + _ http.CloseNotifier = &ResponseRecorder{} +) + // Retry is a middleware that retries requests type Retry struct { attempts int @@ -52,6 +59,7 @@ type ResponseRecorder struct { Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to responseWriter http.ResponseWriter + err error } // NewRecorder returns an initialized ResponseRecorder. @@ -75,10 +83,10 @@ func (rw *ResponseRecorder) Header() http.Header { // Write always succeeds and writes to rw.Body, if not nil. func (rw *ResponseRecorder) Write(buf []byte) (int, error) { - if rw.Body != nil { - return rw.Body.Write(buf) + if rw.err != nil { + return 0, rw.err } - return 0, nil + return rw.Body.Write(buf) } // WriteHeader sets rw.Code. @@ -90,3 +98,24 @@ func (rw *ResponseRecorder) WriteHeader(code int) { func (rw *ResponseRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) { return rw.responseWriter.(http.Hijacker).Hijack() } + +// CloseNotify returns a channel that receives at most a +// single value (true) when the client connection has gone +// away. +func (rw *ResponseRecorder) CloseNotify() <-chan bool { + return rw.responseWriter.(http.CloseNotifier).CloseNotify() +} + +// Flush sends any buffered data to the client. +func (rw *ResponseRecorder) Flush() { + _, err := rw.responseWriter.Write(rw.Body.Bytes()) + if err != nil { + log.Errorf("Error writing response in ResponseRecorder: %s", err) + rw.err = err + } + rw.Body.Reset() + flusher, ok := rw.responseWriter.(http.Flusher) + if ok { + flusher.Flush() + } +} From 8e5355f2d9c6744a6033f535988b4d4cf4c126f7 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 26 Oct 2016 17:38:18 +0200 Subject: [PATCH 06/35] Prepare release v1.1.0-rc3 Signed-off-by: Emile Vauge --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 320724432..bb70df8fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # Change Log +## [v1.1.0-rc3](https://github.com/containous/traefik/tree/v1.1.0-rc3) (2016-10-26) +[Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc2...v1.1.0-rc3) + +**Fixed bugs:** + +- Cannot provide multiple certificates using flag [\#757](https://github.com/containous/traefik/issues/757) +- traefik \* Users: unsupported type: slice [\#743](https://github.com/containous/traefik/issues/743) +- \[Docker swarm mode\] The traefik.docker.network seems to have no effect [\#719](https://github.com/containous/traefik/issues/719) +- Case sensitive domain names breaks routing [\#562](https://github.com/containous/traefik/issues/562) + +**Closed issues:** + +- dependencies installation error [\#755](https://github.com/containous/traefik/issues/755) +- k8s provider w/ acme? [\#752](https://github.com/containous/traefik/issues/752) +- Documented ProvidersThrottleDuration value is invalid [\#741](https://github.com/containous/traefik/issues/741) +- Loadbalaning issues with traefik and Docker Swarm cluster [\#730](https://github.com/containous/traefik/issues/730) +- issues with marathon app ids containing a dot [\#726](https://github.com/containous/traefik/issues/726) +- How Routing traffic depending on path not domain in docker [\#706](https://github.com/containous/traefik/issues/706) +- Traefik crashes when using Consul catalog [\#699](https://github.com/containous/traefik/issues/699) +- File Watcher for rules does not work [\#683](https://github.com/containous/traefik/issues/683) + +**Merged pull requests:** + +- Fix ResponseRecorder Flush [\#776](https://github.com/containous/traefik/pull/776) ([emilevauge](https://github.com/emilevauge)) +- Use sdnotify for systemd [\#768](https://github.com/containous/traefik/pull/768) ([guilhem](https://github.com/guilhem)) +- Fix providers throttle duration doc [\#760](https://github.com/containous/traefik/pull/760) ([emilevauge](https://github.com/emilevauge)) +- Fix mapstructure issue with anonymous slice [\#759](https://github.com/containous/traefik/pull/759) ([emilevauge](https://github.com/emilevauge)) +- Fix multiple certificates using flag [\#758](https://github.com/containous/traefik/pull/758) ([emilevauge](https://github.com/emilevauge)) +- Really fix deploy ghr... [\#748](https://github.com/containous/traefik/pull/748) ([emilevauge](https://github.com/emilevauge)) + ## [v1.1.0-rc2](https://github.com/containous/traefik/tree/v1.1.0-rc2) (2016-10-17) [Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc1...v1.1.0-rc2) From 1c8d3ded3d6cddc3f0ad72393b62d45df49029db Mon Sep 17 00:00:00 2001 From: Guilhem Lettron Date: Thu, 27 Oct 2016 15:49:07 +0200 Subject: [PATCH 07/35] Add name to some case to help debug --- provider/marathon_test.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/provider/marathon_test.go b/provider/marathon_test.go index b9e712ea1..fb2314cbb 100644 --- a/provider/marathon_test.go +++ b/provider/marathon_test.go @@ -371,13 +371,13 @@ func TestMarathonTaskFilter(t *testing.T) { }, { task: marathon.Task{ - AppID: "foo", + AppID: "multiple-ports", Ports: []int{80}, }, applications: &marathon.Applications{ Apps: []marathon.Application{ { - ID: "foo", + ID: "multiple-ports", Ports: []int{80, 443}, Labels: &map[string]string{}, }, @@ -388,13 +388,13 @@ func TestMarathonTaskFilter(t *testing.T) { }, { task: marathon.Task{ - AppID: "foo", + AppID: "disable", Ports: []int{80}, }, applications: &marathon.Applications{ Apps: []marathon.Application{ { - ID: "foo", + ID: "disable", Ports: []int{80}, Labels: &map[string]string{ "traefik.enable": "false", @@ -523,7 +523,7 @@ func TestMarathonTaskFilter(t *testing.T) { }, { task: marathon.Task{ - AppID: "foo", + AppID: "healthcheck-false", Ports: []int{80}, HealthCheckResults: []*marathon.HealthCheckResult{ { @@ -534,7 +534,7 @@ func TestMarathonTaskFilter(t *testing.T) { applications: &marathon.Applications{ Apps: []marathon.Application{ { - ID: "foo", + ID: "healthcheck-false", Ports: []int{80}, Labels: &map[string]string{}, HealthChecks: &[]marathon.HealthCheck{ @@ -576,13 +576,13 @@ func TestMarathonTaskFilter(t *testing.T) { }, { task: marathon.Task{ - AppID: "foo", + AppID: "single-port", Ports: []int{80}, }, applications: &marathon.Applications{ Apps: []marathon.Application{ { - ID: "foo", + ID: "single-port", Ports: []int{80}, Labels: &map[string]string{}, }, @@ -593,7 +593,7 @@ func TestMarathonTaskFilter(t *testing.T) { }, { task: marathon.Task{ - AppID: "foo", + AppID: "healthcheck-alive", Ports: []int{80}, HealthCheckResults: []*marathon.HealthCheckResult{ { @@ -604,7 +604,7 @@ func TestMarathonTaskFilter(t *testing.T) { applications: &marathon.Applications{ Apps: []marathon.Application{ { - ID: "foo", + ID: "healthcheck-alive", Ports: []int{80}, Labels: &map[string]string{}, HealthChecks: &[]marathon.HealthCheck{ @@ -677,7 +677,7 @@ func TestMarathonTaskFilter(t *testing.T) { for _, c := range cases { actual := provider.taskFilter(c.task, c.applications, c.exposedByDefault) if actual != c.expected { - t.Fatalf("expected %v, got %v", c.expected, actual) + t.Fatalf("App %s: expected %v, got %v", c.task.AppID, c.expected, actual) } } } From 5641af437e9242dce64e121eeae10e5869fd4d52 Mon Sep 17 00:00:00 2001 From: Guilhem Lettron Date: Thu, 27 Oct 2016 15:49:34 +0200 Subject: [PATCH 08/35] Use first port by default If no information is given, use first index of ports --- provider/marathon.go | 5 +---- provider/marathon_test.go | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/provider/marathon.go b/provider/marathon.go index f2ec40918..f6cc85563 100644 --- a/provider/marathon.go +++ b/provider/marathon.go @@ -219,10 +219,7 @@ func (provider *Marathon) taskFilter(task marathon.Task, applications *marathon. log.Debugf("Filtering marathon task %s specifying both traefik.portIndex and traefik.port labels", task.AppID) return false } - if portIndexLabel == "" && portValueLabel == "" && len(application.Ports) > 1 { - log.Debugf("Filtering marathon task %s with more than 1 port and no traefik.portIndex or traefik.port label", task.AppID) - return false - } + if portIndexLabel != "" { index, err := strconv.Atoi((*application.Labels)["traefik.portIndex"]) if err != nil || index < 0 || index > len(application.Ports)-1 { diff --git a/provider/marathon_test.go b/provider/marathon_test.go index fb2314cbb..6ce7c4009 100644 --- a/provider/marathon_test.go +++ b/provider/marathon_test.go @@ -372,7 +372,7 @@ func TestMarathonTaskFilter(t *testing.T) { { task: marathon.Task{ AppID: "multiple-ports", - Ports: []int{80}, + Ports: []int{80, 443}, }, applications: &marathon.Applications{ Apps: []marathon.Application{ @@ -383,7 +383,7 @@ func TestMarathonTaskFilter(t *testing.T) { }, }, }, - expected: false, + expected: true, exposedByDefault: true, }, { @@ -927,12 +927,12 @@ func TestMarathonGetPort(t *testing.T) { { applications: []marathon.Application{ { - ID: "test1", + ID: "multiple-ports-take-first", Labels: &map[string]string{}, }, }, task: marathon.Task{ - AppID: "test1", + AppID: "multiple-ports-take-first", Ports: []int{80, 443}, }, expected: "80", From 85a20b9a39321bb8929b7a0e6ee806e0bee13f6c Mon Sep 17 00:00:00 2001 From: Guilhem Lettron Date: Wed, 2 Nov 2016 17:31:27 +0100 Subject: [PATCH 09/35] Use first index for ports --- provider/docker.go | 4 ---- provider/docker_test.go | 25 +++++++++++++++++++++++-- provider/mesos.go | 4 ---- provider/mesos_test.go | 2 +- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/provider/docker.go b/provider/docker.go index cd5ddc847..faff0b6d2 100644 --- a/provider/docker.go +++ b/provider/docker.go @@ -364,10 +364,6 @@ func (provider *Docker) containerFilter(container dockerData) bool { log.Debugf("Filtering container without port and no traefik.port label %s", container.Name) return false } - if len(container.NetworkSettings.Ports) > 1 && err != nil { - log.Debugf("Filtering container with more than 1 port and no traefik.port label %s", container.Name) - return false - } if !isContainerEnabled(container, provider.ExposedByDefault) { log.Debugf("Filtering disabled container %s", container.Name) diff --git a/provider/docker_test.go b/provider/docker_test.go index 3d106bd71..1873c5d56 100644 --- a/provider/docker_test.go +++ b/provider/docker_test.go @@ -390,6 +390,27 @@ func TestDockerGetPort(t *testing.T) { }, expected: "8080", }, + { + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "test-multi-ports", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.port": "8080", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "8080/tcp": {}, + "80/tcp": {}, + }, + }, + }, + }, + expected: "8080", + }, } for _, e := range containers { @@ -735,7 +756,7 @@ func TestDockerTraefikFilter(t *testing.T) { { container: docker.ContainerJSON{ ContainerJSONBase: &docker.ContainerJSONBase{ - Name: "container", + Name: "container-multi-ports", }, Config: &container.Config{}, NetworkSettings: &docker.NetworkSettings{ @@ -748,7 +769,7 @@ func TestDockerTraefikFilter(t *testing.T) { }, }, exposedByDefault: true, - expected: false, + expected: true, }, { container: docker.ContainerJSON{ diff --git a/provider/mesos.go b/provider/mesos.go index 4064c1671..a99318249 100644 --- a/provider/mesos.go +++ b/provider/mesos.go @@ -212,10 +212,6 @@ func mesosTaskFilter(task state.Task, exposedByDefaultFlag bool) bool { log.Debugf("Filtering mesos task %s specifying both traefik.portIndex and traefik.port labels", task.Name) return false } - if portIndexLabel == "" && portValueLabel == "" && len(task.DiscoveryInfo.Ports.DiscoveryPorts) > 1 { - log.Debugf("Filtering mesos task %s with more than 1 port and no traefik.portIndex or traefik.port label", task.Name) - return false - } if portIndexLabel != "" { index, err := strconv.Atoi(labels(task, "traefik.portIndex")) if err != nil || index < 0 || index > len(task.DiscoveryInfo.Ports.DiscoveryPorts)-1 { diff --git a/provider/mesos_test.go b/provider/mesos_test.go index 5968db8e9..5434915b3 100644 --- a/provider/mesos_test.go +++ b/provider/mesos_test.go @@ -95,7 +95,7 @@ func TestMesosTaskFilter(t *testing.T) { setLabels("traefik.enable", "true"), discovery(setDiscoveryPorts("TCP", 80, "WEB HTTP", "TCP", 443, "WEB HTTPS")), ), - expected: false, // more than 1 discovery port but no traefik.port* label + expected: true, // Default to first index exposedByDefault: true, }, { From 7bf5d557c1937b5435928486833feaa12aa7e613 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Thu, 27 Oct 2016 16:09:28 +0200 Subject: [PATCH 10/35] Fix acme renew --- acme/acme.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/acme/acme.go b/acme/acme.go index 0c88caae3..4ec96dd83 100644 --- a/acme/acme.go +++ b/acme/acme.go @@ -136,12 +136,14 @@ func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tl leadership.Pool.AddGoCtx(func(ctx context.Context) { log.Infof("Starting ACME renew job...") defer log.Infof("Stopped ACME renew job...") - select { - case <-ctx.Done(): - return - case <-ticker.C: - if err := a.renewCertificates(); err != nil { - log.Errorf("Error renewing ACME certificate: %s", err.Error()) + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + if err := a.renewCertificates(); err != nil { + log.Errorf("Error renewing ACME certificate: %s", err.Error()) + } } } }) From 3322e564fd1fc298a11a6be5dbbc6bb0c17db2a3 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Thu, 27 Oct 2016 16:17:02 +0200 Subject: [PATCH 11/35] Add version check Signed-off-by: Emile Vauge --- README.md | 2 +- configuration.go | 2 ++ docs/toml.md | 22 ++++++++++++++++++ glide.lock | 10 +++++++-- glide.yaml | 4 +++- traefik.go | 19 ++++++++++++++-- traefik.sample.toml | 14 ++++++++++++ version/version.go | 54 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 121 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 74a832141..23898c243 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Run it and forget it! - Circuit breakers on backends - Round Robin, rebalancer load-balancers - Rest Metrics -- [Tiny](https://imagelayers.io/?images=traefik) [official](https://hub.docker.com/r/_/traefik/) docker image included +- [Tiny](https://microbadger.com/images/traefik) [official](https://hub.docker.com/r/_/traefik/) docker image included - SSL backends support - SSL frontend support (with SNI) - Clean AngularJS Web UI diff --git a/configuration.go b/configuration.go index a677145da..2e55a4ec2 100644 --- a/configuration.go +++ b/configuration.go @@ -25,6 +25,7 @@ type TraefikConfiguration struct { type GlobalConfiguration struct { GraceTimeOut int64 `short:"g" description:"Duration to give active requests a chance to finish during hot-reload"` Debug bool `short:"d" description:"Enable debug mode"` + CheckNewVersion bool `description:"Periodically check if a new version has been released"` AccessLogsFile string `description:"Access logs file"` TraefikLogsFile string `description:"Traefik logs file"` LogLevel string `short:"l" description:"Log level"` @@ -409,6 +410,7 @@ func NewTraefikConfiguration() *TraefikConfiguration { DefaultEntryPoints: []string{}, ProvidersThrottleDuration: time.Duration(2 * time.Second), MaxIdleConnsPerHost: 200, + CheckNewVersion: true, }, ConfigFile: "", } diff --git a/docs/toml.md b/docs/toml.md index b58f911ca..cc40ca0c7 100644 --- a/docs/toml.md +++ b/docs/toml.md @@ -9,6 +9,28 @@ # Global configuration ################################################################ +# Timeout in seconds. +# Duration to give active requests a chance to finish during hot-reloads +# +# Optional +# Default: 10 +# +# graceTimeOut = 10 + +# Enable debug mode +# +# Optional +# Default: false +# +# debug = true + +# Periodically check if a new version has been released +# +# Optional +# Default: true +# +# checkNewVersion = false + # Traefik logs file # If not defined, logs to stdout # diff --git a/glide.lock b/glide.lock index bec1206d5..574af3619 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 45d9abd00276bba5aaeb92cd5f2464e404bba3cf90f37aa538d4866041626327 -updated: 2016-10-26T14:26:07.740582437+02:00 +hash: d2bb370ffd3c0b528587581bc77d900c98921c02df581594bf19655968aa9849 +updated: 2016-10-27T15:54:07.397981259+02:00 imports: - name: github.com/abbot/go-http-auth version: cb4372376e1e00e9f6ab9ec142e029302c9e7140 @@ -168,6 +168,10 @@ imports: - proto - name: github.com/golang/glog version: fca8c8854093a154ff1eb580aae10276ad6b1b5f +- name: github.com/google/go-github + version: ed33550bbf49ddffcc36e1309d3f58ed0b6c2305 + subpackages: + - github - name: github.com/google/go-querystring version: 9235644dd9e52eeae6fa48efd539fdc351a0af53 subpackages: @@ -180,6 +184,8 @@ imports: - api - name: github.com/hashicorp/go-cleanhttp version: ad28ea4487f05916463e2423a55166280e8254b5 +- name: github.com/hashicorp/go-version + version: deeb027c13a95d56c7585df3fe29207208c6706e - name: github.com/hashicorp/serf version: b03bf85930b2349eb04b97c8fac437495296e3e7 subpackages: diff --git a/glide.yaml b/glide.yaml index 1436021bc..205fdf1eb 100644 --- a/glide.yaml +++ b/glide.yaml @@ -107,4 +107,6 @@ import: - package: github.com/coreos/go-systemd version: v12 subpackages: - - daemon \ No newline at end of file + - daemon +- package: github.com/google/go-github +- package: github.com/hashicorp/go-version \ No newline at end of file diff --git a/traefik.go b/traefik.go index 9f924b3b5..36da79202 100644 --- a/traefik.go +++ b/traefik.go @@ -11,6 +11,7 @@ import ( "runtime" "strings" "text/template" + "time" "github.com/Sirupsen/logrus" "github.com/containous/flaeg" @@ -20,12 +21,12 @@ import ( "github.com/containous/traefik/log" "github.com/containous/traefik/middlewares" "github.com/containous/traefik/provider" + "github.com/containous/traefik/safe" "github.com/containous/traefik/types" "github.com/containous/traefik/version" + "github.com/coreos/go-systemd/daemon" "github.com/docker/libkv/store" "github.com/satori/go.uuid" - - "github.com/coreos/go-systemd/daemon" ) var versionTemplate = `Version: {{.Version}} @@ -263,6 +264,20 @@ func run(traefikConfiguration *TraefikConfiguration) { } jsonConf, _ := json.Marshal(globalConfiguration) log.Infof("Traefik version %s built on %s", version.Version, version.BuildDate) + + if globalConfiguration.CheckNewVersion { + ticker := time.NewTicker(24 * time.Hour) + safe.Go(func() { + version.CheckNewVersion() + for { + select { + case <-ticker.C: + version.CheckNewVersion() + } + } + }) + } + if len(traefikConfiguration.ConfigFile) != 0 { log.Infof("Using TOML configuration file %s", traefikConfiguration.ConfigFile) } diff --git a/traefik.sample.toml b/traefik.sample.toml index 905e55579..c53effd28 100644 --- a/traefik.sample.toml +++ b/traefik.sample.toml @@ -10,6 +10,20 @@ # # graceTimeOut = 10 +# Enable debug mode +# +# Optional +# Default: false +# +# debug = true + +# Periodically check if a new version has been released +# +# Optional +# Default: true +# +# checkNewVersion = false + # Traefik logs file # If not defined, logs to stdout # diff --git a/version/version.go b/version/version.go index ba72b1a42..7e4149caf 100644 --- a/version/version.go +++ b/version/version.go @@ -1,5 +1,12 @@ package version +import ( + "github.com/containous/traefik/log" + "github.com/google/go-github/github" + goversion "github.com/hashicorp/go-version" + "net/url" +) + var ( // Version holds the current version of traefik. Version = "dev" @@ -8,3 +15,50 @@ var ( // BuildDate holds the build date of traefik. BuildDate = "I don't remember exactly" ) + +// CheckNewVersion checks if a new version is available +func CheckNewVersion() { + if Version == "dev" { + return + } + client := github.NewClient(nil) + updateURL, err := url.Parse("https://update.traefik.io") + if err != nil { + log.Warnf("Error checking new version: %s", err) + return + } + client.BaseURL = updateURL + releases, resp, err := client.Repositories.ListReleases("containous", "traefik", nil) + if err != nil { + log.Warnf("Error checking new version: %s", err) + return + } + + if resp.StatusCode != 200 { + log.Warnf("Error checking new version: status=%s", resp.Status) + return + } + + currentVersion, err := goversion.NewVersion(Version) + if err != nil { + log.Warnf("Error checking new version: %s", err) + return + } + + for _, release := range releases { + releaseVersion, err := goversion.NewVersion(*release.TagName) + if err != nil { + log.Warnf("Error checking new version: %s", err) + return + } + + if len(currentVersion.Prerelease()) == 0 && len(releaseVersion.Prerelease()) > 0 { + continue + } + + if releaseVersion.GreaterThan(currentVersion) { + log.Warnf("A new release has been found: %s. Please consider updating.", releaseVersion.String()) + return + } + } +} From 174a5e7f1380323bbdbef5c3d051b6b7e3affa78 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Mon, 7 Nov 2016 21:51:23 +0100 Subject: [PATCH 12/35] Fix ACME renew --- acme/acme.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/acme/acme.go b/acme/acme.go index 4ec96dd83..bd128a25a 100644 --- a/acme/acme.go +++ b/acme/acme.go @@ -253,7 +253,6 @@ func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, checkOnDemandDomain func needRegister = true } - log.Infof("buildACMEClient...") a.client, err = a.buildACMEClient(account) if err != nil { return err @@ -271,7 +270,7 @@ func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, checkOnDemandDomain func // The client has a URL to the current Let's Encrypt Subscriber // Agreement. The user will need to agree to it. - log.Infof("AgreeToTOS...") + log.Debugf("AgreeToTOS...") err = a.client.AgreeToTOS() if err != nil { // Let's Encrypt Subscriber Agreement renew ? @@ -375,11 +374,6 @@ func (a *ACME) renewCertificates() error { account := a.store.Get().(*Account) for _, certificateResource := range account.DomainsCertificate.Certs { if certificateResource.needRenew() { - transaction, object, err := a.store.Begin() - if err != nil { - return err - } - account = object.(*Account) log.Debugf("Renewing certificate %+v", certificateResource.Domains) renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{ Domain: certificateResource.Certificate.Domain, @@ -400,6 +394,11 @@ func (a *ACME) renewCertificates() error { PrivateKey: renewedCert.PrivateKey, Certificate: renewedCert.Certificate, } + transaction, object, err := a.store.Begin() + if err != nil { + return err + } + account = object.(*Account) err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains) if err != nil { log.Errorf("Error renewing certificate: %v", err) From 558b31f4d985bf208b5a4078731a5fd712d1df84 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Tue, 8 Nov 2016 10:34:39 +0100 Subject: [PATCH 13/35] Fix oxy version --- glide.lock | 10 +++++----- glide.yaml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/glide.lock b/glide.lock index 574af3619..ed0a02aab 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: d2bb370ffd3c0b528587581bc77d900c98921c02df581594bf19655968aa9849 -updated: 2016-10-27T15:54:07.397981259+02:00 +hash: d771fbae9fc9c496859ab384f3f70de11dbdbbb63af7bc4fa208ff6192b33635 +updated: 2016-11-08T09:30:22.184334518+01:00 imports: - name: github.com/abbot/go-http-auth version: cb4372376e1e00e9f6ab9ec142e029302c9e7140 @@ -169,7 +169,7 @@ imports: - name: github.com/golang/glog version: fca8c8854093a154ff1eb580aae10276ad6b1b5f - name: github.com/google/go-github - version: ed33550bbf49ddffcc36e1309d3f58ed0b6c2305 + version: 55263f30529cb06f5b478efc333390b791cfe3b1 subpackages: - github - name: github.com/google/go-querystring @@ -185,7 +185,7 @@ imports: - name: github.com/hashicorp/go-cleanhttp version: ad28ea4487f05916463e2423a55166280e8254b5 - name: github.com/hashicorp/go-version - version: deeb027c13a95d56c7585df3fe29207208c6706e + version: e96d3840402619007766590ecea8dd7af1292276 - name: github.com/hashicorp/serf version: b03bf85930b2349eb04b97c8fac437495296e3e7 subpackages: @@ -282,7 +282,7 @@ imports: - name: github.com/vdemeester/shakers version: 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 - name: github.com/vulcand/oxy - version: 4298f24d572dc554eb984f2ffdf6bdd54d4bd613 + version: fcc76b52eb8568540a020b7a99e854d9d752b364 repo: https://github.com/containous/oxy.git vcs: git subpackages: diff --git a/glide.yaml b/glide.yaml index 205fdf1eb..ae05211bc 100644 --- a/glide.yaml +++ b/glide.yaml @@ -10,7 +10,7 @@ import: - package: github.com/containous/flaeg version: a731c034dda967333efce5f8d276aeff11f8ff87 - package: github.com/vulcand/oxy - version: 4298f24d572dc554eb984f2ffdf6bdd54d4bd613 + version: fcc76b52eb8568540a020b7a99e854d9d752b364 repo: https://github.com/containous/oxy.git vcs: git subpackages: From 00c7e5c72b366630c08174979268ad87ec503588 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 9 Nov 2016 17:56:41 +0100 Subject: [PATCH 14/35] Ensure HTTP/2 enabled --- server.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server.go b/server.go index fe7d83142..f3a98c03f 100644 --- a/server.go +++ b/server.go @@ -383,6 +383,9 @@ func (server *Server) createTLSConfig(entryPointName string, tlsOption *TLS, rou return nil, err } + // ensure http2 enabled + config.NextProtos = []string{"h2", "http/1.1"} + if len(tlsOption.ClientCAFiles) > 0 { pool := x509.NewCertPool() for _, caFile := range tlsOption.ClientCAFiles { From c9cc3c9895dc9f81670ce5dba051927be8b13ea3 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 9 Nov 2016 19:27:04 +0100 Subject: [PATCH 15/35] Fix contraint store/read from KV Signed-off-by: Emile Vauge --- configuration.go | 18 +++++++++--------- glide.lock | 8 +++++--- glide.yaml | 4 ++-- provider/boltdb.go | 2 +- provider/consul.go | 2 +- provider/consul_catalog.go | 2 +- provider/docker.go | 2 +- provider/etcd.go | 2 +- provider/file.go | 2 +- provider/kubernetes.go | 2 +- provider/kv.go | 2 +- provider/marathon.go | 2 +- provider/marathon_test.go | 4 ++-- provider/mesos.go | 2 +- provider/provider.go | 4 ++-- provider/provider_test.go | 12 ++++++------ provider/zk.go | 2 +- types/types.go | 25 ++++++++++++++++++++----- web.go | 2 +- 19 files changed, 58 insertions(+), 41 deletions(-) diff --git a/configuration.go b/configuration.go index 2e55a4ec2..cf9e75175 100644 --- a/configuration.go +++ b/configuration.go @@ -329,54 +329,54 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration { defaultMarathon.Watch = true defaultMarathon.Endpoint = "http://127.0.0.1:8080" defaultMarathon.ExposedByDefault = true - defaultMarathon.Constraints = []types.Constraint{} + defaultMarathon.Constraints = types.Constraints{} // default Consul var defaultConsul provider.Consul defaultConsul.Watch = true defaultConsul.Endpoint = "127.0.0.1:8500" defaultConsul.Prefix = "traefik" - defaultConsul.Constraints = []types.Constraint{} + defaultConsul.Constraints = types.Constraints{} // default ConsulCatalog var defaultConsulCatalog provider.ConsulCatalog defaultConsulCatalog.Endpoint = "127.0.0.1:8500" - defaultConsulCatalog.Constraints = []types.Constraint{} + defaultConsulCatalog.Constraints = types.Constraints{} // default Etcd var defaultEtcd provider.Etcd defaultEtcd.Watch = true defaultEtcd.Endpoint = "127.0.0.1:2379" defaultEtcd.Prefix = "/traefik" - defaultEtcd.Constraints = []types.Constraint{} + defaultEtcd.Constraints = types.Constraints{} //default Zookeeper var defaultZookeeper provider.Zookepper defaultZookeeper.Watch = true defaultZookeeper.Endpoint = "127.0.0.1:2181" defaultZookeeper.Prefix = "/traefik" - defaultZookeeper.Constraints = []types.Constraint{} + defaultZookeeper.Constraints = types.Constraints{} //default Boltdb var defaultBoltDb provider.BoltDb defaultBoltDb.Watch = true defaultBoltDb.Endpoint = "127.0.0.1:4001" defaultBoltDb.Prefix = "/traefik" - defaultBoltDb.Constraints = []types.Constraint{} + defaultBoltDb.Constraints = types.Constraints{} //default Kubernetes var defaultKubernetes provider.Kubernetes defaultKubernetes.Watch = true defaultKubernetes.Endpoint = "" defaultKubernetes.LabelSelector = "" - defaultKubernetes.Constraints = []types.Constraint{} + defaultKubernetes.Constraints = types.Constraints{} // default Mesos var defaultMesos provider.Mesos defaultMesos.Watch = true defaultMesos.Endpoint = "http://127.0.0.1:5050" defaultMesos.ExposedByDefault = true - defaultMesos.Constraints = []types.Constraint{} + defaultMesos.Constraints = types.Constraints{} defaultConfiguration := GlobalConfiguration{ Docker: &defaultDocker, @@ -406,7 +406,7 @@ func NewTraefikConfiguration() *TraefikConfiguration { TraefikLogsFile: "", LogLevel: "ERROR", EntryPoints: map[string]*EntryPoint{}, - Constraints: []types.Constraint{}, + Constraints: types.Constraints{}, DefaultEntryPoints: []string{}, ProvidersThrottleDuration: time.Duration(2 * time.Second), MaxIdleConnsPerHost: 200, diff --git a/glide.lock b/glide.lock index ed0a02aab..889a70a6d 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: d771fbae9fc9c496859ab384f3f70de11dbdbbb63af7bc4fa208ff6192b33635 -updated: 2016-11-08T09:30:22.184334518+01:00 +hash: 1bbeb842ee639ccc6e2edf8cc13fc2759cb96e3d839a1aec7b7f6af4fb89c8e1 +updated: 2016-11-09T19:24:00.762904389+01:00 imports: - name: github.com/abbot/go-http-auth version: cb4372376e1e00e9f6ab9ec142e029302c9e7140 @@ -24,7 +24,7 @@ imports: - name: github.com/containous/mux version: a819b77bba13f0c0cbe36e437bc2e948411b3996 - name: github.com/containous/staert - version: 92329254783dc01174f03302d51d7cf2c9ff84cf + version: 1e26a71803e428fd933f5f9c8e50a26878f53147 - name: github.com/coreos/etcd version: 1c9e0a0e33051fed6c05c141e6fcbfe5c7f2a899 subpackages: @@ -277,6 +277,8 @@ imports: - codec - name: github.com/unrolled/render version: 526faf80cd4b305bb8134abea8d20d5ced74faa6 +- name: github.com/urfave/negroni + version: e0e50f7dc431c043cb33f91b09c3419d48b7cff5 - name: github.com/vdemeester/docker-events version: be74d4929ec1ad118df54349fda4b0cba60f849b - name: github.com/vdemeester/shakers diff --git a/glide.yaml b/glide.yaml index ae05211bc..613664b57 100644 --- a/glide.yaml +++ b/glide.yaml @@ -6,7 +6,7 @@ import: - fun - package: github.com/Sirupsen/logrus - package: github.com/cenk/backoff -- package: github.com/codegangsta/negroni +- package: github.com/urfave/negroni - package: github.com/containous/flaeg version: a731c034dda967333efce5f8d276aeff11f8ff87 - package: github.com/vulcand/oxy @@ -21,7 +21,7 @@ import: - stream - utils - package: github.com/containous/staert - version: 92329254783dc01174f03302d51d7cf2c9ff84cf + version: 1e26a71803e428fd933f5f9c8e50a26878f53147 - package: github.com/docker/engine-api version: 62043eb79d581a32ea849645277023c550732e52 subpackages: diff --git a/provider/boltdb.go b/provider/boltdb.go index 3347fe340..e604fd428 100644 --- a/provider/boltdb.go +++ b/provider/boltdb.go @@ -17,7 +17,7 @@ type BoltDb struct { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *BoltDb) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *BoltDb) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { store, err := provider.CreateStore() if err != nil { return fmt.Errorf("Failed to Connect to KV store: %v", err) diff --git a/provider/consul.go b/provider/consul.go index 1b628dd4f..9316c513a 100644 --- a/provider/consul.go +++ b/provider/consul.go @@ -17,7 +17,7 @@ type Consul struct { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *Consul) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *Consul) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { store, err := provider.CreateStore() if err != nil { return fmt.Errorf("Failed to Connect to KV store: %v", err) diff --git a/provider/consul_catalog.go b/provider/consul_catalog.go index aad2e8ae5..b83da3b1d 100644 --- a/provider/consul_catalog.go +++ b/provider/consul_catalog.go @@ -317,7 +317,7 @@ func (provider *ConsulCatalog) watch(configurationChan chan<- types.ConfigMessag // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *ConsulCatalog) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *ConsulCatalog) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { config := api.DefaultConfig() config.Address = provider.Endpoint client, err := api.NewClient(config) diff --git a/provider/docker.go b/provider/docker.go index faff0b6d2..e2b312044 100644 --- a/provider/docker.go +++ b/provider/docker.go @@ -114,7 +114,7 @@ func (provider *Docker) createClient() (client.APIClient, error) { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { provider.Constraints = append(provider.Constraints, constraints...) // TODO register this routine in pool, and watch for stop channel safe.Go(func() { diff --git a/provider/etcd.go b/provider/etcd.go index 9c7726baa..7dc49d0aa 100644 --- a/provider/etcd.go +++ b/provider/etcd.go @@ -17,7 +17,7 @@ type Etcd struct { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *Etcd) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *Etcd) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { store, err := provider.CreateStore() if err != nil { return fmt.Errorf("Failed to Connect to KV store: %v", err) diff --git a/provider/file.go b/provider/file.go index aab244a89..c2c513f70 100644 --- a/provider/file.go +++ b/provider/file.go @@ -21,7 +21,7 @@ type File struct { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *File) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, _ []types.Constraint) error { +func (provider *File) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { watcher, err := fsnotify.NewWatcher() if err != nil { log.Error("Error creating file watcher", err) diff --git a/provider/kubernetes.go b/provider/kubernetes.go index 3ca6cd681..b50216636 100644 --- a/provider/kubernetes.go +++ b/provider/kubernetes.go @@ -94,7 +94,7 @@ func (provider *Kubernetes) createClient() (k8s.Client, error) { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { k8sClient, err := provider.createClient() if err != nil { return err diff --git a/provider/kv.go b/provider/kv.go index db8bac553..0e29ec2be 100644 --- a/provider/kv.go +++ b/provider/kv.go @@ -83,7 +83,7 @@ func (provider *Kv) watchKv(configurationChan chan<- types.ConfigMessage, prefix return nil } -func (provider *Kv) provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *Kv) provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { provider.Constraints = append(provider.Constraints, constraints...) operation := func() error { if _, err := provider.kvclient.Exists("qmslkjdfmqlskdjfmqlksjazçueznbvbwzlkajzebvkwjdcqmlsfj"); err != nil { diff --git a/provider/marathon.go b/provider/marathon.go index f6cc85563..e2b3b7386 100644 --- a/provider/marathon.go +++ b/provider/marathon.go @@ -50,7 +50,7 @@ type lightMarathonClient interface { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *Marathon) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *Marathon) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { provider.Constraints = append(provider.Constraints, constraints...) operation := func() error { config := marathon.NewDefaultConfig() diff --git a/provider/marathon_test.go b/provider/marathon_test.go index 6ce7c4009..bcc05404e 100644 --- a/provider/marathon_test.go +++ b/provider/marathon_test.go @@ -740,7 +740,7 @@ func TestMarathonAppConstraints(t *testing.T) { MarathonLBCompatibility: c.marathonLBCompatibility, } constraint, _ := types.NewConstraint("tag==valid") - provider.Constraints = []types.Constraint{*constraint} + provider.Constraints = types.Constraints{constraint} actual := provider.applicationFilter(c.application, c.filteredTasks) if actual != c.expected { t.Fatalf("expected %v, got %v: %v", c.expected, actual, c.application) @@ -820,7 +820,7 @@ func TestMarathonTaskConstraints(t *testing.T) { MarathonLBCompatibility: c.marathonLBCompatibility, } constraint, _ := types.NewConstraint("tag==valid") - provider.Constraints = []types.Constraint{*constraint} + provider.Constraints = types.Constraints{constraint} apps := new(marathon.Applications) apps.Apps = c.applications actual := provider.taskFilter(c.filteredTask, apps, true) diff --git a/provider/mesos.go b/provider/mesos.go index a99318249..fab03d422 100644 --- a/provider/mesos.go +++ b/provider/mesos.go @@ -42,7 +42,7 @@ type Mesos struct { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *Mesos) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *Mesos) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { operation := func() error { // initialize logging diff --git a/provider/provider.go b/provider/provider.go index b2e7d5d09..a7ce0dad4 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -23,7 +23,7 @@ import ( type Provider interface { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. - Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error + Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error } // BaseProvider should be inherited by providers @@ -44,7 +44,7 @@ func (p *BaseProvider) MatchConstraints(tags []string) (bool, *types.Constraint) for _, constraint := range p.Constraints { // xor: if ok and constraint.MustMatch are equal, then no tag is currently matching with the constraint if ok := constraint.MatchConstraintWithAtLeastOneTag(tags); ok != constraint.MustMatch { - return false, &constraint + return false, constraint } } diff --git a/provider/provider_test.go b/provider/provider_test.go index d14d971a1..f7f321989 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -230,13 +230,13 @@ func TestNilClientTLS(t *testing.T) { func TestMatchingConstraints(t *testing.T) { cases := []struct { - constraints []types.Constraint + constraints types.Constraints tags []string expected bool }{ // simple test: must match { - constraints: []types.Constraint{ + constraints: types.Constraints{ { Key: "tag", MustMatch: true, @@ -250,7 +250,7 @@ func TestMatchingConstraints(t *testing.T) { }, // simple test: must match but does not match { - constraints: []types.Constraint{ + constraints: types.Constraints{ { Key: "tag", MustMatch: true, @@ -264,7 +264,7 @@ func TestMatchingConstraints(t *testing.T) { }, // simple test: must not match { - constraints: []types.Constraint{ + constraints: types.Constraints{ { Key: "tag", MustMatch: false, @@ -278,7 +278,7 @@ func TestMatchingConstraints(t *testing.T) { }, // complex test: globbing { - constraints: []types.Constraint{ + constraints: types.Constraints{ { Key: "tag", MustMatch: true, @@ -292,7 +292,7 @@ func TestMatchingConstraints(t *testing.T) { }, // complex test: multiple constraints { - constraints: []types.Constraint{ + constraints: types.Constraints{ { Key: "tag", MustMatch: true, diff --git a/provider/zk.go b/provider/zk.go index 19f3654e5..57ce396b3 100644 --- a/provider/zk.go +++ b/provider/zk.go @@ -17,7 +17,7 @@ type Zookepper struct { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *Zookepper) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { +func (provider *Zookepper) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { store, err := provider.CreateStore() if err != nil { return fmt.Errorf("Failed to Connect to KV store: %v", err) diff --git a/types/types.go b/types/types.go index a8db1a6e3..15c4694b4 100644 --- a/types/types.go +++ b/types/types.go @@ -1,6 +1,7 @@ package types import ( + "encoding" "errors" "fmt" "github.com/docker/libkv/store" @@ -141,11 +142,25 @@ func (c *Constraint) String() string { return c.Key + "!=" + c.Regex } +var _ encoding.TextUnmarshaler = (*Constraint)(nil) + // UnmarshalText define how unmarshal in TOML parsing func (c *Constraint) UnmarshalText(text []byte) error { constraint, err := NewConstraint(string(text)) - *c = *constraint - return err + if err != nil { + return err + } + c.Key = constraint.Key + c.MustMatch = constraint.MustMatch + c.Regex = constraint.Regex + return nil +} + +var _ encoding.TextMarshaler = (*Constraint)(nil) + +// MarshalText encodes the receiver into UTF-8-encoded text and returns the result. +func (c *Constraint) MarshalText() (text []byte, err error) { + return []byte(c.String()), nil } // MatchConstraintWithAtLeastOneTag tests a constraint for one single service @@ -169,16 +184,16 @@ func (cs *Constraints) Set(str string) error { if err != nil { return err } - *cs = append(*cs, *constraint) + *cs = append(*cs, constraint) } return nil } // Constraints holds a Constraint parser -type Constraints []Constraint +type Constraints []*Constraint //Get []*Constraint -func (cs *Constraints) Get() interface{} { return []Constraint(*cs) } +func (cs *Constraints) Get() interface{} { return []*Constraint(*cs) } //String returns []*Constraint in string func (cs *Constraints) String() string { return fmt.Sprintf("%+v", *cs) } diff --git a/web.go b/web.go index 65a10f392..acfed0916 100644 --- a/web.go +++ b/web.go @@ -50,7 +50,7 @@ func goroutines() interface{} { // Provide allows the provider to provide configurations to traefik // using the given configuration channel. -func (provider *WebProvider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, _ []types.Constraint) error { +func (provider *WebProvider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, _ types.Constraints) error { systemRouter := mux.NewRouter() From 3e6d2391f7d389340d142bdd52e1fa92d965d040 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 9 Nov 2016 21:59:58 +0100 Subject: [PATCH 16/35] Add dtomcej, SantoDE remove samber from maintainers --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 23898c243..07980ed8a 100644 --- a/README.md +++ b/README.md @@ -159,9 +159,10 @@ Founded in 2014, Asteris creates next-generation infrastructure software for the - Emile Vauge [@emilevauge](https://github.com/emilevauge) - Vincent Demeester [@vdemeester](https://github.com/vdemeester) -- Samuel Berthe [@samber](https://github.com/samber) - Russell Clare [@Russell-IO](https://github.com/Russell-IO) - Ed Robinson [@errm](https://github.com/errm) +- Daniel Tomcej [@dtomcej](https://github.com/dtomcej) +- Manuel Laufenberg [@SantoDE](https://github.com/SantoDE) ## Credits From 5b6a5f8aa9e124162659b38fdc75def91788cce4 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 9 Nov 2016 22:00:10 +0100 Subject: [PATCH 17/35] Changelog v1.1.0-rc4 --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb70df8fb..13dab63a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ # Change Log +## [v1.1.0-rc4](https://github.com/containous/traefik/tree/v1.1.0-rc4) (2016-11-09) +[Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc3...v1.1.0-rc4) + +**Implemented enhancements:** + +- Feature Request: Enable Health checks to containers. [\#540](https://github.com/containous/traefik/issues/540) + +**Fixed bugs:** + +- Allow multiple certificates on a single entrypoint when trying to use TLS? [\#747](https://github.com/containous/traefik/issues/747) + +**Closed issues:** + +- LoadBalancing doesn't work in single node Swarm-mode [\#815](https://github.com/containous/traefik/issues/815) +- cannot connect to docker daemon [\#813](https://github.com/containous/traefik/issues/813) +- Let's encrypt configuration not working [\#805](https://github.com/containous/traefik/issues/805) +- Question: Wildcard Host for Kubernetes Ingress [\#792](https://github.com/containous/traefik/issues/792) +- Multiple subdomains for Marathon backend. [\#785](https://github.com/containous/traefik/issues/785) +- traefik-1.1.0-rc1: build error [\#781](https://github.com/containous/traefik/issues/781) +- Multiple routes support with Docker or Marathon labels [\#118](https://github.com/containous/traefik/issues/118) + +**Merged pull requests:** + +- Fix multiple issues [\#814](https://github.com/containous/traefik/pull/814) ([emilevauge](https://github.com/emilevauge)) +- Fix ACME renew & add version check [\#783](https://github.com/containous/traefik/pull/783) ([emilevauge](https://github.com/emilevauge)) +- Use first port by default [\#782](https://github.com/containous/traefik/pull/782) ([guilhem](https://github.com/guilhem)) + ## [v1.1.0-rc3](https://github.com/containous/traefik/tree/v1.1.0-rc3) (2016-10-26) [Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc2...v1.1.0-rc3) From 3f3fa61a514249b959a8ad9bbd27186dc6ab9a94 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Thu, 10 Nov 2016 11:12:54 +0100 Subject: [PATCH 18/35] Fix mkdocs theme --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 725e8fc62..3b0e824e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,7 @@ install: - docker version - pip install --user mkdocs - pip install --user pymdown-extensions +- pip install --user mkdocs-bootswatch before_script: - make validate - make binary From 1c4eb4322bdf0655712b05f5dfcc172c0b1c22f4 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Thu, 10 Nov 2016 11:15:42 +0100 Subject: [PATCH 19/35] Fix changelog --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13dab63a8..5507d422b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change Log -## [v1.1.0-rc4](https://github.com/containous/traefik/tree/v1.1.0-rc4) (2016-11-09) +## [v1.1.0-rc4](https://github.com/containous/traefik/tree/v1.1.0-rc4) (2016-11-10) [Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc3...v1.1.0-rc4) **Implemented enhancements:** @@ -9,6 +9,9 @@ **Fixed bugs:** +- Traefik stopped serving on upgrade to v1.1.0-rc3 [\#807](https://github.com/containous/traefik/issues/807) +- Traefik cannot read constraints from KV [\#794](https://github.com/containous/traefik/issues/794) +- HTTP2 - configuration [\#790](https://github.com/containous/traefik/issues/790) - Allow multiple certificates on a single entrypoint when trying to use TLS? [\#747](https://github.com/containous/traefik/issues/747) **Closed issues:** @@ -23,6 +26,7 @@ **Merged pull requests:** +- Prepare release v1.1.0 rc4 [\#822](https://github.com/containous/traefik/pull/822) ([emilevauge](https://github.com/emilevauge)) - Fix multiple issues [\#814](https://github.com/containous/traefik/pull/814) ([emilevauge](https://github.com/emilevauge)) - Fix ACME renew & add version check [\#783](https://github.com/containous/traefik/pull/783) ([emilevauge](https://github.com/emilevauge)) - Use first port by default [\#782](https://github.com/containous/traefik/pull/782) ([guilhem](https://github.com/guilhem)) From 3db6e185e0f3d87501174885fc2e238b5576b86e Mon Sep 17 00:00:00 2001 From: Manuel Laufenberg Date: Fri, 11 Nov 2016 21:50:59 +0100 Subject: [PATCH 20/35] Add Nvd3 Dependency to fix UI / Dashboard --- webui/package.json | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/webui/package.json b/webui/package.json index 92f25402e..762a57a5e 100644 --- a/webui/package.json +++ b/webui/package.json @@ -21,7 +21,8 @@ "angular-ui-bootstrap": "^2.0.0", "angular-ui-router": "^0.3.1", "bootstrap": "^3.3.6", - "moment": "^2.14.1" + "moment": "^2.14.1", + "nvd3": "^1.8.4" }, "devDependencies": { "angular-mocks": "^1.4.2", @@ -80,11 +81,6 @@ "test": "gulp test", "test:auto": "gulp test:auto" }, - "overrides": { - "angular-nvd3": { - "main": "dist/angular-nvd3.js" - } - }, "eslintConfig": { "globals": { "expect": true From 3095da64d77c13846aca792bfa0f6e477b0cc876 Mon Sep 17 00:00:00 2001 From: Thomas Recloux Date: Wed, 9 Nov 2016 18:43:59 +0100 Subject: [PATCH 21/35] Check that we provide HTTP/2 --- integration/https_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/integration/https_test.go b/integration/https_test.go index 36f3953f5..7bf2c2a59 100644 --- a/integration/https_test.go +++ b/integration/https_test.go @@ -30,6 +30,7 @@ func (s *HTTPSSuite) TestWithSNIConfigHandshake(c *check.C) { tlsConfig := &tls.Config{ InsecureSkipVerify: true, ServerName: "snitest.com", + NextProtos: []string{"h2", "http/1.1"}, } conn, err := tls.Dial("tcp", "127.0.0.1:4443", tlsConfig) c.Assert(err, checker.IsNil, check.Commentf("failed to connect to server")) @@ -41,6 +42,9 @@ func (s *HTTPSSuite) TestWithSNIConfigHandshake(c *check.C) { cs := conn.ConnectionState() err = cs.PeerCertificates[0].VerifyHostname("snitest.com") c.Assert(err, checker.IsNil, check.Commentf("certificate did not match SNI servername")) + + proto := conn.ConnectionState().NegotiatedProtocol + c.Assert(proto, checker.Equals, "h2") } // TestWithSNIConfigRoute involves a client sending HTTPS requests with From d3b48cdd228f718de530a65d80fe72a4e284786e Mon Sep 17 00:00:00 2001 From: Guilhem Lettron Date: Mon, 14 Nov 2016 16:34:07 +0100 Subject: [PATCH 22/35] Pass Version, Codename and Date to crosscompiled Copy variables from ./script/binary --- script/crossbinary | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/script/crossbinary b/script/crossbinary index 11537f8e0..86bde97c7 100755 --- a/script/crossbinary +++ b/script/crossbinary @@ -27,7 +27,7 @@ OS_ARCH_ARG=(386 amd64) for OS in ${OS_PLATFORM_ARG[@]}; do for ARCH in ${OS_ARCH_ARG[@]}; do echo "Building binary for $OS/$ARCH..." - GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 go build -ldflags "-s -w -X main.Version=$VERSION -X main.Codename=$CODENAME -X main.BuildDate=$DATE" -o "dist/traefik_$OS-$ARCH" . + GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/containous/traefik/version.Version=$VERSION -X github.com/containous/traefik/version.Codename=$CODENAME -X github.com/containous/traefik/version.BuildDate=$DATE" -o "dist/traefik_$OS-$ARCH" . done done @@ -38,6 +38,6 @@ OS_ARCH_ARG=(arm arm64) for OS in ${OS_PLATFORM_ARG[@]}; do for ARCH in ${OS_ARCH_ARG[@]}; do echo "Building binary for $OS/$ARCH..." - GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 go build -ldflags "-s -w -X main.Version=$VERSION -X main.Codename=$CODENAME -X main.BuildDate=$DATE" -o "dist/traefik_$OS-$ARCH" . + GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/containous/traefik/version.Version=$VERSION -X github.com/containous/traefik/version.Codename=$CODENAME -X github.com/containous/traefik/version.BuildDate=$DATE" -o "dist/traefik_$OS-$ARCH" . done -done \ No newline at end of file +done From ac20ddfc6c6cbb43f00c4b648bea3b7246f259ab Mon Sep 17 00:00:00 2001 From: Ed Robinson Date: Wed, 16 Nov 2016 08:56:52 +0000 Subject: [PATCH 23/35] Fix golint recent additions to golint mean that a number of files cause the build to start failing if they are edited (we only run against changed files) This fixes all the errors in the repo so things don't unexpectedly start failing for people making PRs --- acme/acme.go | 3 ++- acme/localStore.go | 2 +- cluster/datastore.go | 4 ++-- cluster/leadership.go | 4 ++-- configuration.go | 4 ++-- integration/consul_test.go | 4 ++-- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/acme/acme.go b/acme/acme.go index bd128a25a..d40137f2e 100644 --- a/acme/acme.go +++ b/acme/acme.go @@ -119,11 +119,12 @@ func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tl } datastore, err := cluster.NewDataStore( + leadership.Pool.Ctx(), staert.KvSource{ Store: leadership.Store, Prefix: a.Storage, }, - leadership.Pool.Ctx(), &Account{}, + &Account{}, listener) if err != nil { return err diff --git a/acme/localStore.go b/acme/localStore.go index 7432411ee..f01e31d68 100644 --- a/acme/localStore.go +++ b/acme/localStore.go @@ -68,7 +68,7 @@ func (t *localTransaction) Commit(object cluster.Object) error { t.LocalStore.account = object.(*Account) defer t.storageLock.Unlock() if t.dirty { - return fmt.Errorf("Transaction already used. Please begin a new one.") + return fmt.Errorf("transaction already used, please begin a new one") } // write account to file diff --git a/cluster/datastore.go b/cluster/datastore.go index ff81215d9..ec396bb5e 100644 --- a/cluster/datastore.go +++ b/cluster/datastore.go @@ -56,7 +56,7 @@ type Datastore struct { } // NewDataStore creates a Datastore -func NewDataStore(kvSource staert.KvSource, ctx context.Context, object Object, listener Listener) (*Datastore, error) { +func NewDataStore(ctx context.Context, kvSource staert.KvSource, object Object, listener Listener) (*Datastore, error) { datastore := Datastore{ kv: kvSource, ctx: ctx, @@ -230,7 +230,7 @@ func (s *datastoreTransaction) Commit(object Object) error { s.localLock.Lock() defer s.localLock.Unlock() if s.dirty { - return fmt.Errorf("Transaction already used. Please begin a new one.") + return fmt.Errorf("transaction already used, please begin a new one") } s.Datastore.meta.object = object err := s.Datastore.meta.Marshall() diff --git a/cluster/leadership.go b/cluster/leadership.go index bcdff6a1d..80447fa90 100644 --- a/cluster/leadership.go +++ b/cluster/leadership.go @@ -39,7 +39,7 @@ func (l *Leadership) Participate(pool *safe.Pool) { defer log.Debugf("Node %s no more running for election", l.Cluster.Node) backOff := backoff.NewExponentialBackOff() operation := func() error { - return l.run(l.candidate, ctx) + return l.run(ctx, l.candidate) } notify := func(err error, time time.Duration) { @@ -63,7 +63,7 @@ func (l *Leadership) Resign() { log.Infof("Node %s resigned", l.Cluster.Node) } -func (l *Leadership) run(candidate *leadership.Candidate, ctx context.Context) error { +func (l *Leadership) run(ctx context.Context, candidate *leadership.Candidate) error { electedCh, errCh := candidate.RunForElection() for { select { diff --git a/configuration.go b/configuration.go index cf9e75175..ece949c38 100644 --- a/configuration.go +++ b/configuration.go @@ -234,10 +234,10 @@ func (certs *Certificates) CreateTLSConfig() (*tls.Config, error) { if errKey == nil { isAPath = true } else { - return nil, fmt.Errorf("Bad TLS Certificate KeyFile format. Expected a path.") + return nil, fmt.Errorf("bad TLS Certificate KeyFile format, expected a path") } } else if errKey == nil { - return nil, fmt.Errorf("Bad TLS Certificate KeyFile format. Expected a path.") + return nil, fmt.Errorf("bad TLS Certificate KeyFile format, expected a path") } cert := tls.Certificate{} diff --git a/integration/consul_test.go b/integration/consul_test.go index d9b7b8218..e80e4747d 100644 --- a/integration/consul_test.go +++ b/integration/consul_test.go @@ -446,9 +446,9 @@ func (s *ConsulSuite) TestDatastore(c *check.C) { c.Assert(err, checker.IsNil) ctx := context.Background() - datastore1, err := cluster.NewDataStore(*kvSource, ctx, &TestStruct{}, nil) + datastore1, err := cluster.NewDataStore(ctx, *kvSource, &TestStruct{}, nil) c.Assert(err, checker.IsNil) - datastore2, err := cluster.NewDataStore(*kvSource, ctx, &TestStruct{}, nil) + datastore2, err := cluster.NewDataStore(ctx, *kvSource, &TestStruct{}, nil) c.Assert(err, checker.IsNil) setter1, _, err := datastore1.Begin() From 7065f00443fba185f91d1ff98f6ced1e99cfd854 Mon Sep 17 00:00:00 2001 From: Steven Bower Date: Thu, 17 Nov 2016 09:36:10 -0500 Subject: [PATCH 24/35] Fixes #851 (#852) --- rules.go | 8 ++++---- rules_test.go | 12 ++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/rules.go b/rules.go index 96cc73b6e..3bb6edca7 100644 --- a/rules.go +++ b/rules.go @@ -45,7 +45,7 @@ func (r *Rules) hostRegexp(hosts ...string) *mux.Route { func (r *Rules) path(paths ...string) *mux.Route { router := r.route.route.Subrouter() for _, path := range paths { - router.Path(types.CanonicalDomain(path)) + router.Path(strings.TrimSpace(path)) } return r.route.route } @@ -53,7 +53,7 @@ func (r *Rules) path(paths ...string) *mux.Route { func (r *Rules) pathPrefix(paths ...string) *mux.Route { router := r.route.route.Subrouter() for _, path := range paths { - router.PathPrefix(types.CanonicalDomain(path)) + router.PathPrefix(strings.TrimSpace(path)) } return r.route.route } @@ -69,7 +69,7 @@ func (r *Rules) pathStrip(paths ...string) *mux.Route { r.route.stripPrefixes = paths router := r.route.route.Subrouter() for _, path := range paths { - router.Path(types.CanonicalDomain(path)) + router.Path(strings.TrimSpace(path)) } return r.route.route } @@ -79,7 +79,7 @@ func (r *Rules) pathPrefixStrip(paths ...string) *mux.Route { r.route.stripPrefixes = paths router := r.route.route.Subrouter() for _, path := range paths { - router.PathPrefix(types.CanonicalDomain(path)) + router.PathPrefix(strings.TrimSpace(path)) } return r.route.route } diff --git a/rules_test.go b/rules_test.go index 694fde089..72c712423 100644 --- a/rules_test.go +++ b/rules_test.go @@ -40,15 +40,23 @@ func TestParseTwoRules(t *testing.T) { routeResult, err := rules.Parse(expression) if err != nil { - t.Fatal("Error while building route for Host:foo.bar;Path:/foobar") + t.Fatal("Error while building route for Host:foo.bar;Path:/FOObar") } request, err := http.NewRequest("GET", "http://foo.bar/foobar", nil) routeMatch := routeResult.Match(request, &mux.RouteMatch{Route: routeResult}) + if routeMatch == true { + t.Log(err) + t.Fatal("Rule Host:foo.bar;Path:/FOObar don't match") + } + + request, err = http.NewRequest("GET", "http://foo.bar/FOObar", nil) + routeMatch = routeResult.Match(request, &mux.RouteMatch{Route: routeResult}) + if routeMatch == false { t.Log(err) - t.Fatal("Rule Host:foo.bar;Path:/foobar don't match") + t.Fatal("Rule Host:foo.bar;Path:/FOObar don't match") } } From 2dda3d2febe573e91eb82c7a2900c9306c7f065f Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Tue, 15 Nov 2016 20:36:56 +0100 Subject: [PATCH 25/35] Fix Kubernetes watch leak Signed-off-by: Emile Vauge --- provider/k8s/client.go | 29 +++++++++++++---------------- provider/kubernetes.go | 1 + 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/provider/k8s/client.go b/provider/k8s/client.go index ad9679cae..4a6bae919 100644 --- a/provider/k8s/client.go +++ b/provider/k8s/client.go @@ -1,6 +1,7 @@ package k8s import ( + "context" "crypto/tls" "crypto/x509" "encoding/json" @@ -141,20 +142,20 @@ func (c *clientImpl) WatchEndpoints(stopCh <-chan bool) (chan interface{}, chan // WatchAll returns events in the cluster func (c *clientImpl) WatchAll(labelSelector string, stopCh <-chan bool) (chan interface{}, chan error, error) { - watchCh := make(chan interface{}, 10) - errCh := make(chan error, 10) + watchCh := make(chan interface{}, 100) + errCh := make(chan error, 100) - stopIngresses := make(chan bool) + stopIngresses := make(chan bool, 10) chanIngresses, chanIngressesErr, err := c.WatchIngresses(labelSelector, stopIngresses) if err != nil { return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err) } - stopServices := make(chan bool) + stopServices := make(chan bool, 10) chanServices, chanServicesErr, err := c.WatchServices(stopServices) if err != nil { return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err) } - stopEndpoints := make(chan bool) + stopEndpoints := make(chan bool, 10) chanEndpoints, chanEndpointsErr, err := c.WatchEndpoints(stopEndpoints) if err != nil { return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err) @@ -257,16 +258,17 @@ func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool) if err != nil { return watchCh, errCh, fmt.Errorf("failed to make watch request: GET %q : %v", url, err) } + ctx, cancel := context.WithCancel(context.Background()) + req = req.WithContext(ctx) request.Client.Transport = request.Transport res, err := request.Client.Do(req) if err != nil { + cancel() return watchCh, errCh, fmt.Errorf("failed to do watch request: GET %q: %v", url, err) } go func() { - finishCh := make(chan bool) - defer close(finishCh) defer close(watchCh) defer close(errCh) go func() { @@ -277,20 +279,15 @@ func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool) if !strings.Contains(err.Error(), "net/http: request canceled") { errCh <- fmt.Errorf("failed to decode watch event: GET %q : %v", url, err) } - finishCh <- true return } watchCh <- eventList } }() - select { - case <-stopCh: - go func() { - request.Transport.CancelRequest(req) - }() - <-finishCh - return - } + <-stopCh + go func() { + cancel() // cancel watch request + }() }() return watchCh, errCh, nil } diff --git a/provider/kubernetes.go b/provider/kubernetes.go index b50216636..a08014eff 100644 --- a/provider/kubernetes.go +++ b/provider/kubernetes.go @@ -130,6 +130,7 @@ func (provider *Kubernetes) Provide(configurationChan chan<- types.ConfigMessage log.Debugf("Received event from kubernetes %+v", event) templateObjects, err := provider.loadIngresses(k8sClient) if err != nil { + stopWatch <- true return err } if reflect.DeepEqual(provider.lastConfiguration.Get(), templateObjects) { From 8aaca8e55cd61f6c9cf9e9eabe3057e9247b5821 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 16 Nov 2016 11:48:08 +0100 Subject: [PATCH 26/35] Update docs with errm talk --- docs/index.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index 1941c8615..efaa0f31d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -40,10 +40,15 @@ Run it and forget it! You can have a quick look at Træfɪk in this [Katacoda tutorial](https://www.katacoda.com/courses/traefik/deploy-load-balancer) that shows how to load balance requests between multiple Docker containers. -Here is a talk (in french) given by [Emile Vauge](https://github.com/emilevauge) at the [Devoxx France 2016](http://www.devoxx.fr) conference. -You will learn fundamental Træfɪk features and see some demos with Docker, Mesos/Marathon and Lets'Encrypt. +Here is a talk given by [Ed Robinson](https://github.com/errm) at the [ContainerCamp UK](https://container.camp) conference. +You will learn fundamental Træfɪk features and see some demos with Kubernetes. -[![Traefik Devoxx France](https://img.youtube.com/vi/QvAz9mVx5TI/0.jpg)](https://www.youtube.com/watch?v=QvAz9mVx5TI) +[![Traefik ContainerCamp UK](http://img.youtube.com/vi/aFtpIShV60I/0.jpg)](https://www.youtube.com/watch?v=aFtpIShV60I) + +Here is a talk (in French) given by [Emile Vauge](https://github.com/emilevauge) at the [Devoxx France 2016](http://www.devoxx.fr) conference. +You will learn fundamental Træfɪk features and see some demos with Docker, Mesos/Marathon and Let's Encrypt. + +[![Traefik Devoxx France](http://img.youtube.com/vi/QvAz9mVx5TI/0.jpg)](http://www.youtube.com/watch?v=QvAz9mVx5TI) ## Get it From 221ae2427b0789922e6d84a67779dbddda5c40c9 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Thu, 17 Nov 2016 22:07:15 +0100 Subject: [PATCH 27/35] changelog v1.1.0 --- CHANGELOG.md | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5507d422b..2bfa436ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,207 @@ # Change Log +## [v1.1.0](https://github.com/containous/traefik/tree/v1.1.0) (2016-11-17) +[Full Changelog](https://github.com/containous/traefik/compare/v1.0.0...v1.1.0) + +**Implemented enhancements:** + +- Support healthcheck if present for docker [\#666](https://github.com/containous/traefik/issues/666) +- Standard unit for traefik latency in access log [\#559](https://github.com/containous/traefik/issues/559) +- \[CI\] wiredep marked as unmaintained [\#550](https://github.com/containous/traefik/issues/550) +- Feature Request: Enable Health checks to containers. [\#540](https://github.com/containous/traefik/issues/540) +- Feature Request: SSL Cipher Selection [\#535](https://github.com/containous/traefik/issues/535) +- Error with -consulcatalog and missing load balance method on 1.0.0 [\#524](https://github.com/containous/traefik/issues/524) +- Running Traefik with Docker 1.12 Swarm Mode [\#504](https://github.com/containous/traefik/issues/504) +- Kubernetes provider: should allow the master url to be override [\#501](https://github.com/containous/traefik/issues/501) +- \[FRONTEND\]\[LE\] Pre-generate SSL certificates for "Host:" rules [\#483](https://github.com/containous/traefik/issues/483) +- Frontend Rule evolution [\#437](https://github.com/containous/traefik/issues/437) +- Add a Changelog [\#388](https://github.com/containous/traefik/issues/388) +- Add label matching for kubernetes ingests [\#363](https://github.com/containous/traefik/issues/363) +- Acme in HA Traefik Scenario [\#348](https://github.com/containous/traefik/issues/348) +- HTTP Basic Auth support [\#77](https://github.com/containous/traefik/issues/77) +- Session affinity / stickiness / persistence [\#5](https://github.com/containous/traefik/issues/5) + +**Fixed bugs:** + +- 1.1.0-rc4 dashboard UX not displaying [\#828](https://github.com/containous/traefik/issues/828) +- Traefik stopped serving on upgrade to v1.1.0-rc3 [\#807](https://github.com/containous/traefik/issues/807) +- cannot access webui/dashboard [\#796](https://github.com/containous/traefik/issues/796) +- Traefik cannot read constraints from KV [\#794](https://github.com/containous/traefik/issues/794) +- HTTP2 - configuration [\#790](https://github.com/containous/traefik/issues/790) +- Cannot provide multiple certificates using flag [\#757](https://github.com/containous/traefik/issues/757) +- Allow multiple certificates on a single entrypoint when trying to use TLS? [\#747](https://github.com/containous/traefik/issues/747) +- traefik \* Users: unsupported type: slice [\#743](https://github.com/containous/traefik/issues/743) +- \[Docker swarm mode\] The traefik.docker.network seems to have no effect [\#719](https://github.com/containous/traefik/issues/719) +- traefik hangs - stops handling requests [\#662](https://github.com/containous/traefik/issues/662) +- Add long jobs in exponential backoff providers [\#626](https://github.com/containous/traefik/issues/626) +- Tip of tree crashes on invalid pointer on Marathon provider [\#624](https://github.com/containous/traefik/issues/624) +- ACME: revoke certificate on agreement update [\#579](https://github.com/containous/traefik/issues/579) +- WebUI: Providers tabs disappeared [\#577](https://github.com/containous/traefik/issues/577) +- traefik version command contains incorrect information when building from master branch [\#569](https://github.com/containous/traefik/issues/569) +- Case sensitive domain names breaks routing [\#562](https://github.com/containous/traefik/issues/562) +- Flag --etcd.endpoint default [\#508](https://github.com/containous/traefik/issues/508) +- Conditional ACME on demand generation [\#505](https://github.com/containous/traefik/issues/505) +- Important delay with streams \(Mozilla EventSource\) [\#503](https://github.com/containous/traefik/issues/503) +- Traefik crashing [\#458](https://github.com/containous/traefik/issues/458) +- traefik.toml constraints error: `Expected map but found 'string'.` [\#451](https://github.com/containous/traefik/issues/451) +- Multiple path separators in the url path causing redirect [\#167](https://github.com/containous/traefik/issues/167) + +**Closed issues:** + +- All path rules require paths to be lowercase [\#851](https://github.com/containous/traefik/issues/851) +- The UI stops working after a time and have to restart the service. [\#840](https://github.com/containous/traefik/issues/840) +- Incorrect Dashboard page returned [\#831](https://github.com/containous/traefik/issues/831) +- LoadBalancing doesn't work in single node Swarm-mode [\#815](https://github.com/containous/traefik/issues/815) +- cannot connect to docker daemon [\#813](https://github.com/containous/traefik/issues/813) +- Let's encrypt configuration not working [\#805](https://github.com/containous/traefik/issues/805) +- Multiple subdomains for Marathon backend. [\#785](https://github.com/containous/traefik/issues/785) +- traefik-1.1.0-rc1: build error [\#781](https://github.com/containous/traefik/issues/781) +- dependencies installation error [\#755](https://github.com/containous/traefik/issues/755) +- k8s provider w/ acme? [\#752](https://github.com/containous/traefik/issues/752) +- Swarm Docs - How to use a FQDN [\#744](https://github.com/containous/traefik/issues/744) +- Documented ProvidersThrottleDuration value is invalid [\#741](https://github.com/containous/traefik/issues/741) +- Sensible configuration for consulCatalog [\#737](https://github.com/containous/traefik/issues/737) +- Traefik ignoring container listening in more than one TCP port [\#734](https://github.com/containous/traefik/issues/734) +- Loadbalaning issues with traefik and Docker Swarm cluster [\#730](https://github.com/containous/traefik/issues/730) +- issues with marathon app ids containing a dot [\#726](https://github.com/containous/traefik/issues/726) +- Error when using HA acme in kubernetes with etcd [\#725](https://github.com/containous/traefik/issues/725) +- \[Docker swarm mode\] No round robin when using service [\#718](https://github.com/containous/traefik/issues/718) +- Dose it support docker swarm mode [\#712](https://github.com/containous/traefik/issues/712) +- Kubernetes - Undefined backend [\#710](https://github.com/containous/traefik/issues/710) +- How Routing traffic depending on path not domain in docker [\#706](https://github.com/containous/traefik/issues/706) +- Constraints on Consul Catalogue not working as expected [\#703](https://github.com/containous/traefik/issues/703) +- Global InsecureSkipVerify does not work [\#700](https://github.com/containous/traefik/issues/700) +- Traefik crashes when using Consul catalog [\#699](https://github.com/containous/traefik/issues/699) +- \[documentation/feature\] Consul/etcd support atomic multiple key changes now [\#698](https://github.com/containous/traefik/issues/698) +- How to configure which network to use when starting traefik binary? [\#694](https://github.com/containous/traefik/issues/694) +- How to get multiple host headers working for docker labels? [\#692](https://github.com/containous/traefik/issues/692) +- Requests with URL-encoded characters are not forwarded correctly [\#684](https://github.com/containous/traefik/issues/684) +- File Watcher for rules does not work [\#683](https://github.com/containous/traefik/issues/683) +- Issue with global InsecureSkipVerify = true and self signed certificates [\#667](https://github.com/containous/traefik/issues/667) +- Docker exposedbydefault = false didn't work [\#663](https://github.com/containous/traefik/issues/663) +- swarm documentation needs update [\#656](https://github.com/containous/traefik/issues/656) +- \[ACME\] Auto SAN Detection [\#655](https://github.com/containous/traefik/issues/655) +- Fronting a domain with DNS A-record round-robin & ACME [\#654](https://github.com/containous/traefik/issues/654) +- Overriding toml configuration with environment variables [\#650](https://github.com/containous/traefik/issues/650) +- marathon provider exposedByDefault = false [\#647](https://github.com/containous/traefik/issues/647) +- Add status URL for service up checks [\#642](https://github.com/containous/traefik/issues/642) +- acme's storage file, containing private key, is word readable [\#638](https://github.com/containous/traefik/issues/638) +- wildcard domain with exclusions [\#633](https://github.com/containous/traefik/issues/633) +- Enable evenly distribution among backend [\#631](https://github.com/containous/traefik/issues/631) +- Traefik sporadically failing when proxying requests [\#615](https://github.com/containous/traefik/issues/615) +- TCP Proxy [\#608](https://github.com/containous/traefik/issues/608) +- How to use in Windows? [\#605](https://github.com/containous/traefik/issues/605) +- `ClientCAFiles` ignored [\#604](https://github.com/containous/traefik/issues/604) +- Let`s Encrypt enable in etcd [\#600](https://github.com/containous/traefik/issues/600) +- Support HTTP Basic Auth [\#599](https://github.com/containous/traefik/issues/599) +- Consul KV seem broken [\#587](https://github.com/containous/traefik/issues/587) +- HTTPS entryPoint not working [\#574](https://github.com/containous/traefik/issues/574) +- Traefik stuck when used as frontend for a streaming API [\#560](https://github.com/containous/traefik/issues/560) +- Exclude some frontends in consul catalog [\#555](https://github.com/containous/traefik/issues/555) +- Update docs with new Mesos provider [\#548](https://github.com/containous/traefik/issues/548) +- Can I use Traefik without a domain name? [\#539](https://github.com/containous/traefik/issues/539) +- docker run syntax in swarm example has changed [\#528](https://github.com/containous/traefik/issues/528) +- Priortities in 1.0.0 not behaving [\#506](https://github.com/containous/traefik/issues/506) +- Route by path [\#500](https://github.com/containous/traefik/issues/500) +- Secure WebSockets [\#467](https://github.com/containous/traefik/issues/467) +- Container IP Lost [\#375](https://github.com/containous/traefik/issues/375) +- Multiple routes support with Docker or Marathon labels [\#118](https://github.com/containous/traefik/issues/118) + +**Merged pull requests:** + +- Fix path case sensitive v1.1 [\#855](https://github.com/containous/traefik/pull/855) ([emilevauge](https://github.com/emilevauge)) +- Fix golint in v1.1 [\#849](https://github.com/containous/traefik/pull/849) ([emilevauge](https://github.com/emilevauge)) +- Fix Kubernetes watch leak [\#845](https://github.com/containous/traefik/pull/845) ([emilevauge](https://github.com/emilevauge)) +- Pass Version, Codename and Date to crosscompiled [\#842](https://github.com/containous/traefik/pull/842) ([guilhem](https://github.com/guilhem)) +- Add Nvd3 Dependency to fix UI / Dashboard [\#829](https://github.com/containous/traefik/pull/829) ([SantoDE](https://github.com/SantoDE)) +- Fix mkdoc theme [\#823](https://github.com/containous/traefik/pull/823) ([emilevauge](https://github.com/emilevauge)) +- Prepare release v1.1.0 rc4 [\#822](https://github.com/containous/traefik/pull/822) ([emilevauge](https://github.com/emilevauge)) +- Check that we serve HTTP/2 [\#820](https://github.com/containous/traefik/pull/820) ([trecloux](https://github.com/trecloux)) +- Fix multiple issues [\#814](https://github.com/containous/traefik/pull/814) ([emilevauge](https://github.com/emilevauge)) +- Fix ACME renew & add version check [\#783](https://github.com/containous/traefik/pull/783) ([emilevauge](https://github.com/emilevauge)) +- Use first port by default [\#782](https://github.com/containous/traefik/pull/782) ([guilhem](https://github.com/guilhem)) +- Prepare release v1.1.0-rc3 [\#779](https://github.com/containous/traefik/pull/779) ([emilevauge](https://github.com/emilevauge)) +- Fix ResponseRecorder Flush [\#776](https://github.com/containous/traefik/pull/776) ([emilevauge](https://github.com/emilevauge)) +- Use sdnotify for systemd [\#768](https://github.com/containous/traefik/pull/768) ([guilhem](https://github.com/guilhem)) +- Fix providers throttle duration doc [\#760](https://github.com/containous/traefik/pull/760) ([emilevauge](https://github.com/emilevauge)) +- Fix mapstructure issue with anonymous slice [\#759](https://github.com/containous/traefik/pull/759) ([emilevauge](https://github.com/emilevauge)) +- Fix multiple certificates using flag [\#758](https://github.com/containous/traefik/pull/758) ([emilevauge](https://github.com/emilevauge)) +- Really fix deploy ghr... [\#748](https://github.com/containous/traefik/pull/748) ([emilevauge](https://github.com/emilevauge)) +- Fixes deploy ghr [\#742](https://github.com/containous/traefik/pull/742) ([emilevauge](https://github.com/emilevauge)) +- prepare v1.1.0-rc2 [\#740](https://github.com/containous/traefik/pull/740) ([emilevauge](https://github.com/emilevauge)) +- Fix case sensitive host [\#733](https://github.com/containous/traefik/pull/733) ([emilevauge](https://github.com/emilevauge)) +- Update Kubernetes examples [\#731](https://github.com/containous/traefik/pull/731) ([Starefossen](https://github.com/Starefossen)) +- fIx marathon template with dots in ID [\#728](https://github.com/containous/traefik/pull/728) ([emilevauge](https://github.com/emilevauge)) +- Fix networkMap construction in ListServices [\#724](https://github.com/containous/traefik/pull/724) ([vincentlepot](https://github.com/vincentlepot)) +- Add basic compatibility with marathon-lb [\#720](https://github.com/containous/traefik/pull/720) ([guilhem](https://github.com/guilhem)) +- Add Ed's video at ContainerCamp [\#717](https://github.com/containous/traefik/pull/717) ([emilevauge](https://github.com/emilevauge)) +- Add documentation for Træfik on docker swarm mode [\#715](https://github.com/containous/traefik/pull/715) ([vdemeester](https://github.com/vdemeester)) +- Remove duplicated link to Kubernetes.io in README.md [\#713](https://github.com/containous/traefik/pull/713) ([oscerd](https://github.com/oscerd)) +- Show current version in web UI [\#709](https://github.com/containous/traefik/pull/709) ([vhf](https://github.com/vhf)) +- Add support for docker healthcheck 👼 [\#708](https://github.com/containous/traefik/pull/708) ([vdemeester](https://github.com/vdemeester)) +- Fix syntax in Swarm example. Resolves \#528 [\#707](https://github.com/containous/traefik/pull/707) ([billglover](https://github.com/billglover)) +- Add HTTP compression [\#702](https://github.com/containous/traefik/pull/702) ([tuier](https://github.com/tuier)) +- Carry PR 446 - Add sticky session support \(round two!\) [\#701](https://github.com/containous/traefik/pull/701) ([emilevauge](https://github.com/emilevauge)) +- Remove unused endpoint when using constraints with Marathon provider [\#697](https://github.com/containous/traefik/pull/697) ([tuier](https://github.com/tuier)) +- Replace imagelayers.io with microbadger [\#696](https://github.com/containous/traefik/pull/696) ([solidnerd](https://github.com/solidnerd)) +- Selectable TLS Versions [\#690](https://github.com/containous/traefik/pull/690) ([dtomcej](https://github.com/dtomcej)) +- Carry pr 439 [\#689](https://github.com/containous/traefik/pull/689) ([emilevauge](https://github.com/emilevauge)) +- Disable gorilla/mux URL cleaning to prevent sending redirect [\#688](https://github.com/containous/traefik/pull/688) ([ydubreuil](https://github.com/ydubreuil)) +- Some fixes [\#687](https://github.com/containous/traefik/pull/687) ([emilevauge](https://github.com/emilevauge)) +- feat\(constraints\): Supports constraints for Marathon provider [\#686](https://github.com/containous/traefik/pull/686) ([tuier](https://github.com/tuier)) +- Update docs to improve contribution setup [\#685](https://github.com/containous/traefik/pull/685) ([dtomcej](https://github.com/dtomcej)) +- Add basic auth support for web backend [\#677](https://github.com/containous/traefik/pull/677) ([SantoDE](https://github.com/SantoDE)) +- Document accepted values for logLevel. [\#676](https://github.com/containous/traefik/pull/676) ([jimmycuadra](https://github.com/jimmycuadra)) +- If Marathon doesn't have healthcheck, assume it's ok [\#665](https://github.com/containous/traefik/pull/665) ([gomes](https://github.com/gomes)) +- ACME: renew certificates 30 days before expiry [\#660](https://github.com/containous/traefik/pull/660) ([JayH5](https://github.com/JayH5)) +- Update broken link and add a comment to sample config file [\#658](https://github.com/containous/traefik/pull/658) ([Yggdrasil](https://github.com/Yggdrasil)) +- Add possibility to use BindPort IPAddress 👼 [\#657](https://github.com/containous/traefik/pull/657) ([vdemeester](https://github.com/vdemeester)) +- Update marathon [\#648](https://github.com/containous/traefik/pull/648) ([emilevauge](https://github.com/emilevauge)) +- Add backend features to docker [\#646](https://github.com/containous/traefik/pull/646) ([jangie](https://github.com/jangie)) +- enable consul catalog to use maxconn [\#645](https://github.com/containous/traefik/pull/645) ([jangie](https://github.com/jangie)) +- Adopt the Code Of Coduct from http://contributor-covenant.org [\#641](https://github.com/containous/traefik/pull/641) ([errm](https://github.com/errm)) +- Use secure mode 600 instead of 644 for acme.json [\#639](https://github.com/containous/traefik/pull/639) ([discordianfish](https://github.com/discordianfish)) +- docker clarification, fix dead urls, misc typos [\#637](https://github.com/containous/traefik/pull/637) ([djalal](https://github.com/djalal)) +- add PING handler to dashboard API [\#630](https://github.com/containous/traefik/pull/630) ([jangie](https://github.com/jangie)) +- Migrate to JobBackOff [\#628](https://github.com/containous/traefik/pull/628) ([emilevauge](https://github.com/emilevauge)) +- Add long job exponential backoff [\#627](https://github.com/containous/traefik/pull/627) ([emilevauge](https://github.com/emilevauge)) +- HA acme support [\#625](https://github.com/containous/traefik/pull/625) ([emilevauge](https://github.com/emilevauge)) +- Bump go v1.7 [\#620](https://github.com/containous/traefik/pull/620) ([emilevauge](https://github.com/emilevauge)) +- Make duration logging consistent [\#619](https://github.com/containous/traefik/pull/619) ([jangie](https://github.com/jangie)) +- fix for nil clientTLS causing issue [\#617](https://github.com/containous/traefik/pull/617) ([jangie](https://github.com/jangie)) +- Add ability for marathon provider to set maxconn values, loadbalancer algorithm, and circuit breaker expression [\#616](https://github.com/containous/traefik/pull/616) ([jangie](https://github.com/jangie)) +- Make systemd unit installable [\#613](https://github.com/containous/traefik/pull/613) ([keis](https://github.com/keis)) +- Merge v1.0.2 master [\#610](https://github.com/containous/traefik/pull/610) ([emilevauge](https://github.com/emilevauge)) +- update staert and flaeg [\#609](https://github.com/containous/traefik/pull/609) ([cocap10](https://github.com/cocap10)) +- \#504 Initial support for Docker 1.12 Swarm Mode [\#602](https://github.com/containous/traefik/pull/602) ([diegofernandes](https://github.com/diegofernandes)) +- Add Host cert ACME generation [\#601](https://github.com/containous/traefik/pull/601) ([emilevauge](https://github.com/emilevauge)) +- Fixed binary script so traefik version command doesn't just print default values [\#598](https://github.com/containous/traefik/pull/598) ([keiths-osc](https://github.com/keiths-osc)) +- Name servers after thier pods [\#596](https://github.com/containous/traefik/pull/596) ([errm](https://github.com/errm)) +- Fix Consul prefix [\#589](https://github.com/containous/traefik/pull/589) ([jippi](https://github.com/jippi)) +- Prioritize kubernetes routes by path length [\#588](https://github.com/containous/traefik/pull/588) ([philk](https://github.com/philk)) +- beautify help [\#580](https://github.com/containous/traefik/pull/580) ([cocap10](https://github.com/cocap10)) +- Upgrade directives name since we use angular-ui-bootstrap [\#578](https://github.com/containous/traefik/pull/578) ([micaelmbagira](https://github.com/micaelmbagira)) +- Fix basic docs for configuration of multiple rules [\#576](https://github.com/containous/traefik/pull/576) ([ajaegle](https://github.com/ajaegle)) +- Fix k8s watch [\#573](https://github.com/containous/traefik/pull/573) ([errm](https://github.com/errm)) +- Add requirements.txt for netlify [\#567](https://github.com/containous/traefik/pull/567) ([emilevauge](https://github.com/emilevauge)) +- Merge v1.0.1 master [\#565](https://github.com/containous/traefik/pull/565) ([emilevauge](https://github.com/emilevauge)) +- Move webui to FountainJS with Webpack [\#558](https://github.com/containous/traefik/pull/558) ([micaelmbagira](https://github.com/micaelmbagira)) +- Add global InsecureSkipVerify option to disable certificate checking [\#557](https://github.com/containous/traefik/pull/557) ([stuart-c](https://github.com/stuart-c)) +- Move version.go in its own package… [\#553](https://github.com/containous/traefik/pull/553) ([vdemeester](https://github.com/vdemeester)) +- Upgrade libkermit and dependencies [\#552](https://github.com/containous/traefik/pull/552) ([vdemeester](https://github.com/vdemeester)) +- Add command storeconfig [\#551](https://github.com/containous/traefik/pull/551) ([cocap10](https://github.com/cocap10)) +- Add basic/digest auth [\#547](https://github.com/containous/traefik/pull/547) ([emilevauge](https://github.com/emilevauge)) +- Bump node to 6 for webui [\#546](https://github.com/containous/traefik/pull/546) ([vdemeester](https://github.com/vdemeester)) +- Bump golang to 1.6.3 [\#545](https://github.com/containous/traefik/pull/545) ([vdemeester](https://github.com/vdemeester)) +- Fix typos [\#538](https://github.com/containous/traefik/pull/538) ([jimt](https://github.com/jimt)) +- Kubernetes user-guide [\#519](https://github.com/containous/traefik/pull/519) ([errm](https://github.com/errm)) +- Implement Kubernetes Selectors, minor kube endpoint fix [\#516](https://github.com/containous/traefik/pull/516) ([pnegahdar](https://github.com/pnegahdar)) +- Carry \#358 : Option to disable expose of all docker containers [\#514](https://github.com/containous/traefik/pull/514) ([vdemeester](https://github.com/vdemeester)) +- Remove traefik.frontend.value support in docker… [\#510](https://github.com/containous/traefik/pull/510) ([vdemeester](https://github.com/vdemeester)) +- Use KvStores as global config sources [\#481](https://github.com/containous/traefik/pull/481) ([cocap10](https://github.com/cocap10)) +- Add endpoint option to authenticate by client tls cert. [\#461](https://github.com/containous/traefik/pull/461) ([andersbetner](https://github.com/andersbetner)) +- add mesos provider inspired by mesos-dns & marathon provider [\#353](https://github.com/containous/traefik/pull/353) ([skydjol](https://github.com/skydjol)) + ## [v1.1.0-rc4](https://github.com/containous/traefik/tree/v1.1.0-rc4) (2016-11-10) [Full Changelog](https://github.com/containous/traefik/compare/v1.1.0-rc3...v1.1.0-rc4) From a8cb905255176ff308abc464567d0cad30a04abc Mon Sep 17 00:00:00 2001 From: Kristian Klausen Date: Wed, 23 Nov 2016 14:49:55 +0100 Subject: [PATCH 28/35] consul/kv.tmpl: weight default value should be a int (#826) * consul/kv.tmpl: weight default value should be a int Fix #821 * Use 0 as default weight in all backends --- provider/consul_catalog_test.go | 6 +++--- provider/docker.go | 2 +- provider/docker_test.go | 18 +++++++++--------- provider/kubernetes.go | 4 ++-- provider/kubernetes_test.go | 30 +++++++++++++++--------------- provider/kv_test.go | 4 ++-- templates/consul_catalog.tmpl | 2 +- templates/kv.tmpl | 2 +- 8 files changed, 34 insertions(+), 34 deletions(-) diff --git a/provider/consul_catalog_test.go b/provider/consul_catalog_test.go index d6d41207d..789aa432d 100644 --- a/provider/consul_catalog_test.go +++ b/provider/consul_catalog_test.go @@ -61,7 +61,7 @@ func TestConsulCatalogGetAttribute(t *testing.T) { "traefik.backend.weight=42", }, key: "backend.weight", - defaultValue: "", + defaultValue: "0", expected: "42", }, { @@ -70,8 +70,8 @@ func TestConsulCatalogGetAttribute(t *testing.T) { "traefik.backend.wei=42", }, key: "backend.weight", - defaultValue: "", - expected: "", + defaultValue: "0", + expected: "0", }, } diff --git a/provider/docker.go b/provider/docker.go index e2b312044..ec91044f6 100644 --- a/provider/docker.go +++ b/provider/docker.go @@ -455,7 +455,7 @@ func (provider *Docker) getWeight(container dockerData) string { if label, err := getLabel(container, "traefik.weight"); err == nil { return label } - return "1" + return "0" } func (provider *Docker) getSticky(container dockerData) string { diff --git a/provider/docker_test.go b/provider/docker_test.go index 1873c5d56..43fbcb5e4 100644 --- a/provider/docker_test.go +++ b/provider/docker_test.go @@ -436,7 +436,7 @@ func TestDockerGetWeight(t *testing.T) { }, Config: &container.Config{}, }, - expected: "1", + expected: "0", }, { container: docker.ContainerJSON{ @@ -972,7 +972,7 @@ func TestDockerLoadDockerConfig(t *testing.T) { Servers: map[string]types.Server{ "server-test": { URL: "http://127.0.0.1:80", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -1054,11 +1054,11 @@ func TestDockerLoadDockerConfig(t *testing.T) { Servers: map[string]types.Server{ "server-test1": { URL: "http://127.0.0.1:80", - Weight: 1, + Weight: 0, }, "server-test2": { URL: "http://127.0.0.1:80", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -1112,7 +1112,7 @@ func TestDockerLoadDockerConfig(t *testing.T) { Servers: map[string]types.Server{ "server-test1": { URL: "http://127.0.0.1:80", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: &types.CircuitBreaker{ @@ -1527,7 +1527,7 @@ func TestSwarmGetWeight(t *testing.T) { }, }, }, - expected: "1", + expected: "0", networks: map[string]*docker.NetworkResource{}, }, { @@ -2055,7 +2055,7 @@ func TestSwarmLoadDockerConfig(t *testing.T) { Servers: map[string]types.Server{ "server-test": { URL: "http://127.0.0.1:80", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -2143,11 +2143,11 @@ func TestSwarmLoadDockerConfig(t *testing.T) { Servers: map[string]types.Server{ "server-test1": { URL: "http://127.0.0.1:80", - Weight: 1, + Weight: 0, }, "server-test2": { URL: "http://127.0.0.1:80", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, diff --git a/provider/kubernetes.go b/provider/kubernetes.go index a08014eff..546dbe564 100644 --- a/provider/kubernetes.go +++ b/provider/kubernetes.go @@ -262,7 +262,7 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur log.Warnf("Endpoints not found for %s/%s, falling back to Service ClusterIP", service.ObjectMeta.Namespace, service.ObjectMeta.Name) templateObjects.Backends[r.Host+pa.Path].Servers[string(service.UID)] = types.Server{ URL: protocol + "://" + service.Spec.ClusterIP + ":" + strconv.Itoa(port.Port), - Weight: 1, + Weight: 0, } } else { for _, subset := range endpoints.Subsets { @@ -274,7 +274,7 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur } templateObjects.Backends[r.Host+pa.Path].Servers[name] = types.Server{ URL: url, - Weight: 1, + Weight: 0, } } } diff --git a/provider/kubernetes_test.go b/provider/kubernetes_test.go index 2a4e935f9..e450b4934 100644 --- a/provider/kubernetes_test.go +++ b/provider/kubernetes_test.go @@ -204,11 +204,11 @@ func TestLoadIngresses(t *testing.T) { Servers: map[string]types.Server{ "http://10.10.0.1:8080": { URL: "http://10.10.0.1:8080", - Weight: 1, + Weight: 0, }, "http://10.21.0.1:8080": { URL: "http://10.21.0.1:8080", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -218,15 +218,15 @@ func TestLoadIngresses(t *testing.T) { Servers: map[string]types.Server{ "2": { URL: "http://10.0.0.2:802", - Weight: 1, + Weight: 0, }, "https://10.15.0.1:8443": { URL: "https://10.15.0.1:8443", - Weight: 1, + Weight: 0, }, "https://10.15.0.2:9443": { URL: "https://10.15.0.2:9443", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -556,7 +556,7 @@ func TestGetPassHostHeader(t *testing.T) { Servers: map[string]types.Server{ "1": { URL: "http://10.0.0.1:801", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -665,7 +665,7 @@ func TestOnlyReferencesServicesFromOwnNamespace(t *testing.T) { Servers: map[string]types.Server{ "1": { URL: "http://10.0.0.1:80", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -851,7 +851,7 @@ func TestLoadNamespacedIngresses(t *testing.T) { Servers: map[string]types.Server{ "1": { URL: "http://10.0.0.1:801", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -861,11 +861,11 @@ func TestLoadNamespacedIngresses(t *testing.T) { Servers: map[string]types.Server{ "2": { URL: "http://10.0.0.2:802", - Weight: 1, + Weight: 0, }, "3": { URL: "https://10.0.0.3:443", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -1089,7 +1089,7 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) { Servers: map[string]types.Server{ "1": { URL: "http://10.0.0.1:801", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -1099,11 +1099,11 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) { Servers: map[string]types.Server{ "2": { URL: "http://10.0.0.2:802", - Weight: 1, + Weight: 0, }, "3": { URL: "https://10.0.0.3:443", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -1113,7 +1113,7 @@ func TestLoadMultipleNamespacedIngresses(t *testing.T) { Servers: map[string]types.Server{ "17": { URL: "http://10.0.0.4:801", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, @@ -1227,7 +1227,7 @@ func TestHostlessIngress(t *testing.T) { Servers: map[string]types.Server{ "1": { URL: "http://10.0.0.1:801", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, diff --git a/provider/kv_test.go b/provider/kv_test.go index 3e1502529..e0913b110 100644 --- a/provider/kv_test.go +++ b/provider/kv_test.go @@ -408,7 +408,7 @@ func TestKVLoadConfig(t *testing.T) { }, { Key: "traefik/backends/backend.with.dot.too/servers/server.with.dot/weight", - Value: []byte("1"), + Value: []byte("0"), }, }, }, @@ -420,7 +420,7 @@ func TestKVLoadConfig(t *testing.T) { Servers: map[string]types.Server{ "server.with.dot": { URL: "http://172.17.0.2:80", - Weight: 1, + Weight: 0, }, }, CircuitBreaker: nil, diff --git a/templates/consul_catalog.tmpl b/templates/consul_catalog.tmpl index 546132c81..b47f82a17 100644 --- a/templates/consul_catalog.tmpl +++ b/templates/consul_catalog.tmpl @@ -3,7 +3,7 @@ {{if ne (getAttribute "enable" $node.Service.Tags "true") "false"}} [backends."backend-{{getBackend $node}}".servers."{{getBackendName $node $index}}"] url = "{{getAttribute "protocol" $node.Service.Tags "http"}}://{{getBackendAddress $node}}:{{$node.Service.Port}}" - {{$weight := getAttribute "backend.weight" $node.Service.Tags ""}} + {{$weight := getAttribute "backend.weight" $node.Service.Tags "0"}} {{with $weight}} weight = {{$weight}} {{end}} diff --git a/templates/kv.tmpl b/templates/kv.tmpl index c642ff7b1..333a63653 100644 --- a/templates/kv.tmpl +++ b/templates/kv.tmpl @@ -32,7 +32,7 @@ {{range $servers}} [backends."{{Last $backend}}".servers."{{Last .}}"] url = "{{Get "" . "/url"}}" - weight = {{Get "" . "/weight"}} + weight = {{Get "0" . "/weight"}} {{end}} {{end}} From 2bf9acd95e9fc8a24b02fb505363da52d3afcf41 Mon Sep 17 00:00:00 2001 From: WTFKr0 Date: Wed, 23 Nov 2016 21:31:37 +0100 Subject: [PATCH 29/35] Normalize backend even if is user-defined (#865) Signed-off-by: WTFKr0 --- provider/docker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/docker.go b/provider/docker.go index ec91044f6..abeb59018 100644 --- a/provider/docker.go +++ b/provider/docker.go @@ -402,7 +402,7 @@ func (provider *Docker) getFrontendRule(container dockerData) string { func (provider *Docker) getBackend(container dockerData) string { if label, err := getLabel(container, "traefik.backend"); err == nil { - return label + return normalize(label) } return normalize(container.Name) } From b4ea68b88ae9697f69057038d2f2589c5e832d94 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Wed, 23 Nov 2016 23:21:09 +0100 Subject: [PATCH 30/35] Fix missing value for k8s watch request parameter (#874) Fixes: 732 --- provider/k8s/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/k8s/client.go b/provider/k8s/client.go index 4a6bae919..dd4765acb 100644 --- a/provider/k8s/client.go +++ b/provider/k8s/client.go @@ -248,7 +248,7 @@ func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool) return watchCh, errCh, fmt.Errorf("failed to decode version %v", err) } resourceVersion := generic.ResourceVersion - queryParams := map[string]string{"watch": "", "resourceVersion": resourceVersion} + queryParams := map[string]string{"watch": "true", "resourceVersion": resourceVersion} queryData, err := makeQueryString(queryParams, labelSelector) if err != nil { return watchCh, errCh, fmt.Errorf("Unable to construct query args") From 710508dc409ee51560f03fb3f11818ea9a314a60 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Thu, 24 Nov 2016 18:17:57 +0100 Subject: [PATCH 31/35] Fix digest auth doc --- docs/toml.md | 2 +- traefik.sample.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/toml.md b/docs/toml.md index cc40ca0c7..d71a91ac4 100644 --- a/docs/toml.md +++ b/docs/toml.md @@ -511,7 +511,7 @@ address = ":8080" # To enable digest auth on the webui # with 2 user/realm/pass: test:traefik:test and test2:traefik:test2 # You can use htdigest to generate those ones -# [web.auth.basic] +# [web.auth.digest] # users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] ``` diff --git a/traefik.sample.toml b/traefik.sample.toml index c53effd28..78b5a2678 100644 --- a/traefik.sample.toml +++ b/traefik.sample.toml @@ -294,7 +294,7 @@ # To enable digest auth on the webui # with 2 user/realm/pass: test:traefik:test and test2:traefik:test2 # You can use htdigest to generate those ones -# [web.auth.basic] +# [web.auth.digest] # users = ["test:traefik:a2688e031edb4be6a3797f3882655c05 ", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] From 926eb099f14bd6335160502fa7edf5c29d2b3662 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Thu, 24 Nov 2016 18:18:14 +0100 Subject: [PATCH 32/35] Fix k8s client panic Signed-off-by: Emile Vauge --- provider/k8s/client.go | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/provider/k8s/client.go b/provider/k8s/client.go index dd4765acb..f68e54c90 100644 --- a/provider/k8s/client.go +++ b/provider/k8s/client.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "github.com/containous/traefik/log" + "github.com/containous/traefik/safe" "github.com/parnurzeal/gorequest" "net/http" "net/url" @@ -160,7 +161,7 @@ func (c *clientImpl) WatchAll(labelSelector string, stopCh <-chan bool) (chan in if err != nil { return watchCh, errCh, fmt.Errorf("failed to create watch: %v", err) } - go func() { + safe.Go(func() { defer close(watchCh) defer close(errCh) defer close(stopIngresses) @@ -188,7 +189,7 @@ func (c *clientImpl) WatchAll(labelSelector string, stopCh <-chan bool) (chan in watchCh <- event } } - }() + }) return watchCh, errCh, nil } @@ -268,11 +269,16 @@ func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool) return watchCh, errCh, fmt.Errorf("failed to do watch request: GET %q: %v", url, err) } - go func() { + safe.Go(func() { + EndCh := make(chan bool, 1) defer close(watchCh) defer close(errCh) - go func() { + defer close(EndCh) + safe.Go(func() { defer res.Body.Close() + defer func() { + EndCh <- true + }() for { var eventList interface{} if err := json.NewDecoder(res.Body).Decode(&eventList); err != nil { @@ -283,11 +289,12 @@ func (c *clientImpl) watch(url string, labelSelector string, stopCh <-chan bool) } watchCh <- eventList } - }() + }) <-stopCh - go func() { + safe.Go(func() { cancel() // cancel watch request - }() - }() + }) + <-EndCh + }) return watchCh, errCh, nil } From 055cd01bb7dd19fd08567472a9fdcaab122c41c8 Mon Sep 17 00:00:00 2001 From: Ryan Leary Date: Mon, 28 Nov 2016 08:59:08 -0500 Subject: [PATCH 33/35] Fix GroupsAsSubDomains option for Mesos and Marathon (#868) * Fix GroupsAsSubDomains option for Mesos and Marathon * Refactor reverseStringSlice function --- provider/marathon.go | 3 +-- provider/marathon_test.go | 30 ++++++++++++++++++++++++++++++ provider/mesos.go | 6 +++--- provider/mesos_test.go | 35 +++++++++++++++++++++++++++++++++-- provider/provider.go | 6 ++++++ 5 files changed, 73 insertions(+), 7 deletions(-) diff --git a/provider/marathon.go b/provider/marathon.go index e2b3b7386..9b98f0d72 100644 --- a/provider/marathon.go +++ b/provider/marathon.go @@ -3,7 +3,6 @@ package provider import ( "errors" "net/url" - "sort" "strconv" "strings" "text/template" @@ -419,7 +418,7 @@ func (provider *Marathon) getFrontendBackend(application marathon.Application) s func (provider *Marathon) getSubDomain(name string) string { if provider.GroupsAsSubDomains { splitedName := strings.Split(strings.TrimPrefix(name, "/"), "/") - sort.Sort(sort.Reverse(sort.StringSlice(splitedName))) + reverseStringSlice(&splitedName) reverseName := strings.Join(splitedName, ".") return reverseName } diff --git a/provider/marathon_test.go b/provider/marathon_test.go index bcc05404e..1fa1dbe9a 100644 --- a/provider/marathon_test.go +++ b/provider/marathon_test.go @@ -1280,3 +1280,33 @@ func TestMarathonGetBackend(t *testing.T) { } } } + +func TestMarathonGetSubDomain(t *testing.T) { + providerGroups := &Marathon{GroupsAsSubDomains: true} + providerNoGroups := &Marathon{GroupsAsSubDomains: false} + + apps := []struct { + path string + expected string + provider *Marathon + }{ + {"/test", "test", providerNoGroups}, + {"/test", "test", providerGroups}, + {"/a/b/c/d", "d.c.b.a", providerGroups}, + {"/b/a/d/c", "c.d.a.b", providerGroups}, + {"/d/c/b/a", "a.b.c.d", providerGroups}, + {"/c/d/a/b", "b.a.d.c", providerGroups}, + {"/a/b/c/d", "a-b-c-d", providerNoGroups}, + {"/b/a/d/c", "b-a-d-c", providerNoGroups}, + {"/d/c/b/a", "d-c-b-a", providerNoGroups}, + {"/c/d/a/b", "c-d-a-b", providerNoGroups}, + } + + for _, a := range apps { + actual := a.provider.getSubDomain(a.path) + + if actual != a.expected { + t.Errorf("expected %q, got %q", a.expected, actual) + } + } +} diff --git a/provider/mesos.go b/provider/mesos.go index fab03d422..1822a3e60 100644 --- a/provider/mesos.go +++ b/provider/mesos.go @@ -7,6 +7,8 @@ import ( "text/template" "fmt" + "time" + "github.com/BurntSushi/ty/fun" "github.com/cenk/backoff" "github.com/containous/traefik/job" @@ -20,8 +22,6 @@ import ( "github.com/mesosphere/mesos-dns/records" "github.com/mesosphere/mesos-dns/records/state" "github.com/mesosphere/mesos-dns/util" - "sort" - "time" ) var _ Provider = (*Mesos)(nil) @@ -435,7 +435,7 @@ func Ignore(f ErrorFunction) { func (provider *Mesos) getSubDomain(name string) string { if provider.GroupsAsSubDomains { splitedName := strings.Split(strings.TrimPrefix(name, "/"), "/") - sort.Sort(sort.Reverse(sort.StringSlice(splitedName))) + reverseStringSlice(&splitedName) reverseName := strings.Join(splitedName, ".") return reverseName } diff --git a/provider/mesos_test.go b/provider/mesos_test.go index 5434915b3..ba8ccd4db 100644 --- a/provider/mesos_test.go +++ b/provider/mesos_test.go @@ -1,11 +1,12 @@ package provider import ( + "reflect" + "testing" + "github.com/containous/traefik/log" "github.com/containous/traefik/types" "github.com/mesosphere/mesos-dns/records/state" - "reflect" - "testing" ) func TestMesosTaskFilter(t *testing.T) { @@ -244,6 +245,36 @@ func TestMesosLoadConfig(t *testing.T) { } } +func TestMesosGetSubDomain(t *testing.T) { + providerGroups := &Mesos{GroupsAsSubDomains: true} + providerNoGroups := &Mesos{GroupsAsSubDomains: false} + + apps := []struct { + path string + expected string + provider *Mesos + }{ + {"/test", "test", providerNoGroups}, + {"/test", "test", providerGroups}, + {"/a/b/c/d", "d.c.b.a", providerGroups}, + {"/b/a/d/c", "c.d.a.b", providerGroups}, + {"/d/c/b/a", "a.b.c.d", providerGroups}, + {"/c/d/a/b", "b.a.d.c", providerGroups}, + {"/a/b/c/d", "a-b-c-d", providerNoGroups}, + {"/b/a/d/c", "b-a-d-c", providerNoGroups}, + {"/d/c/b/a", "d-c-b-a", providerNoGroups}, + {"/c/d/a/b", "c-d-a-b", providerNoGroups}, + } + + for _, a := range apps { + actual := a.provider.getSubDomain(a.path) + + if actual != a.expected { + t.Errorf("expected %q, got %q", a.expected, actual) + } + } +} + // test helpers type ( diff --git a/provider/provider.go b/provider/provider.go index a7ce0dad4..09982bbec 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -101,6 +101,12 @@ func normalize(name string) string { return strings.Join(strings.FieldsFunc(name, fargs), "-") } +func reverseStringSlice(slice *[]string) { + for i, j := 0, len(*slice)-1; i < j; i, j = i+1, j-1 { + (*slice)[i], (*slice)[j] = (*slice)[j], (*slice)[i] + } +} + // ClientTLS holds TLS specific configurations as client // CA, Cert and Key can be either path or file contents type ClientTLS struct { From 841be8d8065d58631552bec68ff0af4958b3cec3 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Mon, 28 Nov 2016 16:46:37 +0100 Subject: [PATCH 34/35] Fix Swarm panic --- provider/docker.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/provider/docker.go b/provider/docker.go index abeb59018..4f4a7742a 100644 --- a/provider/docker.go +++ b/provider/docker.go @@ -560,6 +560,10 @@ func parseContainer(container dockertypes.ContainerJSON) dockerData { if container.ContainerJSONBase.HostConfig != nil { dockerData.NetworkSettings.NetworkMode = container.ContainerJSONBase.HostConfig.NetworkMode } + + if container.State != nil && container.State.Health != nil { + dockerData.Health = container.State.Health.Status + } } if container.Config != nil && container.Config.Labels != nil { @@ -583,10 +587,6 @@ func parseContainer(container dockertypes.ContainerJSON) dockerData { } - if container.State != nil && container.State.Health != nil { - dockerData.Health = container.State.Health.Status - } - return dockerData } From 1a993f5dfba8f0aa969d02b77da780c61df8a958 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Tue, 29 Nov 2016 14:52:55 +0100 Subject: [PATCH 35/35] Prepare release v1.1.1 Signed-off-by: Emile Vauge --- CHANGELOG.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bfa436ef..d7fbf314d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,49 @@ # Change Log +## [v1.1.1](https://github.com/containous/traefik/tree/v1.1.1) (2016-11-29) +[Full Changelog](https://github.com/containous/traefik/compare/v1.1.0...v1.1.1) + +**Implemented enhancements:** + +- Getting "Kubernetes connection error failed to decode watch event : unexpected EOF" every minute in Traefik log [\#732](https://github.com/containous/traefik/issues/732) + +**Fixed bugs:** + +- 1.1.0 kubernetes panic: send on closed channel [\#877](https://github.com/containous/traefik/issues/877) +- digest auth example is incorrect [\#869](https://github.com/containous/traefik/issues/869) +- Marathon & Mesos providers' GroupsAsSubDomains option broken [\#867](https://github.com/containous/traefik/issues/867) +- 404 responses when a new Marathon leader is elected [\#653](https://github.com/containous/traefik/issues/653) + +**Closed issues:** + +- traefik:latest fails to auto-detect Docker containers [\#901](https://github.com/containous/traefik/issues/901) +- Panic error on bare metal Kubernetes \(installed with Kubeadm\) [\#897](https://github.com/containous/traefik/issues/897) +- api backend readOnly: what is the purpose of this setting [\#893](https://github.com/containous/traefik/issues/893) +- file backend: using external file - doesn't work [\#892](https://github.com/containous/traefik/issues/892) +- auth support for web backend [\#891](https://github.com/containous/traefik/issues/891) +- Basic auth with docker labels [\#890](https://github.com/containous/traefik/issues/890) +- file vs inline config [\#888](https://github.com/containous/traefik/issues/888) +- combine Host and HostRegexp rules [\#882](https://github.com/containous/traefik/issues/882) +- \[Question\] Traefik + Kubernetes + Let's Encrypt \(ssl not used\) [\#881](https://github.com/containous/traefik/issues/881) +- Traefik security for dashboard [\#880](https://github.com/containous/traefik/issues/880) +- Kubernetes Nginx Deployment Panic [\#879](https://github.com/containous/traefik/issues/879) +- Kubernetes Example Address already in use [\#872](https://github.com/containous/traefik/issues/872) +- ETCD Backend - frontend/backends missing [\#866](https://github.com/containous/traefik/issues/866) +- \[Swarm mode\] Dashboard does not work on RC4 [\#864](https://github.com/containous/traefik/issues/864) +- Docker v1.1.0 image does not exist [\#861](https://github.com/containous/traefik/issues/861) +- ConsulService catalog do not support multiple rules [\#859](https://github.com/containous/traefik/issues/859) +- Update official docker repo [\#858](https://github.com/containous/traefik/issues/858) +- Still a memory leak with k8s - 1.1 RC4 [\#844](https://github.com/containous/traefik/issues/844) + +**Merged pull requests:** + +- Fix Swarm panic [\#908](https://github.com/containous/traefik/pull/908) ([emilevauge](https://github.com/emilevauge)) +- Fix k8s panic [\#900](https://github.com/containous/traefik/pull/900) ([emilevauge](https://github.com/emilevauge)) +- Fix missing value for k8s watch request parameter [\#874](https://github.com/containous/traefik/pull/874) ([codablock](https://github.com/codablock)) +- Fix GroupsAsSubDomains option for Mesos and Marathon [\#868](https://github.com/containous/traefik/pull/868) ([ryanleary](https://github.com/ryanleary)) +- Normalize backend even if is user-defined [\#865](https://github.com/containous/traefik/pull/865) ([WTFKr0](https://github.com/WTFKr0)) +- consul/kv.tmpl: weight default value should be a int [\#826](https://github.com/containous/traefik/pull/826) ([klausenbusk](https://github.com/klausenbusk)) + ## [v1.1.0](https://github.com/containous/traefik/tree/v1.1.0) (2016-11-17) [Full Changelog](https://github.com/containous/traefik/compare/v1.0.0...v1.1.0)