mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #29799 from vdemeester/integration-registry-package
[test-integration] Add a registry package with registry v1/v2 code
This commit is contained in:
commit
ed689c48b0
13 changed files with 168 additions and 123 deletions
|
@ -16,6 +16,7 @@ import (
|
|||
cliconfig "github.com/docker/docker/cli/config"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/docker/docker/integration-cli/environment"
|
||||
"github.com/docker/docker/integration-cli/registry"
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
@ -172,7 +173,7 @@ func init() {
|
|||
|
||||
type DockerRegistrySuite struct {
|
||||
ds *DockerSuite
|
||||
reg *testRegistryV2
|
||||
reg *registry.V2
|
||||
d *daemon.Daemon
|
||||
}
|
||||
|
||||
|
@ -181,7 +182,7 @@ func (s *DockerRegistrySuite) OnTimeout(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.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
|
||||
Experimental: experimentalDaemon,
|
||||
|
@ -206,7 +207,7 @@ func init() {
|
|||
|
||||
type DockerSchema1RegistrySuite struct {
|
||||
ds *DockerSuite
|
||||
reg *testRegistryV2
|
||||
reg *registry.V2
|
||||
d *daemon.Daemon
|
||||
}
|
||||
|
||||
|
@ -215,7 +216,7 @@ func (s *DockerSchema1RegistrySuite) OnTimeout(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.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
|
||||
Experimental: experimentalDaemon,
|
||||
|
@ -240,7 +241,7 @@ func init() {
|
|||
|
||||
type DockerRegistryAuthHtpasswdSuite struct {
|
||||
ds *DockerSuite
|
||||
reg *testRegistryV2
|
||||
reg *registry.V2
|
||||
d *daemon.Daemon
|
||||
}
|
||||
|
||||
|
@ -249,7 +250,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) OnTimeout(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.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
|
||||
Experimental: experimentalDaemon,
|
||||
|
@ -276,7 +277,7 @@ func init() {
|
|||
|
||||
type DockerRegistryAuthTokenSuite struct {
|
||||
ds *DockerSuite
|
||||
reg *testRegistryV2
|
||||
reg *registry.V2
|
||||
d *daemon.Daemon
|
||||
}
|
||||
|
||||
|
@ -285,7 +286,7 @@ func (s *DockerRegistryAuthTokenSuite) OnTimeout(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{
|
||||
Experimental: experimentalDaemon,
|
||||
})
|
||||
|
@ -449,12 +450,12 @@ func init() {
|
|||
|
||||
type DockerTrustSuite struct {
|
||||
ds *DockerSuite
|
||||
reg *testRegistryV2
|
||||
reg *registry.V2
|
||||
not *testNotary
|
||||
}
|
||||
|
||||
func (s *DockerTrustSuite) SetUpTest(c *check.C) {
|
||||
testRequires(c, RegistryHosting, NotaryServerHosting)
|
||||
testRequires(c, registry.Hosting, NotaryServerHosting)
|
||||
s.reg = setupRegistry(c, false, "", "")
|
||||
s.not = setupNotary(c)
|
||||
}
|
||||
|
@ -487,7 +488,7 @@ func init() {
|
|||
type DockerTrustedSwarmSuite struct {
|
||||
swarmSuite DockerSwarmSuite
|
||||
trustSuite DockerTrustSuite
|
||||
reg *testRegistryV2
|
||||
reg *registry.V2
|
||||
not *testNotary
|
||||
}
|
||||
|
||||
|
|
|
@ -6580,7 +6580,7 @@ func (s *DockerSuite) TestBuildLabelOverwrite(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"
|
||||
|
||||
|
@ -6625,7 +6625,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestBuildWithExternalAuth(c *check.C)
|
|||
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
|
||||
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)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
|
|
@ -533,7 +533,7 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredManifest(c *check.C) {
|
|||
c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
|
||||
|
||||
// Load the target manifest blob.
|
||||
manifestBlob := s.reg.readBlobContents(c, manifestDigest)
|
||||
manifestBlob := s.reg.ReadBlobContents(c, manifestDigest)
|
||||
|
||||
var imgManifest schema2.Manifest
|
||||
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
|
||||
// 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()
|
||||
|
||||
alteredManifestBlob, err := json.MarshalIndent(imgManifest, "", " ")
|
||||
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
|
||||
// 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"))
|
||||
|
||||
// Load the target manifest blob.
|
||||
manifestBlob := s.reg.readBlobContents(c, manifestDigest)
|
||||
manifestBlob := s.reg.ReadBlobContents(c, manifestDigest)
|
||||
|
||||
var imgManifest schema1.Manifest
|
||||
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
|
||||
// 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()
|
||||
|
||||
alteredManifestBlob, err := json.MarshalIndent(imgManifest, "", " ")
|
||||
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
|
||||
// digest verification for the manifest digest.
|
||||
|
@ -615,7 +615,7 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Load the target manifest blob.
|
||||
manifestBlob := s.reg.readBlobContents(c, manifestDigest)
|
||||
manifestBlob := s.reg.ReadBlobContents(c, manifestDigest)
|
||||
|
||||
var imgManifest schema2.Manifest
|
||||
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
|
||||
// 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()
|
||||
|
||||
// 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
|
||||
// digest verification for the target layer digest.
|
||||
|
@ -658,7 +658,7 @@ func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Load the target manifest blob.
|
||||
manifestBlob := s.reg.readBlobContents(c, manifestDigest)
|
||||
manifestBlob := s.reg.ReadBlobContents(c, manifestDigest)
|
||||
|
||||
var imgManifest schema1.Manifest
|
||||
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
|
||||
// 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()
|
||||
|
||||
// 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
|
||||
// digest verification for the target layer digest.
|
||||
|
|
|
@ -21,10 +21,10 @@ func (s *DockerSuite) TestLoginWithoutTTY(c *check.C) {
|
|||
|
||||
func (s *DockerRegistryAuthHtpasswdSuite) TestLoginToPrivateRegistry(c *check.C) {
|
||||
// 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(out, checker.Contains, "401 Unauthorized")
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithExternalAuth(c *check.C)
|
|||
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
|
||||
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)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
@ -71,7 +71,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithWrongHostnamesStored(c *
|
|||
os.Setenv("PATH", testPath)
|
||||
|
||||
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
|
||||
c.Assert(cmd.Run(), checker.IsNil)
|
||||
|
||||
|
@ -84,7 +84,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithWrongHostnamesStored(c *
|
|||
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
|
||||
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)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
|
|
@ -347,7 +347,7 @@ func (s *DockerRegistrySuite) TestPullManifestList(c *check.C) {
|
|||
manifestListDigest := digest.FromBytes(manifestListJSON)
|
||||
hexDigest := manifestListDigest.Hex()
|
||||
|
||||
registryV2Path := filepath.Join(s.reg.dir, "docker", "registry", "v2")
|
||||
registryV2Path := s.reg.Path()
|
||||
|
||||
// Write manifest list to blob store
|
||||
blobDir := filepath.Join(registryV2Path, "blobs", "sha256", hexDigest[:2], hexDigest)
|
||||
|
@ -411,7 +411,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuthLoginWithSchem
|
|||
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
|
||||
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)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
@ -421,7 +421,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuthLoginWithSchem
|
|||
dockerCmd(c, "--config", tmp, "push", repoName)
|
||||
|
||||
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)
|
||||
|
||||
// likewise push should work
|
||||
|
@ -456,7 +456,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuth(c *check.C) {
|
|||
err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
|
||||
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)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"regexp"
|
||||
|
||||
"github.com/docker/docker/integration-cli/registry"
|
||||
"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"))
|
||||
}
|
||||
|
||||
func registerUserAgentHandler(reg *testRegistry, result *string) {
|
||||
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
|
||||
func registerUserAgentHandler(reg *registry.Mock, result *string) {
|
||||
reg.RegisterHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(404)
|
||||
var ua string
|
||||
for k, v := range r.Header {
|
||||
|
@ -70,30 +71,30 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *check.C) {
|
|||
loginUA string
|
||||
)
|
||||
|
||||
buildReg, err := newTestRegistry(c)
|
||||
buildReg, err := registry.NewMock(c)
|
||||
c.Assert(err, check.IsNil)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
registerUserAgentHandler(loginReg, &loginUA)
|
||||
|
||||
s.d.Start(c,
|
||||
"--insecure-registry", buildReg.hostport,
|
||||
"--insecure-registry", pullReg.hostport,
|
||||
"--insecure-registry", pushReg.hostport,
|
||||
"--insecure-registry", loginReg.hostport,
|
||||
"--insecure-registry", buildReg.URL(),
|
||||
"--insecure-registry", pullReg.URL(),
|
||||
"--insecure-registry", pushReg.URL(),
|
||||
"--insecure-registry", loginReg.URL(),
|
||||
"--disable-legacy-registry=true")
|
||||
|
||||
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, ".")
|
||||
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)
|
||||
|
||||
s.d.Cmd("pull", pullRepoName)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/integration-cli/registry"
|
||||
"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
|
||||
// attempt to contact any v1 registry endpoints.
|
||||
func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
|
||||
reg, err := newTestRegistry(c)
|
||||
reg, err := registry.NewMock(c)
|
||||
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)
|
||||
})
|
||||
|
||||
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")
|
||||
})
|
||||
|
||||
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"))
|
||||
defer cleanup()
|
||||
|
||||
s.d.Cmd("build", "--file", dockerfileName, ".")
|
||||
|
||||
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("push", 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:
|
||||
// login, push, pull, build & run
|
||||
func (s *DockerRegistrySuite) TestV1(c *check.C) {
|
||||
reg, err := newTestRegistry(c)
|
||||
reg, err := registry.NewMock(c)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
v2Pings := 0
|
||||
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
|
||||
reg.RegisterHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
|
||||
v2Pings++
|
||||
// V2 ping 404 causes fallback to v1
|
||||
w.WriteHeader(404)
|
||||
})
|
||||
|
||||
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++
|
||||
})
|
||||
|
||||
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++
|
||||
})
|
||||
|
||||
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++
|
||||
})
|
||||
|
||||
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++
|
||||
})
|
||||
|
||||
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"))
|
||||
defer cleanup()
|
||||
|
||||
s.d.Cmd("build", "--file", dockerfileName, ".")
|
||||
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)
|
||||
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"))
|
||||
|
||||
s.d.Cmd("tag", "busybox", repoName)
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
volumetypes "github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/docker/docker/integration-cli/registry"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/stringutils"
|
||||
|
@ -1083,8 +1084,8 @@ func parseEventTime(t time.Time) string {
|
|||
return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond()))
|
||||
}
|
||||
|
||||
func setupRegistry(c *check.C, schema1 bool, auth, tokenURL string) *testRegistryV2 {
|
||||
reg, err := newTestRegistryV2(c, schema1, auth, tokenURL)
|
||||
func setupRegistry(c *check.C, schema1 bool, auth, tokenURL string) *registry.V2 {
|
||||
reg, err := registry.NewV2(schema1, auth, tokenURL, privateRegistryURL)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Wait for registry to be ready to serve requests.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -9,7 +9,6 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/docker/distribution/digest"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -17,16 +16,29 @@ const (
|
|||
v2binarySchema1 = "registry-v2-schema1"
|
||||
)
|
||||
|
||||
type testRegistryV2 struct {
|
||||
cmd *exec.Cmd
|
||||
dir string
|
||||
auth string
|
||||
username string
|
||||
password string
|
||||
email string
|
||||
type testingT interface {
|
||||
logT
|
||||
Fatal(...interface{})
|
||||
Fatalf(string, ...interface{})
|
||||
}
|
||||
|
||||
func newTestRegistryV2(c *check.C, schema1 bool, auth, tokenURL string) (*testRegistryV2, error) {
|
||||
type logT interface {
|
||||
Logf(string, ...interface{})
|
||||
}
|
||||
|
||||
// V2 represent a registry version 2
|
||||
type V2 struct {
|
||||
cmd *exec.Cmd
|
||||
registryURL string
|
||||
dir string
|
||||
auth string
|
||||
username string
|
||||
password string
|
||||
email string
|
||||
}
|
||||
|
||||
// NewV2 creates a v2 registry server
|
||||
func NewV2(schema1 bool, auth, tokenURL, registryURL string) (*V2, error) {
|
||||
tmp, err := ioutil.TempDir("", "registry-test-")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -78,7 +90,7 @@ http:
|
|||
}
|
||||
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)
|
||||
return nil, err
|
||||
}
|
||||
|
@ -90,31 +102,30 @@ http:
|
|||
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,
|
||||
auth: auth,
|
||||
username: username,
|
||||
password: password,
|
||||
email: email,
|
||||
return &V2{
|
||||
cmd: cmd,
|
||||
dir: tmp,
|
||||
auth: auth,
|
||||
username: username,
|
||||
password: password,
|
||||
email: email,
|
||||
registryURL: registryURL,
|
||||
}, 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.
|
||||
resp, err := http.Get(fmt.Sprintf("http://%s/v2/", privateRegistryURL))
|
||||
resp, err := http.Get(fmt.Sprintf("http://%s/v2/", r.registryURL))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
fail := resp.StatusCode != http.StatusOK
|
||||
if t.auth != "" {
|
||||
if r.auth != "" {
|
||||
// unauthorized is a _good_ status when pinging v2/ and it needs auth
|
||||
fail = fail && resp.StatusCode != http.StatusUnauthorized
|
||||
}
|
||||
|
@ -124,50 +135,55 @@ func (t *testRegistryV2) Ping() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *testRegistryV2) Close() {
|
||||
t.cmd.Process.Kill()
|
||||
os.RemoveAll(t.dir)
|
||||
// Close kills the registry server
|
||||
func (r *V2) Close() {
|
||||
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.
|
||||
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)
|
||||
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.
|
||||
manifestBlob, err := ioutil.ReadFile(t.getBlobFilename(blobDigest))
|
||||
manifestBlob, err := ioutil.ReadFile(r.getBlobFilename(blobDigest))
|
||||
if err != nil {
|
||||
c.Fatalf("unable to read blob: %s", err)
|
||||
t.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)
|
||||
// WriteBlobContents write the file corresponding to the specified digest with the given content
|
||||
func (r *V2) WriteBlobContents(t testingT, blobDigest digest.Digest, data []byte) {
|
||||
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-")
|
||||
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()
|
||||
|
||||
blobFilename := t.getBlobFilename(blobDigest)
|
||||
blobFilename := r.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)
|
||||
t.Fatalf("unable to move data blob: %s", err)
|
||||
}
|
||||
|
||||
return func() {
|
||||
|
@ -175,3 +191,18 @@ func (t *testRegistryV2) tempMoveBlobData(c *check.C, blobDigest digest.Digest)
|
|||
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")
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package registry
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
@ -6,27 +6,28 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
type handlerFunc func(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
type testRegistry struct {
|
||||
// Mock represent a registry mock
|
||||
type Mock struct {
|
||||
server *httptest.Server
|
||||
hostport string
|
||||
handlers map[string]handlerFunc
|
||||
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()
|
||||
defer tr.mu.Unlock()
|
||||
tr.handlers[path] = h
|
||||
}
|
||||
|
||||
func newTestRegistry(c *check.C) (*testRegistry, error) {
|
||||
testReg := &testRegistry{handlers: make(map[string]handlerFunc)}
|
||||
// NewMock creates a registry mock
|
||||
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) {
|
||||
url := r.URL.String()
|
||||
|
@ -36,7 +37,7 @@ func newTestRegistry(c *check.C) (*testRegistry, error) {
|
|||
for re, function := range testReg.handlers {
|
||||
matched, err = regexp.MatchString(re, url)
|
||||
if err != nil {
|
||||
c.Fatal("Error with handler regexp")
|
||||
t.Fatal("Error with handler regexp")
|
||||
}
|
||||
if matched {
|
||||
function(w, r)
|
||||
|
@ -45,7 +46,7 @@ func newTestRegistry(c *check.C) (*testRegistry, error) {
|
|||
}
|
||||
|
||||
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)
|
||||
return testReg, nil
|
||||
}
|
||||
|
||||
// URL returns the url of the registry
|
||||
func (tr *Mock) URL() string {
|
||||
return tr.hostport
|
||||
}
|
12
integration-cli/registry/requirement.go
Normal file
12
integration-cli/registry/requirement.go
Normal 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
|
||||
}
|
|
@ -105,14 +105,6 @@ func Apparmor() bool {
|
|||
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 {
|
||||
// for now notary binary is built only if we're running inside
|
||||
// container through `make test`. Figure that out by testing if
|
||||
|
|
Loading…
Reference in a new issue