github.com/rumpl/bof@v23.0.0-rc.2+incompatible/registry/registry_test.go (about) 1 package registry // import "github.com/docker/docker/registry" 2 3 import ( 4 "net/http" 5 "net/http/httputil" 6 "os" 7 "strings" 8 "testing" 9 10 "github.com/docker/distribution/reference" 11 "github.com/docker/distribution/registry/client/transport" 12 "github.com/docker/docker/api/types" 13 "github.com/docker/docker/api/types/registry" 14 "gotest.tools/v3/assert" 15 is "gotest.tools/v3/assert/cmp" 16 "gotest.tools/v3/skip" 17 ) 18 19 func spawnTestRegistrySession(t *testing.T) *session { 20 authConfig := &types.AuthConfig{} 21 endpoint, err := newV1Endpoint(makeIndex("/v1/"), "", nil) 22 if err != nil { 23 t.Fatal(err) 24 } 25 userAgent := "docker test client" 26 var tr http.RoundTripper = debugTransport{newTransport(nil), t.Log} 27 tr = transport.NewTransport(newAuthTransport(tr, authConfig, false), Headers(userAgent, nil)...) 28 client := httpClient(tr) 29 30 if err := authorizeClient(client, authConfig, endpoint); err != nil { 31 t.Fatal(err) 32 } 33 r := newSession(client, endpoint) 34 35 // In a normal scenario for the v1 registry, the client should send a `X-Docker-Token: true` 36 // header while authenticating, in order to retrieve a token that can be later used to 37 // perform authenticated actions. 38 // 39 // The mock v1 registry does not support that, (TODO(tiborvass): support it), instead, 40 // it will consider authenticated any request with the header `X-Docker-Token: fake-token`. 41 // 42 // Because we know that the client's transport is an `*authTransport` we simply cast it, 43 // in order to set the internal cached token to the fake token, and thus send that fake token 44 // upon every subsequent requests. 45 r.client.Transport.(*authTransport).token = []string{"fake-token"} 46 return r 47 } 48 49 func TestPingRegistryEndpoint(t *testing.T) { 50 skip.If(t, os.Getuid() != 0, "skipping test that requires root") 51 testPing := func(index *registry.IndexInfo, expectedStandalone bool, assertMessage string) { 52 ep, err := newV1Endpoint(index, "", nil) 53 if err != nil { 54 t.Fatal(err) 55 } 56 regInfo, err := ep.ping() 57 if err != nil { 58 t.Fatal(err) 59 } 60 61 assert.Equal(t, regInfo.Standalone, expectedStandalone, assertMessage) 62 } 63 64 testPing(makeIndex("/v1/"), true, "Expected standalone to be true (default)") 65 testPing(makeHTTPSIndex("/v1/"), true, "Expected standalone to be true (default)") 66 testPing(makePublicIndex(), false, "Expected standalone to be false for public index") 67 } 68 69 func TestEndpoint(t *testing.T) { 70 skip.If(t, os.Getuid() != 0, "skipping test that requires root") 71 // Simple wrapper to fail test if err != nil 72 expandEndpoint := func(index *registry.IndexInfo) *v1Endpoint { 73 endpoint, err := newV1Endpoint(index, "", nil) 74 if err != nil { 75 t.Fatal(err) 76 } 77 return endpoint 78 } 79 80 assertInsecureIndex := func(index *registry.IndexInfo) { 81 index.Secure = true 82 _, err := newV1Endpoint(index, "", nil) 83 assert.ErrorContains(t, err, "insecure-registry", index.Name+": Expected insecure-registry error for insecure index") 84 index.Secure = false 85 } 86 87 assertSecureIndex := func(index *registry.IndexInfo) { 88 index.Secure = true 89 _, err := newV1Endpoint(index, "", nil) 90 assert.ErrorContains(t, err, "certificate signed by unknown authority", index.Name+": Expected cert error for secure index") 91 index.Secure = false 92 } 93 94 index := ®istry.IndexInfo{} 95 index.Name = makeURL("/v1/") 96 endpoint := expandEndpoint(index) 97 assert.Equal(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name) 98 assertInsecureIndex(index) 99 100 index.Name = makeURL("") 101 endpoint = expandEndpoint(index) 102 assert.Equal(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/") 103 assertInsecureIndex(index) 104 105 httpURL := makeURL("") 106 index.Name = strings.SplitN(httpURL, "://", 2)[1] 107 endpoint = expandEndpoint(index) 108 assert.Equal(t, endpoint.String(), httpURL+"/v1/", index.Name+": Expected endpoint to be "+httpURL+"/v1/") 109 assertInsecureIndex(index) 110 111 index.Name = makeHTTPSURL("/v1/") 112 endpoint = expandEndpoint(index) 113 assert.Equal(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name) 114 assertSecureIndex(index) 115 116 index.Name = makeHTTPSURL("") 117 endpoint = expandEndpoint(index) 118 assert.Equal(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/") 119 assertSecureIndex(index) 120 121 httpsURL := makeHTTPSURL("") 122 index.Name = strings.SplitN(httpsURL, "://", 2)[1] 123 endpoint = expandEndpoint(index) 124 assert.Equal(t, endpoint.String(), httpsURL+"/v1/", index.Name+": Expected endpoint to be "+httpsURL+"/v1/") 125 assertSecureIndex(index) 126 127 badEndpoints := []string{ 128 "http://127.0.0.1/v1/", 129 "https://127.0.0.1/v1/", 130 "http://127.0.0.1", 131 "https://127.0.0.1", 132 "127.0.0.1", 133 } 134 for _, address := range badEndpoints { 135 index.Name = address 136 _, err := newV1Endpoint(index, "", nil) 137 assert.Check(t, err != nil, "Expected error while expanding bad endpoint: %s", address) 138 } 139 } 140 141 func TestParseRepositoryInfo(t *testing.T) { 142 type staticRepositoryInfo struct { 143 Index *registry.IndexInfo 144 RemoteName string 145 CanonicalName string 146 LocalName string 147 Official bool 148 } 149 150 expectedRepoInfos := map[string]staticRepositoryInfo{ 151 "fooo/bar": { 152 Index: ®istry.IndexInfo{ 153 Name: IndexName, 154 Official: true, 155 }, 156 RemoteName: "fooo/bar", 157 LocalName: "fooo/bar", 158 CanonicalName: "docker.io/fooo/bar", 159 Official: false, 160 }, 161 "library/ubuntu": { 162 Index: ®istry.IndexInfo{ 163 Name: IndexName, 164 Official: true, 165 }, 166 RemoteName: "library/ubuntu", 167 LocalName: "ubuntu", 168 CanonicalName: "docker.io/library/ubuntu", 169 Official: true, 170 }, 171 "nonlibrary/ubuntu": { 172 Index: ®istry.IndexInfo{ 173 Name: IndexName, 174 Official: true, 175 }, 176 RemoteName: "nonlibrary/ubuntu", 177 LocalName: "nonlibrary/ubuntu", 178 CanonicalName: "docker.io/nonlibrary/ubuntu", 179 Official: false, 180 }, 181 "ubuntu": { 182 Index: ®istry.IndexInfo{ 183 Name: IndexName, 184 Official: true, 185 }, 186 RemoteName: "library/ubuntu", 187 LocalName: "ubuntu", 188 CanonicalName: "docker.io/library/ubuntu", 189 Official: true, 190 }, 191 "other/library": { 192 Index: ®istry.IndexInfo{ 193 Name: IndexName, 194 Official: true, 195 }, 196 RemoteName: "other/library", 197 LocalName: "other/library", 198 CanonicalName: "docker.io/other/library", 199 Official: false, 200 }, 201 "127.0.0.1:8000/private/moonbase": { 202 Index: ®istry.IndexInfo{ 203 Name: "127.0.0.1:8000", 204 Official: false, 205 }, 206 RemoteName: "private/moonbase", 207 LocalName: "127.0.0.1:8000/private/moonbase", 208 CanonicalName: "127.0.0.1:8000/private/moonbase", 209 Official: false, 210 }, 211 "127.0.0.1:8000/privatebase": { 212 Index: ®istry.IndexInfo{ 213 Name: "127.0.0.1:8000", 214 Official: false, 215 }, 216 RemoteName: "privatebase", 217 LocalName: "127.0.0.1:8000/privatebase", 218 CanonicalName: "127.0.0.1:8000/privatebase", 219 Official: false, 220 }, 221 "localhost:8000/private/moonbase": { 222 Index: ®istry.IndexInfo{ 223 Name: "localhost:8000", 224 Official: false, 225 }, 226 RemoteName: "private/moonbase", 227 LocalName: "localhost:8000/private/moonbase", 228 CanonicalName: "localhost:8000/private/moonbase", 229 Official: false, 230 }, 231 "localhost:8000/privatebase": { 232 Index: ®istry.IndexInfo{ 233 Name: "localhost:8000", 234 Official: false, 235 }, 236 RemoteName: "privatebase", 237 LocalName: "localhost:8000/privatebase", 238 CanonicalName: "localhost:8000/privatebase", 239 Official: false, 240 }, 241 "example.com/private/moonbase": { 242 Index: ®istry.IndexInfo{ 243 Name: "example.com", 244 Official: false, 245 }, 246 RemoteName: "private/moonbase", 247 LocalName: "example.com/private/moonbase", 248 CanonicalName: "example.com/private/moonbase", 249 Official: false, 250 }, 251 "example.com/privatebase": { 252 Index: ®istry.IndexInfo{ 253 Name: "example.com", 254 Official: false, 255 }, 256 RemoteName: "privatebase", 257 LocalName: "example.com/privatebase", 258 CanonicalName: "example.com/privatebase", 259 Official: false, 260 }, 261 "example.com:8000/private/moonbase": { 262 Index: ®istry.IndexInfo{ 263 Name: "example.com:8000", 264 Official: false, 265 }, 266 RemoteName: "private/moonbase", 267 LocalName: "example.com:8000/private/moonbase", 268 CanonicalName: "example.com:8000/private/moonbase", 269 Official: false, 270 }, 271 "example.com:8000/privatebase": { 272 Index: ®istry.IndexInfo{ 273 Name: "example.com:8000", 274 Official: false, 275 }, 276 RemoteName: "privatebase", 277 LocalName: "example.com:8000/privatebase", 278 CanonicalName: "example.com:8000/privatebase", 279 Official: false, 280 }, 281 "localhost/private/moonbase": { 282 Index: ®istry.IndexInfo{ 283 Name: "localhost", 284 Official: false, 285 }, 286 RemoteName: "private/moonbase", 287 LocalName: "localhost/private/moonbase", 288 CanonicalName: "localhost/private/moonbase", 289 Official: false, 290 }, 291 "localhost/privatebase": { 292 Index: ®istry.IndexInfo{ 293 Name: "localhost", 294 Official: false, 295 }, 296 RemoteName: "privatebase", 297 LocalName: "localhost/privatebase", 298 CanonicalName: "localhost/privatebase", 299 Official: false, 300 }, 301 IndexName + "/public/moonbase": { 302 Index: ®istry.IndexInfo{ 303 Name: IndexName, 304 Official: true, 305 }, 306 RemoteName: "public/moonbase", 307 LocalName: "public/moonbase", 308 CanonicalName: "docker.io/public/moonbase", 309 Official: false, 310 }, 311 "index." + IndexName + "/public/moonbase": { 312 Index: ®istry.IndexInfo{ 313 Name: IndexName, 314 Official: true, 315 }, 316 RemoteName: "public/moonbase", 317 LocalName: "public/moonbase", 318 CanonicalName: "docker.io/public/moonbase", 319 Official: false, 320 }, 321 "ubuntu-12.04-base": { 322 Index: ®istry.IndexInfo{ 323 Name: IndexName, 324 Official: true, 325 }, 326 RemoteName: "library/ubuntu-12.04-base", 327 LocalName: "ubuntu-12.04-base", 328 CanonicalName: "docker.io/library/ubuntu-12.04-base", 329 Official: true, 330 }, 331 IndexName + "/ubuntu-12.04-base": { 332 Index: ®istry.IndexInfo{ 333 Name: IndexName, 334 Official: true, 335 }, 336 RemoteName: "library/ubuntu-12.04-base", 337 LocalName: "ubuntu-12.04-base", 338 CanonicalName: "docker.io/library/ubuntu-12.04-base", 339 Official: true, 340 }, 341 "index." + IndexName + "/ubuntu-12.04-base": { 342 Index: ®istry.IndexInfo{ 343 Name: IndexName, 344 Official: true, 345 }, 346 RemoteName: "library/ubuntu-12.04-base", 347 LocalName: "ubuntu-12.04-base", 348 CanonicalName: "docker.io/library/ubuntu-12.04-base", 349 Official: true, 350 }, 351 } 352 353 for reposName, expectedRepoInfo := range expectedRepoInfos { 354 named, err := reference.ParseNormalizedNamed(reposName) 355 if err != nil { 356 t.Error(err) 357 } 358 359 repoInfo, err := ParseRepositoryInfo(named) 360 if err != nil { 361 t.Error(err) 362 } else { 363 assert.Check(t, is.Equal(repoInfo.Index.Name, expectedRepoInfo.Index.Name), reposName) 364 assert.Check(t, is.Equal(reference.Path(repoInfo.Name), expectedRepoInfo.RemoteName), reposName) 365 assert.Check(t, is.Equal(reference.FamiliarName(repoInfo.Name), expectedRepoInfo.LocalName), reposName) 366 assert.Check(t, is.Equal(repoInfo.Name.Name(), expectedRepoInfo.CanonicalName), reposName) 367 assert.Check(t, is.Equal(repoInfo.Index.Official, expectedRepoInfo.Index.Official), reposName) 368 assert.Check(t, is.Equal(repoInfo.Official, expectedRepoInfo.Official), reposName) 369 } 370 } 371 } 372 373 func TestNewIndexInfo(t *testing.T) { 374 testIndexInfo := func(config *serviceConfig, expectedIndexInfos map[string]*registry.IndexInfo) { 375 for indexName, expectedIndexInfo := range expectedIndexInfos { 376 index, err := newIndexInfo(config, indexName) 377 if err != nil { 378 t.Fatal(err) 379 } else { 380 assert.Check(t, is.Equal(index.Name, expectedIndexInfo.Name), indexName+" name") 381 assert.Check(t, is.Equal(index.Official, expectedIndexInfo.Official), indexName+" is official") 382 assert.Check(t, is.Equal(index.Secure, expectedIndexInfo.Secure), indexName+" is secure") 383 assert.Check(t, is.Equal(len(index.Mirrors), len(expectedIndexInfo.Mirrors)), indexName+" mirrors") 384 } 385 } 386 } 387 388 config := emptyServiceConfig 389 var noMirrors []string 390 expectedIndexInfos := map[string]*registry.IndexInfo{ 391 IndexName: { 392 Name: IndexName, 393 Official: true, 394 Secure: true, 395 Mirrors: noMirrors, 396 }, 397 "index." + IndexName: { 398 Name: IndexName, 399 Official: true, 400 Secure: true, 401 Mirrors: noMirrors, 402 }, 403 "example.com": { 404 Name: "example.com", 405 Official: false, 406 Secure: true, 407 Mirrors: noMirrors, 408 }, 409 "127.0.0.1:5000": { 410 Name: "127.0.0.1:5000", 411 Official: false, 412 Secure: false, 413 Mirrors: noMirrors, 414 }, 415 } 416 testIndexInfo(config, expectedIndexInfos) 417 418 publicMirrors := []string{"http://mirror1.local", "http://mirror2.local"} 419 var err error 420 config, err = makeServiceConfig(publicMirrors, []string{"example.com"}) 421 if err != nil { 422 t.Fatal(err) 423 } 424 425 expectedIndexInfos = map[string]*registry.IndexInfo{ 426 IndexName: { 427 Name: IndexName, 428 Official: true, 429 Secure: true, 430 Mirrors: publicMirrors, 431 }, 432 "index." + IndexName: { 433 Name: IndexName, 434 Official: true, 435 Secure: true, 436 Mirrors: publicMirrors, 437 }, 438 "example.com": { 439 Name: "example.com", 440 Official: false, 441 Secure: false, 442 Mirrors: noMirrors, 443 }, 444 "example.com:5000": { 445 Name: "example.com:5000", 446 Official: false, 447 Secure: true, 448 Mirrors: noMirrors, 449 }, 450 "127.0.0.1": { 451 Name: "127.0.0.1", 452 Official: false, 453 Secure: false, 454 Mirrors: noMirrors, 455 }, 456 "127.0.0.1:5000": { 457 Name: "127.0.0.1:5000", 458 Official: false, 459 Secure: false, 460 Mirrors: noMirrors, 461 }, 462 "other.com": { 463 Name: "other.com", 464 Official: false, 465 Secure: true, 466 Mirrors: noMirrors, 467 }, 468 } 469 testIndexInfo(config, expectedIndexInfos) 470 471 config, err = makeServiceConfig(nil, []string{"42.42.0.0/16"}) 472 if err != nil { 473 t.Fatal(err) 474 } 475 expectedIndexInfos = map[string]*registry.IndexInfo{ 476 "example.com": { 477 Name: "example.com", 478 Official: false, 479 Secure: false, 480 Mirrors: noMirrors, 481 }, 482 "example.com:5000": { 483 Name: "example.com:5000", 484 Official: false, 485 Secure: false, 486 Mirrors: noMirrors, 487 }, 488 "127.0.0.1": { 489 Name: "127.0.0.1", 490 Official: false, 491 Secure: false, 492 Mirrors: noMirrors, 493 }, 494 "127.0.0.1:5000": { 495 Name: "127.0.0.1:5000", 496 Official: false, 497 Secure: false, 498 Mirrors: noMirrors, 499 }, 500 "other.com": { 501 Name: "other.com", 502 Official: false, 503 Secure: true, 504 Mirrors: noMirrors, 505 }, 506 } 507 testIndexInfo(config, expectedIndexInfos) 508 } 509 510 func TestMirrorEndpointLookup(t *testing.T) { 511 skip.If(t, os.Getuid() != 0, "skipping test that requires root") 512 containsMirror := func(endpoints []APIEndpoint) bool { 513 for _, pe := range endpoints { 514 if pe.URL.Host == "my.mirror" { 515 return true 516 } 517 } 518 return false 519 } 520 cfg, err := makeServiceConfig([]string{"https://my.mirror"}, nil) 521 if err != nil { 522 t.Fatal(err) 523 } 524 s := defaultService{config: cfg} 525 526 imageName, err := reference.WithName(IndexName + "/test/image") 527 if err != nil { 528 t.Error(err) 529 } 530 pushAPIEndpoints, err := s.LookupPushEndpoints(reference.Domain(imageName)) 531 if err != nil { 532 t.Fatal(err) 533 } 534 if containsMirror(pushAPIEndpoints) { 535 t.Fatal("Push endpoint should not contain mirror") 536 } 537 538 pullAPIEndpoints, err := s.LookupPullEndpoints(reference.Domain(imageName)) 539 if err != nil { 540 t.Fatal(err) 541 } 542 if !containsMirror(pullAPIEndpoints) { 543 t.Fatal("Pull endpoint should contain mirror") 544 } 545 } 546 547 func TestSearchRepositories(t *testing.T) { 548 r := spawnTestRegistrySession(t) 549 results, err := r.searchRepositories("fakequery", 25) 550 if err != nil { 551 t.Fatal(err) 552 } 553 if results == nil { 554 t.Fatal("Expected non-nil SearchResults object") 555 } 556 assert.Equal(t, results.NumResults, 1, "Expected 1 search results") 557 assert.Equal(t, results.Query, "fakequery", "Expected 'fakequery' as query") 558 assert.Equal(t, results.Results[0].StarCount, 42, "Expected 'fakeimage' to have 42 stars") 559 } 560 561 func TestTrustedLocation(t *testing.T) { 562 for _, url := range []string{"http://example.com", "https://example.com:7777", "http://docker.io", "http://test.docker.com", "https://fakedocker.com"} { 563 req, _ := http.NewRequest(http.MethodGet, url, nil) 564 assert.Check(t, !trustedLocation(req)) 565 } 566 567 for _, url := range []string{"https://docker.io", "https://test.docker.com:80"} { 568 req, _ := http.NewRequest(http.MethodGet, url, nil) 569 assert.Check(t, trustedLocation(req)) 570 } 571 } 572 573 func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) { 574 for _, urls := range [][]string{ 575 {"http://docker.io", "https://docker.com"}, 576 {"https://foo.docker.io:7777", "http://bar.docker.com"}, 577 {"https://foo.docker.io", "https://example.com"}, 578 } { 579 reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil) 580 reqFrom.Header.Add("Content-Type", "application/json") 581 reqFrom.Header.Add("Authorization", "super_secret") 582 reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil) 583 584 _ = addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom}) 585 586 if len(reqTo.Header) != 1 { 587 t.Fatalf("Expected 1 headers, got %d", len(reqTo.Header)) 588 } 589 590 if reqTo.Header.Get("Content-Type") != "application/json" { 591 t.Fatal("'Content-Type' should be 'application/json'") 592 } 593 594 if reqTo.Header.Get("Authorization") != "" { 595 t.Fatal("'Authorization' should be empty") 596 } 597 } 598 599 for _, urls := range [][]string{ 600 {"https://docker.io", "https://docker.com"}, 601 {"https://foo.docker.io:7777", "https://bar.docker.com"}, 602 } { 603 reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil) 604 reqFrom.Header.Add("Content-Type", "application/json") 605 reqFrom.Header.Add("Authorization", "super_secret") 606 reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil) 607 608 _ = addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom}) 609 610 if len(reqTo.Header) != 2 { 611 t.Fatalf("Expected 2 headers, got %d", len(reqTo.Header)) 612 } 613 614 if reqTo.Header.Get("Content-Type") != "application/json" { 615 t.Fatal("'Content-Type' should be 'application/json'") 616 } 617 618 if reqTo.Header.Get("Authorization") != "super_secret" { 619 t.Fatal("'Authorization' should be 'super_secret'") 620 } 621 } 622 } 623 624 func TestAllowNondistributableArtifacts(t *testing.T) { 625 tests := []struct { 626 addr string 627 registries []string 628 expected bool 629 }{ 630 {IndexName, nil, false}, 631 {"example.com", []string{}, false}, 632 {"example.com", []string{"example.com"}, true}, 633 {"localhost", []string{"localhost:5000"}, false}, 634 {"localhost:5000", []string{"localhost:5000"}, true}, 635 {"localhost", []string{"example.com"}, false}, 636 {"127.0.0.1:5000", []string{"127.0.0.1:5000"}, true}, 637 {"localhost", nil, false}, 638 {"localhost:5000", nil, false}, 639 {"127.0.0.1", nil, false}, 640 {"localhost", []string{"example.com"}, false}, 641 {"127.0.0.1", []string{"example.com"}, false}, 642 {"example.com", nil, false}, 643 {"example.com", []string{"example.com"}, true}, 644 {"127.0.0.1", []string{"example.com"}, false}, 645 {"127.0.0.1:5000", []string{"example.com"}, false}, 646 {"example.com:5000", []string{"42.42.0.0/16"}, true}, 647 {"example.com", []string{"42.42.0.0/16"}, true}, 648 {"example.com:5000", []string{"42.42.42.42/8"}, true}, 649 {"127.0.0.1:5000", []string{"127.0.0.0/8"}, true}, 650 {"42.42.42.42:5000", []string{"42.1.1.1/8"}, true}, 651 {"invalid.example.com", []string{"42.42.0.0/16"}, false}, 652 {"invalid.example.com", []string{"invalid.example.com"}, true}, 653 {"invalid.example.com:5000", []string{"invalid.example.com"}, false}, 654 {"invalid.example.com:5000", []string{"invalid.example.com:5000"}, true}, 655 } 656 for _, tt := range tests { 657 config, err := newServiceConfig(ServiceOptions{ 658 AllowNondistributableArtifacts: tt.registries, 659 }) 660 if err != nil { 661 t.Error(err) 662 } 663 if v := config.allowNondistributableArtifacts(tt.addr); v != tt.expected { 664 t.Errorf("allowNondistributableArtifacts failed for %q %v, expected %v got %v", tt.addr, tt.registries, tt.expected, v) 665 } 666 } 667 } 668 669 func TestIsSecureIndex(t *testing.T) { 670 tests := []struct { 671 addr string 672 insecureRegistries []string 673 expected bool 674 }{ 675 {IndexName, nil, true}, 676 {"example.com", []string{}, true}, 677 {"example.com", []string{"example.com"}, false}, 678 {"localhost", []string{"localhost:5000"}, false}, 679 {"localhost:5000", []string{"localhost:5000"}, false}, 680 {"localhost", []string{"example.com"}, false}, 681 {"127.0.0.1:5000", []string{"127.0.0.1:5000"}, false}, 682 {"localhost", nil, false}, 683 {"localhost:5000", nil, false}, 684 {"127.0.0.1", nil, false}, 685 {"localhost", []string{"example.com"}, false}, 686 {"127.0.0.1", []string{"example.com"}, false}, 687 {"example.com", nil, true}, 688 {"example.com", []string{"example.com"}, false}, 689 {"127.0.0.1", []string{"example.com"}, false}, 690 {"127.0.0.1:5000", []string{"example.com"}, false}, 691 {"example.com:5000", []string{"42.42.0.0/16"}, false}, 692 {"example.com", []string{"42.42.0.0/16"}, false}, 693 {"example.com:5000", []string{"42.42.42.42/8"}, false}, 694 {"127.0.0.1:5000", []string{"127.0.0.0/8"}, false}, 695 {"42.42.42.42:5000", []string{"42.1.1.1/8"}, false}, 696 {"invalid.example.com", []string{"42.42.0.0/16"}, true}, 697 {"invalid.example.com", []string{"invalid.example.com"}, false}, 698 {"invalid.example.com:5000", []string{"invalid.example.com"}, true}, 699 {"invalid.example.com:5000", []string{"invalid.example.com:5000"}, false}, 700 } 701 for _, tt := range tests { 702 config, err := makeServiceConfig(nil, tt.insecureRegistries) 703 if err != nil { 704 t.Error(err) 705 } 706 if sec := config.isSecureIndex(tt.addr); sec != tt.expected { 707 t.Errorf("isSecureIndex failed for %q %v, expected %v got %v", tt.addr, tt.insecureRegistries, tt.expected, sec) 708 } 709 } 710 } 711 712 type debugTransport struct { 713 http.RoundTripper 714 log func(...interface{}) 715 } 716 717 func (tr debugTransport) RoundTrip(req *http.Request) (*http.Response, error) { 718 dump, err := httputil.DumpRequestOut(req, false) 719 if err != nil { 720 tr.log("could not dump request") 721 } 722 tr.log(string(dump)) 723 resp, err := tr.RoundTripper.RoundTrip(req) 724 if err != nil { 725 return nil, err 726 } 727 dump, err = httputil.DumpResponse(resp, false) 728 if err != nil { 729 tr.log("could not dump response") 730 } 731 tr.log(string(dump)) 732 return resp, err 733 }