1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Add a registry package with registry v1/v2 code

This extract what was in registry_test.go and
registry_mock_test.go. This also move `RegistryHosting`
requirement to `registry.Hosting`

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
Vincent Demeester 2016-12-30 19:10:04 +01:00
parent 5374d53322
commit 4300e5e881
No known key found for this signature in database
GPG key ID: 083CC6FD6EB699A3
13 changed files with 168 additions and 123 deletions

View file

@ -16,6 +16,7 @@ import (
cliconfig "github.com/docker/docker/cli/config" cliconfig "github.com/docker/docker/cli/config"
"github.com/docker/docker/integration-cli/daemon" "github.com/docker/docker/integration-cli/daemon"
"github.com/docker/docker/integration-cli/environment" "github.com/docker/docker/integration-cli/environment"
"github.com/docker/docker/integration-cli/registry"
"github.com/docker/docker/pkg/reexec" "github.com/docker/docker/pkg/reexec"
"github.com/go-check/check" "github.com/go-check/check"
) )
@ -172,7 +173,7 @@ func init() {
type DockerRegistrySuite struct { type DockerRegistrySuite struct {
ds *DockerSuite ds *DockerSuite
reg *testRegistryV2 reg *registry.V2
d *daemon.Daemon d *daemon.Daemon
} }
@ -181,7 +182,7 @@ func (s *DockerRegistrySuite) OnTimeout(c *check.C) {
} }
func (s *DockerRegistrySuite) SetUpTest(c *check.C) { func (s *DockerRegistrySuite) SetUpTest(c *check.C) {
testRequires(c, DaemonIsLinux, RegistryHosting) testRequires(c, DaemonIsLinux, registry.Hosting)
s.reg = setupRegistry(c, false, "", "") s.reg = setupRegistry(c, false, "", "")
s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
Experimental: experimentalDaemon, Experimental: experimentalDaemon,
@ -206,7 +207,7 @@ func init() {
type DockerSchema1RegistrySuite struct { type DockerSchema1RegistrySuite struct {
ds *DockerSuite ds *DockerSuite
reg *testRegistryV2 reg *registry.V2
d *daemon.Daemon d *daemon.Daemon
} }
@ -215,7 +216,7 @@ func (s *DockerSchema1RegistrySuite) OnTimeout(c *check.C) {
} }
func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) { func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) {
testRequires(c, DaemonIsLinux, RegistryHosting, NotArm64) testRequires(c, DaemonIsLinux, registry.Hosting, NotArm64)
s.reg = setupRegistry(c, true, "", "") s.reg = setupRegistry(c, true, "", "")
s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
Experimental: experimentalDaemon, Experimental: experimentalDaemon,
@ -240,7 +241,7 @@ func init() {
type DockerRegistryAuthHtpasswdSuite struct { type DockerRegistryAuthHtpasswdSuite struct {
ds *DockerSuite ds *DockerSuite
reg *testRegistryV2 reg *registry.V2
d *daemon.Daemon d *daemon.Daemon
} }
@ -249,7 +250,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) OnTimeout(c *check.C) {
} }
func (s *DockerRegistryAuthHtpasswdSuite) SetUpTest(c *check.C) { func (s *DockerRegistryAuthHtpasswdSuite) SetUpTest(c *check.C) {
testRequires(c, DaemonIsLinux, RegistryHosting) testRequires(c, DaemonIsLinux, registry.Hosting)
s.reg = setupRegistry(c, false, "htpasswd", "") s.reg = setupRegistry(c, false, "htpasswd", "")
s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
Experimental: experimentalDaemon, Experimental: experimentalDaemon,
@ -276,7 +277,7 @@ func init() {
type DockerRegistryAuthTokenSuite struct { type DockerRegistryAuthTokenSuite struct {
ds *DockerSuite ds *DockerSuite
reg *testRegistryV2 reg *registry.V2
d *daemon.Daemon d *daemon.Daemon
} }
@ -285,7 +286,7 @@ func (s *DockerRegistryAuthTokenSuite) OnTimeout(c *check.C) {
} }
func (s *DockerRegistryAuthTokenSuite) SetUpTest(c *check.C) { func (s *DockerRegistryAuthTokenSuite) SetUpTest(c *check.C) {
testRequires(c, DaemonIsLinux, RegistryHosting) testRequires(c, DaemonIsLinux, registry.Hosting)
s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
Experimental: experimentalDaemon, Experimental: experimentalDaemon,
}) })
@ -449,12 +450,12 @@ func init() {
type DockerTrustSuite struct { type DockerTrustSuite struct {
ds *DockerSuite ds *DockerSuite
reg *testRegistryV2 reg *registry.V2
not *testNotary not *testNotary
} }
func (s *DockerTrustSuite) SetUpTest(c *check.C) { func (s *DockerTrustSuite) SetUpTest(c *check.C) {
testRequires(c, RegistryHosting, NotaryServerHosting) testRequires(c, registry.Hosting, NotaryServerHosting)
s.reg = setupRegistry(c, false, "", "") s.reg = setupRegistry(c, false, "", "")
s.not = setupNotary(c) s.not = setupNotary(c)
} }
@ -487,7 +488,7 @@ func init() {
type DockerTrustedSwarmSuite struct { type DockerTrustedSwarmSuite struct {
swarmSuite DockerSwarmSuite swarmSuite DockerSwarmSuite
trustSuite DockerTrustSuite trustSuite DockerTrustSuite
reg *testRegistryV2 reg *registry.V2
not *testNotary not *testNotary
} }

View file

@ -6580,7 +6580,7 @@ func (s *DockerSuite) TestBuildLabelOverwrite(c *check.C) {
} }
func (s *DockerRegistryAuthHtpasswdSuite) TestBuildFromAuthenticatedRegistry(c *check.C) { func (s *DockerRegistryAuthHtpasswdSuite) TestBuildFromAuthenticatedRegistry(c *check.C) {
dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL) dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
baseImage := privateRegistryURL + "/baseimage" baseImage := privateRegistryURL + "/baseimage"
@ -6625,7 +6625,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestBuildWithExternalAuth(c *check.C)
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644) err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL) dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
b, err := ioutil.ReadFile(configPath) b, err := ioutil.ReadFile(configPath)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)

View file

@ -533,7 +533,7 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredManifest(c *check.C) {
c.Assert(err, checker.IsNil, check.Commentf("error setting up image")) c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
// Load the target manifest blob. // Load the target manifest blob.
manifestBlob := s.reg.readBlobContents(c, manifestDigest) manifestBlob := s.reg.ReadBlobContents(c, manifestDigest)
var imgManifest schema2.Manifest var imgManifest schema2.Manifest
err = json.Unmarshal(manifestBlob, &imgManifest) err = json.Unmarshal(manifestBlob, &imgManifest)
@ -544,13 +544,13 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredManifest(c *check.C) {
// Move the existing data file aside, so that we can replace it with a // Move the existing data file aside, so that we can replace it with a
// malicious blob of data. NOTE: we defer the returned undo func. // malicious blob of data. NOTE: we defer the returned undo func.
undo := s.reg.tempMoveBlobData(c, manifestDigest) undo := s.reg.TempMoveBlobData(c, manifestDigest)
defer undo() defer undo()
alteredManifestBlob, err := json.MarshalIndent(imgManifest, "", " ") alteredManifestBlob, err := json.MarshalIndent(imgManifest, "", " ")
c.Assert(err, checker.IsNil, check.Commentf("unable to encode altered image manifest to JSON")) c.Assert(err, checker.IsNil, check.Commentf("unable to encode altered image manifest to JSON"))
s.reg.writeBlobContents(c, manifestDigest, alteredManifestBlob) s.reg.WriteBlobContents(c, manifestDigest, alteredManifestBlob)
// Now try pulling that image by digest. We should get an error about // Now try pulling that image by digest. We should get an error about
// digest verification for the manifest digest. // digest verification for the manifest digest.
@ -573,7 +573,7 @@ func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredManifest(c *check.C
c.Assert(err, checker.IsNil, check.Commentf("error setting up image")) c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
// Load the target manifest blob. // Load the target manifest blob.
manifestBlob := s.reg.readBlobContents(c, manifestDigest) manifestBlob := s.reg.ReadBlobContents(c, manifestDigest)
var imgManifest schema1.Manifest var imgManifest schema1.Manifest
err = json.Unmarshal(manifestBlob, &imgManifest) err = json.Unmarshal(manifestBlob, &imgManifest)
@ -586,13 +586,13 @@ func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredManifest(c *check.C
// Move the existing data file aside, so that we can replace it with a // Move the existing data file aside, so that we can replace it with a
// malicious blob of data. NOTE: we defer the returned undo func. // malicious blob of data. NOTE: we defer the returned undo func.
undo := s.reg.tempMoveBlobData(c, manifestDigest) undo := s.reg.TempMoveBlobData(c, manifestDigest)
defer undo() defer undo()
alteredManifestBlob, err := json.MarshalIndent(imgManifest, "", " ") alteredManifestBlob, err := json.MarshalIndent(imgManifest, "", " ")
c.Assert(err, checker.IsNil, check.Commentf("unable to encode altered image manifest to JSON")) c.Assert(err, checker.IsNil, check.Commentf("unable to encode altered image manifest to JSON"))
s.reg.writeBlobContents(c, manifestDigest, alteredManifestBlob) s.reg.WriteBlobContents(c, manifestDigest, alteredManifestBlob)
// Now try pulling that image by digest. We should get an error about // Now try pulling that image by digest. We should get an error about
// digest verification for the manifest digest. // digest verification for the manifest digest.
@ -615,7 +615,7 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
// Load the target manifest blob. // Load the target manifest blob.
manifestBlob := s.reg.readBlobContents(c, manifestDigest) manifestBlob := s.reg.ReadBlobContents(c, manifestDigest)
var imgManifest schema2.Manifest var imgManifest schema2.Manifest
err = json.Unmarshal(manifestBlob, &imgManifest) err = json.Unmarshal(manifestBlob, &imgManifest)
@ -626,11 +626,11 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) {
// Move the existing data file aside, so that we can replace it with a // Move the existing data file aside, so that we can replace it with a
// malicious blob of data. NOTE: we defer the returned undo func. // malicious blob of data. NOTE: we defer the returned undo func.
undo := s.reg.tempMoveBlobData(c, targetLayerDigest) undo := s.reg.TempMoveBlobData(c, targetLayerDigest)
defer undo() defer undo()
// Now make a fake data blob in this directory. // Now make a fake data blob in this directory.
s.reg.writeBlobContents(c, targetLayerDigest, []byte("This is not the data you are looking for.")) s.reg.WriteBlobContents(c, targetLayerDigest, []byte("This is not the data you are looking for."))
// Now try pulling that image by digest. We should get an error about // Now try pulling that image by digest. We should get an error about
// digest verification for the target layer digest. // digest verification for the target layer digest.
@ -658,7 +658,7 @@ func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
// Load the target manifest blob. // Load the target manifest blob.
manifestBlob := s.reg.readBlobContents(c, manifestDigest) manifestBlob := s.reg.ReadBlobContents(c, manifestDigest)
var imgManifest schema1.Manifest var imgManifest schema1.Manifest
err = json.Unmarshal(manifestBlob, &imgManifest) err = json.Unmarshal(manifestBlob, &imgManifest)
@ -669,11 +669,11 @@ func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) {
// Move the existing data file aside, so that we can replace it with a // Move the existing data file aside, so that we can replace it with a
// malicious blob of data. NOTE: we defer the returned undo func. // malicious blob of data. NOTE: we defer the returned undo func.
undo := s.reg.tempMoveBlobData(c, targetLayerDigest) undo := s.reg.TempMoveBlobData(c, targetLayerDigest)
defer undo() defer undo()
// Now make a fake data blob in this directory. // Now make a fake data blob in this directory.
s.reg.writeBlobContents(c, targetLayerDigest, []byte("This is not the data you are looking for.")) s.reg.WriteBlobContents(c, targetLayerDigest, []byte("This is not the data you are looking for."))
// Now try pulling that image by digest. We should get an error about // Now try pulling that image by digest. We should get an error about
// digest verification for the target layer digest. // digest verification for the target layer digest.

View file

@ -21,10 +21,10 @@ func (s *DockerSuite) TestLoginWithoutTTY(c *check.C) {
func (s *DockerRegistryAuthHtpasswdSuite) TestLoginToPrivateRegistry(c *check.C) { func (s *DockerRegistryAuthHtpasswdSuite) TestLoginToPrivateRegistry(c *check.C) {
// wrong credentials // wrong credentials
out, _, err := dockerCmdWithError("login", "-u", s.reg.username, "-p", "WRONGPASSWORD", privateRegistryURL) out, _, err := dockerCmdWithError("login", "-u", s.reg.Username(), "-p", "WRONGPASSWORD", privateRegistryURL)
c.Assert(err, checker.NotNil, check.Commentf(out)) c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "401 Unauthorized") c.Assert(out, checker.Contains, "401 Unauthorized")
// now it's fine // now it's fine
dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL) dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
} }

View file

@ -35,7 +35,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithExternalAuth(c *check.C)
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644) err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL) dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
b, err := ioutil.ReadFile(configPath) b, err := ioutil.ReadFile(configPath)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
@ -71,7 +71,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithWrongHostnamesStored(c *
os.Setenv("PATH", testPath) os.Setenv("PATH", testPath)
cmd := exec.Command("docker-credential-shell-test", "store") cmd := exec.Command("docker-credential-shell-test", "store")
stdin := bytes.NewReader([]byte(fmt.Sprintf(`{"ServerURL": "https://%s", "Username": "%s", "Secret": "%s"}`, privateRegistryURL, s.reg.username, s.reg.password))) stdin := bytes.NewReader([]byte(fmt.Sprintf(`{"ServerURL": "https://%s", "Username": "%s", "Secret": "%s"}`, privateRegistryURL, s.reg.Username(), s.reg.Password())))
cmd.Stdin = stdin cmd.Stdin = stdin
c.Assert(cmd.Run(), checker.IsNil) c.Assert(cmd.Run(), checker.IsNil)
@ -84,7 +84,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithWrongHostnamesStored(c *
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644) err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL) dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
b, err := ioutil.ReadFile(configPath) b, err := ioutil.ReadFile(configPath)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)

View file

@ -347,7 +347,7 @@ func (s *DockerRegistrySuite) TestPullManifestList(c *check.C) {
manifestListDigest := digest.FromBytes(manifestListJSON) manifestListDigest := digest.FromBytes(manifestListJSON)
hexDigest := manifestListDigest.Hex() hexDigest := manifestListDigest.Hex()
registryV2Path := filepath.Join(s.reg.dir, "docker", "registry", "v2") registryV2Path := s.reg.Path()
// Write manifest list to blob store // Write manifest list to blob store
blobDir := filepath.Join(registryV2Path, "blobs", "sha256", hexDigest[:2], hexDigest) blobDir := filepath.Join(registryV2Path, "blobs", "sha256", hexDigest[:2], hexDigest)
@ -411,7 +411,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuthLoginWithSchem
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644) err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL) dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
b, err := ioutil.ReadFile(configPath) b, err := ioutil.ReadFile(configPath)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
@ -421,7 +421,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuthLoginWithSchem
dockerCmd(c, "--config", tmp, "push", repoName) dockerCmd(c, "--config", tmp, "push", repoName)
dockerCmd(c, "--config", tmp, "logout", privateRegistryURL) dockerCmd(c, "--config", tmp, "logout", privateRegistryURL)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, "https://"+privateRegistryURL) dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), "https://"+privateRegistryURL)
dockerCmd(c, "--config", tmp, "pull", repoName) dockerCmd(c, "--config", tmp, "pull", repoName)
// likewise push should work // likewise push should work
@ -456,7 +456,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuth(c *check.C) {
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644) err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.username, "-p", s.reg.password, privateRegistryURL) dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
b, err := ioutil.ReadFile(configPath) b, err := ioutil.ReadFile(configPath)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)

View file

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"regexp" "regexp"
"github.com/docker/docker/integration-cli/registry"
"github.com/go-check/check" "github.com/go-check/check"
) )
@ -46,8 +47,8 @@ func regexpCheckUA(c *check.C, ua string) {
c.Assert(bMatchUpstreamUA, check.Equals, true, check.Commentf("(Upstream) Docker Client User-Agent malformed")) c.Assert(bMatchUpstreamUA, check.Equals, true, check.Commentf("(Upstream) Docker Client User-Agent malformed"))
} }
func registerUserAgentHandler(reg *testRegistry, result *string) { func registerUserAgentHandler(reg *registry.Mock, result *string) {
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) { reg.RegisterHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(404) w.WriteHeader(404)
var ua string var ua string
for k, v := range r.Header { for k, v := range r.Header {
@ -70,30 +71,30 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *check.C) {
loginUA string loginUA string
) )
buildReg, err := newTestRegistry(c) buildReg, err := registry.NewMock(c)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
registerUserAgentHandler(buildReg, &buildUA) registerUserAgentHandler(buildReg, &buildUA)
buildRepoName := fmt.Sprintf("%s/busybox", buildReg.hostport) buildRepoName := fmt.Sprintf("%s/busybox", buildReg.URL())
pullReg, err := newTestRegistry(c) pullReg, err := registry.NewMock(c)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
registerUserAgentHandler(pullReg, &pullUA) registerUserAgentHandler(pullReg, &pullUA)
pullRepoName := fmt.Sprintf("%s/busybox", pullReg.hostport) pullRepoName := fmt.Sprintf("%s/busybox", pullReg.URL())
pushReg, err := newTestRegistry(c) pushReg, err := registry.NewMock(c)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
registerUserAgentHandler(pushReg, &pushUA) registerUserAgentHandler(pushReg, &pushUA)
pushRepoName := fmt.Sprintf("%s/busybox", pushReg.hostport) pushRepoName := fmt.Sprintf("%s/busybox", pushReg.URL())
loginReg, err := newTestRegistry(c) loginReg, err := registry.NewMock(c)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
registerUserAgentHandler(loginReg, &loginUA) registerUserAgentHandler(loginReg, &loginUA)
s.d.Start(c, s.d.Start(c,
"--insecure-registry", buildReg.hostport, "--insecure-registry", buildReg.URL(),
"--insecure-registry", pullReg.hostport, "--insecure-registry", pullReg.URL(),
"--insecure-registry", pushReg.hostport, "--insecure-registry", pushReg.URL(),
"--insecure-registry", loginReg.hostport, "--insecure-registry", loginReg.URL(),
"--disable-legacy-registry=true") "--disable-legacy-registry=true")
dockerfileName, cleanup1, err := makefile(fmt.Sprintf("FROM %s", buildRepoName)) dockerfileName, cleanup1, err := makefile(fmt.Sprintf("FROM %s", buildRepoName))
@ -102,7 +103,7 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *check.C) {
s.d.Cmd("build", "--file", dockerfileName, ".") s.d.Cmd("build", "--file", dockerfileName, ".")
regexpCheckUA(c, buildUA) regexpCheckUA(c, buildUA)
s.d.Cmd("login", "-u", "richard", "-p", "testtest", loginReg.hostport) s.d.Cmd("login", "-u", "richard", "-p", "testtest", loginReg.URL())
regexpCheckUA(c, loginUA) regexpCheckUA(c, loginUA)
s.d.Cmd("pull", pullRepoName) s.d.Cmd("pull", pullRepoName)

View file

@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"os" "os"
"github.com/docker/docker/integration-cli/registry"
"github.com/go-check/check" "github.com/go-check/check"
) )
@ -36,29 +37,29 @@ func makefile(contents string) (string, func(), error) {
// TestV2Only ensures that a daemon in v2-only mode does not // TestV2Only ensures that a daemon in v2-only mode does not
// attempt to contact any v1 registry endpoints. // attempt to contact any v1 registry endpoints.
func (s *DockerRegistrySuite) TestV2Only(c *check.C) { func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
reg, err := newTestRegistry(c) reg, err := registry.NewMock(c)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) { reg.RegisterHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(404) w.WriteHeader(404)
}) })
reg.registerHandler("/v1/.*", func(w http.ResponseWriter, r *http.Request) { reg.RegisterHandler("/v1/.*", func(w http.ResponseWriter, r *http.Request) {
c.Fatal("V1 registry contacted") c.Fatal("V1 registry contacted")
}) })
repoName := fmt.Sprintf("%s/busybox", reg.hostport) repoName := fmt.Sprintf("%s/busybox", reg.URL())
s.d.Start(c, "--insecure-registry", reg.hostport, "--disable-legacy-registry=true") s.d.Start(c, "--insecure-registry", reg.URL(), "--disable-legacy-registry=true")
dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.hostport)) dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.URL()))
c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile")) c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
defer cleanup() defer cleanup()
s.d.Cmd("build", "--file", dockerfileName, ".") s.d.Cmd("build", "--file", dockerfileName, ".")
s.d.Cmd("run", repoName) s.d.Cmd("run", repoName)
s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", reg.hostport) s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", reg.URL())
s.d.Cmd("tag", "busybox", repoName) s.d.Cmd("tag", "busybox", repoName)
s.d.Cmd("push", repoName) s.d.Cmd("push", repoName)
s.d.Cmd("pull", repoName) s.d.Cmd("pull", repoName)
@ -68,49 +69,49 @@ func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
// and ensure v1 endpoints are hit for the following operations: // and ensure v1 endpoints are hit for the following operations:
// login, push, pull, build & run // login, push, pull, build & run
func (s *DockerRegistrySuite) TestV1(c *check.C) { func (s *DockerRegistrySuite) TestV1(c *check.C) {
reg, err := newTestRegistry(c) reg, err := registry.NewMock(c)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
v2Pings := 0 v2Pings := 0
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) { reg.RegisterHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
v2Pings++ v2Pings++
// V2 ping 404 causes fallback to v1 // V2 ping 404 causes fallback to v1
w.WriteHeader(404) w.WriteHeader(404)
}) })
v1Pings := 0 v1Pings := 0
reg.registerHandler("/v1/_ping", func(w http.ResponseWriter, r *http.Request) { reg.RegisterHandler("/v1/_ping", func(w http.ResponseWriter, r *http.Request) {
v1Pings++ v1Pings++
}) })
v1Logins := 0 v1Logins := 0
reg.registerHandler("/v1/users/", func(w http.ResponseWriter, r *http.Request) { reg.RegisterHandler("/v1/users/", func(w http.ResponseWriter, r *http.Request) {
v1Logins++ v1Logins++
}) })
v1Repo := 0 v1Repo := 0
reg.registerHandler("/v1/repositories/busybox/", func(w http.ResponseWriter, r *http.Request) { reg.RegisterHandler("/v1/repositories/busybox/", func(w http.ResponseWriter, r *http.Request) {
v1Repo++ v1Repo++
}) })
reg.registerHandler("/v1/repositories/busybox/images", func(w http.ResponseWriter, r *http.Request) { reg.RegisterHandler("/v1/repositories/busybox/images", func(w http.ResponseWriter, r *http.Request) {
v1Repo++ v1Repo++
}) })
s.d.Start(c, "--insecure-registry", reg.hostport, "--disable-legacy-registry=false") s.d.Start(c, "--insecure-registry", reg.URL(), "--disable-legacy-registry=false")
dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.hostport)) dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.URL()))
c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile")) c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
defer cleanup() defer cleanup()
s.d.Cmd("build", "--file", dockerfileName, ".") s.d.Cmd("build", "--file", dockerfileName, ".")
c.Assert(v1Repo, check.Equals, 1, check.Commentf("Expected v1 repository access after build")) c.Assert(v1Repo, check.Equals, 1, check.Commentf("Expected v1 repository access after build"))
repoName := fmt.Sprintf("%s/busybox", reg.hostport) repoName := fmt.Sprintf("%s/busybox", reg.URL())
s.d.Cmd("run", repoName) s.d.Cmd("run", repoName)
c.Assert(v1Repo, check.Equals, 2, check.Commentf("Expected v1 repository access after run")) c.Assert(v1Repo, check.Equals, 2, check.Commentf("Expected v1 repository access after run"))
s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.hostport) s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.URL())
c.Assert(v1Logins, check.Equals, 1, check.Commentf("Expected v1 login attempt")) c.Assert(v1Logins, check.Equals, 1, check.Commentf("Expected v1 login attempt"))
s.d.Cmd("tag", "busybox", repoName) s.d.Cmd("tag", "busybox", repoName)

View file

@ -24,6 +24,7 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
volumetypes "github.com/docker/docker/api/types/volume" volumetypes "github.com/docker/docker/api/types/volume"
"github.com/docker/docker/integration-cli/daemon" "github.com/docker/docker/integration-cli/daemon"
"github.com/docker/docker/integration-cli/registry"
"github.com/docker/docker/opts" "github.com/docker/docker/opts"
"github.com/docker/docker/pkg/integration" "github.com/docker/docker/pkg/integration"
"github.com/docker/docker/pkg/integration/checker" "github.com/docker/docker/pkg/integration/checker"
@ -1083,8 +1084,8 @@ func parseEventTime(t time.Time) string {
return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())) return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond()))
} }
func setupRegistry(c *check.C, schema1 bool, auth, tokenURL string) *testRegistryV2 { func setupRegistry(c *check.C, schema1 bool, auth, tokenURL string) *registry.V2 {
reg, err := newTestRegistryV2(c, schema1, auth, tokenURL) reg, err := registry.NewV2(schema1, auth, tokenURL, privateRegistryURL)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
// Wait for registry to be ready to serve requests. // Wait for registry to be ready to serve requests.

View file

@ -1,4 +1,4 @@
package main package registry
import ( import (
"fmt" "fmt"
@ -9,7 +9,6 @@ import (
"path/filepath" "path/filepath"
"github.com/docker/distribution/digest" "github.com/docker/distribution/digest"
"github.com/go-check/check"
) )
const ( const (
@ -17,8 +16,20 @@ const (
v2binarySchema1 = "registry-v2-schema1" v2binarySchema1 = "registry-v2-schema1"
) )
type testRegistryV2 struct { type testingT interface {
logT
Fatal(...interface{})
Fatalf(string, ...interface{})
}
type logT interface {
Logf(string, ...interface{})
}
// V2 represent a registry version 2
type V2 struct {
cmd *exec.Cmd cmd *exec.Cmd
registryURL string
dir string dir string
auth string auth string
username string username string
@ -26,7 +37,8 @@ type testRegistryV2 struct {
email string email string
} }
func newTestRegistryV2(c *check.C, schema1 bool, auth, tokenURL string) (*testRegistryV2, error) { // NewV2 creates a v2 registry server
func NewV2(schema1 bool, auth, tokenURL, registryURL string) (*V2, error) {
tmp, err := ioutil.TempDir("", "registry-test-") tmp, err := ioutil.TempDir("", "registry-test-")
if err != nil { if err != nil {
return nil, err return nil, err
@ -78,7 +90,7 @@ http:
} }
defer config.Close() defer config.Close()
if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL, authTemplate); err != nil { if _, err := fmt.Fprintf(config, template, tmp, registryURL, authTemplate); err != nil {
os.RemoveAll(tmp) os.RemoveAll(tmp)
return nil, err return nil, err
} }
@ -90,31 +102,30 @@ http:
cmd := exec.Command(binary, confPath) cmd := exec.Command(binary, confPath)
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
os.RemoveAll(tmp) os.RemoveAll(tmp)
if os.IsNotExist(err) {
c.Skip(err.Error())
}
return nil, err return nil, err
} }
return &testRegistryV2{ return &V2{
cmd: cmd, cmd: cmd,
dir: tmp, dir: tmp,
auth: auth, auth: auth,
username: username, username: username,
password: password, password: password,
email: email, email: email,
registryURL: registryURL,
}, nil }, nil
} }
func (t *testRegistryV2) Ping() error { // Ping sends an http request to the current registry, and fail if it doesn't respond correctly
func (r *V2) Ping() error {
// We always ping through HTTP for our test registry. // We always ping through HTTP for our test registry.
resp, err := http.Get(fmt.Sprintf("http://%s/v2/", privateRegistryURL)) resp, err := http.Get(fmt.Sprintf("http://%s/v2/", r.registryURL))
if err != nil { if err != nil {
return err return err
} }
resp.Body.Close() resp.Body.Close()
fail := resp.StatusCode != http.StatusOK fail := resp.StatusCode != http.StatusOK
if t.auth != "" { if r.auth != "" {
// unauthorized is a _good_ status when pinging v2/ and it needs auth // unauthorized is a _good_ status when pinging v2/ and it needs auth
fail = fail && resp.StatusCode != http.StatusUnauthorized fail = fail && resp.StatusCode != http.StatusUnauthorized
} }
@ -124,50 +135,55 @@ func (t *testRegistryV2) Ping() error {
return nil return nil
} }
func (t *testRegistryV2) Close() { // Close kills the registry server
t.cmd.Process.Kill() func (r *V2) Close() {
os.RemoveAll(t.dir) r.cmd.Process.Kill()
os.RemoveAll(r.dir)
} }
func (t *testRegistryV2) getBlobFilename(blobDigest digest.Digest) string { func (r *V2) getBlobFilename(blobDigest digest.Digest) string {
// Split the digest into its algorithm and hex components. // Split the digest into its algorithm and hex components.
dgstAlg, dgstHex := blobDigest.Algorithm(), blobDigest.Hex() dgstAlg, dgstHex := blobDigest.Algorithm(), blobDigest.Hex()
// The path to the target blob data looks something like: // The path to the target blob data looks something like:
// baseDir + "docker/registry/v2/blobs/sha256/a3/a3ed...46d4/data" // 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) return fmt.Sprintf("%s/docker/registry/v2/blobs/%s/%s/%s/data", r.dir, dgstAlg, dgstHex[:2], dgstHex)
} }
func (t *testRegistryV2) readBlobContents(c *check.C, blobDigest digest.Digest) []byte { // ReadBlobContents read the file corresponding to the specified digest
func (r *V2) ReadBlobContents(t testingT, blobDigest digest.Digest) []byte {
// Load the target manifest blob. // Load the target manifest blob.
manifestBlob, err := ioutil.ReadFile(t.getBlobFilename(blobDigest)) manifestBlob, err := ioutil.ReadFile(r.getBlobFilename(blobDigest))
if err != nil { if err != nil {
c.Fatalf("unable to read blob: %s", err) t.Fatalf("unable to read blob: %s", err)
} }
return manifestBlob return manifestBlob
} }
func (t *testRegistryV2) writeBlobContents(c *check.C, blobDigest digest.Digest, data []byte) { // WriteBlobContents write the file corresponding to the specified digest with the given content
if err := ioutil.WriteFile(t.getBlobFilename(blobDigest), data, os.FileMode(0644)); err != nil { func (r *V2) WriteBlobContents(t testingT, blobDigest digest.Digest, data []byte) {
c.Fatalf("unable to write malicious data blob: %s", err) if err := ioutil.WriteFile(r.getBlobFilename(blobDigest), data, os.FileMode(0644)); err != nil {
t.Fatalf("unable to write malicious data blob: %s", err)
} }
} }
func (t *testRegistryV2) tempMoveBlobData(c *check.C, blobDigest digest.Digest) (undo func()) { // TempMoveBlobData moves the existing data file aside, so that we can replace it with a
// malicious blob of data for example.
func (r *V2) TempMoveBlobData(t testingT, blobDigest digest.Digest) (undo func()) {
tempFile, err := ioutil.TempFile("", "registry-temp-blob-") tempFile, err := ioutil.TempFile("", "registry-temp-blob-")
if err != nil { if err != nil {
c.Fatalf("unable to get temporary blob file: %s", err) t.Fatalf("unable to get temporary blob file: %s", err)
} }
tempFile.Close() tempFile.Close()
blobFilename := t.getBlobFilename(blobDigest) blobFilename := r.getBlobFilename(blobDigest)
// Move the existing data file aside, so that we can replace it with a // Move the existing data file aside, so that we can replace it with a
// another blob of data. // another blob of data.
if err := os.Rename(blobFilename, tempFile.Name()); err != nil { if err := os.Rename(blobFilename, tempFile.Name()); err != nil {
os.Remove(tempFile.Name()) os.Remove(tempFile.Name())
c.Fatalf("unable to move data blob: %s", err) t.Fatalf("unable to move data blob: %s", err)
} }
return func() { return func() {
@ -175,3 +191,18 @@ func (t *testRegistryV2) tempMoveBlobData(c *check.C, blobDigest digest.Digest)
os.Remove(tempFile.Name()) os.Remove(tempFile.Name())
} }
} }
// Username returns the configured user name of the server
func (r *V2) Username() string {
return r.username
}
// Password returns the configured password of the server
func (r *V2) Password() string {
return r.password
}
// Path returns the path where the registry write data
func (r *V2) Path() string {
return filepath.Join(r.dir, "docker", "registry", "v2")
}

View file

@ -1,4 +1,4 @@
package main package registry
import ( import (
"net/http" "net/http"
@ -6,27 +6,28 @@ import (
"regexp" "regexp"
"strings" "strings"
"sync" "sync"
"github.com/go-check/check"
) )
type handlerFunc func(w http.ResponseWriter, r *http.Request) type handlerFunc func(w http.ResponseWriter, r *http.Request)
type testRegistry struct { // Mock represent a registry mock
type Mock struct {
server *httptest.Server server *httptest.Server
hostport string hostport string
handlers map[string]handlerFunc handlers map[string]handlerFunc
mu sync.Mutex mu sync.Mutex
} }
func (tr *testRegistry) registerHandler(path string, h handlerFunc) { // RegisterHandler register the specified handler for the registry mock
func (tr *Mock) RegisterHandler(path string, h handlerFunc) {
tr.mu.Lock() tr.mu.Lock()
defer tr.mu.Unlock() defer tr.mu.Unlock()
tr.handlers[path] = h tr.handlers[path] = h
} }
func newTestRegistry(c *check.C) (*testRegistry, error) { // NewMock creates a registry mock
testReg := &testRegistry{handlers: make(map[string]handlerFunc)} func NewMock(t testingT) (*Mock, error) {
testReg := &Mock{handlers: make(map[string]handlerFunc)}
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
url := r.URL.String() url := r.URL.String()
@ -36,7 +37,7 @@ func newTestRegistry(c *check.C) (*testRegistry, error) {
for re, function := range testReg.handlers { for re, function := range testReg.handlers {
matched, err = regexp.MatchString(re, url) matched, err = regexp.MatchString(re, url)
if err != nil { if err != nil {
c.Fatal("Error with handler regexp") t.Fatal("Error with handler regexp")
} }
if matched { if matched {
function(w, r) function(w, r)
@ -45,7 +46,7 @@ func newTestRegistry(c *check.C) (*testRegistry, error) {
} }
if !matched { if !matched {
c.Fatalf("Unable to match %s with regexp", url) t.Fatalf("Unable to match %s with regexp", url)
} }
})) }))
@ -53,3 +54,8 @@ func newTestRegistry(c *check.C) (*testRegistry, error) {
testReg.hostport = strings.Replace(ts.URL, "http://", "", 1) testReg.hostport = strings.Replace(ts.URL, "http://", "", 1)
return testReg, nil return testReg, nil
} }
// URL returns the url of the registry
func (tr *Mock) URL() string {
return tr.hostport
}

View file

@ -0,0 +1,12 @@
package registry
import "os/exec"
// Hosting returns wether the host can host a registry (v2) or not
func Hosting() bool {
// for now registry binary is built only if we're running inside
// container through `make test`. Figure that out by testing if
// registry binary is in PATH.
_, err := exec.LookPath(v2binary)
return err == nil
}

View file

@ -105,14 +105,6 @@ func Apparmor() bool {
return err == nil && len(buf) > 1 && buf[0] == 'Y' return err == nil && len(buf) > 1 && buf[0] == 'Y'
} }
func RegistryHosting() bool {
// for now registry binary is built only if we're running inside
// container through `make test`. Figure that out by testing if
// registry binary is in PATH.
_, err := exec.LookPath(v2binary)
return err == nil
}
func NotaryHosting() bool { func NotaryHosting() bool {
// for now notary binary is built only if we're running inside // for now notary binary is built only if we're running inside
// container through `make test`. Figure that out by testing if // container through `make test`. Figure that out by testing if