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