Entry point redirection and default routers configuration
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com> Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
This commit is contained in:
parent
93a7af270f
commit
a6040c623b
46 changed files with 1016 additions and 126 deletions
|
@ -191,7 +191,25 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
|
|||
managerFactory := service.NewManagerFactory(*staticConfiguration, routinesPool, metricsRegistry)
|
||||
routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder)
|
||||
|
||||
watcher := server.NewConfigurationWatcher(routinesPool, providerAggregator, time.Duration(staticConfiguration.Providers.ProvidersThrottleDuration))
|
||||
var eps []string
|
||||
for name, cfg := range staticConfiguration.EntryPoints {
|
||||
protocol, err := cfg.GetProtocol()
|
||||
if err != nil {
|
||||
// Should never happen because Traefik should not start if protocol is invalid.
|
||||
log.WithoutContext().Errorf("Invalid protocol: %v", err)
|
||||
}
|
||||
|
||||
if protocol != "udp" {
|
||||
eps = append(eps, name)
|
||||
}
|
||||
}
|
||||
|
||||
watcher := server.NewConfigurationWatcher(
|
||||
routinesPool,
|
||||
providerAggregator,
|
||||
time.Duration(staticConfiguration.Providers.ProvidersThrottleDuration),
|
||||
eps,
|
||||
)
|
||||
|
||||
watcher.AddListener(func(conf dynamic.Configuration) {
|
||||
ctx := context.Background()
|
||||
|
|
|
@ -387,10 +387,8 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd
|
|||
- match: HostRegexp(`{any:.+}`)
|
||||
kind: Rule
|
||||
services:
|
||||
# any service in the namespace
|
||||
# the service will be never called
|
||||
- name: noop
|
||||
port: 80
|
||||
# the noop service will be never called
|
||||
- name: noop@internal
|
||||
middlewares:
|
||||
- name: https_redirect
|
||||
# if the Middleware has distinct namespace
|
||||
|
@ -431,13 +429,8 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd
|
|||
entryPoints = ["web"]
|
||||
middlewares = ["https_redirect"]
|
||||
rule = "HostRegexp(`{any:.+}`)"
|
||||
service = "noop"
|
||||
|
||||
[http.services]
|
||||
# noop service, the URL will be never called
|
||||
[http.services.noop.loadBalancer]
|
||||
[[http.services.noop.loadBalancer.servers]]
|
||||
url = "http://192.168.0.1:1337"
|
||||
# the noop service will be never called
|
||||
service = "noop@internal"
|
||||
|
||||
[http.middlewares]
|
||||
[http.middlewares.https_redirect.redirectScheme]
|
||||
|
@ -472,14 +465,8 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd
|
|||
middlewares:
|
||||
- https_redirect
|
||||
rule: "HostRegexp(`{any:.+}`)"
|
||||
service: noop
|
||||
|
||||
services:
|
||||
# noop service, the URL will be never called
|
||||
noop:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: http://192.168.0.1:1337
|
||||
# the noop service will be never called
|
||||
service: noop@internal
|
||||
|
||||
middlewares:
|
||||
https_redirect:
|
||||
|
|
|
@ -99,6 +99,36 @@ Trust all forwarded headers. (Default: ```false```)
|
|||
`--entrypoints.<name>.forwardedheaders.trustedips`:
|
||||
Trust only forwarded headers from selected IPs.
|
||||
|
||||
`--entrypoints.<name>.http`:
|
||||
HTTP configuration.
|
||||
|
||||
`--entrypoints.<name>.http.middlewares`:
|
||||
Default middlewares for the routers linked to the entry point.
|
||||
|
||||
`--entrypoints.<name>.http.redirections.entrypoint.scheme`:
|
||||
Scheme used for the redirection. Defaults to https. (Default: ```https```)
|
||||
|
||||
`--entrypoints.<name>.http.redirections.entrypoint.to`:
|
||||
Targeted entry point of the redirection.
|
||||
|
||||
`--entrypoints.<name>.http.tls`:
|
||||
Default TLS configuration for the routers linked to the entry point. (Default: ```false```)
|
||||
|
||||
`--entrypoints.<name>.http.tls.certresolver`:
|
||||
Default certificate resolver for the routers linked to the entry point.
|
||||
|
||||
`--entrypoints.<name>.http.tls.domains`:
|
||||
Default TLS domains for the routers linked to the entry point.
|
||||
|
||||
`--entrypoints.<name>.http.tls.domains[n].main`:
|
||||
Default subject name.
|
||||
|
||||
`--entrypoints.<name>.http.tls.domains[n].sans`:
|
||||
Subject alternative names.
|
||||
|
||||
`--entrypoints.<name>.http.tls.options`:
|
||||
Default TLS options for the routers linked to the entry point.
|
||||
|
||||
`--entrypoints.<name>.proxyprotocol`:
|
||||
Proxy-Protocol configuration. (Default: ```false```)
|
||||
|
||||
|
|
|
@ -99,6 +99,36 @@ Trust all forwarded headers. (Default: ```false```)
|
|||
`TRAEFIK_ENTRYPOINTS_<NAME>_FORWARDEDHEADERS_TRUSTEDIPS`:
|
||||
Trust only forwarded headers from selected IPs.
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP`:
|
||||
HTTP configuration.
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_MIDDLEWARES`:
|
||||
Default middlewares for the routers linked to the entry point.
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_REDIRECTIONS_ENTRYPOINT_SCHEME`:
|
||||
Scheme used for the redirection. Defaults to https. (Default: ```https```)
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_REDIRECTIONS_ENTRYPOINT_TO`:
|
||||
Targeted entry point of the redirection.
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS`:
|
||||
Default TLS configuration for the routers linked to the entry point. (Default: ```false```)
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_CERTRESOLVER`:
|
||||
Default certificate resolver for the routers linked to the entry point.
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_DOMAINS`:
|
||||
Default TLS domains for the routers linked to the entry point.
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_DOMAINS[n]_MAIN`:
|
||||
Default subject name.
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_DOMAINS[n]_SANS`:
|
||||
Subject alternative names.
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_OPTIONS`:
|
||||
Default TLS options for the routers linked to the entry point.
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_PROXYPROTOCOL`:
|
||||
Proxy-Protocol configuration. (Default: ```false```)
|
||||
|
||||
|
|
|
@ -28,6 +28,23 @@
|
|||
[entryPoints.EntryPoint0.forwardedHeaders]
|
||||
insecure = true
|
||||
trustedIPs = ["foobar", "foobar"]
|
||||
[entryPoints.EntryPoint0.http]
|
||||
middlewares = ["foobar", "foobar"]
|
||||
[entryPoints.EntryPoint0.http.redirections]
|
||||
[entryPoints.EntryPoint0.http.redirections.entryPoint]
|
||||
to = "foobar"
|
||||
scheme = "foobar"
|
||||
[entryPoints.EntryPoint0.http.tls]
|
||||
options = "foobar"
|
||||
certResolver = "foobar"
|
||||
|
||||
[[entryPoints.EntryPoint0.http.tls.domains]]
|
||||
main = "foobar"
|
||||
sans = ["foobar", "foobar"]
|
||||
|
||||
[[entryPoints.EntryPoint0.http.tls.domains]]
|
||||
main = "foobar"
|
||||
sans = ["foobar", "foobar"]
|
||||
|
||||
[providers]
|
||||
providersThrottleDuration = 42
|
||||
|
@ -133,10 +150,10 @@
|
|||
username = "foobar"
|
||||
password = "foobar"
|
||||
[providers.consul]
|
||||
rootKey = "traefik"
|
||||
rootKey = "traefik"
|
||||
endpoints = ["foobar", "foobar"]
|
||||
username = "foobar"
|
||||
password = "foobar"
|
||||
username = "foobar"
|
||||
password = "foobar"
|
||||
[providers.consul.tls]
|
||||
ca = "foobar"
|
||||
caOptional = true
|
||||
|
@ -144,10 +161,10 @@
|
|||
key = "foobar"
|
||||
insecureSkipVerify = true
|
||||
[providers.etcd]
|
||||
rootKey = "traefik"
|
||||
rootKey = "traefik"
|
||||
endpoints = ["foobar", "foobar"]
|
||||
username = "foobar"
|
||||
password = "foobar"
|
||||
username = "foobar"
|
||||
password = "foobar"
|
||||
[providers.etcd.tls]
|
||||
ca = "foobar"
|
||||
caOptional = true
|
||||
|
@ -155,10 +172,10 @@
|
|||
key = "foobar"
|
||||
insecureSkipVerify = true
|
||||
[providers.zooKeeper]
|
||||
rootKey = "traefik"
|
||||
rootKey = "traefik"
|
||||
endpoints = ["foobar", "foobar"]
|
||||
username = "foobar"
|
||||
password = "foobar"
|
||||
username = "foobar"
|
||||
password = "foobar"
|
||||
[providers.zooKeeper.tls]
|
||||
ca = "foobar"
|
||||
caOptional = true
|
||||
|
@ -166,10 +183,10 @@
|
|||
key = "foobar"
|
||||
insecureSkipVerify = true
|
||||
[providers.redis]
|
||||
rootKey = "traefik"
|
||||
rootKey = "traefik"
|
||||
endpoints = ["foobar", "foobar"]
|
||||
username = "foobar"
|
||||
password = "foobar"
|
||||
username = "foobar"
|
||||
password = "foobar"
|
||||
[providers.redis.tls]
|
||||
ca = "foobar"
|
||||
caOptional = true
|
||||
|
|
|
@ -32,6 +32,26 @@ entryPoints:
|
|||
trustedIPs:
|
||||
- foobar
|
||||
- foobar
|
||||
http:
|
||||
redirections:
|
||||
entryPoint:
|
||||
to: foobar
|
||||
scheme: foobar
|
||||
middlewares:
|
||||
- foobar
|
||||
- foobar
|
||||
tls:
|
||||
options: foobar
|
||||
certResolver: foobar
|
||||
domains:
|
||||
- main: foobar
|
||||
sans:
|
||||
- foobar
|
||||
- foobar
|
||||
- main: foobar
|
||||
sans:
|
||||
- foobar
|
||||
- foobar
|
||||
providers:
|
||||
providersThrottleDuration: 42
|
||||
docker:
|
||||
|
@ -142,8 +162,8 @@ providers:
|
|||
consul:
|
||||
rootKey: traefik
|
||||
endpoints:
|
||||
- foobar
|
||||
- foobar
|
||||
- foobar
|
||||
- foobar
|
||||
username: foobar
|
||||
password: foobar
|
||||
tls:
|
||||
|
@ -155,8 +175,8 @@ providers:
|
|||
etcd:
|
||||
rootKey: traefik
|
||||
endpoints:
|
||||
- foobar
|
||||
- foobar
|
||||
- foobar
|
||||
- foobar
|
||||
username: foobar
|
||||
password: foobar
|
||||
tls:
|
||||
|
|
|
@ -529,3 +529,211 @@ If the Proxy Protocol header is passed, then the version is determined automatic
|
|||
|
||||
When queuing Traefik behind another load-balancer, make sure to configure Proxy Protocol on both sides.
|
||||
Not doing so could introduce a security risk in your system (enabling request forgery).
|
||||
|
||||
## HTTP Options
|
||||
|
||||
This whole section is dedicated to options, keyed by entry point, that will apply only to HTTP routing.
|
||||
|
||||
### Redirection
|
||||
|
||||
??? example "HTTPS redirection (80 to 443)"
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[entryPoints.web]
|
||||
address = ":80"
|
||||
|
||||
[entryPoints.web.http]
|
||||
[entryPoints.web.http.redirections]
|
||||
[entryPoints.web.http.redirections.entryPoint]
|
||||
to = "websecure"
|
||||
scheme = "https"
|
||||
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
entryPoints:
|
||||
web:
|
||||
address: :80
|
||||
http:
|
||||
redirections:
|
||||
entryPoint:
|
||||
to: websecure
|
||||
https: true
|
||||
|
||||
websecure:
|
||||
address: :443
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--entrypoints.web.address=:80
|
||||
--entrypoints.web.http.redirections.entryPoint.to=websecure
|
||||
--entrypoints.web.http.redirections.entryPoint.https=true
|
||||
--entrypoints.websecure.address=:443
|
||||
```
|
||||
|
||||
#### `entryPoint`
|
||||
|
||||
This section is a convenience to enable (permanent) redirecting of all incoming requests on an entry point (e.g. port `80`) to another entry point (e.g. port `443`).
|
||||
|
||||
??? info "`entryPoint.to`"
|
||||
|
||||
_Required_
|
||||
|
||||
The target entry point.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[entryPoints.foo]
|
||||
# ...
|
||||
[entryPoints.foo.http.redirections]
|
||||
[entryPoints.foo.http.redirections.entryPoint]
|
||||
to = "bar"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
entryPoints:
|
||||
foo:
|
||||
# ...
|
||||
http:
|
||||
redirections:
|
||||
entryPoint:
|
||||
to: bar
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--entrypoints.foo.http.redirections.entryPoint.to=websecure
|
||||
```
|
||||
|
||||
??? info "`entryPoint.scheme`"
|
||||
|
||||
_Optional, Default="http"_
|
||||
|
||||
The redirection target scheme.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[entryPoints.foo]
|
||||
# ...
|
||||
[entryPoints.foo.http.redirections]
|
||||
[entryPoints.foo.http.redirections.entryPoint]
|
||||
# ...
|
||||
scheme = "https"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
entryPoints:
|
||||
foo:
|
||||
# ...
|
||||
http:
|
||||
redirections:
|
||||
entryPoint:
|
||||
# ...
|
||||
scheme: https
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--entrypoints.foo.http.redirections.entryPoint.scheme=https
|
||||
```
|
||||
|
||||
### Middlewares
|
||||
|
||||
The list of middlewares that are prepended by default to the list of middlewares of each router associated to the named entry point.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
|
||||
[entryPoints.websecure.http]
|
||||
middlewares = ["auth@file", "strip@file"]
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
entryPoints:
|
||||
websecure:
|
||||
address: ':443'
|
||||
http:
|
||||
middlewares:
|
||||
- auth@file
|
||||
- strip@file
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
entrypoints.websecure.address=:443
|
||||
entrypoints.websecure.http.middlewares=auth@file,strip@file
|
||||
```
|
||||
|
||||
### TLS
|
||||
|
||||
This section is about the default TLS configuration applied to all routers associated with the named entry point.
|
||||
|
||||
If a TLS section (i.e. any of its fields) is user-defined, then the default configuration does not apply at all.
|
||||
|
||||
The TLS section is the same as the [TLS section on HTTP routers](./routers/index.md#tls).
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
|
||||
[entryPoints.websecure.http.tls]
|
||||
options = "foobar"
|
||||
certResolver = "leresolver"
|
||||
[[entryPoints.websecure.http.tls.domains]]
|
||||
main = "example.com"
|
||||
sans = ["foo.example.com", "bar.example.com"]
|
||||
[[entryPoints.websecure.http.tls.domains]]
|
||||
main = "test.com"
|
||||
sans = ["foo.test.com", "bar.test.com"]
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
entryPoints:
|
||||
websecure:
|
||||
address: ':443'
|
||||
http:
|
||||
tls:
|
||||
options: foobar
|
||||
certResolver: leresolver
|
||||
domains:
|
||||
- main: example.com
|
||||
sans:
|
||||
- foo.example.com
|
||||
- bar.example.com
|
||||
- main: test.com
|
||||
sans:
|
||||
- foo.test.com
|
||||
- bar.test.com
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
entrypoints.websecure.address=:443
|
||||
entrypoints.websecure.http.tls.options=foobar
|
||||
entrypoints.websecure.http.tls.certResolver=leresolver
|
||||
entrypoints.websecure.http.tls.domains[0].main=example.com
|
||||
entrypoints.websecure.http.tls.domains[0].sans=foo.example.com,bar.example.com
|
||||
entrypoints.websecure.http.tls.domains[1].main=test.com
|
||||
entrypoints.websecure.http.tls.domains[1].sans=foo.test.com,bar.test.com
|
||||
```
|
||||
|
||||
??? example "Let's Encrypt"
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
|
||||
[entryPoints.websecure.http.tls]
|
||||
certResolver = "leresolver"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
entryPoints:
|
||||
websecure:
|
||||
address: ':443'
|
||||
http:
|
||||
tls:
|
||||
certResolver: leresolver
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
entrypoints.websecure.address=:443
|
||||
entrypoints.websecure.http.tls.certResolver=leresolver
|
||||
```
|
||||
|
|
|
@ -76,7 +76,7 @@ func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
|
|||
|
||||
// check that we have only one service (not counting the internal ones) with n servers
|
||||
services := rtconf.Services
|
||||
c.Assert(services, checker.HasLen, 3)
|
||||
c.Assert(services, checker.HasLen, 4)
|
||||
for name, service := range services {
|
||||
if strings.HasSuffix(name, "@internal") {
|
||||
continue
|
||||
|
|
3
integration/testdata/rawdata-consul.json
vendored
3
integration/testdata/rawdata-consul.json
vendored
|
@ -165,6 +165,9 @@
|
|||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"noop@internal": {
|
||||
"status": "enabled"
|
||||
},
|
||||
"simplesvc@consul": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
|
|
33
integration/testdata/rawdata-crd.json
vendored
33
integration/testdata/rawdata-crd.json
vendored
|
@ -98,10 +98,10 @@
|
|||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.42.0.3:80"
|
||||
"url": "http://10.42.0.2:80"
|
||||
},
|
||||
{
|
||||
"url": "http://10.42.0.5:80"
|
||||
"url": "http://10.42.0.3:80"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
|
@ -111,18 +111,18 @@
|
|||
"default-test-route-6b204d94623b3df4370c@kubernetescrd"
|
||||
],
|
||||
"serverStatus": {
|
||||
"http://10.42.0.3:80": "UP",
|
||||
"http://10.42.0.5:80": "UP"
|
||||
"http://10.42.0.2:80": "UP",
|
||||
"http://10.42.0.3:80": "UP"
|
||||
}
|
||||
},
|
||||
"default-test2-route-23c7f4c450289ee29016@kubernetescrd": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.42.0.3:80"
|
||||
"url": "http://10.42.0.2:80"
|
||||
},
|
||||
{
|
||||
"url": "http://10.42.0.5:80"
|
||||
"url": "http://10.42.0.3:80"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
|
@ -132,26 +132,26 @@
|
|||
"default-test2-route-23c7f4c450289ee29016@kubernetescrd"
|
||||
],
|
||||
"serverStatus": {
|
||||
"http://10.42.0.3:80": "UP",
|
||||
"http://10.42.0.5:80": "UP"
|
||||
"http://10.42.0.2:80": "UP",
|
||||
"http://10.42.0.3:80": "UP"
|
||||
}
|
||||
},
|
||||
"default-whoami-80@kubernetescrd": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.42.0.3:80"
|
||||
"url": "http://10.42.0.2:80"
|
||||
},
|
||||
{
|
||||
"url": "http://10.42.0.5:80"
|
||||
"url": "http://10.42.0.3:80"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"serverStatus": {
|
||||
"http://10.42.0.3:80": "UP",
|
||||
"http://10.42.0.5:80": "UP"
|
||||
"http://10.42.0.2:80": "UP",
|
||||
"http://10.42.0.3:80": "UP"
|
||||
}
|
||||
},
|
||||
"default-wrr1@kubernetescrd": {
|
||||
|
@ -171,6 +171,9 @@
|
|||
"usedBy": [
|
||||
"default-test3-route-7d0ac22d3d8db4b82618@kubernetescrd"
|
||||
]
|
||||
},
|
||||
"noop@internal": {
|
||||
"status": "enabled"
|
||||
}
|
||||
},
|
||||
"tcpRouters": {
|
||||
|
@ -199,7 +202,7 @@
|
|||
"address": "10.42.0.4:8080"
|
||||
},
|
||||
{
|
||||
"address": "10.42.0.6:8080"
|
||||
"address": "10.42.0.8:8080"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -226,10 +229,10 @@
|
|||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"address": "10.42.0.4:8090"
|
||||
"address": "10.42.0.10:8090"
|
||||
},
|
||||
{
|
||||
"address": "10.42.0.6:8090"
|
||||
"address": "10.42.0.9:8090"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
3
integration/testdata/rawdata-etcd.json
vendored
3
integration/testdata/rawdata-etcd.json
vendored
|
@ -165,6 +165,9 @@
|
|||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"noop@internal": {
|
||||
"status": "enabled"
|
||||
},
|
||||
"simplesvc@etcd": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
|
|
11
integration/testdata/rawdata-ingress.json
vendored
11
integration/testdata/rawdata-ingress.json
vendored
|
@ -29,6 +29,10 @@
|
|||
]
|
||||
},
|
||||
"test-ingress-default-whoami-test-whoami@kubernetes": {
|
||||
"entryPoints": [
|
||||
"web",
|
||||
"traefik"
|
||||
],
|
||||
"service": "default-whoami-http",
|
||||
"rule": "Host(`whoami.test`) \u0026\u0026 PathPrefix(`/whoami`)",
|
||||
"status": "enabled",
|
||||
|
@ -38,6 +42,10 @@
|
|||
]
|
||||
},
|
||||
"test-ingress-https-default-whoami-test-https-whoami@kubernetes": {
|
||||
"entryPoints": [
|
||||
"web",
|
||||
"traefik"
|
||||
],
|
||||
"service": "default-whoami-http",
|
||||
"rule": "Host(`whoami.test.https`) \u0026\u0026 PathPrefix(`/whoami`)",
|
||||
"tls": {},
|
||||
|
@ -107,6 +115,9 @@
|
|||
"http://10.42.0.3:80": "UP",
|
||||
"http://10.42.0.5:80": "UP"
|
||||
}
|
||||
},
|
||||
"noop@internal": {
|
||||
"status": "enabled"
|
||||
}
|
||||
}
|
||||
}
|
3
integration/testdata/rawdata-redis.json
vendored
3
integration/testdata/rawdata-redis.json
vendored
|
@ -165,6 +165,9 @@
|
|||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"noop@internal": {
|
||||
"status": "enabled"
|
||||
},
|
||||
"simplesvc@redis": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
|
|
3
integration/testdata/rawdata-zk.json
vendored
3
integration/testdata/rawdata-zk.json
vendored
|
@ -165,6 +165,9 @@
|
|||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"noop@internal": {
|
||||
"status": "enabled"
|
||||
},
|
||||
"simplesvc@zookeeper": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
|
|
1
pkg/api/testdata/entrypoint-bar.json
vendored
1
pkg/api/testdata/entrypoint-bar.json
vendored
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"address": ":81",
|
||||
"http": {},
|
||||
"name": "bar"
|
||||
}
|
|
@ -1,22 +1,27 @@
|
|||
[
|
||||
{
|
||||
"address": ":14",
|
||||
"http": {},
|
||||
"name": "ep14"
|
||||
},
|
||||
{
|
||||
"address": ":15",
|
||||
"http": {},
|
||||
"name": "ep15"
|
||||
},
|
||||
{
|
||||
"address": ":16",
|
||||
"http": {},
|
||||
"name": "ep16"
|
||||
},
|
||||
{
|
||||
"address": ":17",
|
||||
"http": {},
|
||||
"name": "ep17"
|
||||
},
|
||||
{
|
||||
"address": ":18",
|
||||
"http": {},
|
||||
"name": "ep18"
|
||||
}
|
||||
]
|
1
pkg/api/testdata/entrypoints-page2.json
vendored
1
pkg/api/testdata/entrypoints-page2.json
vendored
|
@ -1,6 +1,7 @@
|
|||
[
|
||||
{
|
||||
"address": ":82",
|
||||
"http": {},
|
||||
"name": "web2"
|
||||
}
|
||||
]
|
2
pkg/api/testdata/entrypoints.json
vendored
2
pkg/api/testdata/entrypoints.json
vendored
|
@ -8,6 +8,7 @@
|
|||
"192.168.1.4"
|
||||
]
|
||||
},
|
||||
"http": {},
|
||||
"name": "web",
|
||||
"proxyProtocol": {
|
||||
"insecure": true,
|
||||
|
@ -37,6 +38,7 @@
|
|||
"192.168.1.40"
|
||||
]
|
||||
},
|
||||
"http": {},
|
||||
"name": "websecure",
|
||||
"proxyProtocol": {
|
||||
"insecure": true,
|
||||
|
|
|
@ -11,8 +11,17 @@ import (
|
|||
// HTTPConfiguration contains all the HTTP configuration parameters.
|
||||
type HTTPConfiguration struct {
|
||||
Routers map[string]*Router `json:"routers,omitempty" toml:"routers,omitempty" yaml:"routers,omitempty"`
|
||||
Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||
Services map[string]*Service `json:"services,omitempty" toml:"services,omitempty" yaml:"services,omitempty"`
|
||||
Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||
Models map[string]*Model `json:"models,omitempty" toml:"models,omitempty" yaml:"models,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Model is a set of default router's values.
|
||||
type Model struct {
|
||||
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
|
|
@ -375,6 +375,21 @@ func (in *HTTPConfiguration) DeepCopyInto(out *HTTPConfiguration) {
|
|||
(*out)[key] = outVal
|
||||
}
|
||||
}
|
||||
if in.Services != nil {
|
||||
in, out := &in.Services, &out.Services
|
||||
*out = make(map[string]*Service, len(*in))
|
||||
for key, val := range *in {
|
||||
var outVal *Service
|
||||
if val == nil {
|
||||
(*out)[key] = nil
|
||||
} else {
|
||||
in, out := &val, &outVal
|
||||
*out = new(Service)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
(*out)[key] = outVal
|
||||
}
|
||||
}
|
||||
if in.Middlewares != nil {
|
||||
in, out := &in.Middlewares, &out.Middlewares
|
||||
*out = make(map[string]*Middleware, len(*in))
|
||||
|
@ -390,16 +405,16 @@ func (in *HTTPConfiguration) DeepCopyInto(out *HTTPConfiguration) {
|
|||
(*out)[key] = outVal
|
||||
}
|
||||
}
|
||||
if in.Services != nil {
|
||||
in, out := &in.Services, &out.Services
|
||||
*out = make(map[string]*Service, len(*in))
|
||||
if in.Models != nil {
|
||||
in, out := &in.Models, &out.Models
|
||||
*out = make(map[string]*Model, len(*in))
|
||||
for key, val := range *in {
|
||||
var outVal *Service
|
||||
var outVal *Model
|
||||
if val == nil {
|
||||
(*out)[key] = nil
|
||||
} else {
|
||||
in, out := &val, &outVal
|
||||
*out = new(Service)
|
||||
*out = new(Model)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
(*out)[key] = outVal
|
||||
|
@ -760,6 +775,32 @@ func (in *Mirroring) DeepCopy() *Mirroring {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Model) DeepCopyInto(out *Model) {
|
||||
*out = *in
|
||||
if in.Middlewares != nil {
|
||||
in, out := &in.Middlewares, &out.Middlewares
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.TLS != nil {
|
||||
in, out := &in.TLS, &out.TLS
|
||||
*out = new(RouterTLSConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Model.
|
||||
func (in *Model) DeepCopy() *Model {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Model)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PassTLSClientCert) DeepCopyInto(out *PassTLSClientCert) {
|
||||
*out = *in
|
||||
|
|
|
@ -21,14 +21,8 @@ func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints
|
|||
|
||||
logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName)))
|
||||
|
||||
eps := rt.EntryPoints
|
||||
if len(eps) == 0 {
|
||||
logger.Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints)
|
||||
eps = entryPoints
|
||||
}
|
||||
|
||||
entryPointsCount := 0
|
||||
for _, entryPointName := range eps {
|
||||
for _, entryPointName := range rt.EntryPoints {
|
||||
if !contains(entryPoints, entryPointName) {
|
||||
rt.AddError(fmt.Errorf("entryPoint %q doesn't exist", entryPointName), false)
|
||||
logger.WithField(log.EntryPointName, entryPointName).
|
||||
|
|
|
@ -3,6 +3,8 @@ package static
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/types"
|
||||
)
|
||||
|
||||
// EntryPoint holds the entry point configuration.
|
||||
|
@ -11,6 +13,7 @@ type EntryPoint struct {
|
|||
Transport *EntryPointsTransport `description:"Configures communication between clients and Traefik." json:"transport,omitempty" toml:"transport,omitempty" yaml:"transport,omitempty"`
|
||||
ProxyProtocol *ProxyProtocol `description:"Proxy-Protocol configuration." json:"proxyProtocol,omitempty" toml:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty" label:"allowEmpty"`
|
||||
ForwardedHeaders *ForwardedHeaders `description:"Trust client forwarding headers." json:"forwardedHeaders,omitempty" toml:"forwardedHeaders,omitempty" yaml:"forwardedHeaders,omitempty"`
|
||||
HTTP HTTPConfig `description:"HTTP configuration." json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty"`
|
||||
}
|
||||
|
||||
// GetAddress strips any potential protocol part of the address field of the
|
||||
|
@ -43,6 +46,36 @@ func (ep *EntryPoint) SetDefaults() {
|
|||
ep.ForwardedHeaders = &ForwardedHeaders{}
|
||||
}
|
||||
|
||||
// HTTPConfig is the HTTP configuration of an entry point.
|
||||
type HTTPConfig struct {
|
||||
Redirections *Redirections `description:"Set of redirection" json:"redirections,omitempty" toml:"redirections,omitempty" yaml:"redirections,omitempty"`
|
||||
Middlewares []string `description:"Default middlewares for the routers linked to the entry point." json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||
TLS *TLSConfig `description:"Default TLS configuration for the routers linked to the entry point." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty"`
|
||||
}
|
||||
|
||||
// Redirections is a set of redirection for an entry point.
|
||||
type Redirections struct {
|
||||
EntryPoint *RedirectEntryPoint `description:"Set of redirection for an entry point." json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"`
|
||||
}
|
||||
|
||||
// RedirectEntryPoint is the definition of an entry point redirection.
|
||||
type RedirectEntryPoint struct {
|
||||
To string `description:"Targeted entry point of the redirection." json:"to,omitempty" toml:"to,omitempty" yaml:"to,omitempty"`
|
||||
Scheme string `description:"Scheme used for the redirection. Defaults to https." json:"https,omitempty" toml:"https,omitempty" yaml:"https,omitempty"`
|
||||
}
|
||||
|
||||
// SetDefaults sets the default values.
|
||||
func (r *RedirectEntryPoint) SetDefaults() {
|
||||
r.Scheme = "https"
|
||||
}
|
||||
|
||||
// TLSConfig is the default TLS configuration for all the routers associated to the concerned entry point.
|
||||
type TLSConfig struct {
|
||||
Options string `description:"Default TLS options for the routers linked to the entry point." json:"options,omitempty" toml:"options,omitempty" yaml:"options,omitempty"`
|
||||
CertResolver string `description:"Default certificate resolver for the routers linked to the entry point." json:"certResolver,omitempty" toml:"certResolver,omitempty" yaml:"certResolver,omitempty"`
|
||||
Domains []types.Domain `description:"Default TLS domains for the routers linked to the entry point." json:"domains,omitempty" toml:"domains,omitempty" yaml:"domains,omitempty"`
|
||||
}
|
||||
|
||||
// ForwardedHeaders Trust client forwarding headers.
|
||||
type ForwardedHeaders struct {
|
||||
Insecure bool `description:"Trust all forwarded headers." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"`
|
||||
|
|
|
@ -41,7 +41,8 @@
|
|||
},
|
||||
"services": {
|
||||
"api": {},
|
||||
"dashboard": {}
|
||||
"dashboard": {},
|
||||
"noop": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
}
|
||||
},
|
||||
"services": {
|
||||
"api": {}
|
||||
"api": {},
|
||||
"noop": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
"http": {
|
||||
"services": {
|
||||
"api": {},
|
||||
"dashboard": {}
|
||||
"dashboard": {},
|
||||
"noop": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"api": {}
|
||||
"api": {},
|
||||
"noop": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
"services": {
|
||||
"api": {},
|
||||
"dashboard": {},
|
||||
"noop": {},
|
||||
"ping": {},
|
||||
"prometheus": {},
|
||||
"rest": {}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"services": {
|
||||
"api": {},
|
||||
"dashboard": {},
|
||||
"noop": {},
|
||||
"ping": {},
|
||||
"prometheus": {},
|
||||
"rest": {}
|
||||
|
|
36
pkg/provider/traefik/fixtures/models.json
Normal file
36
pkg/provider/traefik/fixtures/models.json
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"noop": {}
|
||||
},
|
||||
"models": {
|
||||
"websecure": {
|
||||
"middlewares": [
|
||||
"test"
|
||||
],
|
||||
"tls": {
|
||||
"options": "opt",
|
||||
"certResolver": "le",
|
||||
"domains": [
|
||||
{
|
||||
"main": "mainA",
|
||||
"sans": [
|
||||
"sanA1",
|
||||
"sanA2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"main": "mainB",
|
||||
"sans": [
|
||||
"sanB1",
|
||||
"sanB2"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"noop": {},
|
||||
"ping": {}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
}
|
||||
},
|
||||
"services": {
|
||||
"noop": {},
|
||||
"ping": {}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"noop": {},
|
||||
"prometheus": {}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
}
|
||||
},
|
||||
"services": {
|
||||
"noop": {},
|
||||
"prometheus": {}
|
||||
}
|
||||
},
|
||||
|
|
30
pkg/provider/traefik/fixtures/redirection.json
Normal file
30
pkg/provider/traefik/fixtures/redirection.json
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"http": {
|
||||
"routers": {
|
||||
"web-to-websecure": {
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"redirect-web-to-websecure"
|
||||
],
|
||||
"service": "noop@internal",
|
||||
"rule": "HostRegexp(`{host:.+}`)"
|
||||
}
|
||||
},
|
||||
"middlewares": {
|
||||
"redirect-web-to-websecure": {
|
||||
"redirectScheme": {
|
||||
"scheme": "https",
|
||||
"port": "443",
|
||||
"permanent": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"noop": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
}
|
||||
},
|
||||
"services": {
|
||||
"noop": {},
|
||||
"rest": {}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"noop": {},
|
||||
"rest": {}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package traefik
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/containous/traefik/v2/pkg/config/static"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
"github.com/containous/traefik/v2/pkg/provider"
|
||||
"github.com/containous/traefik/v2/pkg/safe"
|
||||
"github.com/containous/traefik/v2/pkg/tls"
|
||||
|
@ -43,6 +47,7 @@ func (i *Provider) createConfiguration() *dynamic.Configuration {
|
|||
Routers: make(map[string]*dynamic.Router),
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: make(map[string]*dynamic.Model),
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: make(map[string]*dynamic.TCPRouter),
|
||||
|
@ -58,10 +63,73 @@ func (i *Provider) createConfiguration() *dynamic.Configuration {
|
|||
i.pingConfiguration(cfg)
|
||||
i.restConfiguration(cfg)
|
||||
i.prometheusConfiguration(cfg)
|
||||
i.entryPointModels(cfg)
|
||||
i.redirection(cfg)
|
||||
|
||||
cfg.HTTP.Services["noop"] = &dynamic.Service{}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (i *Provider) redirection(cfg *dynamic.Configuration) {
|
||||
for name, ep := range i.staticCfg.EntryPoints {
|
||||
if ep.HTTP.Redirections == nil || ep.HTTP.Redirections.EntryPoint == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
def := ep.HTTP.Redirections
|
||||
rtName := provider.Normalize(name + "-to-" + def.EntryPoint.To)
|
||||
mdName := "redirect-" + rtName
|
||||
|
||||
rt := &dynamic.Router{
|
||||
Rule: "HostRegexp(`{host:.+}`)",
|
||||
EntryPoints: []string{name},
|
||||
Middlewares: []string{mdName},
|
||||
Service: "noop@internal",
|
||||
}
|
||||
|
||||
port, err := i.getEntryPointPort(name, def)
|
||||
if err != nil {
|
||||
log.FromContext(context.Background()).WithField(log.EntryPointName, name).Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
cfg.HTTP.Routers[rtName] = rt
|
||||
|
||||
rs := &dynamic.Middleware{
|
||||
RedirectScheme: &dynamic.RedirectScheme{
|
||||
Scheme: def.EntryPoint.Scheme,
|
||||
Port: port,
|
||||
Permanent: true,
|
||||
},
|
||||
}
|
||||
|
||||
cfg.HTTP.Middlewares[mdName] = rs
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Provider) entryPointModels(cfg *dynamic.Configuration) {
|
||||
for name, ep := range i.staticCfg.EntryPoints {
|
||||
if len(ep.HTTP.Middlewares) == 0 && ep.HTTP.TLS == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
m := &dynamic.Model{
|
||||
Middlewares: ep.HTTP.Middlewares,
|
||||
}
|
||||
|
||||
if ep.HTTP.TLS != nil {
|
||||
m.TLS = &dynamic.RouterTLSConfig{
|
||||
Options: ep.HTTP.TLS.Options,
|
||||
CertResolver: ep.HTTP.TLS.CertResolver,
|
||||
Domains: ep.HTTP.TLS.Domains,
|
||||
}
|
||||
}
|
||||
|
||||
cfg.HTTP.Models[name] = m
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Provider) apiConfiguration(cfg *dynamic.Configuration) {
|
||||
if i.staticCfg.API == nil {
|
||||
return
|
||||
|
@ -163,3 +231,18 @@ func (i *Provider) prometheusConfiguration(cfg *dynamic.Configuration) {
|
|||
|
||||
cfg.HTTP.Services["prometheus"] = &dynamic.Service{}
|
||||
}
|
||||
|
||||
func (i *Provider) getEntryPointPort(name string, def *static.Redirections) (string, error) {
|
||||
dst, ok := i.staticCfg.EntryPoints[def.EntryPoint.To]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("'to' entry point field references a non-existing entry point: %s", name)
|
||||
}
|
||||
|
||||
_, port, err := net.SplitHostPort(dst.Address)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid entry point %q address %q: %v",
|
||||
name, i.staticCfg.EntryPoints[def.EntryPoint.To].Address, err)
|
||||
}
|
||||
|
||||
return port, nil
|
||||
}
|
||||
|
|
|
@ -167,6 +167,47 @@ func Test_createConfiguration(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "models.json",
|
||||
staticCfg: static.Configuration{
|
||||
EntryPoints: map[string]*static.EntryPoint{
|
||||
"websecure": {
|
||||
HTTP: static.HTTPConfig{
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &static.TLSConfig{
|
||||
Options: "opt",
|
||||
CertResolver: "le",
|
||||
Domains: []types.Domain{
|
||||
{Main: "mainA", SANs: []string{"sanA1", "sanA2"}},
|
||||
{Main: "mainB", SANs: []string{"sanB1", "sanB2"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "redirection.json",
|
||||
staticCfg: static.Configuration{
|
||||
EntryPoints: map[string]*static.EntryPoint{
|
||||
"web": {
|
||||
Address: ":80",
|
||||
HTTP: static.HTTPConfig{
|
||||
Redirections: &static.Redirections{
|
||||
EntryPoint: &static.RedirectEntryPoint{
|
||||
To: "websecure",
|
||||
Scheme: "https",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"websecure": {
|
||||
Address: ":443",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
|
|
@ -7,12 +7,13 @@ import (
|
|||
"github.com/containous/traefik/v2/pkg/tls"
|
||||
)
|
||||
|
||||
func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configuration {
|
||||
func mergeConfiguration(configurations dynamic.Configurations, entryPoints []string) dynamic.Configuration {
|
||||
conf := dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: make(map[string]*dynamic.Router),
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: make(map[string]*dynamic.Model),
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: make(map[string]*dynamic.TCPRouter),
|
||||
|
@ -33,6 +34,13 @@ func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configura
|
|||
for pvd, configuration := range configurations {
|
||||
if configuration.HTTP != nil {
|
||||
for routerName, router := range configuration.HTTP.Routers {
|
||||
if len(router.EntryPoints) == 0 {
|
||||
log.WithoutContext().
|
||||
WithField(log.RouterName, routerName).
|
||||
Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints)
|
||||
router.EntryPoints = entryPoints
|
||||
}
|
||||
|
||||
conf.HTTP.Routers[provider.MakeQualifiedName(pvd, routerName)] = router
|
||||
}
|
||||
for middlewareName, middleware := range configuration.HTTP.Middlewares {
|
||||
|
@ -41,6 +49,9 @@ func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configura
|
|||
for serviceName, service := range configuration.HTTP.Services {
|
||||
conf.HTTP.Services[provider.MakeQualifiedName(pvd, serviceName)] = service
|
||||
}
|
||||
for modelName, model := range configuration.HTTP.Models {
|
||||
conf.HTTP.Models[provider.MakeQualifiedName(pvd, modelName)] = model
|
||||
}
|
||||
}
|
||||
|
||||
if configuration.TCP != nil {
|
||||
|
@ -101,3 +112,45 @@ func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configura
|
|||
|
||||
return conf
|
||||
}
|
||||
|
||||
func applyModel(cfg dynamic.Configuration) dynamic.Configuration {
|
||||
if cfg.HTTP == nil || len(cfg.HTTP.Models) == 0 {
|
||||
return cfg
|
||||
}
|
||||
|
||||
rts := make(map[string]*dynamic.Router)
|
||||
|
||||
for name, router := range cfg.HTTP.Routers {
|
||||
eps := router.EntryPoints
|
||||
router.EntryPoints = nil
|
||||
|
||||
for _, epName := range eps {
|
||||
m, ok := cfg.HTTP.Models[epName+"@internal"]
|
||||
if ok {
|
||||
cp := router.DeepCopy()
|
||||
|
||||
cp.EntryPoints = []string{epName}
|
||||
|
||||
if cp.TLS == nil {
|
||||
cp.TLS = m.TLS
|
||||
}
|
||||
|
||||
cp.Middlewares = append(m.Middlewares, cp.Middlewares...)
|
||||
|
||||
rtName := name
|
||||
if len(eps) > 1 {
|
||||
rtName = epName + "-" + name
|
||||
}
|
||||
rts[rtName] = cp
|
||||
} else {
|
||||
router.EntryPoints = append(router.EntryPoints, epName)
|
||||
|
||||
rts[name] = router
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg.HTTP.Routers = rts
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAggregator(t *testing.T) {
|
||||
func Test_mergeConfiguration(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
given dynamic.Configurations
|
||||
|
@ -21,6 +21,7 @@ func TestAggregator(t *testing.T) {
|
|||
Routers: make(map[string]*dynamic.Router),
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: make(map[string]*dynamic.Model),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -42,7 +43,9 @@ func TestAggregator(t *testing.T) {
|
|||
},
|
||||
expected: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"router-1@provider-1": {},
|
||||
"router-1@provider-1": {
|
||||
EntryPoints: []string{"defaultEP"},
|
||||
},
|
||||
},
|
||||
Middlewares: map[string]*dynamic.Middleware{
|
||||
"middleware-1@provider-1": {},
|
||||
|
@ -50,6 +53,7 @@ func TestAggregator(t *testing.T) {
|
|||
Services: map[string]*dynamic.Service{
|
||||
"service-1@provider-1": {},
|
||||
},
|
||||
Models: make(map[string]*dynamic.Model),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -84,8 +88,12 @@ func TestAggregator(t *testing.T) {
|
|||
},
|
||||
expected: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"router-1@provider-1": {},
|
||||
"router-1@provider-2": {},
|
||||
"router-1@provider-1": {
|
||||
EntryPoints: []string{"defaultEP"},
|
||||
},
|
||||
"router-1@provider-2": {
|
||||
EntryPoints: []string{"defaultEP"},
|
||||
},
|
||||
},
|
||||
Middlewares: map[string]*dynamic.Middleware{
|
||||
"middleware-1@provider-1": {},
|
||||
|
@ -95,6 +103,7 @@ func TestAggregator(t *testing.T) {
|
|||
"service-1@provider-1": {},
|
||||
"service-1@provider-2": {},
|
||||
},
|
||||
Models: make(map[string]*dynamic.Model),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -104,13 +113,13 @@ func TestAggregator(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
actual := mergeConfiguration(test.given)
|
||||
actual := mergeConfiguration(test.given, []string{"defaultEP"})
|
||||
assert.Equal(t, test.expected, actual.HTTP)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAggregator_tlsoptions(t *testing.T) {
|
||||
func Test_mergeConfiguration_tlsOptions(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
given dynamic.Configurations
|
||||
|
@ -289,13 +298,13 @@ func TestAggregator_tlsoptions(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
actual := mergeConfiguration(test.given)
|
||||
actual := mergeConfiguration(test.given, []string{"defaultEP"})
|
||||
assert.Equal(t, test.expected, actual.TLS.Options)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAggregator_tlsStore(t *testing.T) {
|
||||
func Test_mergeConfiguration_tlsStore(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
given dynamic.Configurations
|
||||
|
@ -381,8 +390,202 @@ func TestAggregator_tlsStore(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
actual := mergeConfiguration(test.given)
|
||||
actual := mergeConfiguration(test.given, []string{"defaultEP"})
|
||||
assert.Equal(t, test.expected, actual.TLS.Stores)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_applyModel(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
input dynamic.Configuration
|
||||
expected dynamic.Configuration
|
||||
}{
|
||||
{
|
||||
desc: "empty configuration",
|
||||
input: dynamic.Configuration{},
|
||||
expected: dynamic.Configuration{},
|
||||
},
|
||||
{
|
||||
desc: "without model",
|
||||
input: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: make(map[string]*dynamic.Router),
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: make(map[string]*dynamic.Model),
|
||||
},
|
||||
},
|
||||
expected: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: make(map[string]*dynamic.Router),
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: make(map[string]*dynamic.Model),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "with model, not used",
|
||||
input: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: make(map[string]*dynamic.Router),
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: map[string]*dynamic.Model{
|
||||
"ep@internal": {
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: make(map[string]*dynamic.Router),
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: map[string]*dynamic.Model{
|
||||
"ep@internal": {
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "with model, one entry point",
|
||||
input: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"test": {
|
||||
EntryPoints: []string{"websecure"},
|
||||
},
|
||||
},
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: map[string]*dynamic.Model{
|
||||
"websecure@internal": {
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"test": {
|
||||
EntryPoints: []string{"websecure"},
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: map[string]*dynamic.Model{
|
||||
"websecure@internal": {
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "with model, one entry point, and router with tls",
|
||||
input: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"test": {
|
||||
EntryPoints: []string{"websecure"},
|
||||
TLS: &dynamic.RouterTLSConfig{CertResolver: "router"},
|
||||
},
|
||||
},
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: map[string]*dynamic.Model{
|
||||
"websecure@internal": {
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{CertResolver: "ep"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"test": {
|
||||
EntryPoints: []string{"websecure"},
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{CertResolver: "router"},
|
||||
},
|
||||
},
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: map[string]*dynamic.Model{
|
||||
"websecure@internal": {
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{CertResolver: "ep"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "with model, two entry points",
|
||||
input: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"test": {
|
||||
EntryPoints: []string{"websecure", "web"},
|
||||
},
|
||||
},
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: map[string]*dynamic.Model{
|
||||
"websecure@internal": {
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"test": {
|
||||
EntryPoints: []string{"web"},
|
||||
},
|
||||
"websecure-test": {
|
||||
EntryPoints: []string{"websecure"},
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
Models: map[string]*dynamic.Model{
|
||||
"websecure@internal": {
|
||||
Middlewares: []string{"test"},
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
actual := applyModel(test.input)
|
||||
|
||||
assert.Equal(t, test.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ import (
|
|||
type ConfigurationWatcher struct {
|
||||
provider provider.Provider
|
||||
|
||||
entryPoints []string
|
||||
|
||||
providersThrottleDuration time.Duration
|
||||
|
||||
currentConfigurations safe.Safe
|
||||
|
@ -32,7 +34,12 @@ type ConfigurationWatcher struct {
|
|||
}
|
||||
|
||||
// NewConfigurationWatcher creates a new ConfigurationWatcher.
|
||||
func NewConfigurationWatcher(routinesPool *safe.Pool, pvd provider.Provider, providersThrottleDuration time.Duration) *ConfigurationWatcher {
|
||||
func NewConfigurationWatcher(
|
||||
routinesPool *safe.Pool,
|
||||
pvd provider.Provider,
|
||||
providersThrottleDuration time.Duration,
|
||||
entryPoints []string,
|
||||
) *ConfigurationWatcher {
|
||||
watcher := &ConfigurationWatcher{
|
||||
provider: pvd,
|
||||
configurationChan: make(chan dynamic.Message, 100),
|
||||
|
@ -40,6 +47,7 @@ func NewConfigurationWatcher(routinesPool *safe.Pool, pvd provider.Provider, pro
|
|||
providerConfigUpdateMap: make(map[string]chan dynamic.Message),
|
||||
providersThrottleDuration: providersThrottleDuration,
|
||||
routinesPool: routinesPool,
|
||||
entryPoints: entryPoints,
|
||||
}
|
||||
|
||||
currentConfigurations := make(dynamic.Configurations)
|
||||
|
@ -135,7 +143,8 @@ func (c *ConfigurationWatcher) loadMessage(configMsg dynamic.Message) {
|
|||
|
||||
c.currentConfigurations.Set(newConfigurations)
|
||||
|
||||
conf := mergeConfiguration(newConfigurations)
|
||||
conf := mergeConfiguration(newConfigurations, c.entryPoints)
|
||||
conf = applyModel(conf)
|
||||
|
||||
for _, listener := range c.configurationListeners {
|
||||
listener(conf)
|
||||
|
|
|
@ -55,7 +55,7 @@ func TestNewConfigurationWatcher(t *testing.T) {
|
|||
}},
|
||||
}
|
||||
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second)
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second, []string{})
|
||||
|
||||
run := make(chan struct{})
|
||||
|
||||
|
@ -112,7 +112,7 @@ func TestListenProvidersThrottleProviderConfigReload(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond)
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond, []string{})
|
||||
|
||||
publishedConfigCount := 0
|
||||
watcher.AddListener(func(_ dynamic.Configuration) {
|
||||
|
@ -136,7 +136,7 @@ func TestListenProvidersSkipsEmptyConfigs(t *testing.T) {
|
|||
messages: []dynamic.Message{{ProviderName: "mock"}},
|
||||
}
|
||||
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second)
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second, []string{})
|
||||
watcher.AddListener(func(_ dynamic.Configuration) {
|
||||
t.Error("An empty configuration was published but it should not")
|
||||
})
|
||||
|
@ -162,7 +162,7 @@ func TestListenProvidersSkipsSameConfigurationForProvider(t *testing.T) {
|
|||
messages: []dynamic.Message{message, message},
|
||||
}
|
||||
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, 0)
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, 0, []string{})
|
||||
|
||||
alreadyCalled := false
|
||||
watcher.AddListener(func(_ dynamic.Configuration) {
|
||||
|
@ -205,7 +205,7 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, 15*time.Millisecond)
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, 15*time.Millisecond, []string{"defaultEP"})
|
||||
|
||||
var lastConfig dynamic.Configuration
|
||||
watcher.AddListener(func(conf dynamic.Configuration) {
|
||||
|
@ -220,7 +220,7 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
|
|||
|
||||
expected := dynamic.Configuration{
|
||||
HTTP: th.BuildConfiguration(
|
||||
th.WithRouters(th.WithRouter("foo@mock")),
|
||||
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("defaultEP"))),
|
||||
th.WithLoadBalancerServices(th.WithService("bar@mock")),
|
||||
th.WithMiddlewares(),
|
||||
),
|
||||
|
@ -260,7 +260,7 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, 0)
|
||||
watcher := NewConfigurationWatcher(routinesPool, pvd, 0, []string{"defaultEP"})
|
||||
|
||||
var publishedProviderConfig dynamic.Configuration
|
||||
|
||||
|
@ -276,7 +276,10 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
|
|||
|
||||
expected := dynamic.Configuration{
|
||||
HTTP: th.BuildConfiguration(
|
||||
th.WithRouters(th.WithRouter("foo@mock"), th.WithRouter("foo@mock2")),
|
||||
th.WithRouters(
|
||||
th.WithRouter("foo@mock", th.WithEntryPoints("defaultEP")),
|
||||
th.WithRouter("foo@mock2", th.WithEntryPoints("defaultEP")),
|
||||
),
|
||||
th.WithLoadBalancerServices(th.WithService("bar@mock"), th.WithService("bar@mock2")),
|
||||
th.WithMiddlewares(),
|
||||
),
|
||||
|
|
|
@ -76,28 +76,6 @@ func TestRouterManager_Get(t *testing.T) {
|
|||
entryPoints: []string{"web"},
|
||||
expected: expectedResult{StatusCode: http.StatusNotFound},
|
||||
},
|
||||
{
|
||||
desc: "no middleware, default entry point",
|
||||
routersConfig: map[string]*dynamic.Router{
|
||||
"foo": {
|
||||
Service: "foo-service",
|
||||
Rule: "Host(`foo.bar`)",
|
||||
},
|
||||
},
|
||||
serviceConfig: map[string]*dynamic.Service{
|
||||
"foo-service": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: server.URL,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
entryPoints: []string{"web"},
|
||||
expected: expectedResult{StatusCode: http.StatusOK},
|
||||
},
|
||||
{
|
||||
desc: "no middleware, no matching",
|
||||
routersConfig: map[string]*dynamic.Router{
|
||||
|
@ -735,6 +713,14 @@ func TestRuntimeConfiguration(t *testing.T) {
|
|||
func TestProviderOnMiddlewares(t *testing.T) {
|
||||
entryPoints := []string{"web"}
|
||||
|
||||
staticCfg := static.Configuration{
|
||||
EntryPoints: map[string]*static.EntryPoint{
|
||||
"web": {
|
||||
Address: ":80",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
rtConf := runtime.NewConfig(dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Services: map[string]*dynamic.Service{
|
||||
|
@ -746,11 +732,13 @@ func TestProviderOnMiddlewares(t *testing.T) {
|
|||
},
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"router@file": {
|
||||
EntryPoints: []string{"web"},
|
||||
Rule: "Host(`test`)",
|
||||
Service: "test@file",
|
||||
Middlewares: []string{"chain@file", "m1"},
|
||||
},
|
||||
"router@docker": {
|
||||
EntryPoints: []string{"web"},
|
||||
Rule: "Host(`test`)",
|
||||
Service: "test@file",
|
||||
Middlewares: []string{"chain", "m1@file"},
|
||||
|
@ -774,7 +762,7 @@ func TestProviderOnMiddlewares(t *testing.T) {
|
|||
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil)
|
||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
|
||||
responseModifierFactory := responsemodifiers.NewBuilder(map[string]*runtime.MiddlewareInfo{})
|
||||
chainBuilder := middleware.NewChainBuilder(static.Configuration{}, nil, nil)
|
||||
chainBuilder := middleware.NewChainBuilder(staticCfg, nil, nil)
|
||||
|
||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory, chainBuilder)
|
||||
|
||||
|
|
|
@ -23,17 +23,18 @@ func TestReuseService(t *testing.T) {
|
|||
|
||||
staticConfig := static.Configuration{
|
||||
EntryPoints: map[string]*static.EntryPoint{
|
||||
"http": {},
|
||||
"web": {},
|
||||
},
|
||||
}
|
||||
|
||||
dynamicConfigs := th.BuildConfiguration(
|
||||
th.WithRouters(
|
||||
th.WithRouter("foo",
|
||||
th.WithEntryPoints("web"),
|
||||
th.WithServiceName("bar"),
|
||||
th.WithRule("Path(`/ok`)")),
|
||||
th.WithRouter("foo2",
|
||||
th.WithEntryPoints("http"),
|
||||
th.WithEntryPoints("web"),
|
||||
th.WithRule("Path(`/unauthorized`)"),
|
||||
th.WithServiceName("bar"),
|
||||
th.WithRouterMiddlewares("basicauth")),
|
||||
|
@ -56,7 +57,7 @@ func TestReuseService(t *testing.T) {
|
|||
// Test that the /ok path returns a status 200.
|
||||
responseRecorderOk := &httptest.ResponseRecorder{}
|
||||
requestOk := httptest.NewRequest(http.MethodGet, testServer.URL+"/ok", nil)
|
||||
entryPointsHandlers["http"].GetHTTPHandler().ServeHTTP(responseRecorderOk, requestOk)
|
||||
entryPointsHandlers["web"].GetHTTPHandler().ServeHTTP(responseRecorderOk, requestOk)
|
||||
|
||||
assert.Equal(t, http.StatusOK, responseRecorderOk.Result().StatusCode, "status code")
|
||||
|
||||
|
@ -64,7 +65,7 @@ func TestReuseService(t *testing.T) {
|
|||
// the basic authentication defined on the frontend.
|
||||
responseRecorderUnauthorized := &httptest.ResponseRecorder{}
|
||||
requestUnauthorized := httptest.NewRequest(http.MethodGet, testServer.URL+"/unauthorized", nil)
|
||||
entryPointsHandlers["http"].GetHTTPHandler().ServeHTTP(responseRecorderUnauthorized, requestUnauthorized)
|
||||
entryPointsHandlers["web"].GetHTTPHandler().ServeHTTP(responseRecorderUnauthorized, requestUnauthorized)
|
||||
|
||||
assert.Equal(t, http.StatusUnauthorized, responseRecorderUnauthorized.Result().StatusCode, "status code")
|
||||
}
|
||||
|
@ -83,7 +84,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||
config: func(testServerURL string) *dynamic.HTTPConfiguration {
|
||||
return th.BuildConfiguration(
|
||||
th.WithRouters(th.WithRouter("foo",
|
||||
th.WithEntryPoints("http"),
|
||||
th.WithEntryPoints("web"),
|
||||
th.WithServiceName("bar"),
|
||||
th.WithRule(routeRule)),
|
||||
),
|
||||
|
@ -106,7 +107,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||
config: func(testServerURL string) *dynamic.HTTPConfiguration {
|
||||
return th.BuildConfiguration(
|
||||
th.WithRouters(th.WithRouter("foo",
|
||||
th.WithEntryPoints("http"),
|
||||
th.WithEntryPoints("web"),
|
||||
th.WithServiceName("bar"),
|
||||
th.WithRule(routeRule)),
|
||||
),
|
||||
|
@ -120,7 +121,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||
config: func(testServerURL string) *dynamic.HTTPConfiguration {
|
||||
return th.BuildConfiguration(
|
||||
th.WithRouters(th.WithRouter("foo",
|
||||
th.WithEntryPoints("http"),
|
||||
th.WithEntryPoints("web"),
|
||||
th.WithServiceName("bar"),
|
||||
th.WithRule(routeRule)),
|
||||
),
|
||||
|
@ -136,7 +137,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||
config: func(testServerURL string) *dynamic.HTTPConfiguration {
|
||||
return th.BuildConfiguration(
|
||||
th.WithRouters(th.WithRouter("foo",
|
||||
th.WithEntryPoints("http"),
|
||||
th.WithEntryPoints("web"),
|
||||
th.WithServiceName("bar"),
|
||||
th.WithRule(routeRule)),
|
||||
),
|
||||
|
@ -150,7 +151,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||
config: func(testServerURL string) *dynamic.HTTPConfiguration {
|
||||
return th.BuildConfiguration(
|
||||
th.WithRouters(th.WithRouter("foo",
|
||||
th.WithEntryPoints("http"),
|
||||
th.WithEntryPoints("web"),
|
||||
th.WithServiceName("bar"),
|
||||
th.WithRule(routeRule)),
|
||||
),
|
||||
|
@ -176,7 +177,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||
|
||||
staticConfig := static.Configuration{
|
||||
EntryPoints: map[string]*static.EntryPoint{
|
||||
"http": {},
|
||||
"web": {},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -190,7 +191,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||
responseRecorder := &httptest.ResponseRecorder{}
|
||||
request := httptest.NewRequest(http.MethodGet, testServer.URL+requestPath, nil)
|
||||
|
||||
entryPointsHandlers["http"].GetHTTPHandler().ServeHTTP(responseRecorder, request)
|
||||
entryPointsHandlers["web"].GetHTTPHandler().ServeHTTP(responseRecorder, request)
|
||||
|
||||
assert.Equal(t, test.expectedStatusCode, responseRecorder.Result().StatusCode, "status code")
|
||||
})
|
||||
|
@ -206,13 +207,14 @@ func TestInternalServices(t *testing.T) {
|
|||
staticConfig := static.Configuration{
|
||||
API: &static.API{},
|
||||
EntryPoints: map[string]*static.EntryPoint{
|
||||
"http": {},
|
||||
"web": {},
|
||||
},
|
||||
}
|
||||
|
||||
dynamicConfigs := th.BuildConfiguration(
|
||||
th.WithRouters(
|
||||
th.WithRouter("foo",
|
||||
th.WithEntryPoints("web"),
|
||||
th.WithServiceName("api@internal"),
|
||||
th.WithRule("PathPrefix(`/api`)")),
|
||||
),
|
||||
|
@ -228,7 +230,7 @@ func TestInternalServices(t *testing.T) {
|
|||
// Test that the /ok path returns a status 200.
|
||||
responseRecorderOk := &httptest.ResponseRecorder{}
|
||||
requestOk := httptest.NewRequest(http.MethodGet, testServer.URL+"/api/rawdata", nil)
|
||||
entryPointsHandlers["http"].GetHTTPHandler().ServeHTTP(responseRecorderOk, requestOk)
|
||||
entryPointsHandlers["web"].GetHTTPHandler().ServeHTTP(responseRecorderOk, requestOk)
|
||||
|
||||
assert.Equal(t, http.StatusOK, responseRecorderOk.Result().StatusCode, "status code")
|
||||
}
|
||||
|
|
|
@ -53,6 +53,11 @@ func (m *InternalHandlers) BuildHTTP(rootCtx context.Context, serviceName string
|
|||
|
||||
func (m *InternalHandlers) get(serviceName string) (http.Handler, error) {
|
||||
switch serviceName {
|
||||
case "noop@internal":
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
|
||||
rw.WriteHeader(http.StatusTeapot)
|
||||
}), nil
|
||||
|
||||
case "api@internal":
|
||||
if m.api == nil {
|
||||
return nil, errors.New("api is not enabled")
|
||||
|
|
|
@ -6,7 +6,10 @@ import (
|
|||
|
||||
// BuildConfiguration is a helper to create a configuration.
|
||||
func BuildConfiguration(dynamicConfigBuilders ...func(*dynamic.HTTPConfiguration)) *dynamic.HTTPConfiguration {
|
||||
conf := &dynamic.HTTPConfiguration{}
|
||||
conf := &dynamic.HTTPConfiguration{
|
||||
Models: map[string]*dynamic.Model{},
|
||||
}
|
||||
|
||||
for _, build := range dynamicConfigBuilders {
|
||||
build(conf)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue