github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/opts/hosts_test.go (about)

     1  package opts // import "github.com/docker/docker/opts"
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  )
     8  
     9  func TestParseHost(t *testing.T) {
    10  	invalid := map[string]string{
    11  		"something with spaces": `invalid bind address (something with spaces): parse "tcp://something with spaces": invalid character " " in host name`,
    12  		"://":                   `invalid bind address (://): unsupported proto ''`,
    13  		"unknown://":            `invalid bind address (unknown://): unsupported proto 'unknown'`,
    14  		"tcp://:port":           `invalid bind address (tcp://:port): parse "tcp://:port": invalid port ":port" after host`,
    15  		"tcp://invalid:port":    `invalid bind address (tcp://invalid:port): parse "tcp://invalid:port": invalid port ":port" after host`,
    16  		"tcp://:5555/":          `invalid bind address (tcp://:5555/): should not contain a path element`,
    17  		"tcp://:5555/p":         `invalid bind address (tcp://:5555/p): should not contain a path element`,
    18  		"tcp://0.0.0.0:5555/":   `invalid bind address (tcp://0.0.0.0:5555/): should not contain a path element`,
    19  		"tcp://0.0.0.0:5555/p":  `invalid bind address (tcp://0.0.0.0:5555/p): should not contain a path element`,
    20  		"tcp://[::1]:/":         `invalid bind address (tcp://[::1]:/): should not contain a path element`,
    21  		"tcp://[::1]:5555/":     `invalid bind address (tcp://[::1]:5555/): should not contain a path element`,
    22  		"tcp://[::1]:5555/p":    `invalid bind address (tcp://[::1]:5555/p): should not contain a path element`,
    23  		" tcp://:5555/path ":    `invalid bind address (tcp://:5555/path): should not contain a path element`,
    24  	}
    25  
    26  	valid := map[string]string{
    27  		"":                         DefaultHost,
    28  		" ":                        DefaultHost,
    29  		"  ":                       DefaultHost,
    30  		"fd://":                    "fd://",
    31  		"fd://something":           "fd://something",
    32  		"tcp://host:":              fmt.Sprintf("tcp://host:%d", DefaultHTTPPort),
    33  		"tcp://":                   DefaultTCPHost,
    34  		"tcp://:":                  DefaultTCPHost,
    35  		"tcp://:5555":              fmt.Sprintf("tcp://%s:5555", DefaultHTTPHost), //nolint:nosprintfhostport // sprintf is more readable for this case.
    36  		"tcp://[::1]":              fmt.Sprintf(`tcp://[::1]:%d`, DefaultHTTPPort),
    37  		"tcp://[::1]:":             fmt.Sprintf(`tcp://[::1]:%d`, DefaultHTTPPort),
    38  		"tcp://[::1]:5555":         `tcp://[::1]:5555`,
    39  		"tcp://0.0.0.0:5555":       "tcp://0.0.0.0:5555",
    40  		"tcp://192.168:5555":       "tcp://192.168:5555",
    41  		"tcp://192.168.0.1:5555":   "tcp://192.168.0.1:5555",
    42  		"tcp://0.0.0.0:1234567890": "tcp://0.0.0.0:1234567890", // yeah it's valid :P
    43  		"tcp://docker.com:5555":    "tcp://docker.com:5555",
    44  		"unix://":                  "unix://" + DefaultUnixSocket,
    45  		"unix://path/to/socket":    "unix://path/to/socket",
    46  		"npipe://":                 "npipe://" + DefaultNamedPipe,
    47  		"npipe:////./pipe/foo":     "npipe:////./pipe/foo",
    48  	}
    49  
    50  	for value, expectedError := range invalid {
    51  		t.Run(value, func(t *testing.T) {
    52  			_, err := ParseHost(false, false, value)
    53  			if err == nil || err.Error() != expectedError {
    54  				t.Errorf(`expected error "%s", got "%v"`, expectedError, err)
    55  			}
    56  		})
    57  	}
    58  
    59  	for value, expected := range valid {
    60  		t.Run(value, func(t *testing.T) {
    61  			actual, err := ParseHost(false, false, value)
    62  			if err != nil {
    63  				t.Errorf(`unexpected error: "%v"`, err)
    64  			}
    65  			if actual != expected {
    66  				t.Errorf(`expected "%s", got "%s""`, expected, actual)
    67  			}
    68  		})
    69  	}
    70  }
    71  
    72  func TestParseDockerDaemonHost(t *testing.T) {
    73  	invalids := map[string]string{
    74  		"tcp:a.b.c.d":                   `invalid bind address (tcp:a.b.c.d): parse "tcp://tcp:a.b.c.d": invalid port ":a.b.c.d" after host`,
    75  		"tcp:a.b.c.d/path":              `invalid bind address (tcp:a.b.c.d/path): parse "tcp://tcp:a.b.c.d/path": invalid port ":a.b.c.d" after host`,
    76  		"tcp://127.0.0.1/":              "invalid bind address (tcp://127.0.0.1/): should not contain a path element",
    77  		"udp://127.0.0.1":               "invalid bind address (udp://127.0.0.1): unsupported proto 'udp'",
    78  		"udp://127.0.0.1:5555":          "invalid bind address (udp://127.0.0.1:5555): unsupported proto 'udp'",
    79  		"tcp://unix:///run/docker.sock": "invalid bind address (tcp://unix:///run/docker.sock): should not contain a path element",
    80  		" tcp://:5555/path ":            "invalid bind address ( tcp://:5555/path ): unsupported proto ' tcp'",
    81  		"":                              "invalid bind address (): unsupported proto ''",
    82  		":5555/path":                    "invalid bind address (:5555/path): should not contain a path element",
    83  		"0.0.0.1:5555/path":             "invalid bind address (0.0.0.1:5555/path): should not contain a path element",
    84  		"[::1]:5555/path":               "invalid bind address ([::1]:5555/path): should not contain a path element",
    85  		"[0:0:0:0:0:0:0:1]:5555/path":   "invalid bind address ([0:0:0:0:0:0:0:1]:5555/path): should not contain a path element",
    86  		"tcp://:5555/path":              "invalid bind address (tcp://:5555/path): should not contain a path element",
    87  		"localhost:5555/path":           "invalid bind address (localhost:5555/path): should not contain a path element",
    88  	}
    89  	valids := map[string]string{
    90  		":":                       DefaultTCPHost,
    91  		":5555":                   fmt.Sprintf("tcp://%s:5555", DefaultHTTPHost), //nolint:nosprintfhostport // sprintf is more readable for this case.
    92  		"0.0.0.1:":                fmt.Sprintf("tcp://0.0.0.1:%d", DefaultHTTPPort),
    93  		"0.0.0.1:5555":            "tcp://0.0.0.1:5555",
    94  		"[::1]":                   fmt.Sprintf("tcp://[::1]:%d", DefaultHTTPPort),
    95  		"[::1]:":                  fmt.Sprintf("tcp://[::1]:%d", DefaultHTTPPort),
    96  		"[::1]:5555":              "tcp://[::1]:5555",
    97  		"[0:0:0:0:0:0:0:1]":       fmt.Sprintf("tcp://[0:0:0:0:0:0:0:1]:%d", DefaultHTTPPort),
    98  		"[0:0:0:0:0:0:0:1]:":      fmt.Sprintf("tcp://[0:0:0:0:0:0:0:1]:%d", DefaultHTTPPort),
    99  		"[0:0:0:0:0:0:0:1]:5555":  "tcp://[0:0:0:0:0:0:0:1]:5555",
   100  		"localhost":               fmt.Sprintf("tcp://localhost:%d", DefaultHTTPPort),
   101  		"localhost:":              fmt.Sprintf("tcp://localhost:%d", DefaultHTTPPort),
   102  		"localhost:5555":          "tcp://localhost:5555",
   103  		"fd://":                   "fd://",
   104  		"fd://something":          "fd://something",
   105  		"npipe://":                "npipe://" + DefaultNamedPipe,
   106  		"npipe:////./pipe/foo":    "npipe:////./pipe/foo",
   107  		"tcp://":                  DefaultTCPHost,
   108  		"tcp://:5555":             fmt.Sprintf("tcp://%s:5555", DefaultHTTPHost),
   109  		"tcp://[::1]":             fmt.Sprintf("tcp://[::1]:%d", DefaultHTTPPort),
   110  		"tcp://[::1]:":            fmt.Sprintf("tcp://[::1]:%d", DefaultHTTPPort),
   111  		"tcp://[::1]:5555":        "tcp://[::1]:5555",
   112  		"unix://":                 "unix://" + DefaultUnixSocket,
   113  		"unix:///run/docker.sock": "unix:///run/docker.sock",
   114  	}
   115  	for invalidAddr, expectedError := range invalids {
   116  		t.Run(invalidAddr, func(t *testing.T) {
   117  			addr, err := parseDaemonHost(invalidAddr)
   118  			if err == nil || err.Error() != expectedError {
   119  				t.Errorf(`expected error "%s", got "%v"`, expectedError, err)
   120  			}
   121  			if addr != "" {
   122  				t.Errorf(`expected addr to be empty, got "%s""`, addr)
   123  			}
   124  		})
   125  	}
   126  	for validAddr, expectedAddr := range valids {
   127  		t.Run(validAddr, func(t *testing.T) {
   128  			addr, err := parseDaemonHost(validAddr)
   129  			if err != nil {
   130  				t.Errorf(`unexpected error: "%v"`, err)
   131  			}
   132  			if addr != expectedAddr {
   133  				t.Errorf(`expected "%s", got "%s""`, expectedAddr, addr)
   134  			}
   135  		})
   136  	}
   137  }
   138  
   139  func TestParseTCP(t *testing.T) {
   140  	var (
   141  		defaultHTTPHost = "tcp://127.0.0.1:8888"
   142  	)
   143  	invalids := map[string]string{
   144  		"tcp:a.b.c.d":                 `invalid bind address (tcp:a.b.c.d): parse "tcp://tcp:a.b.c.d": invalid port ":a.b.c.d" after host`,
   145  		"tcp:a.b.c.d/path":            `invalid bind address (tcp:a.b.c.d/path): parse "tcp://tcp:a.b.c.d/path": invalid port ":a.b.c.d" after host`,
   146  		"udp://127.0.0.1":             "invalid bind address (udp://127.0.0.1): unsupported proto 'udp'",
   147  		"udp://127.0.0.1:5555":        "invalid bind address (udp://127.0.0.1:5555): unsupported proto 'udp'",
   148  		":5555/path":                  "invalid bind address (:5555/path): should not contain a path element",
   149  		"0.0.0.1:5555/path":           "invalid bind address (0.0.0.1:5555/path): should not contain a path element",
   150  		"[::1]:5555/path":             "invalid bind address ([::1]:5555/path): should not contain a path element",
   151  		"[0:0:0:0:0:0:0:1]:5555/path": "invalid bind address ([0:0:0:0:0:0:0:1]:5555/path): should not contain a path element",
   152  		"tcp://:5555/path":            "invalid bind address (tcp://:5555/path): should not contain a path element",
   153  		"localhost:5555/path":         "invalid bind address (localhost:5555/path): should not contain a path element",
   154  	}
   155  	invalidDefaults := map[string]string{
   156  		"localhost":                 `invalid default address (localhost): unsupported proto ''`,
   157  		"udp://localhost":           `invalid default address (udp://localhost): unsupported proto 'udp'`,
   158  		"tcp://localhost:noport":    `invalid default address (tcp://localhost:noport): parse "tcp://localhost:noport": invalid port ":noport" after host`,
   159  		"tcp://localhost:5555/path": `invalid default address (tcp://localhost:5555/path): should not contain a path element`,
   160  	}
   161  	valids := map[string]string{
   162  		"":                       defaultHTTPHost,
   163  		"0.0.0.1":                "tcp://0.0.0.1:8888",
   164  		"0.0.0.1:":               "tcp://0.0.0.1:8888",
   165  		"0.0.0.1:5555":           "tcp://0.0.0.1:5555",
   166  		":":                      "tcp://127.0.0.1:8888",
   167  		":5555":                  "tcp://127.0.0.1:5555",
   168  		"[::1]":                  "tcp://[::1]:8888",
   169  		"[::1]:":                 "tcp://[::1]:8888",
   170  		"[::1]:5555":             "tcp://[::1]:5555",
   171  		"[0:0:0:0:0:0:0:1]":      "tcp://[0:0:0:0:0:0:0:1]:8888",
   172  		"[0:0:0:0:0:0:0:1]:":     "tcp://[0:0:0:0:0:0:0:1]:8888",
   173  		"[0:0:0:0:0:0:0:1]:5555": "tcp://[0:0:0:0:0:0:0:1]:5555",
   174  		"localhost":              "tcp://localhost:8888",
   175  		"localhost:":             "tcp://localhost:8888",
   176  		"localhost:5555":         "tcp://localhost:5555",
   177  		"tcp://":                 defaultHTTPHost,
   178  		"tcp://:":                defaultHTTPHost,
   179  		"tcp://:5555":            "tcp://127.0.0.1:5555",
   180  	}
   181  	for invalidAddr, expectedError := range invalids {
   182  		t.Run(invalidAddr, func(t *testing.T) {
   183  			addr, err := ParseTCPAddr(invalidAddr, defaultHTTPHost)
   184  			if err == nil || err.Error() != expectedError {
   185  				t.Errorf(`expected error "%s", got "%v"`, expectedError, err)
   186  			}
   187  			if addr != "" {
   188  				t.Errorf(`expected addr to be empty, got "%s""`, addr)
   189  			}
   190  		})
   191  	}
   192  	for invalidAddr, expectedError := range invalidDefaults {
   193  		t.Run("default "+invalidAddr, func(t *testing.T) {
   194  			_, err := ParseTCPAddr("tcp://0.0.0.0:2375", invalidAddr)
   195  			if err == nil || err.Error() != expectedError {
   196  				t.Errorf(`expected error "%s", got "%v"`, expectedError, err)
   197  			}
   198  		})
   199  	}
   200  	for validAddr, expectedAddr := range valids {
   201  		t.Run(validAddr, func(t *testing.T) {
   202  			addr, err := ParseTCPAddr(validAddr, defaultHTTPHost)
   203  			if err != nil {
   204  				t.Errorf(`unexpected error: "%v"`, err)
   205  			}
   206  			if addr != expectedAddr {
   207  				t.Errorf(`expected "%s", got "%s""`, expectedAddr, addr)
   208  			}
   209  		})
   210  	}
   211  }
   212  
   213  func TestParseInvalidUnixAddrInvalid(t *testing.T) {
   214  	if _, err := parseSimpleProtoAddr("unix", "tcp://127.0.0.1", "unix:///var/run/docker.sock"); err == nil || err.Error() != "invalid proto, expected unix: tcp://127.0.0.1" {
   215  		t.Fatalf("Expected an error, got %v", err)
   216  	}
   217  	if _, err := parseSimpleProtoAddr("unix", "unix://tcp://127.0.0.1", "/var/run/docker.sock"); err == nil || err.Error() != "invalid proto, expected unix: tcp://127.0.0.1" {
   218  		t.Fatalf("Expected an error, got %v", err)
   219  	}
   220  	if v, err := parseSimpleProtoAddr("unix", "", "/var/run/docker.sock"); err != nil || v != "unix:///var/run/docker.sock" {
   221  		t.Fatalf("Expected an %v, got %v", v, "unix:///var/run/docker.sock")
   222  	}
   223  }
   224  
   225  func TestValidateExtraHosts(t *testing.T) {
   226  	valid := []string{
   227  		`myhost:192.168.0.1`,
   228  		`thathost:10.0.2.1`,
   229  		`anipv6host:2003:ab34:e::1`,
   230  		`ipv6local:::1`,
   231  	}
   232  
   233  	invalid := map[string]string{
   234  		`myhost:192.notanipaddress.1`:  `invalid IP`,
   235  		`thathost-nosemicolon10.0.0.1`: `bad format`,
   236  		`anipv6host:::::1`:             `invalid IP`,
   237  		`ipv6local:::0::`:              `invalid IP`,
   238  	}
   239  
   240  	for _, extrahost := range valid {
   241  		if _, err := ValidateExtraHost(extrahost); err != nil {
   242  			t.Fatalf("ValidateExtraHost(`"+extrahost+"`) should succeed: error %v", err)
   243  		}
   244  	}
   245  
   246  	for extraHost, expectedError := range invalid {
   247  		if _, err := ValidateExtraHost(extraHost); err == nil {
   248  			t.Fatalf("ValidateExtraHost(`%q`) should have failed validation", extraHost)
   249  		} else {
   250  			if !strings.Contains(err.Error(), expectedError) {
   251  				t.Fatalf("ValidateExtraHost(`%q`) error should contain %q", extraHost, expectedError)
   252  			}
   253  		}
   254  	}
   255  }