feat: add consul catalog options

This commit is contained in:
Ludovic Fernandez 2019-10-31 11:56:05 +01:00 committed by Traefiker Bot
parent 3410541a2f
commit c5ec12cd56
6 changed files with 212 additions and 111 deletions

View file

@ -39,65 +39,6 @@ See the dedicated section in [routing](../routing/providers/consul-catalog.md).
## Provider Configuration ## Provider Configuration
### `exposedByDefault`
_Optional, Default=true_
```toml tab="File (TOML)"
[providers.consulCatalog]
exposedByDefault = false
# ...
```
```yaml tab="File (YAML)"
providers:
consulCatalog:
exposedByDefault: false
# ...
```
```bash tab="CLI"
--providers.consulcatalog.exposedByDefault=false
# ...
```
Expose Consul Catalog services by default in Traefik.
If set to false, services that don't have a `traefik.enable=true` label will be ignored from the resulting routing configuration.
See also [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
### `defaultRule`
_Optional, Default=```Host(`{{ normalize .Name }}`)```_
```toml tab="File (TOML)"
[providers.consulCatalog]
defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
```yaml tab="File (YAML)"
providers:
consulCatalog:
defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
```bash tab="CLI"
--providers.consulcatalog.defaultRule="Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
The default host rule for all services.
For a given container if no routing rule was defined by a label, it is defined by this defaultRule instead.
It must be a valid [Go template](https://golang.org/pkg/text/template/),
augmented with the [sprig template functions](http://masterminds.github.io/sprig/).
The service name can be accessed as the `Name` identifier,
and the template has access to all the labels defined on this container.
This option can be overridden on a container basis with the `traefik.http.routers.Router1.rule` label.
### `refreshInterval` ### `refreshInterval`
_Optional, Default=15s_ _Optional, Default=15s_
@ -135,78 +76,88 @@ _Optional, Default=/latest_
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
providers: providers:
consulCatalog: consulCatalog:
prefix: "/test" prefix: /test
# ... # ...
``` ```
```bash tab="CLI" ```bash tab="CLI"
--providers.consulcatalog.prefix="/test" --providers.consulcatalog.prefix=/test
# ... # ...
``` ```
Prefix used for accessing the Consul service metadata. Prefix used for accessing the Consul service metadata.
### `constraints` ### `requireConsistent`
_Optional, Default=""_ _Optional, Default=false_
```toml tab="File (TOML)" ```toml tab="File (TOML)"
[providers.consulCatalog] [providers.consulCatalog]
constraints = "Label(`a.label.name`, `foo`)" requireConsistent = true
# ... # ...
``` ```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
providers: providers:
consulCatalog: consulCatalog:
constraints: "Label(`a.label.name`, `foo`)" requireConsistent: true
# ... # ...
``` ```
```bash tab="CLI" ```bash tab="CLI"
--providers.consulcatalog.constraints="Label(`a.label.name`, `foo`)" --providers.consulcatalog.requireConsistent=true
# ... # ...
``` ```
Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container. Forces the read to be fully consistent.
That is to say, if none of the container's labels match the expression, no route for the container is created.
If the expression is empty, all detected containers are included.
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as the usual boolean logic, as shown in examples below. ### `stale`
??? example "Constraints Expression Examples" _Optional, Default=false_
```toml ```toml tab="File (TOML)"
# Includes only containers having a label with key `a.label.name` and value `foo` [providers.consulCatalog]
constraints = "Label(`a.label.name`, `foo`)" stale = true
``` # ...
```
```toml
# Excludes containers having any label with key `a.label.name` and value `foo`
constraints = "!Label(`a.label.name`, `value`)"
```
```toml
# With logical AND.
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
```
```toml
# With logical OR.
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
```
```toml
# With logical AND and OR, with precedence set by parentheses.
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
```
```toml
# Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
constraints = "LabelRegex(`a.label.name`, `a.+`)"
```
See also [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery). ```yaml tab="File (YAML)"
providers:
consulCatalog:
stale: true
# ...
```
```bash tab="CLI"
--providers.consulcatalog.stale=true
# ...
```
Use stale consistency for catalog reads.
### `cache`
_Optional, Default=false_
```toml tab="File (TOML)"
[providers.consulCatalog]
cache = true
# ...
```
```yaml tab="File (YAML)"
providers:
consulCatalog:
cache: true
# ...
```
```bash tab="CLI"
--providers.consulcatalog.cache=true
# ...
```
Use local agent caching for catalog reads.
### `endpoint` ### `endpoint`
@ -529,3 +480,124 @@ providers:
``` ```
If `insecureSkipVerify` is `true`, TLS for the connection to Consul server accepts any certificate presented by the server and any host name in that certificate. If `insecureSkipVerify` is `true`, TLS for the connection to Consul server accepts any certificate presented by the server and any host name in that certificate.
### `exposedByDefault`
_Optional, Default=true_
```toml tab="File (TOML)"
[providers.consulCatalog]
exposedByDefault = false
# ...
```
```yaml tab="File (YAML)"
providers:
consulCatalog:
exposedByDefault: false
# ...
```
```bash tab="CLI"
--providers.consulcatalog.exposedByDefault=false
# ...
```
Expose Consul Catalog services by default in Traefik.
If set to false, services that don't have a `traefik.enable=true` label will be ignored from the resulting routing configuration.
See also [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
### `defaultRule`
_Optional, Default=```Host(`{{ normalize .Name }}`)```_
```toml tab="File (TOML)"
[providers.consulCatalog]
defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
```yaml tab="File (YAML)"
providers:
consulCatalog:
defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
```bash tab="CLI"
--providers.consulcatalog.defaultRule="Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
The default host rule for all services.
For a given container if no routing rule was defined by a label, it is defined by this defaultRule instead.
It must be a valid [Go template](https://golang.org/pkg/text/template/),
augmented with the [sprig template functions](http://masterminds.github.io/sprig/).
The service name can be accessed as the `Name` identifier,
and the template has access to all the labels defined on this container.
This option can be overridden on a container basis with the `traefik.http.routers.Router1.rule` label.
### `constraints`
_Optional, Default=""_
```toml tab="File (TOML)"
[providers.consulCatalog]
constraints = "Label(`a.label.name`, `foo`)"
# ...
```
```yaml tab="File (YAML)"
providers:
consulCatalog:
constraints: "Label(`a.label.name`, `foo`)"
# ...
```
```bash tab="CLI"
--providers.consulcatalog.constraints="Label(`a.label.name`, `foo`)"
# ...
```
Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container.
That is to say, if none of the container's labels match the expression, no route for the container is created.
If the expression is empty, all detected containers are included.
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as the usual boolean logic, as shown in examples below.
??? example "Constraints Expression Examples"
```toml
# Includes only containers having a label with key `a.label.name` and value `foo`
constraints = "Label(`a.label.name`, `foo`)"
```
```toml
# Excludes containers having any label with key `a.label.name` and value `foo`
constraints = "!Label(`a.label.name`, `value`)"
```
```toml
# With logical AND.
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
```
```toml
# With logical OR.
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
```
```toml
# With logical AND and OR, with precedence set by parentheses.
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
```
```toml
# Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
constraints = "LabelRegex(`a.label.name`, `a.+`)"
```
See also [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).

View file

@ -234,6 +234,9 @@ Enable ping. (Default: ```false```)
`--ping.entrypoint`: `--ping.entrypoint`:
EntryPoint (Default: ```traefik```) EntryPoint (Default: ```traefik```)
`--providers.consulcatalog.cache`:
Use local agent caching for catalog reads. (Default: ```false```)
`--providers.consulcatalog.constraints`: `--providers.consulcatalog.constraints`:
Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container. Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container.
@ -285,6 +288,12 @@ 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 100ms (Default: ```15```)
`--providers.consulcatalog.requireconsistent`:
Forces the read to be fully consistent. (Default: ```false```)
`--providers.consulcatalog.stale`:
Use stale consistency for catalog reads. (Default: ```false```)
`--providers.docker`: `--providers.docker`:
Enable Docker backend with default settings. (Default: ```false```) Enable Docker backend with default settings. (Default: ```false```)

View file

@ -234,6 +234,9 @@ Enable ping. (Default: ```false```)
`TRAEFIK_PING_ENTRYPOINT`: `TRAEFIK_PING_ENTRYPOINT`:
EntryPoint (Default: ```traefik```) EntryPoint (Default: ```traefik```)
`TRAEFIK_PROVIDERS_CONSULCATALOG_CACHE`:
Use local agent caching for catalog reads. (Default: ```false```)
`TRAEFIK_PROVIDERS_CONSULCATALOG_CONSTRAINTS`: `TRAEFIK_PROVIDERS_CONSULCATALOG_CONSTRAINTS`:
Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container. Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container.
@ -285,6 +288,12 @@ 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 100ms (Default: ```15```)
`TRAEFIK_PROVIDERS_CONSULCATALOG_REQUIRECONSISTENT`:
Forces the read to be fully consistent. (Default: ```false```)
`TRAEFIK_PROVIDERS_CONSULCATALOG_STALE`:
Use stale consistency for catalog reads. (Default: ```false```)
`TRAEFIK_PROVIDERS_DOCKER`: `TRAEFIK_PROVIDERS_DOCKER`:
Enable Docker backend with default settings. (Default: ```false```) Enable Docker backend with default settings. (Default: ```false```)

View file

@ -114,6 +114,9 @@
defaultRule = "foobar" defaultRule = "foobar"
exposedByDefault = true exposedByDefault = true
refreshInterval = 15 refreshInterval = 15
requireConsistent = true
stale = true
cache = true
[providers.consulCatalog.endpoint] [providers.consulCatalog.endpoint]
address = "foobar" address = "foobar"
scheme = "foobar" scheme = "foobar"

View file

@ -121,6 +121,9 @@ providers:
defaultRule: foobar defaultRule: foobar
exposedByDefault: true exposedByDefault: true
refreshInterval: 15 refreshInterval: 15
requireConsistent: true
stale: true
cache: true
endpoint: endpoint:
address: foobar address: foobar
scheme: foobar scheme: foobar

View file

@ -34,12 +34,15 @@ type itemData struct {
// Provider holds configurations of the provider. // Provider holds configurations of the provider.
type Provider struct { 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 types.Duration `description:"Interval for check Consul API. Default 100ms" json:"refreshInterval,omitempty" toml:"refreshInterval,omitempty" yaml:"refreshInterval,omitempty" export:"true"` RefreshInterval types.Duration `description:"Interval for check Consul API. Default 100ms" json:"refreshInterval,omitempty" toml:"refreshInterval,omitempty" yaml:"refreshInterval,omitempty" export:"true"`
ExposedByDefault bool `description:"Expose containers by default." json:"exposedByDefault,omitempty" toml:"exposedByDefault,omitempty" yaml:"exposedByDefault,omitempty" export:"true"` RequireConsistent bool `description:"Forces the read to be fully consistent." json:"requireConsistent,omitempty" toml:"requireConsistent,omitempty" yaml:"requireConsistent,omitempty" export:"true"`
DefaultRule string `description:"Default rule." json:"defaultRule,omitempty" toml:"defaultRule,omitempty" yaml:"defaultRule,omitempty"` 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"`
ExposedByDefault bool `description:"Expose containers by default." json:"exposedByDefault,omitempty" toml:"exposedByDefault,omitempty" yaml:"exposedByDefault,omitempty" export:"true"`
DefaultRule string `description:"Default rule." json:"defaultRule,omitempty" toml:"defaultRule,omitempty" yaml:"defaultRule,omitempty"`
client *api.Client client *api.Client
defaultRuleTpl *template.Template defaultRuleTpl *template.Template
@ -110,7 +113,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
case <-ticker.C: case <-ticker.C:
data, err := p.getConsulServicesData(routineCtx) data, err := p.getConsulServicesData(routineCtx)
if err != nil { if err != nil {
logger.Errorf("error get consulCatalog data, %v", err) logger.Errorf("error get consul catalog data, %v", err)
return err return err
} }
@ -132,7 +135,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.
err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxLog), notify) err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxLog), notify)
if err != nil { if err != nil {
logger.Errorf("Cannot connect to consulcatalog server %+v", err) logger.Errorf("Cannot connect to consul catalog server %+v", err)
} }
}) })
@ -182,12 +185,14 @@ func (p *Provider) fetchService(ctx context.Context, name string) ([]*api.Catalo
tagFilter = p.Prefix + ".enable=true" tagFilter = p.Prefix + ".enable=true"
} }
consulServices, _, err := p.client.Catalog().Service(name, tagFilter, &api.QueryOptions{}) opts := &api.QueryOptions{AllowStale: p.Stale, RequireConsistent: p.RequireConsistent, UseCache: p.Cache}
consulServices, _, err := p.client.Catalog().Service(name, tagFilter, opts)
return consulServices, err return consulServices, err
} }
func (p *Provider) fetchServices(ctx context.Context) (map[string][]string, error) { func (p *Provider) fetchServices(ctx context.Context) (map[string][]string, error) {
serviceNames, _, err := p.client.Catalog().Services(&api.QueryOptions{}) opts := &api.QueryOptions{AllowStale: p.Stale, RequireConsistent: p.RequireConsistent, UseCache: p.Cache}
serviceNames, _, err := p.client.Catalog().Services(opts)
return serviceNames, err return serviceNames, err
} }