diff --git a/etcdctl/README.md b/etcdctl/README.md index 12621a2b8..7b2e8df65 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -235,7 +235,8 @@ The following exit codes can be returned from etcdctl: If your etcd cluster isn't available on `http://127.0.0.1:2379` you can specify a `--peers` flag or `ETCDCTL_PEERS` environment variable. You can list one peer, -or a comma-separated list of peers. +or a comma-separated list of peers. This option is ignored if the `--discovery-srv` +option is provided. ``` ETCDCTL_PEERS="http://10.0.28.1:4002" etcdctl set my-key to-a-value @@ -244,6 +245,17 @@ etcdctl --peers http://10.0.28.1:4002 my-key to-a-value etcdctl --peers http://10.0.28.1:4002,http://10.0.28.2:4002,http://10.0.28.3:4002 etcdctl set my-key to-a-value ``` +## DNS Discovery + +If you want to discover your etcd cluster through domain SRV records you can specify +a `--discovery-srv` flag or `ETCDCTL_DISCOVERY_SRV` environment variable. This option takes +precedence over the `--peers` flag. + +``` +ETCDCTL_DISCOVERY_SRV="some-domain" etcdctl set my-key to-a-value +etcdctl --discovery-srv some-domain set my-key to-a-value +``` + ## Project Details ### Versioning diff --git a/etcdctl/command/util.go b/etcdctl/command/util.go index a6cf4aa25..2138d2973 100644 --- a/etcdctl/command/util.go +++ b/etcdctl/command/util.go @@ -75,8 +75,40 @@ func getPeersFlagValue(c *cli.Context) []string { return strings.Split(peerstr, ",") } +func getDomainDiscoveryFlagValue(c *cli.Context) ([]string, error) { + domainstr := c.GlobalString("discovery-srv") + + // Use an environment variable if nothing was supplied on the + // command line + if domainstr == "" { + domainstr = os.Getenv("ETCDCTL_DISCOVERY_SRV") + } + + // If we still don't have domain discovery, return nothing + if domainstr == "" { + return []string{}, nil + } + + discoverer := client.NewSRVDiscover() + eps, err := discoverer.Discover(domainstr) + if err != nil { + return nil, err + } + + return eps, err +} + func getEndpoints(c *cli.Context) ([]string, error) { - eps := getPeersFlagValue(c) + eps, err := getDomainDiscoveryFlagValue(c) + if err != nil { + return nil, err + } + + // If domain discovery returns no endpoints, check peer flag + if len(eps) == 0 { + eps = getPeersFlagValue(c) + } + for i, ep := range eps { u, err := url.Parse(ep) if err != nil { @@ -89,6 +121,7 @@ func getEndpoints(c *cli.Context) ([]string, error) { eps[i] = u.String() } + return eps, nil } diff --git a/etcdctl/main.go b/etcdctl/main.go index 731494062..7d0ee950d 100644 --- a/etcdctl/main.go +++ b/etcdctl/main.go @@ -31,6 +31,7 @@ func main() { cli.BoolFlag{Name: "debug", Usage: "output cURL commands which can be used to reproduce the request"}, cli.BoolFlag{Name: "no-sync", Usage: "don't synchronize cluster information before sending request"}, cli.StringFlag{Name: "output, o", Value: "simple", Usage: "output response in the given format (`simple`, `extended` or `json`)"}, + cli.StringFlag{Name: "discovery-srv, D", Usage: "domain name to query for SRV records describing cluster endpoints"}, cli.StringFlag{Name: "peers, C", Value: "", Usage: "a comma-delimited list of machine addresses in the cluster (default: \"127.0.0.1:4001,127.0.0.1:2379\")"}, cli.StringFlag{Name: "cert-file", Value: "", Usage: "identify HTTPS client using this SSL certificate file"}, cli.StringFlag{Name: "key-file", Value: "", Usage: "identify HTTPS client using this SSL key file"},