From 4477ef636e43fa6c8f9e45523a11377764c873df Mon Sep 17 00:00:00 2001 From: Anthony Romano Date: Mon, 28 Dec 2015 23:00:27 -0800 Subject: [PATCH] etcdctl: return exitcode 2 if can't connect to any peers --- etcdctl/command/util.go | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/etcdctl/command/util.go b/etcdctl/command/util.go index a8e6fa0a4..85a037e83 100644 --- a/etcdctl/command/util.go +++ b/etcdctl/command/util.go @@ -19,10 +19,12 @@ import ( "fmt" "io" "io/ioutil" + "net" "net/http" "net/url" "os" "strings" + "syscall" "time" "github.com/coreos/etcd/Godeps/_workspace/src/github.com/bgentry/speakeasy" @@ -211,11 +213,19 @@ func mustNewClient(c *cli.Context) client.Client { handleError(ExitServerError, err) } + if isConnectionError(err) { + handleError(ExitBadConnection, err) + } + // fail-back to try sync cluster with peer API. this is for making etcdctl work with etcd 0.4.x. // TODO: remove this when we deprecate the support for etcd 0.4. eps, serr := syncWithPeerAPI(c, ctx, hc.Endpoints()) if serr != nil { - handleError(ExitServerError, serr) + if isConnectionError(serr) { + handleError(ExitBadConnection, serr) + } else { + handleError(ExitServerError, serr) + } } err = hc.SetEndpoints(eps) if err != nil { @@ -234,6 +244,32 @@ func mustNewClient(c *cli.Context) client.Client { return hc } +func isConnectionError(err error) bool { + switch t := err.(type) { + case *client.ClusterError: + for _, cerr := range t.Errors { + if !isConnectionError(cerr) { + return false + } + } + return true + case *net.OpError: + if t.Op == "dial" || t.Op == "read" { + return true + } + return isConnectionError(t.Err) + case net.Error: + if t.Timeout() { + return true + } + case syscall.Errno: + if t == syscall.ECONNREFUSED { + return true + } + } + return false +} + func mustNewClientNoSync(c *cli.Context) client.Client { hc, err := newClient(c) if err != nil {