Merge pull request #689 from containous/carry-pr-439

Carry pr 439
This commit is contained in:
Emile Vauge 2016-09-21 15:51:43 +02:00 committed by GitHub
commit 12c1131b0c
4 changed files with 121 additions and 5 deletions

View file

@ -64,6 +64,55 @@
# defaultEntryPoints = ["http", "https"] # defaultEntryPoints = ["http", "https"]
``` ```
### Constraints
In a micro-service architecture, with a central service discovery, setting constraints limits Træfɪk scope to a smaller number of routes.
Træfɪk filters services according to service attributes/tags set in your configuration backends.
Supported backends:
- Docker
- Consul K/V
- BoltDB
- Zookeeper
- Etcd
- Consul Catalog
Supported filters:
- ```tag```
```
# Constraints definition
#
# Optional
#
# Simple matching constraint
# constraints = ["tag==api"]
# Simple mismatching constraint
# constraints = ["tag!=api"]
# Globbing
# constraints = ["tag==us-*"]
# Backend-specific constraint
# [consulCatalog]
# endpoint = 127.0.0.1:8500
# constraints = ["tag==api"]
# Multiple constraints
# - "tag==" must match with at least one tag
# - "tag!=" must match with none of tags
# constraints = ["tag!=us-*", "tag!=asia-*"]
# [consulCatalog]
# endpoint = 127.0.0.1:8500
# constraints = ["tag==api", "tag!=v*-beta"]
```
## Entrypoints definition ## Entrypoints definition
```toml ```toml
@ -834,6 +883,13 @@ prefix = "traefik"
# cert = "/etc/ssl/consul.crt" # cert = "/etc/ssl/consul.crt"
# key = "/etc/ssl/consul.key" # key = "/etc/ssl/consul.key"
# insecureskipverify = true # insecureskipverify = true
# Constraint on ConsulKV tags
#
# Optional
#
# constraints = ["tag==api", "tag==he*ld"]
# Matching with containers having a key "/traefik/backends/backend1/servers/server1/tags" equal to "api,helloworld"
``` ```
Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure. Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure.
@ -937,6 +993,13 @@ prefix = "/traefik"
# cert = "/etc/ssl/etcd.crt" # cert = "/etc/ssl/etcd.crt"
# key = "/etc/ssl/etcd.key" # key = "/etc/ssl/etcd.key"
# insecureskipverify = true # insecureskipverify = true
# Constraint on Etcd tags
#
# Optional
#
# constraints = ["tag==api", "tag==he*ld"]
# Matching with containers having a key "/traefik/backends/backend1/servers/server1/tags" equal to "api,helloworld"
``` ```
Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure. Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure.
@ -980,6 +1043,13 @@ prefix = "/traefik"
# Optional # Optional
# #
# filename = "zookeeper.tmpl" # filename = "zookeeper.tmpl"
# Constraint on Zookeeper tags
#
# Optional
#
# constraints = ["tag==api", "tag==he*ld"]
# Matching with containers having a key "/traefik/backends/backend1/servers/server1/tags" equal to "api,helloworld"
``` ```
Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure. Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure.
@ -1022,6 +1092,13 @@ prefix = "/traefik"
# Optional # Optional
# #
# filename = "boltdb.tmpl" # filename = "boltdb.tmpl"
# Constraint on BoltDB tags
#
# Optional
#
# constraints = ["tag==api", "tag==he*ld"]
# Matching with containers having a key "/traefik/backends/backend1/servers/server1/tags" equal to "api,helloworld"
``` ```
Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure. Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure.

View file

@ -225,6 +225,7 @@ And there, the same dynamic configuration in a KV Store (using `prefix = "traefi
| `/traefik/backends/backend1/servers/server1/weight` | `10` | | `/traefik/backends/backend1/servers/server1/weight` | `10` |
| `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` | | `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` |
| `/traefik/backends/backend1/servers/server2/weight` | `1` | | `/traefik/backends/backend1/servers/server2/weight` | `1` |
| `/traefik/backends/backend1/servers/server2/tags` | `api,helloworld` |
- backend 2 - backend 2
@ -237,6 +238,7 @@ And there, the same dynamic configuration in a KV Store (using `prefix = "traefi
| `/traefik/backends/backend2/servers/server1/weight` | `1` | | `/traefik/backends/backend2/servers/server1/weight` | `1` |
| `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` | | `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` |
| `/traefik/backends/backend2/servers/server2/weight` | `2` | | `/traefik/backends/backend2/servers/server2/weight` | `2` |
| `/traefik/backends/backend2/servers/server2/tags` | `web` |
- frontend 1 - frontend 1

View file

@ -83,6 +83,7 @@ func (provider *Kv) watchKv(configurationChan chan<- types.ConfigMessage, prefix
} }
func (provider *Kv) provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error { func (provider *Kv) provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints []types.Constraint) error {
provider.Constraints = append(provider.Constraints, constraints...)
operation := func() error { operation := func() error {
if _, err := provider.kvclient.Exists("qmslkjdfmqlskdjfmqlksjazçueznbvbwzlkajzebvkwjdcqmlsfj"); err != nil { if _, err := provider.kvclient.Exists("qmslkjdfmqlskdjfmqlksjazçueznbvbwzlkajzebvkwjdcqmlsfj"); err != nil {
return fmt.Errorf("Failed to test KV store connection: %v", err) return fmt.Errorf("Failed to test KV store connection: %v", err)
@ -119,8 +120,10 @@ func (provider *Kv) loadConfig() *types.Configuration {
// Allow `/traefik/alias` to superesede `provider.Prefix` // Allow `/traefik/alias` to superesede `provider.Prefix`
strings.TrimSuffix(provider.get(provider.Prefix, provider.Prefix+"/alias"), "/"), strings.TrimSuffix(provider.get(provider.Prefix, provider.Prefix+"/alias"), "/"),
} }
var KvFuncMap = template.FuncMap{ var KvFuncMap = template.FuncMap{
"List": provider.list, "List": provider.list,
"ListServers": provider.listServers,
"Get": provider.get, "Get": provider.get,
"SplitGet": provider.splitGet, "SplitGet": provider.splitGet,
"Last": provider.last, "Last": provider.last,
@ -130,6 +133,13 @@ func (provider *Kv) loadConfig() *types.Configuration {
if err != nil { if err != nil {
log.Error(err) log.Error(err)
} }
for key, frontend := range configuration.Frontends {
if _, ok := configuration.Backends[frontend.Backend]; ok == false {
delete(configuration.Frontends, key)
}
}
return configuration return configuration
} }
@ -148,6 +158,13 @@ func (provider *Kv) list(keys ...string) []string {
return fun.Values(directoryKeys).([]string) return fun.Values(directoryKeys).([]string)
} }
func (provider *Kv) listServers(backend string) []string {
serverNames := provider.list(backend, "/servers/")
return fun.Filter(func(serverName string) bool {
return provider.checkConstraints(serverName, "/tags")
}, serverNames).([]string)
}
func (provider *Kv) get(defaultValue string, keys ...string) string { func (provider *Kv) get(defaultValue string, keys ...string) string {
joinedKeys := strings.Join(keys, "") joinedKeys := strings.Join(keys, "")
keyPair, err := provider.kvclient.Get(strings.TrimPrefix(joinedKeys, "/")) keyPair, err := provider.kvclient.Get(strings.TrimPrefix(joinedKeys, "/"))
@ -178,3 +195,23 @@ func (provider *Kv) last(key string) string {
splittedKey := strings.Split(key, "/") splittedKey := strings.Split(key, "/")
return splittedKey[len(splittedKey)-1] return splittedKey[len(splittedKey)-1]
} }
func (provider *Kv) checkConstraints(keys ...string) bool {
joinedKeys := strings.Join(keys, "")
keyPair, err := provider.kvclient.Get(joinedKeys)
value := ""
if err == nil && keyPair != nil && keyPair.Value != nil {
value = string(keyPair.Value)
}
constraintTags := strings.Split(value, ",")
ok, failingConstraint := provider.MatchConstraints(constraintTags)
if ok == false {
if failingConstraint != nil {
log.Debugf("Constraint %v not matching with following tags: %v", failingConstraint.String(), value)
}
return false
}
return true
}

View file

@ -3,7 +3,7 @@
[backends]{{range $backends}} [backends]{{range $backends}}
{{$backend := .}} {{$backend := .}}
{{$servers := List $backend "/servers/" }} {{$servers := ListServers $backend }}
{{$circuitBreaker := Get "" . "/circuitbreaker/" "expression"}} {{$circuitBreaker := Get "" . "/circuitbreaker/" "expression"}}
{{with $circuitBreaker}} {{with $circuitBreaker}}