diff --git a/Dockerfile b/Dockerfile index e51a7ebf..441c9cf0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,7 @@ RUN set -x \ RUN set -x \ && yum install -y which git tar wget hostname util-linux bsdtar socat ethtool device-mapper iptables tree findutils nmap-ncat e2fsprogs xfsprogs lsof docker iproute \ && export GOPATH=$(mktemp -d) \ - && git clone -b v1.3.0-alpha.3 git://github.com/openshift/origin "$GOPATH/src/github.com/openshift/origin" \ + && git clone -b v1.5.0-alpha.3 git://github.com/openshift/origin "$GOPATH/src/github.com/openshift/origin" \ && (cd "$GOPATH/src/github.com/openshift/origin" && make clean build && make all WHAT=cmd/dockerregistry) \ && cp -a "$GOPATH/src/github.com/openshift/origin/_output/local/bin/linux"/*/* /usr/local/bin \ && cp "$GOPATH/src/github.com/openshift/origin/images/dockerregistry/config.yml" /atomic-registry-config.yml \ diff --git a/integration/copy_test.go b/integration/copy_test.go index 1c250ce9..8b13837c 100644 --- a/integration/copy_test.go +++ b/integration/copy_test.go @@ -118,8 +118,7 @@ func (s *CopySuite) TestCopySimpleAtomicRegistry(c *check.C) { assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "dir:"+dir1, "atomic:localhost:5000/myns/unsigned:unsigned") // The result of pushing and pulling is an unmodified image. assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/unsigned:unsigned", "dir:"+dir2) - out := combinedOutputOfCommand(c, "diff", "-urN", dir1, dir2) - c.Assert(out, check.Equals, "") + destructiveCheckDirImagesAreEqual(c, dir1, dir2) } // The most basic (skopeo copy) use: @@ -153,22 +152,10 @@ func (s *CopySuite) TestCopySimple(c *check.C) { c.Assert(err, check.IsNil) } -// Streaming (skopeo copy) -func (s *CopySuite) TestCopyStreaming(c *check.C) { - dir1, err := ioutil.TempDir("", "streaming-1") - c.Assert(err, check.IsNil) - defer os.RemoveAll(dir1) - dir2, err := ioutil.TempDir("", "streaming-2") - c.Assert(err, check.IsNil) - defer os.RemoveAll(dir2) - - // FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection. - // streaming: docker: → atomic: - assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "docker://estesp/busybox:amd64", "atomic:localhost:5000/myns/unsigned:streaming") - // Compare (copies of) the original and the copy: - assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:amd64", "dir:"+dir1) - assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/unsigned:streaming", "dir:"+dir2) - // The manifests will have different JWS signatures; so, compare the manifests by digests, which +// Check whether dir: images in dir1 and dir2 are equal. +// WARNING: This modifies the contents of dir1 and dir2! +func destructiveCheckDirImagesAreEqual(c *check.C, dir1, dir2 string) { + // The manifests may have different JWS signatures; so, compare the manifests by digests, which // strips the signatures, and remove them, comparing the rest file by file. digests := []digest.Digest{} for _, dir := range []string{dir1, dir2} { @@ -185,6 +172,24 @@ func (s *CopySuite) TestCopyStreaming(c *check.C) { c.Assert(digests[0], check.Equals, digests[1]) out := combinedOutputOfCommand(c, "diff", "-urN", dir1, dir2) c.Assert(out, check.Equals, "") +} + +// Streaming (skopeo copy) +func (s *CopySuite) TestCopyStreaming(c *check.C) { + dir1, err := ioutil.TempDir("", "streaming-1") + c.Assert(err, check.IsNil) + defer os.RemoveAll(dir1) + dir2, err := ioutil.TempDir("", "streaming-2") + c.Assert(err, check.IsNil) + defer os.RemoveAll(dir2) + + // FIXME: It would be nice to use one of the local Docker registries instead of neeeding an Internet connection. + // streaming: docker: → atomic: + assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "docker://estesp/busybox:amd64", "atomic:localhost:5000/myns/unsigned:streaming") + // Compare (copies of) the original and the copy: + assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:amd64", "dir:"+dir1) + assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/unsigned:streaming", "dir:"+dir2) + destructiveCheckDirImagesAreEqual(c, dir1, dir2) // FIXME: Also check pushing to docker:// } diff --git a/integration/openshift.go b/integration/openshift.go index cf9880e6..493ae398 100644 --- a/integration/openshift.go +++ b/integration/openshift.go @@ -14,6 +14,10 @@ import ( "github.com/go-check/check" ) +var adminKUBECONFIG = map[string]string{ + "KUBECONFIG": "openshift.local.config/master/admin.kubeconfig", +} + // openshiftCluster is an OpenShift API master and integrated registry // running on localhost. type openshiftCluster struct { @@ -42,10 +46,20 @@ func startOpenshiftCluster(c *check.C) *openshiftCluster { return cluster } +// clusterCmd creates an exec.Cmd in c.workingDir with current environment modified by environment +func (c *openshiftCluster) clusterCmd(env map[string]string, name string, args ...string) *exec.Cmd { + cmd := exec.Command(name, args...) + cmd.Dir = c.workingDir + cmd.Env = os.Environ() + for key, value := range env { + cmd.Env = modifyEnviron(cmd.Env, key, value) + } + return cmd +} + // startMaster starts the OpenShift master (etcd+API server) and waits for it to be ready, or terminates on failure. func (c *openshiftCluster) startMaster() { - c.master = exec.Command("openshift", "start", "master") - c.master.Dir = c.workingDir + c.master = c.clusterCmd(nil, "openshift", "start", "master") stdout, err := c.master.StdoutPipe() // Send both to the same pipe. This might cause the two streams to be mixed up, // but logging actually goes only to stderr - this primarily ensure we log any @@ -112,14 +126,35 @@ func (c *openshiftCluster) startMaster() { // startRegistry starts the OpenShift registry and waits for it to be ready, or terminates on failure. func (c *openshiftCluster) startRegistry() { - //KUBECONFIG=openshift.local.config/master/openshift-registry.kubeconfig DOCKER_REGISTRY_URL=127.0.0.1:5000 - c.registry = exec.Command("dockerregistry", "/atomic-registry-config.yml") - c.registry.Dir = c.workingDir - c.registry.Env = os.Environ() - c.registry.Env = modifyEnviron(c.registry.Env, "KUBECONFIG", "openshift.local.config/master/openshift-registry.kubeconfig") - c.registry.Env = modifyEnviron(c.registry.Env, "DOCKER_REGISTRY_URL", "127.0.0.1:5000") + // This partially mimics the objects created by (oadm registry), except that we run the + // server directly as an ordinary process instead of a pod with an implicitly attached service account. + saJSON := `{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "name": "registry" + } + }` + cmd := c.clusterCmd(adminKUBECONFIG, "oc", "create", "-f", "-") + runExecCmdWithInput(c.c, cmd, saJSON) + + cmd = c.clusterCmd(adminKUBECONFIG, "oadm", "policy", "add-cluster-role-to-user", "system:registry", "-z", "registry") + out, err := cmd.CombinedOutput() + c.c.Assert(err, check.IsNil, check.Commentf("%s", string(out))) + c.c.Assert(string(out), check.Equals, "cluster role \"system:registry\" added: \"registry\"\n") + + cmd = c.clusterCmd(adminKUBECONFIG, "oadm", "create-api-client-config", "--client-dir=openshift.local.registry", "--basename=openshift-registry", "--user=system:serviceaccount:default:registry") + out, err = cmd.CombinedOutput() + c.c.Assert(err, check.IsNil, check.Commentf("%s", string(out))) + c.c.Assert(string(out), check.Equals, "") + + //KUBECONFIG=openshift.local.registry/openshift-registry.kubeconfig DOCKER_REGISTRY_URL=127.0.0.1:5000 + c.registry = c.clusterCmd(map[string]string{ + "KUBECONFIG": "openshift.local.registry/openshift-registry.kubeconfig", + "DOCKER_REGISTRY_URL": "127.0.0.1:5000", + }, "dockerregistry", "/atomic-registry-config.yml") consumeAndLogOutputs(c.c, "registry", c.registry) - err := c.registry.Start() + err = c.registry.Start() c.c.Assert(err, check.IsNil) portOpen, terminatePortCheck := newPortChecker(c.c, 5000) @@ -134,8 +169,7 @@ func (c *openshiftCluster) startRegistry() { // ocLogin runs (oc login) and (oc new-project) on the cluster, or terminates on failure. func (c *openshiftCluster) ocLoginToProject() { c.c.Logf("oc login") - cmd := exec.Command("oc", "login", "--certificate-authority=openshift.local.config/master/ca.crt", "-u", "myuser", "-p", "mypw", "https://localhost:8443") - cmd.Dir = c.workingDir + cmd := c.clusterCmd(nil, "oc", "login", "--certificate-authority=openshift.local.config/master/ca.crt", "-u", "myuser", "-p", "mypw", "https://localhost:8443") out, err := cmd.CombinedOutput() c.c.Assert(err, check.IsNil, check.Commentf("%s", out)) c.c.Assert(string(out), check.Matches, "(?s).*Login successful.*") // (?s) : '.' will also match newlines @@ -170,13 +204,10 @@ func (c *openshiftCluster) dockerLogin() { // FIXME: This also allows anyone to DoS anyone else; this design is really not all // that workable, but it is the best we can do for now. func (c *openshiftCluster) relaxImageSignerPermissions() { - cmd := exec.Command("oadm", "policy", "add-cluster-role-to-group", "system:image-signer", "system:authenticated") - cmd.Dir = c.workingDir - cmd.Env = os.Environ() - cmd.Env = modifyEnviron(cmd.Env, "KUBECONFIG", "openshift.local.config/master/admin.kubeconfig") + cmd := c.clusterCmd(adminKUBECONFIG, "oadm", "policy", "add-cluster-role-to-group", "system:image-signer", "system:authenticated") out, err := cmd.CombinedOutput() c.c.Assert(err, check.IsNil, check.Commentf("%s", string(out))) - c.c.Assert(string(out), check.Equals, "") + c.c.Assert(string(out), check.Equals, "cluster role \"system:image-signer\" added: \"system:authenticated\"\n") } // tearDown stops the cluster services and deletes (only some!) of the state. diff --git a/integration/utils.go b/integration/utils.go index a6b85111..c58afeed 100644 --- a/integration/utils.go +++ b/integration/utils.go @@ -74,9 +74,15 @@ func assertSkopeoFails(c *check.C, regexp string, args ...string) { // runCommandWithInput runs a command as if exec.Command(), sending it the input to stdin, // and verifies that the exit status is 0, or terminates c on failure. func runCommandWithInput(c *check.C, input string, name string, args ...string) { - c.Logf("Running %s %s", name, strings.Join(args, " ")) cmd := exec.Command(name, args...) - consumeAndLogOutputs(c, name+" "+strings.Join(args, " "), cmd) + runExecCmdWithInput(c, cmd, input) +} + +// runExecCmdWithInput runs an exec.Cmd, sending it the input to stdin, +// and verifies that the exit status is 0, or terminates c on failure. +func runExecCmdWithInput(c *check.C, cmd *exec.Cmd, input string) { + c.Logf("Running %s %s", cmd.Path, strings.Join(cmd.Args, " ")) + consumeAndLogOutputs(c, cmd.Path+" "+strings.Join(cmd.Args, " "), cmd) stdin, err := cmd.StdinPipe() c.Assert(err, check.IsNil) err = cmd.Start()