Browse Source

Merge pull request #15370 from cpuguy83/better_error_on_client_connect

Better/more specific error messages on connect
David Calavera 10 years ago
parent
commit
0262d40ba7
3 changed files with 31 additions and 8 deletions
  1. 8 7
      api/client/utils.go
  2. 21 0
      api/types/errors.go
  3. 2 1
      registry/session.go

+ 8 - 7
api/client/utils.go

@@ -30,7 +30,7 @@ import (
 )
 
 var (
-	errConnectionRefused = errors.New("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
+	errConnectionFailed = errors.New("Cannot connect to the Docker daemon. Is the docker daemon running on this host?")
 )
 
 type serverResponse struct {
@@ -94,13 +94,14 @@ func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers m
 	if resp != nil {
 		serverResp.statusCode = resp.StatusCode
 	}
+
 	if err != nil {
-		if strings.Contains(err.Error(), "connection refused") {
-			return serverResp, errConnectionRefused
+		if types.IsTimeout(err) || strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") {
+			return serverResp, errConnectionFailed
 		}
 
-		if cli.tlsConfig == nil {
-			return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?\n* Is your docker daemon up and running?", err)
+		if cli.tlsConfig == nil && strings.Contains(err.Error(), "malformed HTTP response") {
+			return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
 		}
 		if cli.tlsConfig != nil && strings.Contains(err.Error(), "remote error: bad certificate") {
 			return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err)
@@ -280,7 +281,7 @@ func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
 	serverResp, err := cli.call("GET", "/containers/"+containerID+"/json", nil, nil)
 	if err != nil {
 		// If we can't connect, then the daemon probably died.
-		if err != errConnectionRefused {
+		if err != errConnectionFailed {
 			return false, -1, err
 		}
 		return false, -1, nil
@@ -302,7 +303,7 @@ func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
 	serverResp, err := cli.call("GET", "/exec/"+execID+"/json", nil, nil)
 	if err != nil {
 		// If we can't connect, then the daemon probably died.
-		if err != errConnectionRefused {
+		if err != errConnectionFailed {
 			return false, -1, err
 		}
 		return false, -1, nil

+ 21 - 0
api/types/errors.go

@@ -0,0 +1,21 @@
+package types
+
+import (
+	"net"
+	"net/url"
+)
+
+// IsTimeout takes an error returned from (generally) the http package and determines if it is a timeout error.
+func IsTimeout(err error) bool {
+	switch e := err.(type) {
+	case net.Error:
+		return e.Timeout()
+	case *url.Error:
+		if t, ok := e.Err.(net.Error); ok {
+			return t.Timeout()
+		}
+		return false
+	default:
+		return false
+	}
+}

+ 2 - 1
registry/session.go

@@ -20,6 +20,7 @@ import (
 	"time"
 
 	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/cliconfig"
 	"github.com/docker/docker/pkg/httputils"
 	"github.com/docker/docker/pkg/ioutils"
@@ -424,7 +425,7 @@ func (r *Session) GetRepositoryData(remote string) (*RepositoryData, error) {
 		// and return a non-obtuse error message for users
 		// "Get https://index.docker.io/v1/repositories/library/busybox/images: i/o timeout"
 		// was a top search on the docker user forum
-		if strings.HasSuffix(err.Error(), "i/o timeout") {
+		if types.IsTimeout(err) {
 			return nil, fmt.Errorf("Network timed out while trying to connect to %s. You may want to check your internet connection or if you are behind a proxy.", repositoryTarget)
 		}
 		return nil, fmt.Errorf("Error while pulling image: %v", err)