config_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. package registry // import "github.com/docker/docker/registry"
  2. import (
  3. "reflect"
  4. "sort"
  5. "strings"
  6. "testing"
  7. "github.com/docker/docker/errdefs"
  8. "gotest.tools/v3/assert"
  9. is "gotest.tools/v3/assert/cmp"
  10. )
  11. func TestLoadAllowNondistributableArtifacts(t *testing.T) {
  12. testCases := []struct {
  13. registries []string
  14. cidrStrs []string
  15. hostnames []string
  16. err string
  17. }{
  18. {
  19. registries: []string{"1.2.3.0/24"},
  20. cidrStrs: []string{"1.2.3.0/24"},
  21. },
  22. {
  23. registries: []string{"2001:db8::/120"},
  24. cidrStrs: []string{"2001:db8::/120"},
  25. },
  26. {
  27. registries: []string{"127.0.0.1"},
  28. hostnames: []string{"127.0.0.1"},
  29. },
  30. {
  31. registries: []string{"127.0.0.1:8080"},
  32. hostnames: []string{"127.0.0.1:8080"},
  33. },
  34. {
  35. registries: []string{"2001:db8::1"},
  36. hostnames: []string{"2001:db8::1"},
  37. },
  38. {
  39. registries: []string{"[2001:db8::1]:80"},
  40. hostnames: []string{"[2001:db8::1]:80"},
  41. },
  42. {
  43. registries: []string{"[2001:db8::1]:80"},
  44. hostnames: []string{"[2001:db8::1]:80"},
  45. },
  46. {
  47. registries: []string{"1.2.3.0/24", "2001:db8::/120", "127.0.0.1", "127.0.0.1:8080"},
  48. cidrStrs: []string{"1.2.3.0/24", "2001:db8::/120"},
  49. hostnames: []string{"127.0.0.1", "127.0.0.1:8080"},
  50. },
  51. {
  52. registries: []string{"http://myregistry.example.com"},
  53. err: "allow-nondistributable-artifacts registry http://myregistry.example.com should not contain '://'",
  54. },
  55. {
  56. registries: []string{"https://myregistry.example.com"},
  57. err: "allow-nondistributable-artifacts registry https://myregistry.example.com should not contain '://'",
  58. },
  59. {
  60. registries: []string{"HTTP://myregistry.example.com"},
  61. err: "allow-nondistributable-artifacts registry HTTP://myregistry.example.com should not contain '://'",
  62. },
  63. {
  64. registries: []string{"svn://myregistry.example.com"},
  65. err: "allow-nondistributable-artifacts registry svn://myregistry.example.com should not contain '://'",
  66. },
  67. {
  68. registries: []string{"-invalid-registry"},
  69. err: "Cannot begin or end with a hyphen",
  70. },
  71. {
  72. registries: []string{`mytest-.com`},
  73. err: `allow-nondistributable-artifacts registry mytest-.com is not valid: invalid host "mytest-.com"`,
  74. },
  75. {
  76. registries: []string{`1200:0000:AB00:1234:0000:2552:7777:1313:8080`},
  77. err: `allow-nondistributable-artifacts registry 1200:0000:AB00:1234:0000:2552:7777:1313:8080 is not valid: invalid host "1200:0000:AB00:1234:0000:2552:7777:1313:8080"`,
  78. },
  79. {
  80. registries: []string{`myregistry.example.com:500000`},
  81. err: `allow-nondistributable-artifacts registry myregistry.example.com:500000 is not valid: invalid port "500000"`,
  82. },
  83. {
  84. registries: []string{`"myregistry.example.com"`},
  85. err: `allow-nondistributable-artifacts registry "myregistry.example.com" is not valid: invalid host "\"myregistry.example.com\""`,
  86. },
  87. {
  88. registries: []string{`"myregistry.example.com:5000"`},
  89. err: `allow-nondistributable-artifacts registry "myregistry.example.com:5000" is not valid: invalid host "\"myregistry.example.com"`,
  90. },
  91. }
  92. for _, testCase := range testCases {
  93. config := emptyServiceConfig
  94. err := config.loadAllowNondistributableArtifacts(testCase.registries)
  95. if testCase.err == "" {
  96. if err != nil {
  97. t.Fatalf("expect no error, got '%s'", err)
  98. }
  99. var cidrStrs []string
  100. for _, c := range config.AllowNondistributableArtifactsCIDRs {
  101. cidrStrs = append(cidrStrs, c.String())
  102. }
  103. sort.Strings(testCase.cidrStrs)
  104. sort.Strings(cidrStrs)
  105. if (len(testCase.cidrStrs) > 0 || len(cidrStrs) > 0) && !reflect.DeepEqual(testCase.cidrStrs, cidrStrs) {
  106. t.Fatalf("expect AllowNondistributableArtifactsCIDRs to be '%+v', got '%+v'", testCase.cidrStrs, cidrStrs)
  107. }
  108. sort.Strings(testCase.hostnames)
  109. sort.Strings(config.AllowNondistributableArtifactsHostnames)
  110. if (len(testCase.hostnames) > 0 || len(config.AllowNondistributableArtifactsHostnames) > 0) && !reflect.DeepEqual(testCase.hostnames, config.AllowNondistributableArtifactsHostnames) {
  111. t.Fatalf("expect AllowNondistributableArtifactsHostnames to be '%+v', got '%+v'", testCase.hostnames, config.AllowNondistributableArtifactsHostnames)
  112. }
  113. } else {
  114. if err == nil {
  115. t.Fatalf("expect error '%s', got no error", testCase.err)
  116. }
  117. if !strings.Contains(err.Error(), testCase.err) {
  118. t.Fatalf("expect error '%s', got '%s'", testCase.err, err)
  119. }
  120. }
  121. }
  122. }
  123. func TestValidateMirror(t *testing.T) {
  124. valid := []string{
  125. "http://mirror-1.example.com",
  126. "http://mirror-1.example.com/",
  127. "https://mirror-1.example.com",
  128. "https://mirror-1.example.com/",
  129. "http://localhost",
  130. "https://localhost",
  131. "http://localhost:5000",
  132. "https://localhost:5000",
  133. "http://127.0.0.1",
  134. "https://127.0.0.1",
  135. "http://127.0.0.1:5000",
  136. "https://127.0.0.1:5000",
  137. "http://mirror-1.example.com/v1/",
  138. "https://mirror-1.example.com/v1/",
  139. }
  140. invalid := []string{
  141. "!invalid!://%as%",
  142. "ftp://mirror-1.example.com",
  143. "http://mirror-1.example.com/?q=foo",
  144. "http://mirror-1.example.com/v1/?q=foo",
  145. "http://mirror-1.example.com/v1/?q=foo#frag",
  146. "http://mirror-1.example.com?q=foo",
  147. "https://mirror-1.example.com#frag",
  148. "https://mirror-1.example.com/#frag",
  149. "http://foo:bar@mirror-1.example.com/",
  150. "https://mirror-1.example.com/v1/#frag",
  151. "https://mirror-1.example.com?q",
  152. }
  153. for _, address := range valid {
  154. if ret, err := ValidateMirror(address); err != nil || ret == "" {
  155. t.Errorf("ValidateMirror(`"+address+"`) got %s %s", ret, err)
  156. }
  157. }
  158. for _, address := range invalid {
  159. if ret, err := ValidateMirror(address); err == nil || ret != "" {
  160. t.Errorf("ValidateMirror(`"+address+"`) got %s %s", ret, err)
  161. }
  162. }
  163. }
  164. func TestLoadInsecureRegistries(t *testing.T) {
  165. testCases := []struct {
  166. registries []string
  167. index string
  168. err string
  169. }{
  170. {
  171. registries: []string{"127.0.0.1"},
  172. index: "127.0.0.1",
  173. },
  174. {
  175. registries: []string{"127.0.0.1:8080"},
  176. index: "127.0.0.1:8080",
  177. },
  178. {
  179. registries: []string{"2001:db8::1"},
  180. index: "2001:db8::1",
  181. },
  182. {
  183. registries: []string{"[2001:db8::1]:80"},
  184. index: "[2001:db8::1]:80",
  185. },
  186. {
  187. registries: []string{"http://myregistry.example.com"},
  188. index: "myregistry.example.com",
  189. },
  190. {
  191. registries: []string{"https://myregistry.example.com"},
  192. index: "myregistry.example.com",
  193. },
  194. {
  195. registries: []string{"HTTP://myregistry.example.com"},
  196. index: "myregistry.example.com",
  197. },
  198. {
  199. registries: []string{"svn://myregistry.example.com"},
  200. err: "insecure registry svn://myregistry.example.com should not contain '://'",
  201. },
  202. {
  203. registries: []string{"-invalid-registry"},
  204. err: "Cannot begin or end with a hyphen",
  205. },
  206. {
  207. registries: []string{`mytest-.com`},
  208. err: `insecure registry mytest-.com is not valid: invalid host "mytest-.com"`,
  209. },
  210. {
  211. registries: []string{`1200:0000:AB00:1234:0000:2552:7777:1313:8080`},
  212. err: `insecure registry 1200:0000:AB00:1234:0000:2552:7777:1313:8080 is not valid: invalid host "1200:0000:AB00:1234:0000:2552:7777:1313:8080"`,
  213. },
  214. {
  215. registries: []string{`myregistry.example.com:500000`},
  216. err: `insecure registry myregistry.example.com:500000 is not valid: invalid port "500000"`,
  217. },
  218. {
  219. registries: []string{`"myregistry.example.com"`},
  220. err: `insecure registry "myregistry.example.com" is not valid: invalid host "\"myregistry.example.com\""`,
  221. },
  222. {
  223. registries: []string{`"myregistry.example.com:5000"`},
  224. err: `insecure registry "myregistry.example.com:5000" is not valid: invalid host "\"myregistry.example.com"`,
  225. },
  226. }
  227. for _, testCase := range testCases {
  228. config := emptyServiceConfig
  229. err := config.loadInsecureRegistries(testCase.registries)
  230. if testCase.err == "" {
  231. if err != nil {
  232. t.Fatalf("expect no error, got '%s'", err)
  233. }
  234. match := false
  235. for index := range config.IndexConfigs {
  236. if index == testCase.index {
  237. match = true
  238. }
  239. }
  240. if !match {
  241. t.Fatalf("expect index configs to contain '%s', got %+v", testCase.index, config.IndexConfigs)
  242. }
  243. } else {
  244. if err == nil {
  245. t.Fatalf("expect error '%s', got no error", testCase.err)
  246. }
  247. assert.ErrorContains(t, err, testCase.err)
  248. assert.Check(t, errdefs.IsInvalidParameter(err))
  249. }
  250. }
  251. }
  252. func TestNewServiceConfig(t *testing.T) {
  253. testCases := []struct {
  254. opts ServiceOptions
  255. errStr string
  256. }{
  257. {
  258. ServiceOptions{},
  259. "",
  260. },
  261. {
  262. ServiceOptions{
  263. Mirrors: []string{"example.com:5000"},
  264. },
  265. `invalid mirror: unsupported scheme "example.com" in "example.com:5000"`,
  266. },
  267. {
  268. ServiceOptions{
  269. Mirrors: []string{"http://example.com:5000"},
  270. },
  271. "",
  272. },
  273. {
  274. ServiceOptions{
  275. InsecureRegistries: []string{"[fe80::]/64"},
  276. },
  277. `insecure registry [fe80::]/64 is not valid: invalid host "[fe80::]/64"`,
  278. },
  279. {
  280. ServiceOptions{
  281. InsecureRegistries: []string{"102.10.8.1/24"},
  282. },
  283. "",
  284. },
  285. {
  286. ServiceOptions{
  287. AllowNondistributableArtifacts: []string{"[fe80::]/64"},
  288. },
  289. `allow-nondistributable-artifacts registry [fe80::]/64 is not valid: invalid host "[fe80::]/64"`,
  290. },
  291. {
  292. ServiceOptions{
  293. AllowNondistributableArtifacts: []string{"102.10.8.1/24"},
  294. },
  295. "",
  296. },
  297. }
  298. for _, testCase := range testCases {
  299. _, err := newServiceConfig(testCase.opts)
  300. if testCase.errStr != "" {
  301. assert.Check(t, is.Error(err, testCase.errStr))
  302. assert.Check(t, errdefs.IsInvalidParameter(err))
  303. } else {
  304. assert.Check(t, err)
  305. }
  306. }
  307. }
  308. func TestValidateIndexName(t *testing.T) {
  309. valid := []struct {
  310. index string
  311. expect string
  312. }{
  313. {
  314. index: "index.docker.io",
  315. expect: "docker.io",
  316. },
  317. {
  318. index: "example.com",
  319. expect: "example.com",
  320. },
  321. {
  322. index: "127.0.0.1:8080",
  323. expect: "127.0.0.1:8080",
  324. },
  325. {
  326. index: "mytest-1.com",
  327. expect: "mytest-1.com",
  328. },
  329. {
  330. index: "mirror-1.example.com/v1/?q=foo",
  331. expect: "mirror-1.example.com/v1/?q=foo",
  332. },
  333. }
  334. for _, testCase := range valid {
  335. result, err := ValidateIndexName(testCase.index)
  336. if assert.Check(t, err) {
  337. assert.Check(t, is.Equal(testCase.expect, result))
  338. }
  339. }
  340. }
  341. func TestValidateIndexNameWithError(t *testing.T) {
  342. invalid := []struct {
  343. index string
  344. err string
  345. }{
  346. {
  347. index: "docker.io-",
  348. err: "invalid index name (docker.io-). Cannot begin or end with a hyphen",
  349. },
  350. {
  351. index: "-example.com",
  352. err: "invalid index name (-example.com). Cannot begin or end with a hyphen",
  353. },
  354. {
  355. index: "mirror-1.example.com/v1/?q=foo-",
  356. err: "invalid index name (mirror-1.example.com/v1/?q=foo-). Cannot begin or end with a hyphen",
  357. },
  358. }
  359. for _, testCase := range invalid {
  360. _, err := ValidateIndexName(testCase.index)
  361. assert.Check(t, is.Error(err, testCase.err))
  362. assert.Check(t, errdefs.IsInvalidParameter(err))
  363. }
  364. }