mirror of
https://github.com/containous/traefik.git
synced 2024-12-23 17:34:13 +03:00
Merge v2.4 into master
This commit is contained in:
commit
d211437d6c
@ -61,6 +61,7 @@
|
|||||||
"exhaustivestruct", # Not relevant
|
"exhaustivestruct", # Not relevant
|
||||||
"makezero", # not relevant
|
"makezero", # not relevant
|
||||||
"forbidigo", # not relevant
|
"forbidigo", # not relevant
|
||||||
|
"ifshort", # not relevant
|
||||||
]
|
]
|
||||||
|
|
||||||
[issues]
|
[issues]
|
||||||
|
30
CHANGELOG.md
30
CHANGELOG.md
@ -1,3 +1,33 @@
|
|||||||
|
## [v2.4.2](https://github.com/traefik/traefik/tree/v2.4.2) (2021-02-02)
|
||||||
|
[All Commits](https://github.com/traefik/traefik/compare/v2.4.1...v2.4.2)
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[acme]** Fix the redirect entrypoint default priority ([#7851](https://github.com/traefik/traefik/pull/7851) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[middleware]** Fix the infinite loop in forwarded header middleware. ([#7847](https://github.com/traefik/traefik/pull/7847) by [ldez](https://github.com/ldez))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- Fix the static configuration generation for environment variables ([#7849](https://github.com/traefik/traefik/pull/7849) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
|
||||||
|
## [v2.4.1](https://github.com/traefik/traefik/tree/v2.4.1) (2021-02-01)
|
||||||
|
[All Commits](https://github.com/traefik/traefik/compare/v2.4.0...v2.4.1)
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[acme,provider]** Fix HTTP challenge router unexpected delayed creation ([#7805](https://github.com/traefik/traefik/pull/7805) by [jspdown](https://github.com/jspdown))
|
||||||
|
- **[acme]** Update go-acme/lego to v4.2.0 ([#7793](https://github.com/traefik/traefik/pull/7793) by [ldez](https://github.com/ldez))
|
||||||
|
- **[api,plugins]** Fix plugin type on middleware endpoint response ([#7782](https://github.com/traefik/traefik/pull/7782) by [jspdown](https://github.com/jspdown))
|
||||||
|
- **[authentication,middleware]** Forward Proxy-Authorization header to authentication server ([#7433](https://github.com/traefik/traefik/pull/7433) by [Scapal](https://github.com/Scapal))
|
||||||
|
- **[k8s,k8s/ingress]** Add support for multiple ingress classes ([#7799](https://github.com/traefik/traefik/pull/7799) by [LandryBe](https://github.com/LandryBe))
|
||||||
|
- **[middleware]** Improve forwarded header and recovery middlewares performances ([#7783](https://github.com/traefik/traefik/pull/7783) by [juliens](https://github.com/juliens))
|
||||||
|
- **[pilot]** Reduce pressure of pilot services when errors occurs ([#7824](https://github.com/traefik/traefik/pull/7824) by [darkweaver87](https://github.com/darkweaver87))
|
||||||
|
- **[provider]** Fix aggregator test comment ([#7840](https://github.com/traefik/traefik/pull/7840) by [rtribotte](https://github.com/rtribotte))
|
||||||
|
- **[provider]** Fix servers transport not found ([#7839](https://github.com/traefik/traefik/pull/7839) by [jspdown](https://github.com/jspdown))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- **[consulcatalog]** Fix refresh interval option description in consulcatalog provider ([#7810](https://github.com/traefik/traefik/pull/7810) by [GabeL7r](https://github.com/GabeL7r))
|
||||||
|
- **[docker]** Fix missing serverstransport documentation ([#7822](https://github.com/traefik/traefik/pull/7822) by [kevinpollet](https://github.com/kevinpollet))
|
||||||
|
- **[k8s]** Fix YAML syntax in providers docs ([#7787](https://github.com/traefik/traefik/pull/7787) by [4ops](https://github.com/4ops))
|
||||||
|
- **[service]** Fix typo in server transports documentation ([#7797](https://github.com/traefik/traefik/pull/7797) by [obezuk](https://github.com/obezuk))
|
||||||
|
|
||||||
## [v2.4.0](https://github.com/traefik/traefik/tree/v2.4.0) (2021-01-19)
|
## [v2.4.0](https://github.com/traefik/traefik/tree/v2.4.0) (2021-01-19)
|
||||||
[All Commits](https://github.com/traefik/traefik/compare/v2.3.0-rc1...v2.4.0)
|
[All Commits](https://github.com/traefik/traefik/compare/v2.3.0-rc1...v2.4.0)
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ RUN mkdir -p /usr/local/bin \
|
|||||||
&& chmod +x /usr/local/bin/go-bindata
|
&& chmod +x /usr/local/bin/go-bindata
|
||||||
|
|
||||||
# Download golangci-lint binary to bin folder in $GOPATH
|
# 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.34.0
|
RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.36.0
|
||||||
|
|
||||||
# Download misspell binary to bin folder in $GOPATH
|
# 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
|
RUN curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.3.4
|
||||||
|
@ -159,6 +159,7 @@
|
|||||||
- "traefik.http.services.service01.loadbalancer.sticky.cookie.secure=true"
|
- "traefik.http.services.service01.loadbalancer.sticky.cookie.secure=true"
|
||||||
- "traefik.http.services.service01.loadbalancer.server.port=foobar"
|
- "traefik.http.services.service01.loadbalancer.server.port=foobar"
|
||||||
- "traefik.http.services.service01.loadbalancer.server.scheme=foobar"
|
- "traefik.http.services.service01.loadbalancer.server.scheme=foobar"
|
||||||
|
- "traefik.http.services.service01.loadbalancer.serverstransport=foobar"
|
||||||
- "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar"
|
- "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar"
|
||||||
- "traefik.tcp.routers.tcprouter0.rule=foobar"
|
- "traefik.tcp.routers.tcprouter0.rule=foobar"
|
||||||
- "traefik.tcp.routers.tcprouter0.service=foobar"
|
- "traefik.tcp.routers.tcprouter0.service=foobar"
|
||||||
|
@ -96,6 +96,7 @@ spec:
|
|||||||
strategy: RoundRobin
|
strategy: RoundRobin
|
||||||
- name: s2
|
- name: s2
|
||||||
port: 433
|
port: 433
|
||||||
|
serversTransport: mytransport
|
||||||
- match: PathPrefix(`/misc`)
|
- match: PathPrefix(`/misc`)
|
||||||
services:
|
services:
|
||||||
- name: s3
|
- name: s3
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
"traefik.http.middlewares.middleware10.headers.accesscontrolallowmethods": "foobar, foobar",
|
"traefik.http.middlewares.middleware10.headers.accesscontrolallowmethods": "foobar, foobar",
|
||||||
"traefik.http.middlewares.middleware10.headers.accesscontrolalloworigin": "foobar",
|
"traefik.http.middlewares.middleware10.headers.accesscontrolalloworigin": "foobar",
|
||||||
"traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlist": "foobar, foobar",
|
"traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlist": "foobar, foobar",
|
||||||
|
"traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlistregex": "foobar, foobar",
|
||||||
"traefik.http.middlewares.middleware10.headers.accesscontrolexposeheaders": "foobar, foobar",
|
"traefik.http.middlewares.middleware10.headers.accesscontrolexposeheaders": "foobar, foobar",
|
||||||
"traefik.http.middlewares.middleware10.headers.accesscontrolmaxage": "42",
|
"traefik.http.middlewares.middleware10.headers.accesscontrolmaxage": "42",
|
||||||
"traefik.http.middlewares.middleware10.headers.addvaryheader": "true",
|
"traefik.http.middlewares.middleware10.headers.addvaryheader": "true",
|
||||||
@ -120,6 +121,7 @@
|
|||||||
"traefik.http.routers.router0.priority": "42",
|
"traefik.http.routers.router0.priority": "42",
|
||||||
"traefik.http.routers.router0.rule": "foobar",
|
"traefik.http.routers.router0.rule": "foobar",
|
||||||
"traefik.http.routers.router0.service": "foobar",
|
"traefik.http.routers.router0.service": "foobar",
|
||||||
|
"traefik.http.routers.router0.tls": "true",
|
||||||
"traefik.http.routers.router0.tls.certresolver": "foobar",
|
"traefik.http.routers.router0.tls.certresolver": "foobar",
|
||||||
"traefik.http.routers.router0.tls.domains[0].main": "foobar",
|
"traefik.http.routers.router0.tls.domains[0].main": "foobar",
|
||||||
"traefik.http.routers.router0.tls.domains[0].sans": "foobar, foobar",
|
"traefik.http.routers.router0.tls.domains[0].sans": "foobar, foobar",
|
||||||
@ -131,6 +133,7 @@
|
|||||||
"traefik.http.routers.router1.priority": "42",
|
"traefik.http.routers.router1.priority": "42",
|
||||||
"traefik.http.routers.router1.rule": "foobar",
|
"traefik.http.routers.router1.rule": "foobar",
|
||||||
"traefik.http.routers.router1.service": "foobar",
|
"traefik.http.routers.router1.service": "foobar",
|
||||||
|
"traefik.http.routers.router1.tls": "true",
|
||||||
"traefik.http.routers.router1.tls.certresolver": "foobar",
|
"traefik.http.routers.router1.tls.certresolver": "foobar",
|
||||||
"traefik.http.routers.router1.tls.domains[0].main": "foobar",
|
"traefik.http.routers.router1.tls.domains[0].main": "foobar",
|
||||||
"traefik.http.routers.router1.tls.domains[0].sans": "foobar, foobar",
|
"traefik.http.routers.router1.tls.domains[0].sans": "foobar, foobar",
|
||||||
@ -156,9 +159,11 @@
|
|||||||
"traefik.http.services.service01.loadbalancer.sticky.cookie.secure": "true",
|
"traefik.http.services.service01.loadbalancer.sticky.cookie.secure": "true",
|
||||||
"traefik.http.services.service01.loadbalancer.server.port": "foobar",
|
"traefik.http.services.service01.loadbalancer.server.port": "foobar",
|
||||||
"traefik.http.services.service01.loadbalancer.server.scheme": "foobar",
|
"traefik.http.services.service01.loadbalancer.server.scheme": "foobar",
|
||||||
|
"traefik.http.services.service01.loadbalancer.serverstransport": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar",
|
"traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.rule": "foobar",
|
"traefik.tcp.routers.tcprouter0.rule": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.service": "foobar",
|
"traefik.tcp.routers.tcprouter0.service": "foobar",
|
||||||
|
"traefik.tcp.routers.tcprouter0.tls": "true",
|
||||||
"traefik.tcp.routers.tcprouter0.tls.certresolver": "foobar",
|
"traefik.tcp.routers.tcprouter0.tls.certresolver": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.tls.domains[0].main": "foobar",
|
"traefik.tcp.routers.tcprouter0.tls.domains[0].main": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.tls.domains[0].sans": "foobar, foobar",
|
"traefik.tcp.routers.tcprouter0.tls.domains[0].sans": "foobar, foobar",
|
||||||
@ -169,6 +174,7 @@
|
|||||||
"traefik.tcp.routers.tcprouter1.entrypoints": "foobar, foobar",
|
"traefik.tcp.routers.tcprouter1.entrypoints": "foobar, foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.rule": "foobar",
|
"traefik.tcp.routers.tcprouter1.rule": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.service": "foobar",
|
"traefik.tcp.routers.tcprouter1.service": "foobar",
|
||||||
|
"traefik.tcp.routers.tcprouter1.tls": "true",
|
||||||
"traefik.tcp.routers.tcprouter1.tls.certresolver": "foobar",
|
"traefik.tcp.routers.tcprouter1.tls.certresolver": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.tls.domains[0].main": "foobar",
|
"traefik.tcp.routers.tcprouter1.tls.domains[0].main": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.tls.domains[0].sans": "foobar, foobar",
|
"traefik.tcp.routers.tcprouter1.tls.domains[0].sans": "foobar, foobar",
|
||||||
|
@ -403,7 +403,7 @@ Expose containers by default. (Default: ```true```)
|
|||||||
Prefix for consul service tags. Default 'traefik' (Default: ```traefik```)
|
Prefix for consul service tags. Default 'traefik' (Default: ```traefik```)
|
||||||
|
|
||||||
`--providers.consulcatalog.refreshinterval`:
|
`--providers.consulcatalog.refreshinterval`:
|
||||||
Interval for check Consul API. Default 100ms (Default: ```15```)
|
Interval for check Consul API. Default 15s (Default: ```15```)
|
||||||
|
|
||||||
`--providers.consulcatalog.requireconsistent`:
|
`--providers.consulcatalog.requireconsistent`:
|
||||||
Forces the read to be fully consistent. (Default: ```false```)
|
Forces the read to be fully consistent. (Default: ```false```)
|
||||||
|
@ -138,10 +138,10 @@ Default certificate resolver for the routers linked to the entry point.
|
|||||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_DOMAINS`:
|
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_DOMAINS`:
|
||||||
Default TLS domains for the routers linked to the entry point.
|
Default TLS domains for the routers linked to the entry point.
|
||||||
|
|
||||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_DOMAINS[n]_MAIN`:
|
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_DOMAINS_n_MAIN`:
|
||||||
Default subject name.
|
Default subject name.
|
||||||
|
|
||||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_DOMAINS[n]_SANS`:
|
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_DOMAINS_n_SANS`:
|
||||||
Subject alternative names.
|
Subject alternative names.
|
||||||
|
|
||||||
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_OPTIONS`:
|
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_TLS_OPTIONS`:
|
||||||
@ -376,7 +376,7 @@ Expose containers by default. (Default: ```true```)
|
|||||||
Prefix for consul service tags. Default 'traefik' (Default: ```traefik```)
|
Prefix for consul service tags. Default 'traefik' (Default: ```traefik```)
|
||||||
|
|
||||||
`TRAEFIK_PROVIDERS_CONSULCATALOG_REFRESHINTERVAL`:
|
`TRAEFIK_PROVIDERS_CONSULCATALOG_REFRESHINTERVAL`:
|
||||||
Interval for check Consul API. Default 100ms (Default: ```15```)
|
Interval for check Consul API. Default 15s (Default: ```15```)
|
||||||
|
|
||||||
`TRAEFIK_PROVIDERS_CONSULCATALOG_REQUIRECONSISTENT`:
|
`TRAEFIK_PROVIDERS_CONSULCATALOG_REQUIRECONSISTENT`:
|
||||||
Forces the read to be fully consistent. (Default: ```false```)
|
Forces the read to be fully consistent. (Default: ```false```)
|
||||||
|
@ -383,6 +383,7 @@
|
|||||||
token = "foobar"
|
token = "foobar"
|
||||||
|
|
||||||
[experimental]
|
[experimental]
|
||||||
|
kubernetesGateway = true
|
||||||
[experimental.plugins]
|
[experimental.plugins]
|
||||||
[experimental.plugins.Descriptor0]
|
[experimental.plugins.Descriptor0]
|
||||||
moduleName = "foobar"
|
moduleName = "foobar"
|
||||||
|
@ -403,6 +403,7 @@ certificatesResolvers:
|
|||||||
pilot:
|
pilot:
|
||||||
token: foobar
|
token: foobar
|
||||||
experimental:
|
experimental:
|
||||||
|
kubernetesGateway: true
|
||||||
plugins:
|
plugins:
|
||||||
Descriptor0:
|
Descriptor0:
|
||||||
moduleName: foobar
|
moduleName: foobar
|
||||||
|
@ -285,6 +285,14 @@ you'd add the label `traefik.http.services.<name-of-your-choice>.loadbalancer.pa
|
|||||||
- "traefik.http.services.myservice.loadbalancer.server.scheme=http"
|
- "traefik.http.services.myservice.loadbalancer.server.scheme=http"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
??? info "`traefik.http.services.<service_name>.loadbalancer.serverstransport`"
|
||||||
|
|
||||||
|
See [serverstransport](../services/index.md#serverstransport) for more information.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- "traefik.http.services.<service_name>.loadbalancer.serverstransport=foobar"
|
||||||
|
```
|
||||||
|
|
||||||
??? info "`traefik.http.services.<service_name>.loadbalancer.passhostheader`"
|
??? info "`traefik.http.services.<service_name>.loadbalancer.passhostheader`"
|
||||||
|
|
||||||
See [pass Host header](../services/index.md#pass-host-header) for more information.
|
See [pass Host header](../services/index.md#pass-host-header) for more information.
|
||||||
|
@ -335,6 +335,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
|
|||||||
responseForwarding:
|
responseForwarding:
|
||||||
flushInterval: 1ms
|
flushInterval: 1ms
|
||||||
scheme: https
|
scheme: https
|
||||||
|
serversTransport: transport
|
||||||
sticky:
|
sticky:
|
||||||
cookie:
|
cookie:
|
||||||
httpOnly: true
|
httpOnly: true
|
||||||
|
@ -462,7 +462,7 @@ By default, `passHostHeader` is true.
|
|||||||
|
|
||||||
#### ServersTransport
|
#### ServersTransport
|
||||||
|
|
||||||
`serversTransport` allows to reference a ServersTransport configuration for the communication between Traefik and your servers.
|
`serversTransport` allows to reference a [ServersTransport](./index.md#serverstransport_1) configuration for the communication between Traefik and your servers.
|
||||||
|
|
||||||
??? example "Specify a transport -- Using the [File Provider](../../providers/file.md)"
|
??? example "Specify a transport -- Using the [File Provider](../../providers/file.md)"
|
||||||
|
|
||||||
@ -573,7 +573,7 @@ that will be set as client certificates for mTLS.
|
|||||||
http:
|
http:
|
||||||
serversTransports:
|
serversTransports:
|
||||||
mytransport:
|
mytransport:
|
||||||
certficates:
|
certificates:
|
||||||
- certFile: foo.crt
|
- certFile: foo.crt
|
||||||
keyFile: bar.crt
|
keyFile: bar.crt
|
||||||
```
|
```
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
whoami:
|
whoami:
|
||||||
image: traefik/whoami
|
image: traefik/whoami
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.route1.rule=PathPrefix(`/`)
|
- traefik.http.routers.route1.rule=PathPrefix(`/foo`)
|
||||||
- traefik.http.routers.route1.middlewares=passtls
|
- traefik.http.routers.route1.middlewares=passtls
|
||||||
- traefik.http.routers.route1.tls=true
|
- traefik.http.routers.route1.tls=true
|
||||||
- traefik.http.middlewares.passtls.passtlsclientcert.pem=true
|
- traefik.http.middlewares.passtls.passtlsclientcert.pem=true
|
||||||
|
@ -50,10 +50,10 @@ func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) {
|
|||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
defer s.killCmd(cmd)
|
defer s.killCmd(cmd)
|
||||||
|
|
||||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("PathPrefix(`/foo`)"))
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
request, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:8443", nil)
|
request, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:8443/foo", nil)
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
certificate, err := tls.LoadX509KeyPair(certPemPath, certKeyPath)
|
certificate, err := tls.LoadX509KeyPair(certPemPath, certKeyPath)
|
||||||
|
@ -64,7 +64,12 @@ THIS FILE MUST NOT BE EDITED BY HAND
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if prefix == "" {
|
||||||
|
w.writeln("`" + prefix + strings.ReplaceAll(flat.Name, "[0]", "_n") + "`: ")
|
||||||
|
} else {
|
||||||
w.writeln("`" + prefix + strings.ReplaceAll(flat.Name, "[0]", "[n]") + "`: ")
|
w.writeln("`" + prefix + strings.ReplaceAll(flat.Name, "[0]", "[n]") + "`: ")
|
||||||
|
}
|
||||||
|
|
||||||
if flat.Default == "" {
|
if flat.Default == "" {
|
||||||
w.writeln(flat.Description)
|
w.writeln(flat.Description)
|
||||||
} else {
|
} else {
|
||||||
|
@ -76,7 +76,7 @@ type RedirectEntryPoint struct {
|
|||||||
func (r *RedirectEntryPoint) SetDefaults() {
|
func (r *RedirectEntryPoint) SetDefaults() {
|
||||||
r.Scheme = "https"
|
r.Scheme = "https"
|
||||||
r.Permanent = true
|
r.Permanent = true
|
||||||
r.Priority = math.MaxInt32
|
r.Priority = math.MaxInt32 - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// TLSConfig is the default TLS configuration for all the routers associated to the concerned entry point.
|
// TLSConfig is the default TLS configuration for all the routers associated to the concerned entry point.
|
||||||
|
@ -391,12 +391,12 @@ func (d *dynamicConfig) hasServerURL(serviceName, serverURL string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCollector(metricName string, labels stdprometheus.Labels, c stdprometheus.Collector, delete func()) *collector {
|
func newCollector(metricName string, labels stdprometheus.Labels, c stdprometheus.Collector, deleteFn func()) *collector {
|
||||||
return &collector{
|
return &collector{
|
||||||
id: buildMetricID(metricName, labels),
|
id: buildMetricID(metricName, labels),
|
||||||
labels: labels,
|
labels: labels,
|
||||||
collector: c,
|
collector: c,
|
||||||
delete: delete,
|
delete: deleteFn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,9 +284,9 @@ func TestIntegrationShouldCompress(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateBytes(len int) []byte {
|
func generateBytes(length int) []byte {
|
||||||
var value []byte
|
var value []byte
|
||||||
for i := 0; i < len; i++ {
|
for i := 0; i < length; i++ {
|
||||||
value = append(value, 0x61+byte(i))
|
value = append(value, 0x61+byte(i))
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
|
@ -29,6 +29,7 @@ func TestHandler(t *testing.T) {
|
|||||||
fmt.Fprintln(w, "My error page.")
|
fmt.Fprintln(w, "My error page.")
|
||||||
}),
|
}),
|
||||||
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
||||||
|
t.Helper()
|
||||||
assert.Equal(t, http.StatusOK, recorder.Code, "HTTP status")
|
assert.Equal(t, http.StatusOK, recorder.Code, "HTTP status")
|
||||||
assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusOK))
|
assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusOK))
|
||||||
},
|
},
|
||||||
@ -41,6 +42,7 @@ func TestHandler(t *testing.T) {
|
|||||||
fmt.Fprintln(w, "My error page.")
|
fmt.Fprintln(w, "My error page.")
|
||||||
}),
|
}),
|
||||||
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
||||||
|
t.Helper()
|
||||||
assert.Equal(t, http.StatusPartialContent, recorder.Code, "HTTP status")
|
assert.Equal(t, http.StatusPartialContent, recorder.Code, "HTTP status")
|
||||||
assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusPartialContent))
|
assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusPartialContent))
|
||||||
},
|
},
|
||||||
@ -53,6 +55,7 @@ func TestHandler(t *testing.T) {
|
|||||||
fmt.Fprintln(w, "whatever, should not be called")
|
fmt.Fprintln(w, "whatever, should not be called")
|
||||||
}),
|
}),
|
||||||
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
||||||
|
t.Helper()
|
||||||
assert.Equal(t, http.StatusNotModified, recorder.Code, "HTTP status")
|
assert.Equal(t, http.StatusNotModified, recorder.Code, "HTTP status")
|
||||||
assert.Contains(t, recorder.Body.String(), "")
|
assert.Contains(t, recorder.Body.String(), "")
|
||||||
},
|
},
|
||||||
@ -65,6 +68,7 @@ func TestHandler(t *testing.T) {
|
|||||||
fmt.Fprintln(w, "My error page.")
|
fmt.Fprintln(w, "My error page.")
|
||||||
}),
|
}),
|
||||||
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
||||||
|
t.Helper()
|
||||||
assert.Equal(t, http.StatusInternalServerError, recorder.Code, "HTTP status")
|
assert.Equal(t, http.StatusInternalServerError, recorder.Code, "HTTP status")
|
||||||
assert.Contains(t, recorder.Body.String(), "My error page.")
|
assert.Contains(t, recorder.Body.String(), "My error page.")
|
||||||
assert.NotContains(t, recorder.Body.String(), "oops", "Should not return the oops page")
|
assert.NotContains(t, recorder.Body.String(), "oops", "Should not return the oops page")
|
||||||
@ -78,6 +82,7 @@ func TestHandler(t *testing.T) {
|
|||||||
fmt.Fprintln(w, "My error page.")
|
fmt.Fprintln(w, "My error page.")
|
||||||
}),
|
}),
|
||||||
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
||||||
|
t.Helper()
|
||||||
assert.Equal(t, http.StatusBadGateway, recorder.Code, "HTTP status")
|
assert.Equal(t, http.StatusBadGateway, recorder.Code, "HTTP status")
|
||||||
assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusBadGateway))
|
assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusBadGateway))
|
||||||
assert.NotContains(t, recorder.Body.String(), "Test Server", "Should return the oops page since we have not configured the 502 code")
|
assert.NotContains(t, recorder.Body.String(), "Test Server", "Should return the oops page since we have not configured the 502 code")
|
||||||
@ -95,6 +100,7 @@ func TestHandler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
||||||
|
t.Helper()
|
||||||
assert.Equal(t, http.StatusServiceUnavailable, recorder.Code, "HTTP status")
|
assert.Equal(t, http.StatusServiceUnavailable, recorder.Code, "HTTP status")
|
||||||
assert.Contains(t, recorder.Body.String(), "My 503 page.")
|
assert.Contains(t, recorder.Body.String(), "My 503 page.")
|
||||||
assert.NotContains(t, recorder.Body.String(), "oops", "Should not return the oops page")
|
assert.NotContains(t, recorder.Body.String(), "oops", "Should not return the oops page")
|
||||||
@ -112,6 +118,7 @@ func TestHandler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
||||||
|
t.Helper()
|
||||||
assert.Equal(t, http.StatusServiceUnavailable, recorder.Code, "HTTP status")
|
assert.Equal(t, http.StatusServiceUnavailable, recorder.Code, "HTTP status")
|
||||||
assert.Contains(t, recorder.Body.String(), "My 503 page.")
|
assert.Contains(t, recorder.Body.String(), "My 503 page.")
|
||||||
assert.NotContains(t, recorder.Body.String(), "oops", "Should not return the oops page")
|
assert.NotContains(t, recorder.Body.String(), "oops", "Should not return the oops page")
|
||||||
|
@ -104,9 +104,10 @@ func isWebsocketRequest(req *http.Request) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
h = h[pos:]
|
h = h[pos+1:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return containsHeader(connection, "upgrade") && containsHeader(upgrade, "websocket")
|
return containsHeader(connection, "upgrade") && containsHeader(upgrade, "websocket")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package forwardedheaders
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -299,3 +300,71 @@ func TestServeHTTP(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_isWebsocketRequest(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
connectionHeader string
|
||||||
|
upgradeHeader string
|
||||||
|
assert assert.BoolAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "connection Header multiple values middle",
|
||||||
|
connectionHeader: "foo,upgrade,bar",
|
||||||
|
upgradeHeader: "websocket",
|
||||||
|
assert: assert.True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "connection Header multiple values end",
|
||||||
|
connectionHeader: "foo,bar,upgrade",
|
||||||
|
upgradeHeader: "websocket",
|
||||||
|
assert: assert.True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "connection Header multiple values begin",
|
||||||
|
connectionHeader: "upgrade,foo,bar",
|
||||||
|
upgradeHeader: "websocket",
|
||||||
|
assert: assert.True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "connection Header no upgrade",
|
||||||
|
connectionHeader: "foo,bar",
|
||||||
|
upgradeHeader: "websocket",
|
||||||
|
assert: assert.False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "connection Header empty",
|
||||||
|
connectionHeader: "",
|
||||||
|
upgradeHeader: "websocket",
|
||||||
|
assert: assert.False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "no header values",
|
||||||
|
connectionHeader: "foo,bar",
|
||||||
|
upgradeHeader: "foo,bar",
|
||||||
|
assert: assert.False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "upgrade header multiple values",
|
||||||
|
connectionHeader: "upgrade",
|
||||||
|
upgradeHeader: "foo,bar,websocket",
|
||||||
|
assert: assert.True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
|
||||||
|
|
||||||
|
req.Header.Set(connection, test.connectionHeader)
|
||||||
|
req.Header.Set(upgrade, test.upgradeHeader)
|
||||||
|
|
||||||
|
ok := isWebsocketRequest(req)
|
||||||
|
|
||||||
|
test.assert(t, ok)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -33,6 +33,8 @@ const (
|
|||||||
pilotInstanceInfoTimer = 5 * time.Minute
|
pilotInstanceInfoTimer = 5 * time.Minute
|
||||||
pilotDynConfTimer = 12 * time.Hour
|
pilotDynConfTimer = 12 * time.Hour
|
||||||
maxElapsedTime = 4 * time.Minute
|
maxElapsedTime = 4 * time.Minute
|
||||||
|
initialInterval = 5 * time.Second
|
||||||
|
multiplier = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
type instanceInfo struct {
|
type instanceInfo struct {
|
||||||
@ -219,6 +221,8 @@ func (c *client) SendInstanceInfo(ctx context.Context, pilotMetrics []metrics.Pi
|
|||||||
func (c *client) sendDataRetryable(ctx context.Context, req *http.Request) error {
|
func (c *client) sendDataRetryable(ctx context.Context, req *http.Request) error {
|
||||||
exponentialBackOff := backoff.NewExponentialBackOff()
|
exponentialBackOff := backoff.NewExponentialBackOff()
|
||||||
exponentialBackOff.MaxElapsedTime = maxElapsedTime
|
exponentialBackOff.MaxElapsedTime = maxElapsedTime
|
||||||
|
exponentialBackOff.InitialInterval = initialInterval
|
||||||
|
exponentialBackOff.Multiplier = multiplier
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
req.Header.Set(tokenHashHeader, c.tokenHash)
|
req.Header.Set(tokenHashHeader, c.tokenHash)
|
||||||
|
@ -8,12 +8,14 @@ import (
|
|||||||
"github.com/traefik/traefik/v2/pkg/log"
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
"github.com/traefik/traefik/v2/pkg/provider"
|
"github.com/traefik/traefik/v2/pkg/provider"
|
||||||
"github.com/traefik/traefik/v2/pkg/provider/file"
|
"github.com/traefik/traefik/v2/pkg/provider/file"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/provider/traefik"
|
||||||
"github.com/traefik/traefik/v2/pkg/safe"
|
"github.com/traefik/traefik/v2/pkg/safe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProviderAggregator aggregates providers.
|
// ProviderAggregator aggregates providers.
|
||||||
type ProviderAggregator struct {
|
type ProviderAggregator struct {
|
||||||
fileProvider *file.Provider
|
internalProvider provider.Provider
|
||||||
|
fileProvider provider.Provider
|
||||||
providers []provider.Provider
|
providers []provider.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,11 +100,15 @@ func (p *ProviderAggregator) AddProvider(provider provider.Provider) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileProvider, ok := provider.(*file.Provider); ok {
|
switch provider.(type) {
|
||||||
p.fileProvider = fileProvider
|
case *file.Provider:
|
||||||
} else {
|
p.fileProvider = provider
|
||||||
|
case *traefik.Provider:
|
||||||
|
p.internalProvider = provider
|
||||||
|
default:
|
||||||
p.providers = append(p.providers, provider)
|
p.providers = append(p.providers, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,6 +119,10 @@ func (p ProviderAggregator) Init() error {
|
|||||||
|
|
||||||
// Provide calls the provide method of every providers.
|
// Provide calls the provide method of every providers.
|
||||||
func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
||||||
|
if p.internalProvider != nil {
|
||||||
|
launchProvider(configurationChan, pool, p.internalProvider)
|
||||||
|
}
|
||||||
|
|
||||||
if p.fileProvider != nil {
|
if p.fileProvider != nil {
|
||||||
launchProvider(configurationChan, pool, p.fileProvider)
|
launchProvider(configurationChan, pool, p.fileProvider)
|
||||||
}
|
}
|
||||||
@ -123,6 +133,7 @@ func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, po
|
|||||||
launchProvider(configurationChan, pool, prd)
|
launchProvider(configurationChan, pool, prd)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
79
pkg/provider/aggregator/aggregator_test.go
Normal file
79
pkg/provider/aggregator/aggregator_test.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package aggregator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/provider"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/safe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProviderAggregator_Provide(t *testing.T) {
|
||||||
|
aggregator := ProviderAggregator{
|
||||||
|
internalProvider: &providerMock{"internal"},
|
||||||
|
fileProvider: &providerMock{"file"},
|
||||||
|
providers: []provider.Provider{
|
||||||
|
&providerMock{"salad"},
|
||||||
|
&providerMock{"tomato"},
|
||||||
|
&providerMock{"onion"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgCh := make(chan dynamic.Message)
|
||||||
|
errCh := make(chan error)
|
||||||
|
pool := safe.NewPool(context.Background())
|
||||||
|
|
||||||
|
t.Cleanup(pool.Stop)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
errCh <- aggregator.Provide(cfgCh, pool)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Make sure the internal provider is always called first, followed by the file provider.
|
||||||
|
requireReceivedMessageFromProviders(t, cfgCh, []string{"internal"})
|
||||||
|
requireReceivedMessageFromProviders(t, cfgCh, []string{"file"})
|
||||||
|
|
||||||
|
// Check if all providers have been called, the order doesn't matter.
|
||||||
|
requireReceivedMessageFromProviders(t, cfgCh, []string{"salad", "tomato", "onion"})
|
||||||
|
|
||||||
|
require.NoError(t, <-errCh)
|
||||||
|
}
|
||||||
|
|
||||||
|
// requireReceivedMessageFromProviders makes sure the given providers have emitted a message on the given message channel.
|
||||||
|
// Providers order is not enforced.
|
||||||
|
func requireReceivedMessageFromProviders(t *testing.T, cfgCh <-chan dynamic.Message, names []string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var msg dynamic.Message
|
||||||
|
var receivedMessagesFrom []string
|
||||||
|
|
||||||
|
for range names {
|
||||||
|
select {
|
||||||
|
case <-time.After(10 * time.Millisecond):
|
||||||
|
case msg = <-cfgCh:
|
||||||
|
receivedMessagesFrom = append(receivedMessagesFrom, msg.ProviderName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
require.ElementsMatch(t, names, receivedMessagesFrom)
|
||||||
|
}
|
||||||
|
|
||||||
|
type providerMock struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *providerMock) Init() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *providerMock) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
||||||
|
configurationChan <- dynamic.Message{
|
||||||
|
ProviderName: p.Name,
|
||||||
|
Configuration: &dynamic.Configuration{},
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -42,7 +42,7 @@ type Provider struct {
|
|||||||
Constraints string `description:"Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container." json:"constraints,omitempty" toml:"constraints,omitempty" yaml:"constraints,omitempty" export:"true"`
|
Constraints string `description:"Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container." json:"constraints,omitempty" toml:"constraints,omitempty" yaml:"constraints,omitempty" export:"true"`
|
||||||
Endpoint *EndpointConfig `description:"Consul endpoint settings" json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty" export:"true"`
|
Endpoint *EndpointConfig `description:"Consul endpoint settings" json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty" export:"true"`
|
||||||
Prefix string `description:"Prefix for consul service tags. Default 'traefik'" json:"prefix,omitempty" toml:"prefix,omitempty" yaml:"prefix,omitempty" export:"true"`
|
Prefix string `description:"Prefix for consul service tags. Default 'traefik'" json:"prefix,omitempty" toml:"prefix,omitempty" yaml:"prefix,omitempty" export:"true"`
|
||||||
RefreshInterval ptypes.Duration `description:"Interval for check Consul API. Default 100ms" json:"refreshInterval,omitempty" toml:"refreshInterval,omitempty" yaml:"refreshInterval,omitempty" export:"true"`
|
RefreshInterval ptypes.Duration `description:"Interval for check Consul API. Default 15s" json:"refreshInterval,omitempty" toml:"refreshInterval,omitempty" yaml:"refreshInterval,omitempty" export:"true"`
|
||||||
RequireConsistent bool `description:"Forces the read to be fully consistent." json:"requireConsistent,omitempty" toml:"requireConsistent,omitempty" yaml:"requireConsistent,omitempty" export:"true"`
|
RequireConsistent bool `description:"Forces the read to be fully consistent." json:"requireConsistent,omitempty" toml:"requireConsistent,omitempty" yaml:"requireConsistent,omitempty" export:"true"`
|
||||||
Stale bool `description:"Use stale consistency for catalog reads." json:"stale,omitempty" toml:"stale,omitempty" yaml:"stale,omitempty" export:"true"`
|
Stale bool `description:"Use stale consistency for catalog reads." json:"stale,omitempty" toml:"stale,omitempty" yaml:"stale,omitempty" export:"true"`
|
||||||
Cache bool `description:"Use local agent caching for catalog reads." json:"cache,omitempty" toml:"cache,omitempty" yaml:"cache,omitempty" export:"true"`
|
Cache bool `description:"Use local agent caching for catalog reads." json:"cache,omitempty" toml:"cache,omitempty" yaml:"cache,omitempty" export:"true"`
|
||||||
|
@ -56,7 +56,7 @@ func (reh *resourceEventHandler) OnDelete(obj interface{}) {
|
|||||||
type Client interface {
|
type Client interface {
|
||||||
WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error)
|
WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error)
|
||||||
GetIngresses() []*networkingv1beta1.Ingress
|
GetIngresses() []*networkingv1beta1.Ingress
|
||||||
GetIngressClass() (*networkingv1beta1.IngressClass, error)
|
GetIngressClasses() ([]*networkingv1beta1.IngressClass, error)
|
||||||
GetService(namespace, name string) (*corev1.Service, bool, error)
|
GetService(namespace, name string) (*corev1.Service, bool, error)
|
||||||
GetSecret(namespace, name string) (*corev1.Secret, bool, error)
|
GetSecret(namespace, name string) (*corev1.Secret, bool, error)
|
||||||
GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error)
|
GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error)
|
||||||
@ -393,9 +393,9 @@ func (c *clientWrapper) GetSecret(namespace, name string) (*corev1.Secret, bool,
|
|||||||
return secret, exist, err
|
return secret, exist, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientWrapper) GetIngressClass() (*networkingv1beta1.IngressClass, error) {
|
func (c *clientWrapper) GetIngressClasses() ([]*networkingv1beta1.IngressClass, error) {
|
||||||
if c.clusterFactory == nil {
|
if c.clusterFactory == nil {
|
||||||
return nil, errors.New("failed to find ingressClass: factory not loaded")
|
return nil, errors.New("cluster factory not loaded")
|
||||||
}
|
}
|
||||||
|
|
||||||
ingressClasses, err := c.clusterFactory.Networking().V1beta1().IngressClasses().Lister().List(labels.Everything())
|
ingressClasses, err := c.clusterFactory.Networking().V1beta1().IngressClasses().Lister().List(labels.Everything())
|
||||||
@ -403,13 +403,14 @@ func (c *clientWrapper) GetIngressClass() (*networkingv1beta1.IngressClass, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ics []*networkingv1beta1.IngressClass
|
||||||
for _, ic := range ingressClasses {
|
for _, ic := range ingressClasses {
|
||||||
if ic.Spec.Controller == traefikDefaultIngressClassController {
|
if ic.Spec.Controller == traefikDefaultIngressClassController {
|
||||||
return ic, nil
|
ics = append(ics, ic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return ics, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// lookupNamespace returns the lookup namespace key for the given namespace.
|
// lookupNamespace returns the lookup namespace key for the given namespace.
|
||||||
|
@ -18,7 +18,7 @@ type clientMock struct {
|
|||||||
services []*corev1.Service
|
services []*corev1.Service
|
||||||
secrets []*corev1.Secret
|
secrets []*corev1.Secret
|
||||||
endpoints []*corev1.Endpoints
|
endpoints []*corev1.Endpoints
|
||||||
ingressClass *networkingv1beta1.IngressClass
|
ingressClasses []*networkingv1beta1.IngressClass
|
||||||
|
|
||||||
serverVersion *version.Version
|
serverVersion *version.Version
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ func newClientMock(serverVersion string, paths ...string) clientMock {
|
|||||||
}
|
}
|
||||||
c.ingresses = append(c.ingresses, ing)
|
c.ingresses = append(c.ingresses, ing)
|
||||||
case *networkingv1beta1.IngressClass:
|
case *networkingv1beta1.IngressClass:
|
||||||
c.ingressClass = o
|
c.ingressClasses = append(c.ingressClasses, o)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o))
|
panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o))
|
||||||
}
|
}
|
||||||
@ -117,8 +117,8 @@ func (c clientMock) GetSecret(namespace, name string) (*corev1.Secret, bool, err
|
|||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c clientMock) GetIngressClass() (*networkingv1beta1.IngressClass, error) {
|
func (c clientMock) GetIngressClasses() ([]*networkingv1beta1.IngressClass, error) {
|
||||||
return c.ingressClass, nil
|
return c.ingressClasses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c clientMock) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) {
|
func (c clientMock) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) {
|
||||||
|
@ -8,7 +8,7 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- name: tchouk
|
- name: tchouk
|
||||||
port: 80
|
port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Service
|
kind: Service
|
||||||
@ -21,4 +21,4 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- name: tchouk
|
- name: tchouk
|
||||||
port: 80
|
port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,7 +7,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Service
|
kind: Service
|
||||||
@ -19,4 +19,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -8,7 +8,7 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 8080
|
port: 8080
|
||||||
clusterIp: "fc00:f853:ccd:e793::1"
|
clusterIP: "fc00:f853:ccd:e793::1"
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -8,4 +8,4 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- port: 443
|
- port: 443
|
||||||
targetPort: 8443
|
targetPort: 8443
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -9,4 +9,4 @@ spec:
|
|||||||
- name: https
|
- name: https
|
||||||
protocol: ""
|
protocol: ""
|
||||||
port: 8443
|
port: 8443
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -9,4 +9,4 @@ spec:
|
|||||||
- name: https-foo
|
- name: https-foo
|
||||||
protocol: ""
|
protocol: ""
|
||||||
port: 8443
|
port: 8443
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -8,4 +8,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -17,4 +17,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -8,5 +8,5 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 80
|
port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -10,5 +10,5 @@ spec:
|
|||||||
port: 8082
|
port: 8082
|
||||||
- name: tchouk
|
- name: tchouk
|
||||||
port: 80
|
port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
|
@ -10,5 +10,5 @@ spec:
|
|||||||
port: 8082
|
port: 8082
|
||||||
- name: tchouk
|
- name: tchouk
|
||||||
port: 80
|
port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 8080
|
- port: 8080
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
type: ExternalName
|
type: ExternalName
|
||||||
externalName: traefik.wtf
|
externalName: traefik.wtf
|
||||||
|
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -10,5 +10,5 @@ spec:
|
|||||||
port: 8082
|
port: 8082
|
||||||
- name: tchouk
|
- name: tchouk
|
||||||
port: 80
|
port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Service
|
kind: Service
|
||||||
@ -19,4 +19,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 8082
|
- port: 8082
|
||||||
clusterIp: 10.1.0.1
|
clusterIP: 10.1.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -8,4 +8,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -10,5 +10,5 @@ spec:
|
|||||||
port: 8082
|
port: 8082
|
||||||
- name: tchouk
|
- name: tchouk
|
||||||
port: 80
|
port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -8,7 +8,7 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 80
|
port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -22,5 +22,5 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 80
|
port: 80
|
||||||
clusterIp: 10.0.0.2
|
clusterIP: 10.0.0.2
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
kind: Endpoints
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: service1
|
||||||
|
namespace: testing
|
||||||
|
|
||||||
|
subsets:
|
||||||
|
- addresses:
|
||||||
|
- ip: 10.10.0.1
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
@ -0,0 +1,30 @@
|
|||||||
|
kind: Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ""
|
||||||
|
namespace: testing
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik-lb
|
||||||
|
rules:
|
||||||
|
- http:
|
||||||
|
paths:
|
||||||
|
- path: /bar
|
||||||
|
backend:
|
||||||
|
serviceName: service1
|
||||||
|
servicePort: 80
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ""
|
||||||
|
namespace: testing
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik-lb2
|
||||||
|
rules:
|
||||||
|
- http:
|
||||||
|
paths:
|
||||||
|
- path: /foo
|
||||||
|
backend:
|
||||||
|
serviceName: service1
|
||||||
|
servicePort: 80
|
@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
kind: IngressClass
|
||||||
|
metadata:
|
||||||
|
name: traefik-lb2
|
||||||
|
spec:
|
||||||
|
controller: traefik.io/ingress-controller
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
kind: IngressClass
|
||||||
|
metadata:
|
||||||
|
name: traefik-lb
|
||||||
|
spec:
|
||||||
|
controller: traefik.io/ingress-controller
|
@ -0,0 +1,10 @@
|
|||||||
|
kind: Service
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: service1
|
||||||
|
namespace: testing
|
||||||
|
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
clusterIP: 10.0.0.1
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -7,4 +7,4 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
clusterIp: 10.0.0.1
|
clusterIP: 10.0.0.1
|
||||||
|
@ -190,15 +190,15 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
|||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
||||||
var ingressClass *networkingv1beta1.IngressClass
|
var ingressClasses []*networkingv1beta1.IngressClass
|
||||||
|
|
||||||
if supportsIngressClass(serverVersion) {
|
if supportsIngressClass(serverVersion) {
|
||||||
ic, err := client.GetIngressClass()
|
ics, err := client.GetIngressClasses()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.FromContext(ctx).Warnf("Failed to find an ingress class: %v", err)
|
log.FromContext(ctx).Warnf("Failed to list ingress classes: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ingressClass = ic
|
ingressClasses = ics
|
||||||
}
|
}
|
||||||
|
|
||||||
ingresses := client.GetIngresses()
|
ingresses := client.GetIngresses()
|
||||||
@ -207,7 +207,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
|||||||
for _, ingress := range ingresses {
|
for _, ingress := range ingresses {
|
||||||
ctx = log.With(ctx, log.Str("ingress", ingress.Name), log.Str("namespace", ingress.Namespace))
|
ctx = log.With(ctx, log.Str("ingress", ingress.Name), log.Str("namespace", ingress.Namespace))
|
||||||
|
|
||||||
if !p.shouldProcessIngress(p.IngressClass, ingress, ingressClass) {
|
if !p.shouldProcessIngress(ingress, ingressClasses) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,14 +351,20 @@ func (p *Provider) updateIngressStatus(ing *networkingv1beta1.Ingress, k8sClient
|
|||||||
return k8sClient.UpdateIngressStatus(ing, service.Status.LoadBalancer.Ingress)
|
return k8sClient.UpdateIngressStatus(ing, service.Status.LoadBalancer.Ingress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) shouldProcessIngress(providerIngressClass string, ingress *networkingv1beta1.Ingress, ingressClass *networkingv1beta1.IngressClass) bool {
|
func (p *Provider) shouldProcessIngress(ingress *networkingv1beta1.Ingress, ingressClasses []*networkingv1beta1.IngressClass) bool {
|
||||||
// configuration through the new kubernetes ingressClass
|
// configuration through the new kubernetes ingressClass
|
||||||
if ingress.Spec.IngressClassName != nil {
|
if ingress.Spec.IngressClassName != nil {
|
||||||
return ingressClass != nil && ingressClass.ObjectMeta.Name == *ingress.Spec.IngressClassName
|
for _, ic := range ingressClasses {
|
||||||
|
if *ingress.Spec.IngressClassName == ic.ObjectMeta.Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return providerIngressClass == ingress.Annotations[annotationKubernetesIngressClass] ||
|
return false
|
||||||
len(providerIngressClass) == 0 && ingress.Annotations[annotationKubernetesIngressClass] == traefikDefaultIngressClass
|
}
|
||||||
|
|
||||||
|
return p.IngressClass == ingress.Annotations[annotationKubernetesIngressClass] ||
|
||||||
|
len(p.IngressClass) == 0 && ingress.Annotations[annotationKubernetesIngressClass] == traefikDefaultIngressClass
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildHostRule(host string) string {
|
func buildHostRule(host string) string {
|
||||||
|
@ -1061,6 +1061,38 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "v18 Ingress with multiple ingressClasses",
|
||||||
|
serverVersion: "v1.18",
|
||||||
|
expected: &dynamic.Configuration{
|
||||||
|
TCP: &dynamic.TCPConfiguration{},
|
||||||
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
|
Routers: map[string]*dynamic.Router{
|
||||||
|
"testing-foo": {
|
||||||
|
Rule: "PathPrefix(`/foo`)",
|
||||||
|
Service: "testing-service1-80",
|
||||||
|
},
|
||||||
|
"testing-bar": {
|
||||||
|
Rule: "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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "v18 Ingress with no pathType",
|
desc: "v18 Ingress with no pathType",
|
||||||
serverVersion: "v1.18",
|
serverVersion: "v1.18",
|
||||||
|
@ -4,11 +4,11 @@ RepositoryName = "traefik"
|
|||||||
OutputType = "file"
|
OutputType = "file"
|
||||||
FileName = "traefik_changelog.md"
|
FileName = "traefik_changelog.md"
|
||||||
|
|
||||||
# example new bugfix v2.3.7
|
# example new bugfix v2.4.2
|
||||||
CurrentRef = "v2.3"
|
CurrentRef = "v2.4"
|
||||||
PreviousRef = "v2.3.6"
|
PreviousRef = "v2.4.1"
|
||||||
BaseBranch = "v2.3"
|
BaseBranch = "v2.4"
|
||||||
FutureCurrentRefName = "v2.3.7"
|
FutureCurrentRefName = "v2.4.2"
|
||||||
|
|
||||||
ThresholdPreviousRef = 10
|
ThresholdPreviousRef = 10
|
||||||
ThresholdCurrentRef = 10
|
ThresholdCurrentRef = 10
|
||||||
|
Loading…
Reference in New Issue
Block a user