etcd: Allow disabling sync for load balanced etcd

Some etcd configurations (such as that provided by compose.io) place the
etcd cluster behind multiple load balancers or proxies.  In this
configuration, calling Sync (or AutoSync) on the etcd client will
replace the load balancer addresses with the underlying etcd server
address.

This will cause the etcd client to bypass the load balancers, and may
cause the connection to fail completely if the etcd servers are
protected by a firewall.

This patch provides a "sync" option for the etcd backend, which defaults
to the current behavior, but which can be used to turn off of sync.
This corresponds to etcdctl's --no-sync option.
This commit is contained in:
Eric Kidd 2016-01-11 13:56:58 -05:00
parent ebabcd857a
commit 69434fd13e
2 changed files with 27 additions and 5 deletions

View File

@ -6,6 +6,7 @@ import (
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -43,6 +44,7 @@ const (
) )
var ( var (
EtcdSyncConfigError = errors.New("client setup failed: unable to parse etcd sync field in config")
EtcdSyncClusterError = errors.New("client setup failed: unable to sync etcd cluster") EtcdSyncClusterError = errors.New("client setup failed: unable to sync etcd cluster")
EtcdAddressError = errors.New("client setup failed: address must be valid URL (ex. 'scheme://host:port')") EtcdAddressError = errors.New("client setup failed: address must be valid URL (ex. 'scheme://host:port')")
EtcdSemaphoreKeysEmptyError = errors.New("lock queue is empty") EtcdSemaphoreKeysEmptyError = errors.New("lock queue is empty")
@ -143,11 +145,25 @@ func newEtcdBackend(conf map[string]string) (Backend, error) {
return nil, err return nil, err
} }
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout) // Should we sync the cluster state? There are three available options
syncErr := c.Sync(ctx) // for our client library: don't sync (required for some proxies), sync
cancel() // once, or sync periodically with AutoSync. We currently support the
if syncErr != nil { // first two.
return nil, EtcdSyncClusterError sync := true
if v, ok := conf["sync"]; ok {
parsed, err := strconv.ParseBool(v)
if err != nil {
return nil, EtcdSyncConfigError
}
sync = parsed
}
if sync {
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
syncErr := c.Sync(ctx)
cancel()
if syncErr != nil {
return nil, EtcdSyncClusterError
}
} }
kAPI := client.NewKeysAPI(c) kAPI := client.NewKeysAPI(c)

View File

@ -221,6 +221,12 @@ For etcd, the following options are supported:
Can be comma separated list (protocol://host:port) of many etcd instances. Can be comma separated list (protocol://host:port) of many etcd instances.
Defaults to "http://localhost:2379" if not specified. Defaults to "http://localhost:2379" if not specified.
* `sync` (optional) - Should we synchronize the list of available etcd
servers on startup? This will parse as a boolean value, and can be set
to "0", "no", "false", "1", "yes", or "true". Defaults to true. Set
to false if your etcd cluster is behind a proxy server and syncing
causes Vault to fail.
* `username` (optional) - Username to use when authenticating with the etcd * `username` (optional) - Username to use when authenticating with the etcd
server. May also be specified via the ETCD_USERNAME environment variable. server. May also be specified via the ETCD_USERNAME environment variable.