diff --git a/.golangci.toml b/.golangci.toml index 64e06b670..c028010c2 100644 --- a/.golangci.toml +++ b/.golangci.toml @@ -57,7 +57,10 @@ "nlreturn", # Not relevant "wrapcheck", # Too strict "tparallel", # Not relevant + "paralleltest", # Not relevant "exhaustivestruct", # Not relevant + "makezero", # not relevant + "forbidigo", # not relevant ] [issues] diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e1c2913e..be9bd798d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [v2.3.6](https://github.com/traefik/traefik/tree/v2.3.6) (2020-12-17) +[All Commits](https://github.com/traefik/traefik/compare/v2.3.5...v2.3.6) + +**Bug fixes:** +- **[logs]** Update Logrus to v1.7.0 ([#7663](https://github.com/traefik/traefik/pull/7663) by [jspdown](https://github.com/jspdown)) +- **[plugins]** Update Yaegi to v0.9.8 ([#7659](https://github.com/traefik/traefik/pull/7659) by [ldez](https://github.com/ldez)) +- **[rules]** Disable router when a rule has an error ([#7680](https://github.com/traefik/traefik/pull/7680) by [ldez](https://github.com/ldez)) + +**Documentation:** +- **[logs]** Add configuration example for access log filePath ([#7655](https://github.com/traefik/traefik/pull/7655) by [wernerfred](https://github.com/wernerfred)) +- **[middleware]** Add missing quotes in errorpages k8s example yaml ([#7675](https://github.com/traefik/traefik/pull/7675) by [icelynjennings](https://github.com/icelynjennings)) + ## [v2.4.0-rc1](https://github.com/traefik/traefik/tree/v2.4.0-rc1) (2020-12-16) [All Commits](https://github.com/traefik/traefik/compare/v2.3.0-rc1...v2.4.0-rc1) diff --git a/build.Dockerfile b/build.Dockerfile index 6df51c544..29b4c1b24 100644 --- a/build.Dockerfile +++ b/build.Dockerfile @@ -19,7 +19,7 @@ RUN mkdir -p /usr/local/bin \ && chmod +x /usr/local/bin/go-bindata # Download golangci-lint binary to bin folder in $GOPATH -RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.32.2 +RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.34.0 # Download misspell binary to bin folder in $GOPATH RUN curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.3.4 diff --git a/docs/content/middlewares/forwardauth.md b/docs/content/middlewares/forwardauth.md index 4211a191e..f0a64ca89 100644 --- a/docs/content/middlewares/forwardauth.md +++ b/docs/content/middlewares/forwardauth.md @@ -285,7 +285,7 @@ http: ### `authRequestHeaders` The `authRequestHeaders` option is the list of the headers to copy from the request to the authentication server. -It allows to prevent passing headers that have not to be passed to the authentication server. +It allows filtering headers that should not be passed to the authentication server. If not set or empty then all request headers will be passed. ```yaml tab="Docker" diff --git a/docs/content/providers/docker.md b/docs/content/providers/docker.md index 439e53a0e..f51862ce0 100644 --- a/docs/content/providers/docker.md +++ b/docs/content/providers/docker.md @@ -188,7 +188,7 @@ While in Swarm Mode, Traefik uses labels found on services, not on individual co Therefore, if you use a compose file with Swarm Mode, labels should be defined in the [`deploy`](https://docs.docker.com/compose/compose-file/compose-file-v3/#labels-1) part of your service. -This behavior is only enabled for docker-compose version 3+ ([Compose file reference](https://docs.docker.com/compose/compose-file)). +This behavior is only enabled for docker-compose version 3+ ([Compose file reference](https://docs.docker.com/compose/compose-file/compose-file-v3/)). ### Port Detection diff --git a/docs/content/providers/overview.md b/docs/content/providers/overview.md index 758afedc3..e9e9a12d8 100644 --- a/docs/content/providers/overview.md +++ b/docs/content/providers/overview.md @@ -131,13 +131,14 @@ Below is the list of the currently supported providers in Traefik. | [Docker](./docker.md) | Orchestrator | Label | | [Kubernetes](./kubernetes-crd.md) | Orchestrator | Custom Resource or Ingress | | [Consul Catalog](./consul-catalog.md) | Orchestrator | Label | +| [ECS](./ecs.md) | Orchestrator | Label | | [Marathon](./marathon.md) | Orchestrator | Label | | [Rancher](./rancher.md) | Orchestrator | Label | | [File](./file.md) | Manual | TOML/YAML format | | [Consul](./consul.md) | KV | KV | | [Etcd](./etcd.md) | KV | KV | -| [Redis](./redis.md) | KV | KV | | [ZooKeeper](./zookeeper.md) | KV | KV | +| [Redis](./redis.md) | KV | KV | | [HTTP](./http.md) | Manual | JSON format | !!! info "More Providers" diff --git a/pkg/metrics/pilot_test.go b/pkg/metrics/pilot_test.go index 73ffb0335..451c1eb93 100644 --- a/pkg/metrics/pilot_test.go +++ b/pkg/metrics/pilot_test.go @@ -300,6 +300,8 @@ func findPilotMetric(name string, metrics []PilotMetric) *PilotMetric { } func buildPilotCounterAssert(t *testing.T, metricName string, expectedValue float64) func(metric *PilotMetric) { + t.Helper() + return func(metric *PilotMetric) { for _, value := range metric.Observations { if cv := value.(float64); cv != expectedValue { @@ -311,6 +313,8 @@ func buildPilotCounterAssert(t *testing.T, metricName string, expectedValue floa } func buildPilotGreaterThanCounterAssert(t *testing.T, metricName string, expectedMinValue float64) func(metric *PilotMetric) { + t.Helper() + return func(metric *PilotMetric) { for _, value := range metric.Observations { if cv := value.(float64); cv < expectedMinValue { @@ -322,6 +326,8 @@ func buildPilotGreaterThanCounterAssert(t *testing.T, metricName string, expecte } func buildPilotHistogramAssert(t *testing.T, metricName string, expectedSampleCount float64) func(metric *PilotMetric) { + t.Helper() + return func(metric *PilotMetric) { for _, value := range metric.Observations { if pho := value.(*pilotHistogramObservation); pho.Count != expectedSampleCount { @@ -333,6 +339,8 @@ func buildPilotHistogramAssert(t *testing.T, metricName string, expectedSampleCo } func buildPilotGaugeAssert(t *testing.T, metricName string, expectedValue float64) func(metric *PilotMetric) { + t.Helper() + return func(metric *PilotMetric) { for _, value := range metric.Observations { if gv := value.(float64); gv != expectedValue { @@ -344,6 +352,8 @@ func buildPilotGaugeAssert(t *testing.T, metricName string, expectedValue float6 } func buildPilotTimestampAssert(t *testing.T, metricName string) func(metric *PilotMetric) { + t.Helper() + return func(metric *PilotMetric) { for _, value := range metric.Observations { if ts := time.Unix(int64(value.(float64)), 0); time.Since(ts) > time.Minute { diff --git a/pkg/metrics/prometheus_test.go b/pkg/metrics/prometheus_test.go index 5d5a5e34d..6fc10ee73 100644 --- a/pkg/metrics/prometheus_test.go +++ b/pkg/metrics/prometheus_test.go @@ -486,6 +486,8 @@ func assertCounterValue(t *testing.T, want float64, family *dto.MetricFamily, la } func buildCounterAssert(t *testing.T, metricName string, expectedValue int) func(family *dto.MetricFamily) { + t.Helper() + return func(family *dto.MetricFamily) { if cv := int(family.Metric[0].Counter.GetValue()); cv != expectedValue { t.Errorf("metric %s has value %d, want %d", metricName, cv, expectedValue) @@ -494,6 +496,8 @@ func buildCounterAssert(t *testing.T, metricName string, expectedValue int) func } func buildGreaterThanCounterAssert(t *testing.T, metricName string, expectedMinValue int) func(family *dto.MetricFamily) { + t.Helper() + return func(family *dto.MetricFamily) { if cv := int(family.Metric[0].Counter.GetValue()); cv < expectedMinValue { t.Errorf("metric %s has value %d, want at least %d", metricName, cv, expectedMinValue) @@ -502,6 +506,8 @@ func buildGreaterThanCounterAssert(t *testing.T, metricName string, expectedMinV } func buildHistogramAssert(t *testing.T, metricName string, expectedSampleCount int) func(family *dto.MetricFamily) { + t.Helper() + return func(family *dto.MetricFamily) { if sc := int(family.Metric[0].Histogram.GetSampleCount()); sc != expectedSampleCount { t.Errorf("metric %s has sample count value %d, want %d", metricName, sc, expectedSampleCount) @@ -510,6 +516,8 @@ func buildHistogramAssert(t *testing.T, metricName string, expectedSampleCount i } func buildGaugeAssert(t *testing.T, metricName string, expectedValue int) func(family *dto.MetricFamily) { + t.Helper() + return func(family *dto.MetricFamily) { if gv := int(family.Metric[0].Gauge.GetValue()); gv != expectedValue { t.Errorf("metric %s has value %d, want %d", metricName, gv, expectedValue) @@ -518,6 +526,8 @@ func buildGaugeAssert(t *testing.T, metricName string, expectedValue int) func(f } func buildTimestampAssert(t *testing.T, metricName string) func(family *dto.MetricFamily) { + t.Helper() + return func(family *dto.MetricFamily) { if ts := time.Unix(int64(family.Metric[0].Gauge.GetValue()), 0); time.Since(ts) > time.Minute { t.Errorf("metric %s has wrong timestamp %v", metricName, ts) diff --git a/pkg/middlewares/accesslog/logger_test.go b/pkg/middlewares/accesslog/logger_test.go index 5bc749eab..aaa145e5b 100644 --- a/pkg/middlewares/accesslog/logger_test.go +++ b/pkg/middlewares/accesslog/logger_test.go @@ -683,6 +683,8 @@ func TestNewLogHandlerOutputStdout(t *testing.T) { } func assertValidLogData(t *testing.T, expected string, logData []byte) { + t.Helper() + if len(expected) == 0 { assert.Zero(t, len(logData)) t.Log(string(logData)) @@ -716,6 +718,8 @@ func assertValidLogData(t *testing.T, expected string, logData []byte) { } func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) { + t.Helper() + file, err := ioutil.TempFile("", "testlogger") require.NoError(t, err, "failed to create temp file") @@ -731,6 +735,8 @@ func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) { } func createTempDir(t *testing.T, prefix string) string { + t.Helper() + tmpDir, err := ioutil.TempDir("", prefix) require.NoError(t, err, "failed to create temp dir") @@ -740,6 +746,8 @@ func createTempDir(t *testing.T, prefix string) string { } func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) { + t.Helper() + logger, err := NewHandler(config) require.NoError(t, err) defer logger.Close() @@ -771,10 +779,14 @@ func doLoggingTLSOpt(t *testing.T, config *types.AccessLog, enableTLS bool) { } func doLoggingTLS(t *testing.T, config *types.AccessLog) { + t.Helper() + doLoggingTLSOpt(t, config, true) } func doLogging(t *testing.T, config *types.AccessLog) { + t.Helper() + doLoggingTLSOpt(t, config, false) } diff --git a/pkg/provider/file/file_test.go b/pkg/provider/file/file_test.go index be4755766..ca6f36728 100644 --- a/pkg/provider/file/file_test.go +++ b/pkg/provider/file/file_test.go @@ -76,8 +76,7 @@ func TestErrorWhenEmptyConfig(t *testing.T) { func TestProvideWithoutWatch(t *testing.T) { for _, test := range getTestCases() { t.Run(test.desc+" without watch", func(t *testing.T) { - provider, clean := createProvider(t, test, false) - defer clean() + provider := createProvider(t, test, false) configChan := make(chan dynamic.Message) provider.DebugLogGeneratedTemplate = true @@ -109,8 +108,7 @@ func TestProvideWithoutWatch(t *testing.T) { func TestProvideWithWatch(t *testing.T) { for _, test := range getTestCases() { t.Run(test.desc+" with watch", func(t *testing.T) { - provider, clean := createProvider(t, test, true) - defer clean() + provider := createProvider(t, test, true) configChan := make(chan dynamic.Message) go func() { @@ -244,7 +242,9 @@ func getTestCases() []ProvideTestCase { } } -func createProvider(t *testing.T, test ProvideTestCase, watch bool) (*Provider, func()) { +func createProvider(t *testing.T, test ProvideTestCase, watch bool) *Provider { + t.Helper() + tempDir := createTempDir(t, "testdir") provider := &Provider{} @@ -276,9 +276,11 @@ func createProvider(t *testing.T, test ProvideTestCase, watch bool) (*Provider, provider.Filename = file.Name() } - return provider, func() { + t.Cleanup(func() { os.RemoveAll(tempDir) - } + }) + + return provider } // createTempDir Helper. diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-host_endpoint.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-host_endpoint.yml new file mode 100644 index 000000000..b19cd5c3f --- /dev/null +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-host_endpoint.yml @@ -0,0 +1,15 @@ +kind: Endpoints +apiVersion: v1 +metadata: + name: service1 + namespace: testing + +subsets: +- addresses: + - ip: 10.10.0.1 + ports: + - port: 8080 +- addresses: + - ip: 10.21.0.1 + ports: + - port: 8080 diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-host_ingress.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-host_ingress.yml new file mode 100644 index 000000000..a8aa09dcd --- /dev/null +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-host_ingress.yml @@ -0,0 +1,23 @@ +kind: Ingress +apiVersion: networking.k8s.io/v1beta1 +metadata: + name: "" + namespace: testing + +spec: + rules: + - host: "*.bar" + http: + paths: + - path: /bar + backend: + serviceName: service1 + servicePort: 80 + + - host: "bar" + http: + paths: + - path: /bar + backend: + serviceName: service1 + servicePort: 80 diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-host_service.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-host_service.yml new file mode 100644 index 000000000..7c58aeed5 --- /dev/null +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-host_service.yml @@ -0,0 +1,10 @@ +kind: Service +apiVersion: v1 +metadata: + name: service1 + namespace: testing + +spec: + ports: + - port: 80 + clusterIp: 10.0.0.1 diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-path_endpoint.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-path_endpoint.yml new file mode 100644 index 000000000..b19cd5c3f --- /dev/null +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-path_endpoint.yml @@ -0,0 +1,15 @@ +kind: Endpoints +apiVersion: v1 +metadata: + name: service1 + namespace: testing + +subsets: +- addresses: + - ip: 10.10.0.1 + ports: + - port: 8080 +- addresses: + - ip: 10.21.0.1 + ports: + - port: 8080 diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-path_ingress.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-path_ingress.yml new file mode 100644 index 000000000..abfe74519 --- /dev/null +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-path_ingress.yml @@ -0,0 +1,19 @@ +kind: Ingress +apiVersion: networking.k8s.io/v1beta1 +metadata: + name: "" + namespace: testing + +spec: + rules: + - http: + paths: + - path: /foo/bar + backend: + serviceName: service1 + servicePort: 80 + + - path: /foo-bar + backend: + serviceName: service1 + servicePort: 80 diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-path_service.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-path_service.yml new file mode 100644 index 000000000..7c58aeed5 --- /dev/null +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-conflicting-routers-on-path_service.yml @@ -0,0 +1,10 @@ +kind: Service +apiVersion: v1 +metadata: + name: service1 + namespace: testing + +spec: + ports: + - port: 80 + clusterIp: 10.0.0.1 diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index e9f37b7d7..28c0e2a16 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -2,6 +2,7 @@ package ingress import ( "context" + "crypto/sha256" "errors" "fmt" "math" @@ -252,6 +253,8 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl conf.HTTP.Services["default-backend"] = service } + routers := map[string][]*dynamic.Router{} + for _, rule := range ingress.Spec.Rules { if err := p.updateIngressStatus(ingress, client); err != nil { log.FromContext(ctx).Errorf("Error while updating ingress status: %v", err) @@ -275,8 +278,26 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl conf.HTTP.Services[serviceName] = service routerKey := strings.TrimPrefix(provider.Normalize(ingress.Name+"-"+ingress.Namespace+"-"+rule.Host+pa.Path), "-") + routers[routerKey] = append(routers[routerKey], loadRouter(rule, pa, rtConfig, serviceName)) + } + } - conf.HTTP.Routers[routerKey] = loadRouter(rule, pa, rtConfig, serviceName) + for routerKey, conflictingRouters := range routers { + if len(conflictingRouters) == 1 { + conf.HTTP.Routers[routerKey] = conflictingRouters[0] + continue + } + + log.FromContext(ctx).Debugf("Multiple routers are defined with the same key %q, generating hashes to avoid conflicts", routerKey) + + for _, router := range conflictingRouters { + key, err := makeRouterKeyWithHash(routerKey, router.Rule) + if err != nil { + log.FromContext(ctx).Error(err) + continue + } + + conf.HTTP.Routers[key] = router } } } @@ -542,6 +563,17 @@ func getProtocol(portSpec corev1.ServicePort, portName string, svcConfig *Servic return protocol } +func makeRouterKeyWithHash(key, rule string) (string, error) { + h := sha256.New() + if _, err := h.Write([]byte(rule)); err != nil { + return "", err + } + + dupKey := fmt.Sprintf("%s-%.10x", key, h.Sum(nil)) + + return dupKey, nil +} + func loadRouter(rule networkingv1beta1.IngressRule, pa networkingv1beta1.HTTPIngressPath, rtConfig *RouterConfig, serviceName string) *dynamic.Router { var rules []string if len(rule.Host) > 0 { diff --git a/pkg/provider/kubernetes/ingress/kubernetes_test.go b/pkg/provider/kubernetes/ingress/kubernetes_test.go index ee9c98347..90c7b45c3 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes_test.go +++ b/pkg/provider/kubernetes/ingress/kubernetes_test.go @@ -169,6 +169,74 @@ func TestLoadConfigurationFromIngresses(t *testing.T) { }, }, }, + { + desc: "Ingress with conflicting routers on host", + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{}, + HTTP: &dynamic.HTTPConfiguration{ + Middlewares: map[string]*dynamic.Middleware{}, + Routers: map[string]*dynamic.Router{ + "testing-bar-bar-3be6cfd7daba66cf2fdd": { + Rule: "HostRegexp(`{subdomain:[a-zA-Z0-9-]+}.bar`) && PathPrefix(`/bar`)", + Service: "testing-service1-80", + }, + "testing-bar-bar-636bf36c00fedaab3d44": { + Rule: "Host(`bar`) && PathPrefix(`/bar`)", + Service: "testing-service1-80", + }, + }, + Services: map[string]*dynamic.Service{ + "testing-service1-80": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + PassHostHeader: Bool(true), + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:8080", + }, + { + URL: "http://10.21.0.1:8080", + }, + }, + }, + }, + }, + }, + }, + }, + { + desc: "Ingress with conflicting routers on path", + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{}, + HTTP: &dynamic.HTTPConfiguration{ + Middlewares: map[string]*dynamic.Middleware{}, + Routers: map[string]*dynamic.Router{ + "testing-foo-bar-d0b30949e54d6a7515ca": { + Rule: "PathPrefix(`/foo/bar`)", + Service: "testing-service1-80", + }, + "testing-foo-bar-dcd54bae39a6d7557f48": { + Rule: "PathPrefix(`/foo-bar`)", + Service: "testing-service1-80", + }, + }, + Services: map[string]*dynamic.Service{ + "testing-service1-80": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + PassHostHeader: Bool(true), + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:8080", + }, + { + URL: "http://10.21.0.1:8080", + }, + }, + }, + }, + }, + }, + }, + }, { desc: "Ingress one rule with two paths", expected: &dynamic.Configuration{ diff --git a/pkg/rules/rules.go b/pkg/rules/rules.go index 469bcbe56..a6bfedb1b 100644 --- a/pkg/rules/rules.go +++ b/pkg/rules/rules.go @@ -59,7 +59,14 @@ func (r *Router) AddRoute(rule string, priority int, handler http.Handler) error } route := r.NewRoute().Handler(handler).Priority(priority) - return addRuleOnRoute(route, buildTree()) + + err = addRuleOnRoute(route, buildTree()) + if err != nil { + route.BuildOnly() + return err + } + + return nil } type tree struct { diff --git a/pkg/rules/rules_test.go b/pkg/rules/rules_test.go index a6a79eace..ca38ef28f 100644 --- a/pkg/rules/rules_test.go +++ b/pkg/rules/rules_test.go @@ -29,6 +29,16 @@ func Test_addRoute(t *testing.T) { rule: "rulewithnotmatcher", expectedError: true, }, + { + desc: "Host empty", + rule: "Host(``)", + expectedError: true, + }, + { + desc: "PathPrefix empty", + rule: "PathPrefix(``)", + expectedError: true, + }, { desc: "PathPrefix", rule: "PathPrefix(`/foo`)", diff --git a/pkg/server/router/router_test.go b/pkg/server/router/router_test.go index 722cae5a3..55db73ccc 100644 --- a/pkg/server/router/router_test.go +++ b/pkg/server/router/router_test.go @@ -62,6 +62,29 @@ func TestRouterManager_Get(t *testing.T) { entryPoints: []string{"web"}, expected: expectedResult{StatusCode: http.StatusOK}, }, + { + desc: "empty host", + routersConfig: map[string]*dynamic.Router{ + "foo": { + EntryPoints: []string{"web"}, + Service: "foo-service", + Rule: "Host(``)", + }, + }, + serviceConfig: map[string]*dynamic.Service{ + "foo-service": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: server.URL, + }, + }, + }, + }, + }, + entryPoints: []string{"web"}, + expected: expectedResult{StatusCode: http.StatusNotFound}, + }, { desc: "no load balancer", routersConfig: map[string]*dynamic.Router{ diff --git a/pkg/server/server_entrypoint_tcp_test.go b/pkg/server/server_entrypoint_tcp_test.go index 6c76c768d..a8845d16b 100644 --- a/pkg/server/server_entrypoint_tcp_test.go +++ b/pkg/server/server_entrypoint_tcp_test.go @@ -28,6 +28,7 @@ func TestShutdownHijacked(t *testing.T) { err = resp.Write(conn) require.NoError(t, err) })) + testShutdown(t, router) } @@ -37,6 +38,7 @@ func TestShutdownHTTP(t *testing.T) { rw.WriteHeader(http.StatusOK) time.Sleep(time.Second) })) + testShutdown(t, router) } @@ -61,6 +63,8 @@ func TestShutdownTCP(t *testing.T) { } func testShutdown(t *testing.T, router *tcp.Router) { + t.Helper() + epConfig := &static.EntryPointsTransport{} epConfig.SetDefaults() diff --git a/pkg/server/server_entrypoint_udp_test.go b/pkg/server/server_entrypoint_udp_test.go index 00a6ba8cd..2aa5e70d8 100644 --- a/pkg/server/server_entrypoint_udp_test.go +++ b/pkg/server/server_entrypoint_udp_test.go @@ -103,6 +103,8 @@ func TestShutdownUDPConn(t *testing.T) { // It fatals if the read blocks longer than timeout, which is useful to detect // regressions that would make a test wait forever. func requireEcho(t *testing.T, data string, conn io.ReadWriter, timeout time.Duration) { + t.Helper() + _, err := conn.Write([]byte(data)) require.NoError(t, err) diff --git a/pkg/server/service/proxy_websocket_test.go b/pkg/server/service/proxy_websocket_test.go index a759cf95a..a03a06666 100644 --- a/pkg/server/service/proxy_websocket_test.go +++ b/pkg/server/service/proxy_websocket_test.go @@ -696,12 +696,16 @@ func (w *websocketRequest) open() (*websocket.Conn, net.Conn, error) { } func parseURI(t *testing.T, uri string) *url.URL { + t.Helper() + out, err := url.ParseRequestURI(uri) require.NoError(t, err) return out } func createProxyWithForwarder(t *testing.T, proxy http.Handler, url string) *httptest.Server { + t.Helper() + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { path := req.URL.Path // keep the original path // Set new backend URL diff --git a/pkg/tcp/proxy_test.go b/pkg/tcp/proxy_test.go index e83017fba..11fdb47c4 100644 --- a/pkg/tcp/proxy_test.go +++ b/pkg/tcp/proxy_test.go @@ -17,6 +17,8 @@ import ( ) func fakeRedis(t *testing.T, listener net.Listener) { + t.Helper() + for { conn, err := listener.Accept() fmt.Println("Accept on server") diff --git a/pkg/udp/conn_test.go b/pkg/udp/conn_test.go index f97eb3958..3f0116e07 100644 --- a/pkg/udp/conn_test.go +++ b/pkg/udp/conn_test.go @@ -171,6 +171,8 @@ func TestTimeoutWithoutRead(t *testing.T) { } func testTimeout(t *testing.T, withRead bool) { + t.Helper() + addr, err := net.ResolveUDPAddr("udp", ":0") require.NoError(t, err) @@ -312,6 +314,8 @@ func TestShutdown(t *testing.T) { // It fatals if the read blocks longer than timeout, // which is useful to detect regressions that would make a test wait forever. func requireEcho(t *testing.T, data string, conn io.ReadWriter, timeout time.Duration) { + t.Helper() + _, err := conn.Write([]byte(data)) require.NoError(t, err) diff --git a/pkg/udp/proxy_test.go b/pkg/udp/proxy_test.go index 509f9aabd..e2995846d 100644 --- a/pkg/udp/proxy_test.go +++ b/pkg/udp/proxy_test.go @@ -41,6 +41,8 @@ func TestUDPProxy(t *testing.T) { } func newServer(t *testing.T, addr string, handler Handler) { + t.Helper() + addrL, err := net.ResolveUDPAddr("udp", addr) require.NoError(t, err) diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index 408b454d1..01c1e79c1 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -6,9 +6,9 @@ FileName = "traefik_changelog.md" # example new bugfix v2.3.5 CurrentRef = "v2.3" -PreviousRef = "v2.3.4" +PreviousRef = "v2.3.5" BaseBranch = "v2.3" -FutureCurrentRefName = "v2.3.5" +FutureCurrentRefName = "v2.3.6" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/webui/src/components/_commons/PanelMiddlewares.vue b/webui/src/components/_commons/PanelMiddlewares.vue index f9776239f..13837b73c 100644 --- a/webui/src/components/_commons/PanelMiddlewares.vue +++ b/webui/src/components/_commons/PanelMiddlewares.vue @@ -330,7 +330,7 @@ v-for="(val, key) in exData(middleware).customRequestHeaders" :key="key" dense class="app-chip app-chip-green"> - {{ val }} + {{ key }}: {{ val }} @@ -344,7 +344,7 @@ v-for="(val, key) in exData(middleware).customResponseHeaders" :key="key" dense class="app-chip app-chip-green"> - {{ val }} + {{ key }}: {{ val }}