diff --git a/docs/content/ref/registry.consul.kvpath.md b/docs/content/ref/registry.consul.kvpath.md index 62223e7ac..452d9f498 100644 --- a/docs/content/ref/registry.consul.kvpath.md +++ b/docs/content/ref/registry.consul.kvpath.md @@ -8,6 +8,26 @@ The consul KV path is watched for changes which get appended to the routing table. This allows for manual overrides and weighted round-robin routes. +As of version 1.5.7 fabio will treat the kv path as a prefix and +combine the values of the key itself and all its subkeys in +alphabetical order. + +To see all updates you may want to set [`-log.routes.format`](/ref/log.routes.format/) +to `all`. + +You can modify the content of the routes with the `consul` tool or via +the [Consul API](https://www.consul.io/api/index.html): + +``` +consul put fabio/config "route add svc /maint http://5.6.7.8:5000\nroute add svc / http://1.2.3.4:5000\n" + +# fabio >= 1.5.7 supports prefix match +consul put fabio/config/maint "route add svc /maint http://5.6.7.8:5000" +consul put fabio/config/catchall "route add svc / http://1.2.3.4:5000" + +consul delete fabio/config/maint +``` + The default is registry.consul.kvpath = /fabio/config diff --git a/fabio.properties b/fabio.properties index 578d764ad..b8ce0c74b 100644 --- a/fabio.properties +++ b/fabio.properties @@ -577,7 +577,9 @@ # # The consul KV path is watched for changes which get appended to # the routing table. This allows for manual overrides and weighted -# round-robin routes. +# round-robin routes. The key itself (e.g. fabio/config) and all +# subkeys (e.g. fabio/config/foo and fabio/config/bar) are combined +# in alphabetical order. # # The default is # diff --git a/registry/consul/kv.go b/registry/consul/kv.go index af2c13942..020b4ac47 100644 --- a/registry/consul/kv.go +++ b/registry/consul/kv.go @@ -15,7 +15,7 @@ func watchKV(client *api.Client, path string, config chan string) { var lastValue string for { - value, index, err := getKV(client, path, lastIndex) + value, index, err := listKV(client, path, lastIndex) if err != nil { log.Printf("[WARN] consul: Error fetching config from %s. %v", path, err) time.Sleep(time.Second) @@ -30,6 +30,23 @@ func watchKV(client *api.Client, path string, config chan string) { } } +func listKV(client *api.Client, path string, waitIndex uint64) (string, uint64, error) { + q := &api.QueryOptions{RequireConsistent: true, WaitIndex: waitIndex} + kvpairs, meta, err := client.KV().List(path, q) + if err != nil { + return "", 0, err + } + if len(kvpairs) == 0 { + return "", meta.LastIndex, nil + } + var s []string + for _, kvpair := range kvpairs { + val := "# --- " + kvpair.Key + "\n" + strings.TrimSpace(string(kvpair.Value)) + s = append(s, val) + } + return strings.Join(s, "\n\n"), meta.LastIndex, nil +} + func getKV(client *api.Client, key string, waitIndex uint64) (string, uint64, error) { q := &api.QueryOptions{RequireConsistent: true, WaitIndex: waitIndex} kvpair, meta, err := client.KV().Get(key, q)