Merge branch v2.4 into master
This commit is contained in:
commit
0509b6fdb9
29 changed files with 317 additions and 17 deletions
|
@ -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]
|
||||
|
|
12
CHANGELOG.md
12
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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,10 @@
|
|||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: service1
|
||||
namespace: testing
|
||||
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
clusterIp: 10.0.0.1
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,10 @@
|
|||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: service1
|
||||
namespace: testing
|
||||
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
clusterIp: 10.0.0.1
|
|
@ -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 {
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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`)",
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -330,7 +330,7 @@
|
|||
v-for="(val, key) in exData(middleware).customRequestHeaders" :key="key"
|
||||
dense
|
||||
class="app-chip app-chip-green">
|
||||
{{ val }}
|
||||
{{ key }}: {{ val }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -344,7 +344,7 @@
|
|||
v-for="(val, key) in exData(middleware).customResponseHeaders" :key="key"
|
||||
dense
|
||||
class="app-chip app-chip-green">
|
||||
{{ val }}
|
||||
{{ key }}: {{ val }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue