registry.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "net/http"
  6. "os"
  7. "os/exec"
  8. "path/filepath"
  9. "github.com/docker/distribution/digest"
  10. "github.com/go-check/check"
  11. )
  12. const v2binary = "registry-v2"
  13. type testRegistryV2 struct {
  14. cmd *exec.Cmd
  15. dir string
  16. }
  17. func newTestRegistryV2(c *check.C) (*testRegistryV2, error) {
  18. template := `version: 0.1
  19. loglevel: debug
  20. storage:
  21. filesystem:
  22. rootdirectory: %s
  23. http:
  24. addr: %s`
  25. tmp, err := ioutil.TempDir("", "registry-test-")
  26. if err != nil {
  27. return nil, err
  28. }
  29. confPath := filepath.Join(tmp, "config.yaml")
  30. config, err := os.Create(confPath)
  31. if err != nil {
  32. return nil, err
  33. }
  34. if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL); err != nil {
  35. os.RemoveAll(tmp)
  36. return nil, err
  37. }
  38. cmd := exec.Command(v2binary, confPath)
  39. if err := cmd.Start(); err != nil {
  40. os.RemoveAll(tmp)
  41. if os.IsNotExist(err) {
  42. c.Skip(err.Error())
  43. }
  44. return nil, err
  45. }
  46. return &testRegistryV2{
  47. cmd: cmd,
  48. dir: tmp,
  49. }, nil
  50. }
  51. func (t *testRegistryV2) Ping() error {
  52. // We always ping through HTTP for our test registry.
  53. resp, err := http.Get(fmt.Sprintf("http://%s/v2/", privateRegistryURL))
  54. if err != nil {
  55. return err
  56. }
  57. if resp.StatusCode != 200 {
  58. return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode)
  59. }
  60. return nil
  61. }
  62. func (t *testRegistryV2) Close() {
  63. t.cmd.Process.Kill()
  64. os.RemoveAll(t.dir)
  65. }
  66. func (t *testRegistryV2) getBlobFilename(blobDigest digest.Digest) string {
  67. // Split the digest into it's algorithm and hex components.
  68. dgstAlg, dgstHex := blobDigest.Algorithm(), blobDigest.Hex()
  69. // The path to the target blob data looks something like:
  70. // baseDir + "docker/registry/v2/blobs/sha256/a3/a3ed...46d4/data"
  71. return fmt.Sprintf("%s/docker/registry/v2/blobs/%s/%s/%s/data", t.dir, dgstAlg, dgstHex[:2], dgstHex)
  72. }
  73. func (t *testRegistryV2) readBlobContents(c *check.C, blobDigest digest.Digest) []byte {
  74. // Load the target manifest blob.
  75. manifestBlob, err := ioutil.ReadFile(t.getBlobFilename(blobDigest))
  76. if err != nil {
  77. c.Fatalf("unable to read blob: %s", err)
  78. }
  79. return manifestBlob
  80. }
  81. func (t *testRegistryV2) writeBlobContents(c *check.C, blobDigest digest.Digest, data []byte) {
  82. if err := ioutil.WriteFile(t.getBlobFilename(blobDigest), data, os.FileMode(0644)); err != nil {
  83. c.Fatalf("unable to write malicious data blob: %s", err)
  84. }
  85. }
  86. func (t *testRegistryV2) tempMoveBlobData(c *check.C, blobDigest digest.Digest) (undo func()) {
  87. tempFile, err := ioutil.TempFile("", "registry-temp-blob-")
  88. if err != nil {
  89. c.Fatalf("unable to get temporary blob file: %s", err)
  90. }
  91. tempFile.Close()
  92. blobFilename := t.getBlobFilename(blobDigest)
  93. // Move the existing data file aside, so that we can replace it with a
  94. // another blob of data.
  95. if err := os.Rename(blobFilename, tempFile.Name()); err != nil {
  96. os.Remove(tempFile.Name())
  97. c.Fatalf("unable to move data blob: %s", err)
  98. }
  99. return func() {
  100. os.Rename(tempFile.Name(), blobFilename)
  101. os.Remove(tempFile.Name())
  102. }
  103. }