diff --git a/opts/hosts_windows.go b/opts/hosts_windows.go index 0b5c8a5b8d..ec52e9a70a 100644 --- a/opts/hosts_windows.go +++ b/opts/hosts_windows.go @@ -2,7 +2,5 @@ package opts -import "fmt" - // DefaultHost constant defines the default host string used by docker on Windows -var DefaultHost = fmt.Sprintf("tcp://%s:%d", DefaultHTTPHost, DefaultHTTPPort) +var DefaultHost = DefaultTCPHost diff --git a/opts/opts.go b/opts/opts.go index 392bc49735..2601c00cf0 100644 --- a/opts/opts.go +++ b/opts/opts.go @@ -25,6 +25,8 @@ var ( // DefaultUnixSocket Path for the unix socket. // Docker daemon by default always listens on the default unix socket DefaultUnixSocket = "/var/run/docker.sock" + // DefaultTCPHost constant defines the default host string used by docker on Windows + DefaultTCPHost = fmt.Sprintf("tcp://%s:%d", DefaultHTTPHost, DefaultHTTPPort) ) // ListOpts holds a list of values and a validation function. @@ -333,7 +335,7 @@ func ValidateLabel(val string) (string, error) { // ValidateHost validates that the specified string is a valid host and returns it. func ValidateHost(val string) (string, error) { - host, err := parsers.ParseHost(DefaultHTTPHost, DefaultUnixSocket, val) + host, err := parsers.ParseDockerDaemonHost(DefaultTCPHost, DefaultUnixSocket, val) if err != nil { return val, err } diff --git a/opts/opts_test.go b/opts/opts_test.go index e3ff970b32..48b21f3442 100644 --- a/opts/opts_test.go +++ b/opts/opts_test.go @@ -441,7 +441,6 @@ func TestValidateHost(t *testing.T) { "something with spaces": "Invalid bind address format: something with spaces", "://": "Invalid bind address format: ://", "unknown://": "Invalid bind address format: unknown://", - "tcp://": "Invalid proto, expected tcp: ", "tcp://:port": "Invalid bind address format: :port", "tcp://invalid": "Invalid bind address format: invalid", "tcp://invalid:port": "Invalid bind address format: invalid:port", @@ -449,6 +448,8 @@ func TestValidateHost(t *testing.T) { valid := map[string]string{ "fd://": "fd://", "fd://something": "fd://something", + "tcp://host:": "tcp://host:2375", + "tcp://": "tcp://127.0.0.1:2375", "tcp://:2375": "tcp://127.0.0.1:2375", // default ip address "tcp://:2376": "tcp://127.0.0.1:2376", // default ip address "tcp://0.0.0.0:8080": "tcp://0.0.0.0:8080", diff --git a/pkg/parsers/parsers.go b/pkg/parsers/parsers.go index 96433a26a9..30b1932914 100644 --- a/pkg/parsers/parsers.go +++ b/pkg/parsers/parsers.go @@ -12,17 +12,17 @@ import ( "strings" ) -// ParseHost parses the specified address and returns an address that will be used as the host. +// ParseDockerDaemonHost parses the specified address and returns an address that will be used as the host. // Depending of the address specified, will use the defaultTCPAddr or defaultUnixAddr -func ParseHost(defaultTCPAddr, defaultUnixAddr, addr string) (string, error) { +// defaultUnixAddr must be a absolute file path (no `unix://` prefix) +// defaultTCPAddr must be the full `tcp://host:port` form +func ParseDockerDaemonHost(defaultTCPAddr, defaultUnixAddr, addr string) (string, error) { addr = strings.TrimSpace(addr) if addr == "" { if runtime.GOOS != "windows" { - addr = fmt.Sprintf("unix://%s", defaultUnixAddr) - } else { - // Note - defaultTCPAddr already includes tcp:// prefix - addr = defaultTCPAddr + return fmt.Sprintf("unix://%s", defaultUnixAddr), nil } + return defaultTCPAddr, nil } addrParts := strings.Split(addr, "://") if len(addrParts) == 1 { @@ -58,11 +58,16 @@ func ParseUnixAddr(addr string, defaultAddr string) (string, error) { // ParseTCPAddr parses and validates that the specified address is a valid TCP // address. It returns a formatted TCP address, either using the address parsed -// from addr, or the contents of defaultAddr if addr is a blank string. -func ParseTCPAddr(addr string, defaultAddr string) (string, error) { - addr = strings.TrimPrefix(addr, "tcp://") +// from tryAddr, or the contents of defaultAddr if tryAddr is a blank string. +// tryAddr is expected to have already been Trim()'d +// defaultAddr must be in the full `tcp://host:port` form +func ParseTCPAddr(tryAddr string, defaultAddr string) (string, error) { + if tryAddr == "" || tryAddr == "tcp://" { + return defaultAddr, nil + } + addr := strings.TrimPrefix(tryAddr, "tcp://") if strings.Contains(addr, "://") || addr == "" { - return "", fmt.Errorf("Invalid proto, expected tcp: %s", addr) + return "", fmt.Errorf("Invalid proto, expected tcp: %s", tryAddr) } u, err := url.Parse("tcp://" + addr) @@ -71,16 +76,23 @@ func ParseTCPAddr(addr string, defaultAddr string) (string, error) { } hostParts := strings.Split(u.Host, ":") if len(hostParts) != 2 { - return "", fmt.Errorf("Invalid bind address format: %s", addr) + return "", fmt.Errorf("Invalid bind address format: %s", tryAddr) } - host := hostParts[0] - if host == "" { - host = defaultAddr + defaults := strings.Split(defaultAddr, ":") + if len(defaults) != 3 { + return "", fmt.Errorf("Invalid defaults address format: %s", defaultAddr) } + host := hostParts[0] + if host == "" { + host = strings.TrimPrefix(defaults[1], "//") + } + if hostParts[1] == "" { + hostParts[1] = defaults[2] + } p, err := strconv.Atoi(hostParts[1]) if err != nil && p == 0 { - return "", fmt.Errorf("Invalid bind address format: %s", addr) + return "", fmt.Errorf("Invalid bind address format: %s", tryAddr) } return fmt.Sprintf("tcp://%s:%d%s", host, p, u.Path), nil } diff --git a/pkg/parsers/parsers_test.go b/pkg/parsers/parsers_test.go index e3c1b3b4f9..ac8237724c 100644 --- a/pkg/parsers/parsers_test.go +++ b/pkg/parsers/parsers_test.go @@ -6,16 +6,17 @@ import ( "testing" ) -func TestParseHost(t *testing.T) { +func TestParseDockerDaemonHost(t *testing.T) { var ( - defaultHTTPHost = "127.0.0.1" + defaultHTTPHost = "tcp://127.0.0.1:2376" defaultUnix = "/var/run/docker.sock" defaultHOST = "unix:///var/run/docker.sock" ) + if runtime.GOOS == "windows" { + defaultHOST = defaultHTTPHost + } invalids := map[string]string{ "0.0.0.0": "Invalid bind address format: 0.0.0.0", - "0.0.0.0:": "Invalid bind address format: 0.0.0.0:", - "tcp://": "Invalid proto, expected tcp: ", "tcp:a.b.c.d": "Invalid bind address format: tcp:a.b.c.d", "tcp:a.b.c.d/path": "Invalid bind address format: tcp:a.b.c.d/path", "udp://127.0.0.1": "Invalid bind address format: udp://127.0.0.1", @@ -26,37 +27,30 @@ func TestParseHost(t *testing.T) { "fd": "Invalid bind address format: fd", } valids := map[string]string{ - "0.0.0.1:5555": "tcp://0.0.0.1:5555", - "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path", - ":6666": "tcp://127.0.0.1:6666", - ":6666/path": "tcp://127.0.0.1:6666/path", - "tcp://:7777": "tcp://127.0.0.1:7777", - "tcp://:7777/path": "tcp://127.0.0.1:7777/path", - // as there's a TrimSpace in there, we should test for it. + "0.0.0.1:": "tcp://0.0.0.1:2376", + "0.0.0.1:5555": "tcp://0.0.0.1:5555", + "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path", + ":6666": "tcp://127.0.0.1:6666", + ":6666/path": "tcp://127.0.0.1:6666/path", + "": defaultHOST, + " ": defaultHOST, + " ": defaultHOST, + "tcp://": defaultHTTPHost, + "tcp://:7777": "tcp://127.0.0.1:7777", + "tcp://:7777/path": "tcp://127.0.0.1:7777/path", " tcp://:7777/path ": "tcp://127.0.0.1:7777/path", "unix:///run/docker.sock": "unix:///run/docker.sock", "unix://": "unix:///var/run/docker.sock", "fd://": "fd://", "fd://something": "fd://something", } - if runtime.GOOS == "windows" { - defaultHOST = "Invalid bind address format: 127.0.0.1" - // SVEN: an example of the conflicted defaultHTTPHost - invalids[""] = defaultHOST - invalids[" "] = defaultHOST - invalids[" "] = defaultHOST - } else { - valids[""] = defaultHOST - valids[" "] = defaultHOST - valids[" "] = defaultHOST - } for invalidAddr, expectedError := range invalids { - if addr, err := ParseHost(defaultHTTPHost, defaultUnix, invalidAddr); err == nil || err.Error() != expectedError { + if addr, err := ParseDockerDaemonHost(defaultHTTPHost, defaultUnix, invalidAddr); err == nil || err.Error() != expectedError { t.Errorf("tcp %v address expected error %v return, got %s and addr %v", invalidAddr, expectedError, err, addr) } } for validAddr, expectedAddr := range valids { - if addr, err := ParseHost(defaultHTTPHost, defaultUnix, validAddr); err != nil || addr != expectedAddr { + if addr, err := ParseDockerDaemonHost(defaultHTTPHost, defaultUnix, validAddr); err != nil || addr != expectedAddr { t.Errorf("%v -> expected %v, got (%v) addr (%v)", validAddr, expectedAddr, err, addr) } } @@ -64,20 +58,19 @@ func TestParseHost(t *testing.T) { func TestParseTCP(t *testing.T) { var ( - //SVEN if this is set to tcp://127.0.0.1, then we end up with results like 'tcp://tcp://127.0.0.1:6666' - defaultHTTPHost = "127.0.0.1" + defaultHTTPHost = "tcp://127.0.0.1:2376" ) invalids := map[string]string{ "0.0.0.0": "Invalid bind address format: 0.0.0.0", - "0.0.0.0:": "Invalid bind address format: 0.0.0.0:", - "tcp://": "Invalid proto, expected tcp: ", "tcp:a.b.c.d": "Invalid bind address format: tcp:a.b.c.d", "tcp:a.b.c.d/path": "Invalid bind address format: tcp:a.b.c.d/path", "udp://127.0.0.1": "Invalid proto, expected tcp: udp://127.0.0.1", "udp://127.0.0.1:2375": "Invalid proto, expected tcp: udp://127.0.0.1:2375", - "": "Invalid proto, expected tcp: ", } valids := map[string]string{ + "": defaultHTTPHost, + "tcp://": defaultHTTPHost, + "0.0.0.1:": "tcp://0.0.0.1:2376", "0.0.0.1:5555": "tcp://0.0.0.1:5555", "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path", ":6666": "tcp://127.0.0.1:6666", @@ -101,7 +94,7 @@ func TestParseInvalidUnixAddrInvalid(t *testing.T) { if _, err := ParseUnixAddr("tcp://127.0.0.1", "unix:///var/run/docker.sock"); err == nil || err.Error() != "Invalid proto, expected unix: tcp://127.0.0.1" { t.Fatalf("Expected an error, got %v", err) } - if _, err := ParseUnixAddr("unix://tcp://127.0.0.1", "unix:///var/run/docker.sock"); err == nil || err.Error() != "Invalid proto, expected unix: tcp://127.0.0.1" { + if _, err := ParseUnixAddr("unix://tcp://127.0.0.1", "/var/run/docker.sock"); err == nil || err.Error() != "Invalid proto, expected unix: tcp://127.0.0.1" { t.Fatalf("Expected an error, got %v", err) } if v, err := ParseUnixAddr("", "/var/run/docker.sock"); err != nil || v != "unix:///var/run/docker.sock" {