Compare commits
No commits in common. "d1e864b11eeee5aa9839004ce6fc5b2b4f6a2a84" and "2d337ab5afef2279107df672bf65872f84fd6665" have entirely different histories.
d1e864b11e
...
2d337ab5af
12 changed files with 17 additions and 527 deletions
|
@ -714,32 +714,6 @@ providers:
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
### `strictChecks`
|
|
||||||
|
|
||||||
_Optional, Default="passing,warning"_
|
|
||||||
|
|
||||||
Define which [Consul Service health checks](https://developer.hashicorp.com/consul/docs/services/usage/checks#define-initial-health-check-status) are allowed to take on traffic.
|
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
|
||||||
providers:
|
|
||||||
consulCatalog:
|
|
||||||
strictChecks:
|
|
||||||
- "passing"
|
|
||||||
- "warning"
|
|
||||||
# ...
|
|
||||||
```
|
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
|
||||||
[providers.consulCatalog]
|
|
||||||
strictChecks = ["passing", "warning"]
|
|
||||||
# ...
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash tab="CLI"
|
|
||||||
--providers.consulcatalog.strictChecks=passing,warning
|
|
||||||
# ...
|
|
||||||
```
|
|
||||||
|
|
||||||
### `watch`
|
### `watch`
|
||||||
|
|
||||||
_Optional, Default=false_
|
_Optional, Default=false_
|
||||||
|
|
|
@ -14,7 +14,7 @@ The Gateway API project is part of Kubernetes, working under SIG-NETWORK.
|
||||||
The Kubernetes Gateway provider is a Traefik implementation of the [Gateway API](https://gateway-api.sigs.k8s.io/)
|
The Kubernetes Gateway provider is a Traefik implementation of the [Gateway API](https://gateway-api.sigs.k8s.io/)
|
||||||
specifications from the Kubernetes Special Interest Groups (SIGs).
|
specifications from the Kubernetes Special Interest Groups (SIGs).
|
||||||
|
|
||||||
This provider is proposed as an experimental feature and partially supports Gateway API [v1.0.0](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.0.0) specification.
|
This provider is proposed as an experimental feature and partially supports the Gateway API [v0.4.0](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v0.4.0) specification.
|
||||||
|
|
||||||
!!! warning "Enabling The Experimental Kubernetes Gateway Provider"
|
!!! warning "Enabling The Experimental Kubernetes Gateway Provider"
|
||||||
|
|
||||||
|
|
|
@ -537,9 +537,6 @@ Name of the Traefik service in Consul Catalog (needs to be registered via the or
|
||||||
`--providers.consulcatalog.stale`:
|
`--providers.consulcatalog.stale`:
|
||||||
Use stale consistency for catalog reads. (Default: ```false```)
|
Use stale consistency for catalog reads. (Default: ```false```)
|
||||||
|
|
||||||
`--providers.consulcatalog.strictchecks`:
|
|
||||||
A list of service health statuses to allow taking traffic. (Default: ```passing, warning```)
|
|
||||||
|
|
||||||
`--providers.consulcatalog.watch`:
|
`--providers.consulcatalog.watch`:
|
||||||
Watch Consul API events. (Default: ```false```)
|
Watch Consul API events. (Default: ```false```)
|
||||||
|
|
||||||
|
|
|
@ -513,9 +513,6 @@ Name of the Traefik service in Consul Catalog (needs to be registered via the or
|
||||||
`TRAEFIK_PROVIDERS_CONSULCATALOG_STALE`:
|
`TRAEFIK_PROVIDERS_CONSULCATALOG_STALE`:
|
||||||
Use stale consistency for catalog reads. (Default: ```false```)
|
Use stale consistency for catalog reads. (Default: ```false```)
|
||||||
|
|
||||||
`TRAEFIK_PROVIDERS_CONSULCATALOG_STRICTCHECKS`:
|
|
||||||
A list of service health statuses to allow taking traffic. (Default: ```passing, warning```)
|
|
||||||
|
|
||||||
`TRAEFIK_PROVIDERS_CONSULCATALOG_WATCH`:
|
`TRAEFIK_PROVIDERS_CONSULCATALOG_WATCH`:
|
||||||
Watch Consul API events. (Default: ```false```)
|
Watch Consul API events. (Default: ```false```)
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,6 @@
|
||||||
connectByDefault = true
|
connectByDefault = true
|
||||||
serviceName = "foobar"
|
serviceName = "foobar"
|
||||||
watch = true
|
watch = true
|
||||||
strictChecks = ["foobar", "foobar"]
|
|
||||||
namespaces = ["foobar", "foobar"]
|
namespaces = ["foobar", "foobar"]
|
||||||
[providers.consulCatalog.endpoint]
|
[providers.consulCatalog.endpoint]
|
||||||
address = "foobar"
|
address = "foobar"
|
||||||
|
|
|
@ -192,9 +192,6 @@ providers:
|
||||||
connectByDefault: true
|
connectByDefault: true
|
||||||
serviceName: foobar
|
serviceName: foobar
|
||||||
watch: true
|
watch: true
|
||||||
strictChecks:
|
|
||||||
- foobar
|
|
||||||
- foobar
|
|
||||||
namespaces:
|
namespaces:
|
||||||
- foobar
|
- foobar
|
||||||
- foobar
|
- foobar
|
||||||
|
|
|
@ -5,8 +5,7 @@ description: "The Kubernetes Gateway API can be used as a provider for routing a
|
||||||
|
|
||||||
# Traefik & Kubernetes
|
# Traefik & Kubernetes
|
||||||
|
|
||||||
The Kubernetes Gateway API, The Experimental Way.
|
The Kubernetes Gateway API, The Experimental Way. {: .subtitle }
|
||||||
{: .subtitle }
|
|
||||||
|
|
||||||
## Configuration Examples
|
## Configuration Examples
|
||||||
|
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -29,7 +29,7 @@ require (
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.5
|
github.com/hashicorp/go-retryablehttp v0.7.5
|
||||||
github.com/hashicorp/go-version v1.6.0
|
github.com/hashicorp/go-version v1.6.0
|
||||||
github.com/hashicorp/nomad/api v0.0.0-20240122103822-8a4bd61caf74
|
github.com/hashicorp/nomad/api v0.0.0-20240122103822-8a4bd61caf74
|
||||||
github.com/http-wasm/http-wasm-host-go v0.6.0
|
github.com/http-wasm/http-wasm-host-go v0.5.2
|
||||||
github.com/influxdata/influxdb-client-go/v2 v2.7.0
|
github.com/influxdata/influxdb-client-go/v2 v2.7.0
|
||||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
|
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
|
||||||
github.com/klauspost/compress v1.17.2
|
github.com/klauspost/compress v1.17.2
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -598,8 +598,8 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J
|
||||||
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
|
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
|
||||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/http-wasm/http-wasm-host-go v0.6.0 h1:Vd4XvcFB3NMgWp2VLCQaiqYgLneN2lChbyN9NGoNDro=
|
github.com/http-wasm/http-wasm-host-go v0.5.2 h1:5d/QgaaJtTF+qd0goBaxJJ7tcHP9n+gQUldJ7TsTexA=
|
||||||
github.com/http-wasm/http-wasm-host-go v0.6.0/go.mod h1:zQB3w+df4hryDEqBorGyA1DwPJ86LfKIASNLFuj6CuI=
|
github.com/http-wasm/http-wasm-host-go v0.5.2/go.mod h1:zQB3w+df4hryDEqBorGyA1DwPJ86LfKIASNLFuj6CuI=
|
||||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
|
|
|
@ -132,8 +132,8 @@ func (p *Provider) keepContainer(ctx context.Context, item itemData) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !p.includesHealthStatus(item.Status) {
|
if item.Status != api.HealthPassing && item.Status != api.HealthWarning {
|
||||||
logger.Debug().Msgf("Status %q is not included in the configured strictChecks of %q", item.Status, strings.Join(p.StrictChecks, ","))
|
logger.Debug().Msg("Filtering unhealthy or starting item")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,8 +324,3 @@ func getName(i itemData) string {
|
||||||
hasher.Write([]byte(strings.Join(tags, "")))
|
hasher.Write([]byte(strings.Join(tags, "")))
|
||||||
return provider.Normalize(fmt.Sprintf("%s-%d", i.Name, hasher.Sum64()))
|
return provider.Normalize(fmt.Sprintf("%s-%d", i.Name, hasher.Sum64()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultStrictChecks returns the default healthchecks to allow an upstream to be registered a route for loadbalancers.
|
|
||||||
func defaultStrictChecks() []string {
|
|
||||||
return []string{api.HealthPassing, api.HealthWarning}
|
|
||||||
}
|
|
||||||
|
|
|
@ -287,13 +287,11 @@ func TestDefaultRule(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var config Configuration
|
|
||||||
|
|
||||||
config.SetDefaults()
|
|
||||||
config.DefaultRule = test.defaultRule
|
|
||||||
|
|
||||||
p := Provider{
|
p := Provider{
|
||||||
Configuration: config,
|
Configuration: Configuration{
|
||||||
|
ExposedByDefault: true,
|
||||||
|
DefaultRule: test.defaultRule,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Init()
|
err := p.Init()
|
||||||
|
@ -3127,15 +3125,13 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var config Configuration
|
|
||||||
|
|
||||||
config.SetDefaults()
|
|
||||||
config.DefaultRule = "Host(`{{ normalize .Name }}.traefik.wtf`)"
|
|
||||||
config.ConnectAware = test.ConnectAware
|
|
||||||
config.Constraints = test.constraints
|
|
||||||
|
|
||||||
p := Provider{
|
p := Provider{
|
||||||
Configuration: config,
|
Configuration: Configuration{
|
||||||
|
ExposedByDefault: true,
|
||||||
|
DefaultRule: "Host(`{{ normalize .Name }}.traefik.wtf`)",
|
||||||
|
ConnectAware: test.ConnectAware,
|
||||||
|
Constraints: test.constraints,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.Init()
|
err := p.Init()
|
||||||
|
@ -3210,449 +3206,3 @@ func extractNSFromProvider(providers []*Provider) []string {
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterHealthStatuses(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
desc string
|
|
||||||
items []itemData
|
|
||||||
strictChecks []string
|
|
||||||
expected *dynamic.Configuration
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
// No value passed in here, we assume the default of ["passing", "warning"]
|
|
||||||
desc: "test default strict checks",
|
|
||||||
strictChecks: defaultStrictChecks(),
|
|
||||||
items: []itemData{
|
|
||||||
{
|
|
||||||
ID: "id",
|
|
||||||
Node: "Node1",
|
|
||||||
Name: "Test1",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "80",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthPassing,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "id",
|
|
||||||
Node: "Node2",
|
|
||||||
Name: "Test2",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "81",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthWarning,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: &dynamic.Configuration{
|
|
||||||
TCP: &dynamic.TCPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.TCPRouter{},
|
|
||||||
Middlewares: map[string]*dynamic.TCPMiddleware{},
|
|
||||||
Services: map[string]*dynamic.TCPService{},
|
|
||||||
ServersTransports: map[string]*dynamic.TCPServersTransport{},
|
|
||||||
},
|
|
||||||
UDP: &dynamic.UDPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.UDPRouter{},
|
|
||||||
Services: map[string]*dynamic.UDPService{},
|
|
||||||
},
|
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.Router{
|
|
||||||
"Test1": {
|
|
||||||
Service: "Test1",
|
|
||||||
Rule: "Host(`foo.bar`)",
|
|
||||||
DefaultRule: true,
|
|
||||||
},
|
|
||||||
"Test2": {
|
|
||||||
Service: "Test2",
|
|
||||||
Rule: "Host(`foo.bar`)",
|
|
||||||
DefaultRule: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
|
||||||
Services: map[string]*dynamic.Service{
|
|
||||||
"Test1": {
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: []dynamic.Server{
|
|
||||||
{
|
|
||||||
URL: "http://127.0.0.1:80",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PassHostHeader: Bool(true),
|
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"Test2": {
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: []dynamic.Server{
|
|
||||||
{
|
|
||||||
URL: "http://127.0.0.1:81",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PassHostHeader: Bool(true),
|
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// The item's health status is not included in the default checks, do not expect any containers
|
|
||||||
desc: "test status not included",
|
|
||||||
strictChecks: defaultStrictChecks(),
|
|
||||||
items: []itemData{
|
|
||||||
{
|
|
||||||
ID: "id",
|
|
||||||
Node: "Node1",
|
|
||||||
Name: "Test",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "80",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthCritical,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: &dynamic.Configuration{
|
|
||||||
TCP: &dynamic.TCPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.TCPRouter{},
|
|
||||||
Middlewares: map[string]*dynamic.TCPMiddleware{},
|
|
||||||
Services: map[string]*dynamic.TCPService{},
|
|
||||||
ServersTransports: map[string]*dynamic.TCPServersTransport{},
|
|
||||||
},
|
|
||||||
UDP: &dynamic.UDPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.UDPRouter{},
|
|
||||||
Services: map[string]*dynamic.UDPService{},
|
|
||||||
},
|
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.Router{},
|
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
|
||||||
Services: map[string]*dynamic.Service{},
|
|
||||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Allow only "warning" status containers to be included
|
|
||||||
desc: "test only include warning",
|
|
||||||
strictChecks: []string{api.HealthWarning},
|
|
||||||
items: []itemData{
|
|
||||||
{
|
|
||||||
ID: "id",
|
|
||||||
Node: "Node1",
|
|
||||||
Name: "Test1",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "80",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthPassing,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "id2",
|
|
||||||
Node: "Node2",
|
|
||||||
Name: "Test2",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "81",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthWarning,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: &dynamic.Configuration{
|
|
||||||
TCP: &dynamic.TCPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.TCPRouter{},
|
|
||||||
Middlewares: map[string]*dynamic.TCPMiddleware{},
|
|
||||||
Services: map[string]*dynamic.TCPService{},
|
|
||||||
ServersTransports: map[string]*dynamic.TCPServersTransport{},
|
|
||||||
},
|
|
||||||
UDP: &dynamic.UDPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.UDPRouter{},
|
|
||||||
Services: map[string]*dynamic.UDPService{},
|
|
||||||
},
|
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.Router{
|
|
||||||
"Test2": {
|
|
||||||
Service: "Test2",
|
|
||||||
Rule: "Host(`foo.bar`)",
|
|
||||||
DefaultRule: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
|
||||||
Services: map[string]*dynamic.Service{
|
|
||||||
"Test2": {
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: []dynamic.Server{
|
|
||||||
{
|
|
||||||
URL: "http://127.0.0.1:81",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PassHostHeader: Bool(true),
|
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Reject "critical" health status
|
|
||||||
desc: "test critical status not included",
|
|
||||||
strictChecks: defaultStrictChecks(),
|
|
||||||
items: []itemData{
|
|
||||||
{
|
|
||||||
ID: "id",
|
|
||||||
Node: "Node1",
|
|
||||||
Name: "Test1",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "80",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthPassing,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "id2",
|
|
||||||
Node: "Node2",
|
|
||||||
Name: "Test2",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "81",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthWarning,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "id3",
|
|
||||||
Node: "Node3",
|
|
||||||
Name: "Test3",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "82",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthCritical,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: &dynamic.Configuration{
|
|
||||||
TCP: &dynamic.TCPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.TCPRouter{},
|
|
||||||
Middlewares: map[string]*dynamic.TCPMiddleware{},
|
|
||||||
Services: map[string]*dynamic.TCPService{},
|
|
||||||
ServersTransports: map[string]*dynamic.TCPServersTransport{},
|
|
||||||
},
|
|
||||||
UDP: &dynamic.UDPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.UDPRouter{},
|
|
||||||
Services: map[string]*dynamic.UDPService{},
|
|
||||||
},
|
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.Router{
|
|
||||||
"Test1": {
|
|
||||||
Service: "Test1",
|
|
||||||
Rule: "Host(`foo.bar`)",
|
|
||||||
DefaultRule: true,
|
|
||||||
},
|
|
||||||
"Test2": {
|
|
||||||
Service: "Test2",
|
|
||||||
Rule: "Host(`foo.bar`)",
|
|
||||||
DefaultRule: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
|
||||||
Services: map[string]*dynamic.Service{
|
|
||||||
"Test1": {
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: []dynamic.Server{
|
|
||||||
{
|
|
||||||
URL: "http://127.0.0.1:80",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PassHostHeader: Bool(true),
|
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"Test2": {
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: []dynamic.Server{
|
|
||||||
{
|
|
||||||
URL: "http://127.0.0.1:81",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PassHostHeader: Bool(true),
|
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// The "any" health status allows for all status types, including ones not yet directly included in Consul
|
|
||||||
desc: "test include 'any' health status",
|
|
||||||
strictChecks: []string{api.HealthAny},
|
|
||||||
items: []itemData{
|
|
||||||
{
|
|
||||||
ID: "id",
|
|
||||||
Node: "Node1",
|
|
||||||
Name: "Test1",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "80",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthPassing,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "id2",
|
|
||||||
Node: "Node2",
|
|
||||||
Name: "Test2",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "81",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthWarning,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "id3",
|
|
||||||
Node: "Node3",
|
|
||||||
Name: "Test3",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "82",
|
|
||||||
Labels: nil,
|
|
||||||
Status: api.HealthCritical,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "id4",
|
|
||||||
Node: "Node4",
|
|
||||||
Name: "Test4",
|
|
||||||
Address: "127.0.0.1",
|
|
||||||
Port: "83",
|
|
||||||
Labels: nil,
|
|
||||||
Status: "some unsupported status",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: &dynamic.Configuration{
|
|
||||||
TCP: &dynamic.TCPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.TCPRouter{},
|
|
||||||
Middlewares: map[string]*dynamic.TCPMiddleware{},
|
|
||||||
Services: map[string]*dynamic.TCPService{},
|
|
||||||
ServersTransports: map[string]*dynamic.TCPServersTransport{},
|
|
||||||
},
|
|
||||||
UDP: &dynamic.UDPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.UDPRouter{},
|
|
||||||
Services: map[string]*dynamic.UDPService{},
|
|
||||||
},
|
|
||||||
HTTP: &dynamic.HTTPConfiguration{
|
|
||||||
Routers: map[string]*dynamic.Router{
|
|
||||||
"Test1": {
|
|
||||||
Service: "Test1",
|
|
||||||
Rule: "Host(`foo.bar`)",
|
|
||||||
DefaultRule: true,
|
|
||||||
},
|
|
||||||
"Test2": {
|
|
||||||
Service: "Test2",
|
|
||||||
Rule: "Host(`foo.bar`)",
|
|
||||||
DefaultRule: true,
|
|
||||||
},
|
|
||||||
"Test3": {
|
|
||||||
Service: "Test3",
|
|
||||||
Rule: "Host(`foo.bar`)",
|
|
||||||
DefaultRule: true,
|
|
||||||
},
|
|
||||||
"Test4": {
|
|
||||||
Service: "Test4",
|
|
||||||
Rule: "Host(`foo.bar`)",
|
|
||||||
DefaultRule: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
|
||||||
Services: map[string]*dynamic.Service{
|
|
||||||
"Test1": {
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: []dynamic.Server{
|
|
||||||
{
|
|
||||||
URL: "http://127.0.0.1:80",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PassHostHeader: Bool(true),
|
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"Test2": {
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: []dynamic.Server{
|
|
||||||
{
|
|
||||||
URL: "http://127.0.0.1:81",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PassHostHeader: Bool(true),
|
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"Test3": {
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: []dynamic.Server{
|
|
||||||
{
|
|
||||||
URL: "http://127.0.0.1:82",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PassHostHeader: Bool(true),
|
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"Test4": {
|
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
||||||
Servers: []dynamic.Server{
|
|
||||||
{
|
|
||||||
URL: "http://127.0.0.1:83",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PassHostHeader: Bool(true),
|
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range testCases {
|
|
||||||
test := test
|
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
var config Configuration
|
|
||||||
|
|
||||||
config.SetDefaults()
|
|
||||||
config.DefaultRule = "Host(`foo.bar`)"
|
|
||||||
|
|
||||||
if test.strictChecks != nil {
|
|
||||||
config.StrictChecks = test.strictChecks
|
|
||||||
}
|
|
||||||
|
|
||||||
p := Provider{
|
|
||||||
Configuration: config,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := p.Init()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
for i := 0; i < len(test.items); i++ {
|
|
||||||
var err error
|
|
||||||
test.items[i].ExtraConf, err = p.getExtraConf(test.items[i].Labels)
|
|
||||||
require.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration := p.buildConfiguration(context.Background(), test.items, nil)
|
|
||||||
|
|
||||||
assert.Equal(t, test.expected, configuration)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -89,7 +88,6 @@ type Configuration struct {
|
||||||
ConnectByDefault bool `description:"Consider every service as Connect capable by default." json:"connectByDefault,omitempty" toml:"connectByDefault,omitempty" yaml:"connectByDefault,omitempty" export:"true"`
|
ConnectByDefault bool `description:"Consider every service as Connect capable by default." json:"connectByDefault,omitempty" toml:"connectByDefault,omitempty" yaml:"connectByDefault,omitempty" export:"true"`
|
||||||
ServiceName string `description:"Name of the Traefik service in Consul Catalog (needs to be registered via the orchestrator or manually)." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"`
|
ServiceName string `description:"Name of the Traefik service in Consul Catalog (needs to be registered via the orchestrator or manually)." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"`
|
||||||
Watch bool `description:"Watch Consul API events." json:"watch,omitempty" toml:"watch,omitempty" yaml:"watch,omitempty" export:"true"`
|
Watch bool `description:"Watch Consul API events." json:"watch,omitempty" toml:"watch,omitempty" yaml:"watch,omitempty" export:"true"`
|
||||||
StrictChecks []string `description:"A list of service health statuses to allow taking traffic." json:"strictChecks,omitempty" toml:"strictChecks,omitempty" yaml:"strictChecks,omitempty" export:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets the default values.
|
// SetDefaults sets the default values.
|
||||||
|
@ -100,7 +98,6 @@ func (c *Configuration) SetDefaults() {
|
||||||
c.ExposedByDefault = true
|
c.ExposedByDefault = true
|
||||||
c.DefaultRule = defaultTemplateRule
|
c.DefaultRule = defaultTemplateRule
|
||||||
c.ServiceName = "traefik"
|
c.ServiceName = "traefik"
|
||||||
c.StrictChecks = defaultStrictChecks()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provider is the Consul Catalog provider implementation.
|
// Provider is the Consul Catalog provider implementation.
|
||||||
|
@ -581,21 +578,6 @@ func (p *Provider) watchConnectTLS(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// includesHealthStatus returns true if the status passed in exists in the configured StrictChecks configuration. Statuses are case insensitive.
|
|
||||||
func (p *Provider) includesHealthStatus(status string) bool {
|
|
||||||
for _, s := range p.StrictChecks {
|
|
||||||
// If the "any" status is included, assume all health checks are included
|
|
||||||
if strings.EqualFold(s, api.HealthAny) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.EqualFold(s, status) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func createClient(namespace string, endpoint *EndpointConfig) (*api.Client, error) {
|
func createClient(namespace string, endpoint *EndpointConfig) (*api.Client, error) {
|
||||||
config := api.Config{
|
config := api.Config{
|
||||||
Address: endpoint.Address,
|
Address: endpoint.Address,
|
||||||
|
|
Loading…
Reference in a new issue