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