github.com/ctmnz/docker@v1.6.0-rc3/registry/registry_test.go (about) 1 package registry 2 3 import ( 4 "fmt" 5 "net/http" 6 "net/url" 7 "strings" 8 "testing" 9 10 "github.com/docker/docker/utils" 11 ) 12 13 var ( 14 token = []string{"fake-token"} 15 ) 16 17 const ( 18 imageID = "42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d" 19 REPO = "foo42/bar" 20 ) 21 22 func spawnTestRegistrySession(t *testing.T) *Session { 23 authConfig := &AuthConfig{} 24 endpoint, err := NewEndpoint(makeIndex("/v1/")) 25 if err != nil { 26 t.Fatal(err) 27 } 28 r, err := NewSession(authConfig, utils.NewHTTPRequestFactory(), endpoint, true) 29 if err != nil { 30 t.Fatal(err) 31 } 32 return r 33 } 34 35 func TestPublicSession(t *testing.T) { 36 authConfig := &AuthConfig{} 37 38 getSessionDecorators := func(index *IndexInfo) int { 39 endpoint, err := NewEndpoint(index) 40 if err != nil { 41 t.Fatal(err) 42 } 43 r, err := NewSession(authConfig, utils.NewHTTPRequestFactory(), endpoint, true) 44 if err != nil { 45 t.Fatal(err) 46 } 47 return len(r.reqFactory.GetDecorators()) 48 } 49 50 decorators := getSessionDecorators(makeIndex("/v1/")) 51 assertEqual(t, decorators, 0, "Expected no decorator on http session") 52 53 decorators = getSessionDecorators(makeHttpsIndex("/v1/")) 54 assertNotEqual(t, decorators, 0, "Expected decorator on https session") 55 56 decorators = getSessionDecorators(makePublicIndex()) 57 assertEqual(t, decorators, 0, "Expected no decorator on public session") 58 } 59 60 func TestPingRegistryEndpoint(t *testing.T) { 61 testPing := func(index *IndexInfo, expectedStandalone bool, assertMessage string) { 62 ep, err := NewEndpoint(index) 63 if err != nil { 64 t.Fatal(err) 65 } 66 regInfo, err := ep.Ping() 67 if err != nil { 68 t.Fatal(err) 69 } 70 71 assertEqual(t, regInfo.Standalone, expectedStandalone, assertMessage) 72 } 73 74 testPing(makeIndex("/v1/"), true, "Expected standalone to be true (default)") 75 testPing(makeHttpsIndex("/v1/"), true, "Expected standalone to be true (default)") 76 testPing(makePublicIndex(), false, "Expected standalone to be false for public index") 77 } 78 79 func TestEndpoint(t *testing.T) { 80 // Simple wrapper to fail test if err != nil 81 expandEndpoint := func(index *IndexInfo) *Endpoint { 82 endpoint, err := NewEndpoint(index) 83 if err != nil { 84 t.Fatal(err) 85 } 86 return endpoint 87 } 88 89 assertInsecureIndex := func(index *IndexInfo) { 90 index.Secure = true 91 _, err := NewEndpoint(index) 92 assertNotEqual(t, err, nil, index.Name+": Expected error for insecure index") 93 assertEqual(t, strings.Contains(err.Error(), "insecure-registry"), true, index.Name+": Expected insecure-registry error for insecure index") 94 index.Secure = false 95 } 96 97 assertSecureIndex := func(index *IndexInfo) { 98 index.Secure = true 99 _, err := NewEndpoint(index) 100 assertNotEqual(t, err, nil, index.Name+": Expected cert error for secure index") 101 assertEqual(t, strings.Contains(err.Error(), "certificate signed by unknown authority"), true, index.Name+": Expected cert error for secure index") 102 index.Secure = false 103 } 104 105 index := &IndexInfo{} 106 index.Name = makeURL("/v1/") 107 endpoint := expandEndpoint(index) 108 assertEqual(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name) 109 if endpoint.Version != APIVersion1 { 110 t.Fatal("Expected endpoint to be v1") 111 } 112 assertInsecureIndex(index) 113 114 index.Name = makeURL("") 115 endpoint = expandEndpoint(index) 116 assertEqual(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/") 117 if endpoint.Version != APIVersion1 { 118 t.Fatal("Expected endpoint to be v1") 119 } 120 assertInsecureIndex(index) 121 122 httpURL := makeURL("") 123 index.Name = strings.SplitN(httpURL, "://", 2)[1] 124 endpoint = expandEndpoint(index) 125 assertEqual(t, endpoint.String(), httpURL+"/v1/", index.Name+": Expected endpoint to be "+httpURL+"/v1/") 126 if endpoint.Version != APIVersion1 { 127 t.Fatal("Expected endpoint to be v1") 128 } 129 assertInsecureIndex(index) 130 131 index.Name = makeHttpsURL("/v1/") 132 endpoint = expandEndpoint(index) 133 assertEqual(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name) 134 if endpoint.Version != APIVersion1 { 135 t.Fatal("Expected endpoint to be v1") 136 } 137 assertSecureIndex(index) 138 139 index.Name = makeHttpsURL("") 140 endpoint = expandEndpoint(index) 141 assertEqual(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/") 142 if endpoint.Version != APIVersion1 { 143 t.Fatal("Expected endpoint to be v1") 144 } 145 assertSecureIndex(index) 146 147 httpsURL := makeHttpsURL("") 148 index.Name = strings.SplitN(httpsURL, "://", 2)[1] 149 endpoint = expandEndpoint(index) 150 assertEqual(t, endpoint.String(), httpsURL+"/v1/", index.Name+": Expected endpoint to be "+httpsURL+"/v1/") 151 if endpoint.Version != APIVersion1 { 152 t.Fatal("Expected endpoint to be v1") 153 } 154 assertSecureIndex(index) 155 156 badEndpoints := []string{ 157 "http://127.0.0.1/v1/", 158 "https://127.0.0.1/v1/", 159 "http://127.0.0.1", 160 "https://127.0.0.1", 161 "127.0.0.1", 162 } 163 for _, address := range badEndpoints { 164 index.Name = address 165 _, err := NewEndpoint(index) 166 checkNotEqual(t, err, nil, "Expected error while expanding bad endpoint") 167 } 168 } 169 170 func TestGetRemoteHistory(t *testing.T) { 171 r := spawnTestRegistrySession(t) 172 hist, err := r.GetRemoteHistory(imageID, makeURL("/v1/"), token) 173 if err != nil { 174 t.Fatal(err) 175 } 176 assertEqual(t, len(hist), 2, "Expected 2 images in history") 177 assertEqual(t, hist[0], imageID, "Expected "+imageID+"as first ancestry") 178 assertEqual(t, hist[1], "77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20", 179 "Unexpected second ancestry") 180 } 181 182 func TestLookupRemoteImage(t *testing.T) { 183 r := spawnTestRegistrySession(t) 184 err := r.LookupRemoteImage(imageID, makeURL("/v1/"), token) 185 assertEqual(t, err, nil, "Expected error of remote lookup to nil") 186 if err := r.LookupRemoteImage("abcdef", makeURL("/v1/"), token); err == nil { 187 t.Fatal("Expected error of remote lookup to not nil") 188 } 189 } 190 191 func TestGetRemoteImageJSON(t *testing.T) { 192 r := spawnTestRegistrySession(t) 193 json, size, err := r.GetRemoteImageJSON(imageID, makeURL("/v1/"), token) 194 if err != nil { 195 t.Fatal(err) 196 } 197 assertEqual(t, size, 154, "Expected size 154") 198 if len(json) <= 0 { 199 t.Fatal("Expected non-empty json") 200 } 201 202 _, _, err = r.GetRemoteImageJSON("abcdef", makeURL("/v1/"), token) 203 if err == nil { 204 t.Fatal("Expected image not found error") 205 } 206 } 207 208 func TestGetRemoteImageLayer(t *testing.T) { 209 r := spawnTestRegistrySession(t) 210 data, err := r.GetRemoteImageLayer(imageID, makeURL("/v1/"), token, 0) 211 if err != nil { 212 t.Fatal(err) 213 } 214 if data == nil { 215 t.Fatal("Expected non-nil data result") 216 } 217 218 _, err = r.GetRemoteImageLayer("abcdef", makeURL("/v1/"), token, 0) 219 if err == nil { 220 t.Fatal("Expected image not found error") 221 } 222 } 223 224 func TestGetRemoteTags(t *testing.T) { 225 r := spawnTestRegistrySession(t) 226 tags, err := r.GetRemoteTags([]string{makeURL("/v1/")}, REPO, token) 227 if err != nil { 228 t.Fatal(err) 229 } 230 assertEqual(t, len(tags), 1, "Expected one tag") 231 assertEqual(t, tags["latest"], imageID, "Expected tag latest to map to "+imageID) 232 233 _, err = r.GetRemoteTags([]string{makeURL("/v1/")}, "foo42/baz", token) 234 if err == nil { 235 t.Fatal("Expected error when fetching tags for bogus repo") 236 } 237 } 238 239 func TestGetRepositoryData(t *testing.T) { 240 r := spawnTestRegistrySession(t) 241 parsedURL, err := url.Parse(makeURL("/v1/")) 242 if err != nil { 243 t.Fatal(err) 244 } 245 host := "http://" + parsedURL.Host + "/v1/" 246 data, err := r.GetRepositoryData("foo42/bar") 247 if err != nil { 248 t.Fatal(err) 249 } 250 assertEqual(t, len(data.ImgList), 2, "Expected 2 images in ImgList") 251 assertEqual(t, len(data.Endpoints), 2, 252 fmt.Sprintf("Expected 2 endpoints in Endpoints, found %d instead", len(data.Endpoints))) 253 assertEqual(t, data.Endpoints[0], host, 254 fmt.Sprintf("Expected first endpoint to be %s but found %s instead", host, data.Endpoints[0])) 255 assertEqual(t, data.Endpoints[1], "http://test.example.com/v1/", 256 fmt.Sprintf("Expected first endpoint to be http://test.example.com/v1/ but found %s instead", data.Endpoints[1])) 257 258 } 259 260 func TestPushImageJSONRegistry(t *testing.T) { 261 r := spawnTestRegistrySession(t) 262 imgData := &ImgData{ 263 ID: "77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20", 264 Checksum: "sha256:1ac330d56e05eef6d438586545ceff7550d3bdcb6b19961f12c5ba714ee1bb37", 265 } 266 267 err := r.PushImageJSONRegistry(imgData, []byte{0x42, 0xdf, 0x0}, makeURL("/v1/"), token) 268 if err != nil { 269 t.Fatal(err) 270 } 271 } 272 273 func TestPushImageLayerRegistry(t *testing.T) { 274 r := spawnTestRegistrySession(t) 275 layer := strings.NewReader("") 276 _, _, err := r.PushImageLayerRegistry(imageID, layer, makeURL("/v1/"), token, []byte{}) 277 if err != nil { 278 t.Fatal(err) 279 } 280 } 281 282 func TestValidateRepositoryName(t *testing.T) { 283 validRepoNames := []string{ 284 "docker/docker", 285 "library/debian", 286 "debian", 287 "docker.io/docker/docker", 288 "docker.io/library/debian", 289 "docker.io/debian", 290 "index.docker.io/docker/docker", 291 "index.docker.io/library/debian", 292 "index.docker.io/debian", 293 "127.0.0.1:5000/docker/docker", 294 "127.0.0.1:5000/library/debian", 295 "127.0.0.1:5000/debian", 296 "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev", 297 } 298 invalidRepoNames := []string{ 299 "https://github.com/docker/docker", 300 "docker/Docker", 301 "docker///docker", 302 "docker.io/docker/Docker", 303 "docker.io/docker///docker", 304 "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a", 305 "docker.io/1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a", 306 } 307 308 for _, name := range invalidRepoNames { 309 err := ValidateRepositoryName(name) 310 assertNotEqual(t, err, nil, "Expected invalid repo name: "+name) 311 } 312 313 for _, name := range validRepoNames { 314 err := ValidateRepositoryName(name) 315 assertEqual(t, err, nil, "Expected valid repo name: "+name) 316 } 317 318 err := ValidateRepositoryName(invalidRepoNames[0]) 319 assertEqual(t, err, ErrInvalidRepositoryName, "Expected ErrInvalidRepositoryName: "+invalidRepoNames[0]) 320 } 321 322 func TestParseRepositoryInfo(t *testing.T) { 323 expectedRepoInfos := map[string]RepositoryInfo{ 324 "fooo/bar": { 325 Index: &IndexInfo{ 326 Name: IndexServerName(), 327 Official: true, 328 }, 329 RemoteName: "fooo/bar", 330 LocalName: "fooo/bar", 331 CanonicalName: "fooo/bar", 332 Official: false, 333 }, 334 "library/ubuntu": { 335 Index: &IndexInfo{ 336 Name: IndexServerName(), 337 Official: true, 338 }, 339 RemoteName: "library/ubuntu", 340 LocalName: "ubuntu", 341 CanonicalName: "ubuntu", 342 Official: true, 343 }, 344 "nonlibrary/ubuntu": { 345 Index: &IndexInfo{ 346 Name: IndexServerName(), 347 Official: true, 348 }, 349 RemoteName: "nonlibrary/ubuntu", 350 LocalName: "nonlibrary/ubuntu", 351 CanonicalName: "nonlibrary/ubuntu", 352 Official: false, 353 }, 354 "ubuntu": { 355 Index: &IndexInfo{ 356 Name: IndexServerName(), 357 Official: true, 358 }, 359 RemoteName: "library/ubuntu", 360 LocalName: "ubuntu", 361 CanonicalName: "ubuntu", 362 Official: true, 363 }, 364 "other/library": { 365 Index: &IndexInfo{ 366 Name: IndexServerName(), 367 Official: true, 368 }, 369 RemoteName: "other/library", 370 LocalName: "other/library", 371 CanonicalName: "other/library", 372 Official: false, 373 }, 374 "127.0.0.1:8000/private/moonbase": { 375 Index: &IndexInfo{ 376 Name: "127.0.0.1:8000", 377 Official: false, 378 }, 379 RemoteName: "private/moonbase", 380 LocalName: "127.0.0.1:8000/private/moonbase", 381 CanonicalName: "127.0.0.1:8000/private/moonbase", 382 Official: false, 383 }, 384 "127.0.0.1:8000/privatebase": { 385 Index: &IndexInfo{ 386 Name: "127.0.0.1:8000", 387 Official: false, 388 }, 389 RemoteName: "privatebase", 390 LocalName: "127.0.0.1:8000/privatebase", 391 CanonicalName: "127.0.0.1:8000/privatebase", 392 Official: false, 393 }, 394 "localhost:8000/private/moonbase": { 395 Index: &IndexInfo{ 396 Name: "localhost:8000", 397 Official: false, 398 }, 399 RemoteName: "private/moonbase", 400 LocalName: "localhost:8000/private/moonbase", 401 CanonicalName: "localhost:8000/private/moonbase", 402 Official: false, 403 }, 404 "localhost:8000/privatebase": { 405 Index: &IndexInfo{ 406 Name: "localhost:8000", 407 Official: false, 408 }, 409 RemoteName: "privatebase", 410 LocalName: "localhost:8000/privatebase", 411 CanonicalName: "localhost:8000/privatebase", 412 Official: false, 413 }, 414 "example.com/private/moonbase": { 415 Index: &IndexInfo{ 416 Name: "example.com", 417 Official: false, 418 }, 419 RemoteName: "private/moonbase", 420 LocalName: "example.com/private/moonbase", 421 CanonicalName: "example.com/private/moonbase", 422 Official: false, 423 }, 424 "example.com/privatebase": { 425 Index: &IndexInfo{ 426 Name: "example.com", 427 Official: false, 428 }, 429 RemoteName: "privatebase", 430 LocalName: "example.com/privatebase", 431 CanonicalName: "example.com/privatebase", 432 Official: false, 433 }, 434 "example.com:8000/private/moonbase": { 435 Index: &IndexInfo{ 436 Name: "example.com:8000", 437 Official: false, 438 }, 439 RemoteName: "private/moonbase", 440 LocalName: "example.com:8000/private/moonbase", 441 CanonicalName: "example.com:8000/private/moonbase", 442 Official: false, 443 }, 444 "example.com:8000/privatebase": { 445 Index: &IndexInfo{ 446 Name: "example.com:8000", 447 Official: false, 448 }, 449 RemoteName: "privatebase", 450 LocalName: "example.com:8000/privatebase", 451 CanonicalName: "example.com:8000/privatebase", 452 Official: false, 453 }, 454 "localhost/private/moonbase": { 455 Index: &IndexInfo{ 456 Name: "localhost", 457 Official: false, 458 }, 459 RemoteName: "private/moonbase", 460 LocalName: "localhost/private/moonbase", 461 CanonicalName: "localhost/private/moonbase", 462 Official: false, 463 }, 464 "localhost/privatebase": { 465 Index: &IndexInfo{ 466 Name: "localhost", 467 Official: false, 468 }, 469 RemoteName: "privatebase", 470 LocalName: "localhost/privatebase", 471 CanonicalName: "localhost/privatebase", 472 Official: false, 473 }, 474 IndexServerName() + "/public/moonbase": { 475 Index: &IndexInfo{ 476 Name: IndexServerName(), 477 Official: true, 478 }, 479 RemoteName: "public/moonbase", 480 LocalName: "public/moonbase", 481 CanonicalName: "public/moonbase", 482 Official: false, 483 }, 484 "index." + IndexServerName() + "/public/moonbase": { 485 Index: &IndexInfo{ 486 Name: IndexServerName(), 487 Official: true, 488 }, 489 RemoteName: "public/moonbase", 490 LocalName: "public/moonbase", 491 CanonicalName: "public/moonbase", 492 Official: false, 493 }, 494 IndexServerName() + "/public/moonbase": { 495 Index: &IndexInfo{ 496 Name: IndexServerName(), 497 Official: true, 498 }, 499 RemoteName: "public/moonbase", 500 LocalName: "public/moonbase", 501 CanonicalName: "public/moonbase", 502 Official: false, 503 }, 504 "ubuntu-12.04-base": { 505 Index: &IndexInfo{ 506 Name: IndexServerName(), 507 Official: true, 508 }, 509 RemoteName: "library/ubuntu-12.04-base", 510 LocalName: "ubuntu-12.04-base", 511 CanonicalName: "ubuntu-12.04-base", 512 Official: true, 513 }, 514 IndexServerName() + "/ubuntu-12.04-base": { 515 Index: &IndexInfo{ 516 Name: IndexServerName(), 517 Official: true, 518 }, 519 RemoteName: "library/ubuntu-12.04-base", 520 LocalName: "ubuntu-12.04-base", 521 CanonicalName: "ubuntu-12.04-base", 522 Official: true, 523 }, 524 IndexServerName() + "/ubuntu-12.04-base": { 525 Index: &IndexInfo{ 526 Name: IndexServerName(), 527 Official: true, 528 }, 529 RemoteName: "library/ubuntu-12.04-base", 530 LocalName: "ubuntu-12.04-base", 531 CanonicalName: "ubuntu-12.04-base", 532 Official: true, 533 }, 534 "index." + IndexServerName() + "/ubuntu-12.04-base": { 535 Index: &IndexInfo{ 536 Name: IndexServerName(), 537 Official: true, 538 }, 539 RemoteName: "library/ubuntu-12.04-base", 540 LocalName: "ubuntu-12.04-base", 541 CanonicalName: "ubuntu-12.04-base", 542 Official: true, 543 }, 544 } 545 546 for reposName, expectedRepoInfo := range expectedRepoInfos { 547 repoInfo, err := ParseRepositoryInfo(reposName) 548 if err != nil { 549 t.Error(err) 550 } else { 551 checkEqual(t, repoInfo.Index.Name, expectedRepoInfo.Index.Name, reposName) 552 checkEqual(t, repoInfo.RemoteName, expectedRepoInfo.RemoteName, reposName) 553 checkEqual(t, repoInfo.LocalName, expectedRepoInfo.LocalName, reposName) 554 checkEqual(t, repoInfo.CanonicalName, expectedRepoInfo.CanonicalName, reposName) 555 checkEqual(t, repoInfo.Index.Official, expectedRepoInfo.Index.Official, reposName) 556 checkEqual(t, repoInfo.Official, expectedRepoInfo.Official, reposName) 557 } 558 } 559 } 560 561 func TestNewIndexInfo(t *testing.T) { 562 testIndexInfo := func(config *ServiceConfig, expectedIndexInfos map[string]*IndexInfo) { 563 for indexName, expectedIndexInfo := range expectedIndexInfos { 564 index, err := config.NewIndexInfo(indexName) 565 if err != nil { 566 t.Fatal(err) 567 } else { 568 checkEqual(t, index.Name, expectedIndexInfo.Name, indexName+" name") 569 checkEqual(t, index.Official, expectedIndexInfo.Official, indexName+" is official") 570 checkEqual(t, index.Secure, expectedIndexInfo.Secure, indexName+" is secure") 571 checkEqual(t, len(index.Mirrors), len(expectedIndexInfo.Mirrors), indexName+" mirrors") 572 } 573 } 574 } 575 576 config := NewServiceConfig(nil) 577 noMirrors := make([]string, 0) 578 expectedIndexInfos := map[string]*IndexInfo{ 579 IndexServerName(): { 580 Name: IndexServerName(), 581 Official: true, 582 Secure: true, 583 Mirrors: noMirrors, 584 }, 585 "index." + IndexServerName(): { 586 Name: IndexServerName(), 587 Official: true, 588 Secure: true, 589 Mirrors: noMirrors, 590 }, 591 "example.com": { 592 Name: "example.com", 593 Official: false, 594 Secure: true, 595 Mirrors: noMirrors, 596 }, 597 "127.0.0.1:5000": { 598 Name: "127.0.0.1:5000", 599 Official: false, 600 Secure: false, 601 Mirrors: noMirrors, 602 }, 603 } 604 testIndexInfo(config, expectedIndexInfos) 605 606 publicMirrors := []string{"http://mirror1.local", "http://mirror2.local"} 607 config = makeServiceConfig(publicMirrors, []string{"example.com"}) 608 609 expectedIndexInfos = map[string]*IndexInfo{ 610 IndexServerName(): { 611 Name: IndexServerName(), 612 Official: true, 613 Secure: true, 614 Mirrors: publicMirrors, 615 }, 616 "index." + IndexServerName(): { 617 Name: IndexServerName(), 618 Official: true, 619 Secure: true, 620 Mirrors: publicMirrors, 621 }, 622 "example.com": { 623 Name: "example.com", 624 Official: false, 625 Secure: false, 626 Mirrors: noMirrors, 627 }, 628 "example.com:5000": { 629 Name: "example.com:5000", 630 Official: false, 631 Secure: true, 632 Mirrors: noMirrors, 633 }, 634 "127.0.0.1": { 635 Name: "127.0.0.1", 636 Official: false, 637 Secure: false, 638 Mirrors: noMirrors, 639 }, 640 "127.0.0.1:5000": { 641 Name: "127.0.0.1:5000", 642 Official: false, 643 Secure: false, 644 Mirrors: noMirrors, 645 }, 646 "other.com": { 647 Name: "other.com", 648 Official: false, 649 Secure: true, 650 Mirrors: noMirrors, 651 }, 652 } 653 testIndexInfo(config, expectedIndexInfos) 654 655 config = makeServiceConfig(nil, []string{"42.42.0.0/16"}) 656 expectedIndexInfos = map[string]*IndexInfo{ 657 "example.com": { 658 Name: "example.com", 659 Official: false, 660 Secure: false, 661 Mirrors: noMirrors, 662 }, 663 "example.com:5000": { 664 Name: "example.com:5000", 665 Official: false, 666 Secure: false, 667 Mirrors: noMirrors, 668 }, 669 "127.0.0.1": { 670 Name: "127.0.0.1", 671 Official: false, 672 Secure: false, 673 Mirrors: noMirrors, 674 }, 675 "127.0.0.1:5000": { 676 Name: "127.0.0.1:5000", 677 Official: false, 678 Secure: false, 679 Mirrors: noMirrors, 680 }, 681 "other.com": { 682 Name: "other.com", 683 Official: false, 684 Secure: true, 685 Mirrors: noMirrors, 686 }, 687 } 688 testIndexInfo(config, expectedIndexInfos) 689 } 690 691 func TestPushRegistryTag(t *testing.T) { 692 r := spawnTestRegistrySession(t) 693 err := r.PushRegistryTag("foo42/bar", imageID, "stable", makeURL("/v1/"), token) 694 if err != nil { 695 t.Fatal(err) 696 } 697 } 698 699 func TestPushImageJSONIndex(t *testing.T) { 700 r := spawnTestRegistrySession(t) 701 imgData := []*ImgData{ 702 { 703 ID: "77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20", 704 Checksum: "sha256:1ac330d56e05eef6d438586545ceff7550d3bdcb6b19961f12c5ba714ee1bb37", 705 }, 706 { 707 ID: "42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d", 708 Checksum: "sha256:bea7bf2e4bacd479344b737328db47b18880d09096e6674165533aa994f5e9f2", 709 }, 710 } 711 repoData, err := r.PushImageJSONIndex("foo42/bar", imgData, false, nil) 712 if err != nil { 713 t.Fatal(err) 714 } 715 if repoData == nil { 716 t.Fatal("Expected RepositoryData object") 717 } 718 repoData, err = r.PushImageJSONIndex("foo42/bar", imgData, true, []string{r.indexEndpoint.String()}) 719 if err != nil { 720 t.Fatal(err) 721 } 722 if repoData == nil { 723 t.Fatal("Expected RepositoryData object") 724 } 725 } 726 727 func TestSearchRepositories(t *testing.T) { 728 r := spawnTestRegistrySession(t) 729 results, err := r.SearchRepositories("fakequery") 730 if err != nil { 731 t.Fatal(err) 732 } 733 if results == nil { 734 t.Fatal("Expected non-nil SearchResults object") 735 } 736 assertEqual(t, results.NumResults, 1, "Expected 1 search results") 737 assertEqual(t, results.Query, "fakequery", "Expected 'fakequery' as query") 738 assertEqual(t, results.Results[0].StarCount, 42, "Expected 'fakeimage' a ot hae 42 stars") 739 } 740 741 func TestValidRemoteName(t *testing.T) { 742 validRepositoryNames := []string{ 743 // Sanity check. 744 "docker/docker", 745 746 // Allow 64-character non-hexadecimal names (hexadecimal names are forbidden). 747 "thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev", 748 749 // Allow embedded hyphens. 750 "docker-rules/docker", 751 752 // Allow underscores everywhere (as opposed to hyphens). 753 "____/____", 754 755 //Username doc and image name docker being tested. 756 "doc/docker", 757 } 758 for _, repositoryName := range validRepositoryNames { 759 if err := validateRemoteName(repositoryName); err != nil { 760 t.Errorf("Repository name should be valid: %v. Error: %v", repositoryName, err) 761 } 762 } 763 764 invalidRepositoryNames := []string{ 765 // Disallow capital letters. 766 "docker/Docker", 767 768 // Only allow one slash. 769 "docker///docker", 770 771 // Disallow 64-character hexadecimal. 772 "1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a", 773 774 // Disallow leading and trailing hyphens in namespace. 775 "-docker/docker", 776 "docker-/docker", 777 "-docker-/docker", 778 779 // Disallow consecutive hyphens. 780 "dock--er/docker", 781 782 // No repository. 783 "docker/", 784 785 //namespace too short 786 "d/docker", 787 788 //namespace too long 789 "this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255/docker", 790 } 791 for _, repositoryName := range invalidRepositoryNames { 792 if err := validateRemoteName(repositoryName); err == nil { 793 t.Errorf("Repository name should be invalid: %v", repositoryName) 794 } 795 } 796 } 797 798 func TestTrustedLocation(t *testing.T) { 799 for _, url := range []string{"http://example.com", "https://example.com:7777", "http://docker.io", "http://test.docker.com", "https://fakedocker.com"} { 800 req, _ := http.NewRequest("GET", url, nil) 801 if trustedLocation(req) == true { 802 t.Fatalf("'%s' shouldn't be detected as a trusted location", url) 803 } 804 } 805 806 for _, url := range []string{"https://docker.io", "https://test.docker.com:80"} { 807 req, _ := http.NewRequest("GET", url, nil) 808 if trustedLocation(req) == false { 809 t.Fatalf("'%s' should be detected as a trusted location", url) 810 } 811 } 812 } 813 814 func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) { 815 for _, urls := range [][]string{ 816 {"http://docker.io", "https://docker.com"}, 817 {"https://foo.docker.io:7777", "http://bar.docker.com"}, 818 {"https://foo.docker.io", "https://example.com"}, 819 } { 820 reqFrom, _ := http.NewRequest("GET", urls[0], nil) 821 reqFrom.Header.Add("Content-Type", "application/json") 822 reqFrom.Header.Add("Authorization", "super_secret") 823 reqTo, _ := http.NewRequest("GET", urls[1], nil) 824 825 AddRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom}) 826 827 if len(reqTo.Header) != 1 { 828 t.Fatalf("Expected 1 headers, got %d", len(reqTo.Header)) 829 } 830 831 if reqTo.Header.Get("Content-Type") != "application/json" { 832 t.Fatal("'Content-Type' should be 'application/json'") 833 } 834 835 if reqTo.Header.Get("Authorization") != "" { 836 t.Fatal("'Authorization' should be empty") 837 } 838 } 839 840 for _, urls := range [][]string{ 841 {"https://docker.io", "https://docker.com"}, 842 {"https://foo.docker.io:7777", "https://bar.docker.com"}, 843 } { 844 reqFrom, _ := http.NewRequest("GET", urls[0], nil) 845 reqFrom.Header.Add("Content-Type", "application/json") 846 reqFrom.Header.Add("Authorization", "super_secret") 847 reqTo, _ := http.NewRequest("GET", urls[1], nil) 848 849 AddRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom}) 850 851 if len(reqTo.Header) != 2 { 852 t.Fatalf("Expected 2 headers, got %d", len(reqTo.Header)) 853 } 854 855 if reqTo.Header.Get("Content-Type") != "application/json" { 856 t.Fatal("'Content-Type' should be 'application/json'") 857 } 858 859 if reqTo.Header.Get("Authorization") != "super_secret" { 860 t.Fatal("'Authorization' should be 'super_secret'") 861 } 862 } 863 } 864 865 func TestIsSecureIndex(t *testing.T) { 866 tests := []struct { 867 addr string 868 insecureRegistries []string 869 expected bool 870 }{ 871 {IndexServerName(), nil, true}, 872 {"example.com", []string{}, true}, 873 {"example.com", []string{"example.com"}, false}, 874 {"localhost", []string{"localhost:5000"}, false}, 875 {"localhost:5000", []string{"localhost:5000"}, false}, 876 {"localhost", []string{"example.com"}, false}, 877 {"127.0.0.1:5000", []string{"127.0.0.1:5000"}, false}, 878 {"localhost", nil, false}, 879 {"localhost:5000", nil, false}, 880 {"127.0.0.1", nil, false}, 881 {"localhost", []string{"example.com"}, false}, 882 {"127.0.0.1", []string{"example.com"}, false}, 883 {"example.com", nil, true}, 884 {"example.com", []string{"example.com"}, false}, 885 {"127.0.0.1", []string{"example.com"}, false}, 886 {"127.0.0.1:5000", []string{"example.com"}, false}, 887 {"example.com:5000", []string{"42.42.0.0/16"}, false}, 888 {"example.com", []string{"42.42.0.0/16"}, false}, 889 {"example.com:5000", []string{"42.42.42.42/8"}, false}, 890 {"127.0.0.1:5000", []string{"127.0.0.0/8"}, false}, 891 {"42.42.42.42:5000", []string{"42.1.1.1/8"}, false}, 892 {"invalid.domain.com", []string{"42.42.0.0/16"}, true}, 893 {"invalid.domain.com", []string{"invalid.domain.com"}, false}, 894 {"invalid.domain.com:5000", []string{"invalid.domain.com"}, true}, 895 {"invalid.domain.com:5000", []string{"invalid.domain.com:5000"}, false}, 896 } 897 for _, tt := range tests { 898 config := makeServiceConfig(nil, tt.insecureRegistries) 899 if sec := config.isSecureIndex(tt.addr); sec != tt.expected { 900 t.Errorf("isSecureIndex failed for %q %v, expected %v got %v", tt.addr, tt.insecureRegistries, tt.expected, sec) 901 } 902 } 903 }