github.com/noxiouz/docker@v0.7.3-0.20160629055221-3d231c78e8c5/integration-cli/registry.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "os" 8 "os/exec" 9 "path/filepath" 10 11 "github.com/docker/distribution/digest" 12 "github.com/go-check/check" 13 ) 14 15 const ( 16 v2binary = "registry-v2" 17 v2binarySchema1 = "registry-v2-schema1" 18 ) 19 20 type testRegistryV2 struct { 21 cmd *exec.Cmd 22 dir string 23 auth string 24 username string 25 password string 26 email string 27 } 28 29 func newTestRegistryV2(c *check.C, schema1 bool, auth, tokenURL string) (*testRegistryV2, error) { 30 tmp, err := ioutil.TempDir("", "registry-test-") 31 if err != nil { 32 return nil, err 33 } 34 template := `version: 0.1 35 loglevel: debug 36 storage: 37 filesystem: 38 rootdirectory: %s 39 http: 40 addr: %s 41 %s` 42 var ( 43 authTemplate string 44 username string 45 password string 46 email string 47 ) 48 switch auth { 49 case "htpasswd": 50 htpasswdPath := filepath.Join(tmp, "htpasswd") 51 // generated with: htpasswd -Bbn testuser testpassword 52 userpasswd := "testuser:$2y$05$sBsSqk0OpSD1uTZkHXc4FeJ0Z70wLQdAX/82UiHuQOKbNbBrzs63m" 53 username = "testuser" 54 password = "testpassword" 55 email = "test@test.org" 56 if err := ioutil.WriteFile(htpasswdPath, []byte(userpasswd), os.FileMode(0644)); err != nil { 57 return nil, err 58 } 59 authTemplate = fmt.Sprintf(`auth: 60 htpasswd: 61 realm: basic-realm 62 path: %s 63 `, htpasswdPath) 64 case "token": 65 authTemplate = fmt.Sprintf(`auth: 66 token: 67 realm: %s 68 service: "registry" 69 issuer: "auth-registry" 70 rootcertbundle: "fixtures/registry/cert.pem" 71 `, tokenURL) 72 } 73 74 confPath := filepath.Join(tmp, "config.yaml") 75 config, err := os.Create(confPath) 76 if err != nil { 77 return nil, err 78 } 79 if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL, authTemplate); err != nil { 80 os.RemoveAll(tmp) 81 return nil, err 82 } 83 84 binary := v2binary 85 if schema1 { 86 binary = v2binarySchema1 87 } 88 cmd := exec.Command(binary, confPath) 89 if err := cmd.Start(); err != nil { 90 os.RemoveAll(tmp) 91 if os.IsNotExist(err) { 92 c.Skip(err.Error()) 93 } 94 return nil, err 95 } 96 return &testRegistryV2{ 97 cmd: cmd, 98 dir: tmp, 99 auth: auth, 100 username: username, 101 password: password, 102 email: email, 103 }, nil 104 } 105 106 func (t *testRegistryV2) Ping() error { 107 // We always ping through HTTP for our test registry. 108 resp, err := http.Get(fmt.Sprintf("http://%s/v2/", privateRegistryURL)) 109 if err != nil { 110 return err 111 } 112 resp.Body.Close() 113 114 fail := resp.StatusCode != http.StatusOK 115 if t.auth != "" { 116 // unauthorized is a _good_ status when pinging v2/ and it needs auth 117 fail = fail && resp.StatusCode != http.StatusUnauthorized 118 } 119 if fail { 120 return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode) 121 } 122 return nil 123 } 124 125 func (t *testRegistryV2) Close() { 126 t.cmd.Process.Kill() 127 os.RemoveAll(t.dir) 128 } 129 130 func (t *testRegistryV2) getBlobFilename(blobDigest digest.Digest) string { 131 // Split the digest into it's algorithm and hex components. 132 dgstAlg, dgstHex := blobDigest.Algorithm(), blobDigest.Hex() 133 134 // The path to the target blob data looks something like: 135 // baseDir + "docker/registry/v2/blobs/sha256/a3/a3ed...46d4/data" 136 return fmt.Sprintf("%s/docker/registry/v2/blobs/%s/%s/%s/data", t.dir, dgstAlg, dgstHex[:2], dgstHex) 137 } 138 139 func (t *testRegistryV2) readBlobContents(c *check.C, blobDigest digest.Digest) []byte { 140 // Load the target manifest blob. 141 manifestBlob, err := ioutil.ReadFile(t.getBlobFilename(blobDigest)) 142 if err != nil { 143 c.Fatalf("unable to read blob: %s", err) 144 } 145 146 return manifestBlob 147 } 148 149 func (t *testRegistryV2) writeBlobContents(c *check.C, blobDigest digest.Digest, data []byte) { 150 if err := ioutil.WriteFile(t.getBlobFilename(blobDigest), data, os.FileMode(0644)); err != nil { 151 c.Fatalf("unable to write malicious data blob: %s", err) 152 } 153 } 154 155 func (t *testRegistryV2) tempMoveBlobData(c *check.C, blobDigest digest.Digest) (undo func()) { 156 tempFile, err := ioutil.TempFile("", "registry-temp-blob-") 157 if err != nil { 158 c.Fatalf("unable to get temporary blob file: %s", err) 159 } 160 tempFile.Close() 161 162 blobFilename := t.getBlobFilename(blobDigest) 163 164 // Move the existing data file aside, so that we can replace it with a 165 // another blob of data. 166 if err := os.Rename(blobFilename, tempFile.Name()); err != nil { 167 os.Remove(tempFile.Name()) 168 c.Fatalf("unable to move data blob: %s", err) 169 } 170 171 return func() { 172 os.Rename(tempFile.Name(), blobFilename) 173 os.Remove(tempFile.Name()) 174 } 175 }