hosts_test.go 12 KB

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