diff --git a/autogen/gentemplates/gen.go b/autogen/gentemplates/gen.go index 177802f1d..faeccc4cc 100644 --- a/autogen/gentemplates/gen.go +++ b/autogen/gentemplates/gen.go @@ -164,6 +164,7 @@ var _templatesConsul_catalogTmpl = []byte(`[backends] {{ $healthCheck := getHealthCheck $service.TraefikLabels }} {{if $healthCheck }} [backends."backend-{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" @@ -573,6 +574,7 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}} {{ $healthCheck := getHealthCheck $backend.SegmentLabels }} {{if $healthCheck }} [backends."backend-{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" @@ -833,6 +835,7 @@ var _templatesEcsTmpl = []byte(`[backends] {{ $healthCheck := getHealthCheck $firstInstance.TraefikLabels }} {{if $healthCheck }} [backends."backend-{{ $serviceName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" @@ -1252,6 +1255,7 @@ var _templatesKvTmpl = []byte(`[backends] {{ $healthCheck := getHealthCheck $backend }} {{if $healthCheck }} [backends.{{ $backendName }}.healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" @@ -1554,6 +1558,7 @@ var _templatesMarathonTmpl = []byte(`{{ $apps := .Applications }} {{ $healthCheck := getHealthCheck $app.SegmentLabels }} {{if $healthCheck }} [backends."{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" @@ -1800,6 +1805,7 @@ var _templatesMesosTmpl = []byte(`[backends] {{ $healthCheck := getHealthCheck $app.TraefikLabels }} {{if $healthCheck }} [backends."backend-{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" @@ -2100,6 +2106,7 @@ var _templatesRancherTmpl = []byte(`{{ $backendServers := .Backends }} {{ $healthCheck := getHealthCheck $backend.SegmentLabels }} {{if $healthCheck }} [backends."backend-{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" diff --git a/docs/basics.md b/docs/basics.md index 15204edef..0b12fe08f 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -471,7 +471,7 @@ For example: interval = "10s" ``` -To use a different port for the healthcheck: +To use a different port for the health check: ```toml [backends] [backends.backend1] @@ -481,7 +481,18 @@ To use a different port for the healthcheck: port = 8080 ``` -Additional http headers and hostname to healthcheck request can be specified, for instance: + +To use a different scheme for the health check: +```toml +[backends] + [backends.backend1] + [backends.backend1.healthcheck] + path = "/health" + interval = "10s" + scheme = "http" +``` + +Additional http headers and hostname to health check request can be specified, for instance: ```toml [backends] [backends.backend1] @@ -491,8 +502,8 @@ Additional http headers and hostname to healthcheck request can be specified, fo hostname = "myhost.com" port = 8080 [backends.backend1.healthcheck.headers] - mycustomheader = "foo" - myheader2 = "bar" + My-Custom-Header = "foo" + My-Header = "bar" ``` ## Configuration diff --git a/docs/configuration/backends/consulcatalog.md b/docs/configuration/backends/consulcatalog.md index 3c62f09c1..3eddfd8fb 100644 --- a/docs/configuration/backends/consulcatalog.md +++ b/docs/configuration/backends/consulcatalog.md @@ -99,8 +99,9 @@ Additional settings can be defined using Consul Catalog tags. | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `.backend.circuitbreaker.expression=EXPR` | Create a [circuit breaker](/basics/#backends) to be used against the backend. ex: `NetworkErrorRatio() > 0.` | | `.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. | -| `.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | | `.backend.healthcheck.interval=1s` | Define the health check interval. | +| `.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | +| `traefik.backend.healthcheck.scheme=http` | Override the server URL scheme. | | `.backend.healthcheck.hostname=foobar.com` | Define the health check hostname. | | `.backend.healthcheck.headers=EXPR` | Define the health check request headers
Format: HEADER:value||HEADER2:value2 | | `.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm. | diff --git a/docs/configuration/backends/docker.md b/docs/configuration/backends/docker.md index 0db4c5f76..6200a75ac 100644 --- a/docs/configuration/backends/docker.md +++ b/docs/configuration/backends/docker.md @@ -209,8 +209,9 @@ Labels can be used on containers to override default behavior. | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Create a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | | `traefik.backend.healthcheck.interval=1s` | Define the health check interval. | +| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | +| `traefik.backend.healthcheck.scheme=http` | Override the server URL scheme. | | `traefik.backend.healthcheck.hostname=foobar.com` | Define the health check hostname. | | `traefik.backend.healthcheck.headers=EXPR` | Define the health check request headers
Format: HEADER:value||HEADER2:value2 | | `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm | diff --git a/docs/configuration/backends/ecs.md b/docs/configuration/backends/ecs.md index e53b8a94c..697ffeca4 100644 --- a/docs/configuration/backends/ecs.md +++ b/docs/configuration/backends/ecs.md @@ -149,8 +149,9 @@ Labels can be used on task containers to override default behaviour: | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Create a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | | `traefik.backend.healthcheck.interval=1s` | Define the health check interval. (Default: 30s) | +| `traefik.backend.healthcheck.scheme=http` | Override the server URL scheme. | +| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | | `traefik.backend.healthcheck.hostname=foobar.com` | Define the health check hostname. | | `traefik.backend.healthcheck.headers=EXPR` | Define the health check request headers
Format: HEADER:value||HEADER2:value2 | | `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm | diff --git a/docs/configuration/backends/file.md b/docs/configuration/backends/file.md index 58e950651..1a9ad6ab5 100644 --- a/docs/configuration/backends/file.md +++ b/docs/configuration/backends/file.md @@ -37,6 +37,11 @@ Træfik can be configured with a file. path = "/health" port = 88 interval = "30s" + scheme = "http" + hostname = "myhost.com" + [backends.backend1.healthcheck.headers] + My-Custom-Header = "foo" + My-Header = "bar" [backends.backend2] # ... diff --git a/docs/configuration/backends/marathon.md b/docs/configuration/backends/marathon.md index 5b4aa7ae7..8f35483a1 100644 --- a/docs/configuration/backends/marathon.md +++ b/docs/configuration/backends/marathon.md @@ -185,8 +185,9 @@ The following labels can be defined on Marathon applications. They adjust the be | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Create a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | | `traefik.backend.healthcheck.interval=1s` | Define the health check interval. (Default: 30s) | +| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | +| `traefik.backend.healthcheck.scheme=http` | Override the server URL scheme. | | `traefik.backend.healthcheck.hostname=foobar.com` | Define the health check hostname. | | `traefik.backend.healthcheck.headers=EXPR` | Define the health check request headers
Format: HEADER:value||HEADER2:value2 | | `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm | diff --git a/docs/configuration/backends/mesos.md b/docs/configuration/backends/mesos.md index 1597f1b10..cbd087be2 100644 --- a/docs/configuration/backends/mesos.md +++ b/docs/configuration/backends/mesos.md @@ -122,8 +122,9 @@ The following labels can be defined on Mesos tasks. They adjust the behavior for | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Create a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | | `traefik.backend.healthcheck.interval=1s` | Define the health check interval. (Default: 30s) | +| `traefik.backend.healthcheck.scheme=http` | Override the server URL scheme. | +| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | | `traefik.backend.healthcheck.hostname=foobar.com` | Define the health check hostname. | | `traefik.backend.healthcheck.headers=EXPR` | Define the health check request headers
Format: HEADER:value||HEADER2:value2 | | `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm | diff --git a/docs/configuration/backends/rancher.md b/docs/configuration/backends/rancher.md index c8b689809..af4d42b59 100644 --- a/docs/configuration/backends/rancher.md +++ b/docs/configuration/backends/rancher.md @@ -153,8 +153,9 @@ Labels can be used on task containers to override default behavior: | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Create a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | | `traefik.backend.healthcheck.interval=1s` | Define the health check interval. | +| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | +| `traefik.backend.healthcheck.scheme=http` | Override the server URL scheme. | | `traefik.backend.healthcheck.hostname=foobar.com` | Define the health check hostname. | | `traefik.backend.healthcheck.headers=EXPR` | Define the health check request headers
Format: HEADER:value||HEADER2:value2 | | `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm | diff --git a/healthcheck/healthcheck.go b/healthcheck/healthcheck.go index 94779d6a2..cc5a5edd8 100644 --- a/healthcheck/healthcheck.go +++ b/healthcheck/healthcheck.go @@ -31,6 +31,7 @@ func GetHealthCheck(metrics metricsRegistry) *HealthCheck { type Options struct { Headers map[string]string Hostname string + Scheme string Path string Port int Transport http.RoundTripper @@ -50,7 +51,7 @@ type BackendHealthCheck struct { requestTimeout time.Duration } -//HealthCheck struct +// HealthCheck struct type HealthCheck struct { Backends map[string]*BackendHealthCheck metrics metricsRegistry @@ -71,8 +72,8 @@ func newHealthCheck(metrics metricsRegistry) *HealthCheck { } } -// metricsRegistry is a local interface in the healthcheck package, exposing only the required metrics -// necessary for the healthcheck package. This makes it easier for the tests. +// metricsRegistry is a local interface in the health check package, exposing only the required metrics +// necessary for the health check package. This makes it easier for the tests. type metricsRegistry interface { BackendServerUpGauge() metrics.Gauge } @@ -152,15 +153,18 @@ func (hc *HealthCheck) checkBackend(backend *BackendHealthCheck) { } func (b *BackendHealthCheck) newRequest(serverURL *url.URL) (*http.Request, error) { - if b.Port == 0 { - return http.NewRequest(http.MethodGet, serverURL.String()+b.Path, nil) - } - - // copy the url and add the port to the host u := &url.URL{} *u = *serverURL - u.Host = net.JoinHostPort(u.Hostname(), strconv.Itoa(b.Port)) - u.Path = u.Path + b.Path + + if len(b.Scheme) > 0 { + u.Scheme = b.Scheme + } + + if b.Port != 0 { + u.Host = net.JoinHostPort(u.Hostname(), strconv.Itoa(b.Port)) + } + + u.Path += b.Path return http.NewRequest(http.MethodGet, u.String(), nil) } diff --git a/healthcheck/healthcheck_test.go b/healthcheck/healthcheck_test.go index 5ef75504a..c1d65f783 100644 --- a/healthcheck/healthcheck_test.go +++ b/healthcheck/healthcheck_test.go @@ -134,40 +134,57 @@ func TestSetBackendsConfiguration(t *testing.T) { func TestNewRequest(t *testing.T) { testCases := []struct { - desc string - host string - port int - path string - expected string + desc string + serverURL string + options Options + expected string }{ { - desc: "no port override", - host: "backend1:80", - port: 0, - path: "/test", + desc: "no port override", + serverURL: "http://backend1:80", + options: Options{ + Path: "/test", + Port: 0, + }, expected: "http://backend1:80/test", }, { - desc: "port override", - host: "backend2:80", - port: 8080, - path: "/test", + desc: "port override", + serverURL: "http://backend2:80", + options: Options{ + Path: "/test", + Port: 8080, + }, expected: "http://backend2:8080/test", }, { - desc: "no port override with no port in host", - host: "backend1", - port: 0, - path: "/health", + desc: "no port override with no port in server URL", + serverURL: "http://backend1", + options: Options{ + Path: "/health", + Port: 0, + }, expected: "http://backend1/health", }, { - desc: "port override with no port in host", - host: "backend2", - port: 8080, - path: "/health", + desc: "port override with no port in server URL", + serverURL: "http://backend2", + options: Options{ + Path: "/health", + Port: 8080, + }, expected: "http://backend2:8080/health", }, + { + desc: "scheme override", + serverURL: "https://backend1:80", + options: Options{ + Scheme: "http", + Path: "/test", + Port: 0, + }, + expected: "http://backend1:80/test", + }, } for _, test := range testCases { @@ -175,16 +192,10 @@ func TestNewRequest(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - backend := NewBackendHealthCheck( - Options{ - Path: test.path, - Port: test.port, - }, "backendName") + backend := NewBackendHealthCheck(test.options, "backendName") - u := &url.URL{ - Scheme: "http", - Host: test.host, - } + u, err := url.Parse(test.serverURL) + require.NoError(t, err) req, err := backend.newRequest(u) require.NoError(t, err, "failed to create new backend request") @@ -194,54 +205,53 @@ func TestNewRequest(t *testing.T) { } } -func TestNewRequestWithAddHeaders(t *testing.T) { +func TestAddHeadersAndHost(t *testing.T) { testCases := []struct { desc string - host string - headers map[string]string - hostname string - port int - path string + serverURL string + options Options expectedHostname string expectedHeader string }{ { - desc: "override hostname", - host: "backend1:80", - headers: map[string]string{}, - hostname: "myhost", - port: 0, - path: "/", + desc: "override hostname", + serverURL: "http://backend1:80", + options: Options{ + Hostname: "myhost", + Path: "/", + }, expectedHostname: "myhost", expectedHeader: "", }, { - desc: "not override hostname", - host: "backend1:80", - headers: map[string]string{}, - hostname: "", - port: 0, - path: "/", + desc: "not override hostname", + serverURL: "http://backend1:80", + options: Options{ + Hostname: "", + Path: "/", + }, expectedHostname: "backend1:80", expectedHeader: "", }, { - desc: "custom header", - host: "backend1:80", - headers: map[string]string{"Custom-Header": "foo"}, - hostname: "", - port: 0, - path: "/", + desc: "custom header", + serverURL: "http://backend1:80", + options: Options{ + Headers: map[string]string{"Custom-Header": "foo"}, + Hostname: "", + Path: "/", + }, expectedHostname: "backend1:80", expectedHeader: "foo", }, { - desc: "custom header with host override", - host: "backend1:80", - headers: map[string]string{"Custom-Header": "foo"}, - hostname: "myhost", - port: 0, - path: "/", + desc: "custom header with hostname override", + serverURL: "http://backend1:80", + options: Options{ + Headers: map[string]string{"Custom-Header": "foo"}, + Hostname: "myhost", + Path: "/", + }, expectedHostname: "myhost", expectedHeader: "foo", }, @@ -252,26 +262,17 @@ func TestNewRequestWithAddHeaders(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - backend := NewBackendHealthCheck( - Options{ - Hostname: test.hostname, - Path: test.path, - Port: test.port, - Headers: test.headers, - }, "backendName") + backend := NewBackendHealthCheck(test.options, "backendName") - u := &url.URL{ - Scheme: "http", - Host: test.host, - } + u, err := url.Parse(test.serverURL) + require.NoError(t, err) req, err := backend.newRequest(u) - if err != nil { - t.Fatalf("failed to create new backend request: %s", err) - } + require.NoError(t, err, "failed to create new backend request") req = backend.addHeadersAndHost(req) + assert.Equal(t, "http://backend1:80/", req.URL.String()) assert.Equal(t, test.expectedHostname, req.Host) assert.Equal(t, test.expectedHeader, req.Header.Get("Custom-Header")) }) diff --git a/provider/consulcatalog/config_test.go b/provider/consulcatalog/config_test.go index 4e92f8682..ec0d8b850 100644 --- a/provider/consulcatalog/config_test.go +++ b/provider/consulcatalog/config_test.go @@ -126,6 +126,7 @@ func TestProviderBuildConfiguration(t *testing.T) { label.TraefikBackendCircuitBreakerExpression + "=NetworkErrorRatio() > 0.5", label.TraefikBackendHealthCheckPath + "=/health", + label.TraefikBackendHealthCheckScheme + "=http", label.TraefikBackendHealthCheckPort + "=880", label.TraefikBackendHealthCheckInterval + "=6", label.TraefikBackendHealthCheckHostname + "=foo.com", @@ -356,6 +357,7 @@ func TestProviderBuildConfiguration(t *testing.T) { ExtractorFunc: "client.ip", }, HealthCheck: &types.HealthCheck{ + Scheme: "http", Path: "/health", Port: 880, Interval: "6", diff --git a/provider/docker/config_container_docker_test.go b/provider/docker/config_container_docker_test.go index 09c37d39b..ecbcfa64c 100644 --- a/provider/docker/config_container_docker_test.go +++ b/provider/docker/config_container_docker_test.go @@ -98,6 +98,7 @@ func TestDockerBuildConfiguration(t *testing.T) { label.TraefikBackend: "foobar", label.TraefikBackendCircuitBreakerExpression: "NetworkErrorRatio() > 0.5", + label.TraefikBackendHealthCheckScheme: "http", label.TraefikBackendHealthCheckPath: "/health", label.TraefikBackendHealthCheckPort: "880", label.TraefikBackendHealthCheckInterval: "6", @@ -294,6 +295,7 @@ func TestDockerBuildConfiguration(t *testing.T) { ExtractorFunc: "client.ip", }, HealthCheck: &types.HealthCheck{ + Scheme: "http", Path: "/health", Port: 880, Interval: "6", diff --git a/provider/docker/config_container_swarm_test.go b/provider/docker/config_container_swarm_test.go index 751613049..f70a77da2 100644 --- a/provider/docker/config_container_swarm_test.go +++ b/provider/docker/config_container_swarm_test.go @@ -107,6 +107,7 @@ func TestSwarmBuildConfiguration(t *testing.T) { label.TraefikBackend: "foobar", label.TraefikBackendCircuitBreakerExpression: "NetworkErrorRatio() > 0.5", + label.TraefikBackendHealthCheckScheme: "http", label.TraefikBackendHealthCheckPath: "/health", label.TraefikBackendHealthCheckPort: "880", label.TraefikBackendHealthCheckInterval: "6", @@ -300,6 +301,7 @@ func TestSwarmBuildConfiguration(t *testing.T) { ExtractorFunc: "client.ip", }, HealthCheck: &types.HealthCheck{ + Scheme: "http", Path: "/health", Port: 880, Interval: "6", diff --git a/provider/ecs/config_test.go b/provider/ecs/config_test.go index a27c37d21..29a688ae9 100644 --- a/provider/ecs/config_test.go +++ b/provider/ecs/config_test.go @@ -135,9 +135,12 @@ func TestBuildConfiguration(t *testing.T) { label.TraefikBackend: aws.String("foobar"), label.TraefikBackendCircuitBreakerExpression: aws.String("NetworkErrorRatio() > 0.5"), + label.TraefikBackendHealthCheckScheme: aws.String("http"), label.TraefikBackendHealthCheckPath: aws.String("/health"), label.TraefikBackendHealthCheckPort: aws.String("880"), label.TraefikBackendHealthCheckInterval: aws.String("6"), + label.TraefikBackendHealthCheckHostname: aws.String("foo.com"), + label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"), label.TraefikBackendLoadBalancerMethod: aws.String("drr"), label.TraefikBackendLoadBalancerSticky: aws.String("true"), label.TraefikBackendLoadBalancerStickiness: aws.String("true"), @@ -238,9 +241,15 @@ func TestBuildConfiguration(t *testing.T) { ExtractorFunc: "client.ip", }, HealthCheck: &types.HealthCheck{ + Scheme: "http", Path: "/health", Port: 880, Interval: "6", + Hostname: "foo.com", + Headers: map[string]string{ + "Foo": "bar", + "Bar": "foo", + }, }, Buffering: &types.Buffering{ MaxResponseBodyBytes: 10485760, diff --git a/provider/kv/keynames.go b/provider/kv/keynames.go index 05fec79e4..16efdcbd7 100644 --- a/provider/kv/keynames.go +++ b/provider/kv/keynames.go @@ -3,6 +3,7 @@ package kv const ( pathBackends = "/backends/" pathBackendCircuitBreakerExpression = "/circuitbreaker/expression" + pathBackendHealthCheckScheme = "/healthcheck/scheme" pathBackendHealthCheckPath = "/healthcheck/path" pathBackendHealthCheckPort = "/healthcheck/port" pathBackendHealthCheckInterval = "/healthcheck/interval" diff --git a/provider/kv/kv_config.go b/provider/kv/kv_config.go index 6e373275e..d8faa52a1 100644 --- a/provider/kv/kv_config.go +++ b/provider/kv/kv_config.go @@ -301,17 +301,19 @@ func (p *Provider) getHealthCheck(rootPath string) *types.HealthCheck { return nil } + scheme := p.get("", rootPath, pathBackendHealthCheckScheme) port := p.getInt(label.DefaultBackendHealthCheckPort, rootPath, pathBackendHealthCheckPort) interval := p.get("30s", rootPath, pathBackendHealthCheckInterval) hostname := p.get("", rootPath, pathBackendHealthCheckHostname) headers := p.getMap(rootPath, pathBackendHealthCheckHeaders) return &types.HealthCheck{ - Hostname: hostname, - Headers: headers, + Scheme: scheme, Path: path, Port: port, Interval: interval, + Hostname: hostname, + Headers: headers, } } diff --git a/provider/kv/kv_config_test.go b/provider/kv/kv_config_test.go index 3c99d0336..2b82f0755 100644 --- a/provider/kv/kv_config_test.go +++ b/provider/kv/kv_config_test.go @@ -71,9 +71,13 @@ func TestProviderBuildConfiguration(t *testing.T) { withPair(pathBackendLoadBalancerSticky, "true"), withPair(pathBackendLoadBalancerStickiness, "true"), withPair(pathBackendLoadBalancerStickinessCookieName, "tomate"), + withPair(pathBackendHealthCheckScheme, "http"), withPair(pathBackendHealthCheckPath, "/health"), withPair(pathBackendHealthCheckPort, "80"), withPair(pathBackendHealthCheckInterval, "30s"), + withPair(pathBackendHealthCheckHostname, "foo.com"), + withPair(pathBackendHealthCheckHeaders+"Foo", "bar"), + withPair(pathBackendHealthCheckHeaders+"Bar", "foo"), withPair(pathBackendMaxConnAmount, "5"), withPair(pathBackendMaxConnExtractorFunc, "client.ip"), withPair(pathBackendBufferingMaxResponseBodyBytes, "10485760"), @@ -167,9 +171,15 @@ func TestProviderBuildConfiguration(t *testing.T) { ExtractorFunc: "client.ip", }, HealthCheck: &types.HealthCheck{ + Scheme: "http", Path: "/health", Port: 80, Interval: "30s", + Hostname: "foo.com", + Headers: map[string]string{ + "Foo": "bar", + "Bar": "foo", + }, }, Buffering: &types.Buffering{ MaxResponseBodyBytes: 10485760, diff --git a/provider/label/names.go b/provider/label/names.go index e9533a38a..c6f0c318b 100644 --- a/provider/label/names.go +++ b/provider/label/names.go @@ -14,6 +14,7 @@ const ( SuffixBackendID = "backend.id" SuffixBackendCircuitBreaker = "backend.circuitbreaker" SuffixBackendCircuitBreakerExpression = "backend.circuitbreaker.expression" + SuffixBackendHealthCheckScheme = "backend.healthcheck.scheme" SuffixBackendHealthCheckPath = "backend.healthcheck.path" SuffixBackendHealthCheckPort = "backend.healthcheck.port" SuffixBackendHealthCheckInterval = "backend.healthcheck.interval" @@ -83,6 +84,7 @@ const ( TraefikBackendID = Prefix + SuffixBackendID TraefikBackendCircuitBreaker = Prefix + SuffixBackendCircuitBreaker TraefikBackendCircuitBreakerExpression = Prefix + SuffixBackendCircuitBreakerExpression + TraefikBackendHealthCheckScheme = Prefix + SuffixBackendHealthCheckScheme TraefikBackendHealthCheckPath = Prefix + SuffixBackendHealthCheckPath TraefikBackendHealthCheckPort = Prefix + SuffixBackendHealthCheckPort TraefikBackendHealthCheckInterval = Prefix + SuffixBackendHealthCheckInterval diff --git a/provider/label/partial.go b/provider/label/partial.go index 067a5a8eb..797286e2b 100644 --- a/provider/label/partial.go +++ b/provider/label/partial.go @@ -235,17 +235,19 @@ func GetHealthCheck(labels map[string]string) *types.HealthCheck { return nil } + scheme := GetStringValue(labels, TraefikBackendHealthCheckScheme, "") port := GetIntValue(labels, TraefikBackendHealthCheckPort, DefaultBackendHealthCheckPort) interval := GetStringValue(labels, TraefikBackendHealthCheckInterval, "") hostname := GetStringValue(labels, TraefikBackendHealthCheckHostname, "") headers := GetMapValue(labels, TraefikBackendHealthCheckHeaders) return &types.HealthCheck{ - Hostname: hostname, - Headers: headers, + Scheme: scheme, Path: path, Port: port, Interval: interval, + Hostname: hostname, + Headers: headers, } } diff --git a/provider/label/partial_test.go b/provider/label/partial_test.go index 644c46e9f..0ff7497f1 100644 --- a/provider/label/partial_test.go +++ b/provider/label/partial_test.go @@ -371,11 +371,20 @@ func TestGetHealthCheck(t *testing.T) { TraefikBackendHealthCheckPath: "/health", TraefikBackendHealthCheckPort: "80", TraefikBackendHealthCheckInterval: "6", + TraefikBackendHealthCheckHeaders: "Foo:bar || Goo:bir", + TraefikBackendHealthCheckHostname: "traefik", + TraefikBackendHealthCheckScheme: "http", }, expected: &types.HealthCheck{ + Scheme: "http", Path: "/health", Port: 80, Interval: "6", + Hostname: "traefik", + Headers: map[string]string{ + "Foo": "bar", + "Goo": "bir", + }, }, }, } diff --git a/provider/marathon/config_test.go b/provider/marathon/config_test.go index 04dfffa33..6634f3baf 100644 --- a/provider/marathon/config_test.go +++ b/provider/marathon/config_test.go @@ -173,6 +173,7 @@ func TestBuildConfiguration(t *testing.T) { withLabel(label.TraefikBackend, "foobar"), withLabel(label.TraefikBackendCircuitBreakerExpression, "NetworkErrorRatio() > 0.5"), + withLabel(label.TraefikBackendHealthCheckScheme, "http"), withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckInterval, "6"), @@ -367,6 +368,7 @@ func TestBuildConfiguration(t *testing.T) { ExtractorFunc: "client.ip", }, HealthCheck: &types.HealthCheck{ + Scheme: "http", Path: "/health", Port: 880, Interval: "6", diff --git a/provider/mesos/config_test.go b/provider/mesos/config_test.go index 25c32e88d..d294c23ce 100644 --- a/provider/mesos/config_test.go +++ b/provider/mesos/config_test.go @@ -123,6 +123,7 @@ func TestBuildConfiguration(t *testing.T) { withLabel(label.TraefikBackend, "foobar"), withLabel(label.TraefikBackendCircuitBreakerExpression, "NetworkErrorRatio() > 0.5"), + withLabel(label.TraefikBackendHealthCheckScheme, "http"), withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckInterval, "6"), @@ -318,6 +319,7 @@ func TestBuildConfiguration(t *testing.T) { ExtractorFunc: "client.ip", }, HealthCheck: &types.HealthCheck{ + Scheme: "http", Path: "/health", Port: 880, Interval: "6", diff --git a/provider/rancher/config_test.go b/provider/rancher/config_test.go index 9db9ac6ba..93853345c 100644 --- a/provider/rancher/config_test.go +++ b/provider/rancher/config_test.go @@ -41,6 +41,7 @@ func TestProviderBuildConfiguration(t *testing.T) { label.TraefikBackend: "foobar", label.TraefikBackendCircuitBreakerExpression: "NetworkErrorRatio() > 0.5", + label.TraefikBackendHealthCheckScheme: "http", label.TraefikBackendHealthCheckPath: "/health", label.TraefikBackendHealthCheckPort: "880", label.TraefikBackendHealthCheckInterval: "6", @@ -241,6 +242,7 @@ func TestProviderBuildConfiguration(t *testing.T) { ExtractorFunc: "client.ip", }, HealthCheck: &types.HealthCheck{ + Scheme: "http", Path: "/health", Port: 880, Interval: "6", diff --git a/server/server.go b/server/server.go index 047125e50..f42b38245 100644 --- a/server/server.go +++ b/server/server.go @@ -1335,21 +1335,22 @@ func parseHealthCheckOptions(lb healthcheck.LoadBalancer, backend string, hc *ty intervalOverride, err := time.ParseDuration(hc.Interval) switch { case err != nil: - log.Errorf("Illegal healthcheck interval for backend '%s': %s", backend, err) + log.Errorf("Illegal health check interval for backend '%s': %s", backend, err) case intervalOverride <= 0: - log.Errorf("Healthcheck interval smaller than zero for backend '%s', backend", backend) + log.Errorf("Health check interval smaller than zero for backend '%s', backend", backend) default: interval = intervalOverride } } return &healthcheck.Options{ - Hostname: hc.Hostname, - Headers: hc.Headers, + Scheme: hc.Scheme, Path: hc.Path, Port: hc.Port, Interval: interval, LB: lb, + Hostname: hc.Hostname, + Headers: hc.Headers, } } diff --git a/templates/consul_catalog.tmpl b/templates/consul_catalog.tmpl index a1c91805d..76320afff 100644 --- a/templates/consul_catalog.tmpl +++ b/templates/consul_catalog.tmpl @@ -29,6 +29,7 @@ {{ $healthCheck := getHealthCheck $service.TraefikLabels }} {{if $healthCheck }} [backends."backend-{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" diff --git a/templates/docker.tmpl b/templates/docker.tmpl index 9df0f3e19..847be8bda 100644 --- a/templates/docker.tmpl +++ b/templates/docker.tmpl @@ -30,6 +30,7 @@ {{ $healthCheck := getHealthCheck $backend.SegmentLabels }} {{if $healthCheck }} [backends."backend-{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" diff --git a/templates/ecs.tmpl b/templates/ecs.tmpl index 11c5e97d5..d6bfadb27 100644 --- a/templates/ecs.tmpl +++ b/templates/ecs.tmpl @@ -29,6 +29,7 @@ {{ $healthCheck := getHealthCheck $firstInstance.TraefikLabels }} {{if $healthCheck }} [backends."backend-{{ $serviceName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" diff --git a/templates/kv.tmpl b/templates/kv.tmpl index cf77aee2a..cb79d9107 100644 --- a/templates/kv.tmpl +++ b/templates/kv.tmpl @@ -29,6 +29,7 @@ {{ $healthCheck := getHealthCheck $backend }} {{if $healthCheck }} [backends.{{ $backendName }}.healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" diff --git a/templates/marathon.tmpl b/templates/marathon.tmpl index e8185be01..23a1522dd 100644 --- a/templates/marathon.tmpl +++ b/templates/marathon.tmpl @@ -32,6 +32,7 @@ {{ $healthCheck := getHealthCheck $app.SegmentLabels }} {{if $healthCheck }} [backends."{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" diff --git a/templates/mesos.tmpl b/templates/mesos.tmpl index a29f0d324..92b75ef68 100644 --- a/templates/mesos.tmpl +++ b/templates/mesos.tmpl @@ -32,6 +32,7 @@ {{ $healthCheck := getHealthCheck $app.TraefikLabels }} {{if $healthCheck }} [backends."backend-{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" diff --git a/templates/rancher.tmpl b/templates/rancher.tmpl index 8887ded47..fc3ea275e 100644 --- a/templates/rancher.tmpl +++ b/templates/rancher.tmpl @@ -31,6 +31,7 @@ {{ $healthCheck := getHealthCheck $backend.SegmentLabels }} {{if $healthCheck }} [backends."backend-{{ $backendName }}".healthCheck] + scheme = "{{ $healthCheck.Scheme }}" path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" diff --git a/types/types.go b/types/types.go index 1557e7272..29eb5ab9d 100644 --- a/types/types.go +++ b/types/types.go @@ -69,11 +69,12 @@ type WhiteList struct { // HealthCheck holds HealthCheck configuration type HealthCheck struct { - Headers map[string]string `json:"headers,omitempty"` - Hostname string `json:"hostname,omitempty"` + Scheme string `json:"scheme,omitempty"` Path string `json:"path,omitempty"` Port int `json:"port,omitempty"` Interval string `json:"interval,omitempty"` + Hostname string `json:"hostname,omitempty"` + Headers map[string]string `json:"headers,omitempty"` } // Server holds server configuration.