etcdctl: return exitcode 2 if can't connect to any peers
This commit is contained in:
@ -19,10 +19,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/bgentry/speakeasy"
|
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/bgentry/speakeasy"
|
||||||
@ -211,12 +213,20 @@ func mustNewClient(c *cli.Context) client.Client {
|
|||||||
handleError(ExitServerError, err)
|
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.
|
// 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.
|
// TODO: remove this when we deprecate the support for etcd 0.4.
|
||||||
eps, serr := syncWithPeerAPI(c, ctx, hc.Endpoints())
|
eps, serr := syncWithPeerAPI(c, ctx, hc.Endpoints())
|
||||||
if serr != nil {
|
if serr != nil {
|
||||||
|
if isConnectionError(serr) {
|
||||||
|
handleError(ExitBadConnection, serr)
|
||||||
|
} else {
|
||||||
handleError(ExitServerError, serr)
|
handleError(ExitServerError, serr)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
err = hc.SetEndpoints(eps)
|
err = hc.SetEndpoints(eps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleError(ExitServerError, err)
|
handleError(ExitServerError, err)
|
||||||
@ -234,6 +244,32 @@ func mustNewClient(c *cli.Context) client.Client {
|
|||||||
return hc
|
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 {
|
func mustNewClientNoSync(c *cli.Context) client.Client {
|
||||||
hc, err := newClient(c)
|
hc, err := newClient(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Reference in New Issue
Block a user