2014-02-25 11:17:48 -05:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2015-05-01 18:01:10 -04:00
|
|
|
"archive/tar"
|
2014-02-25 11:17:48 -05:00
|
|
|
"fmt"
|
2015-01-24 16:08:47 -05:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2014-02-25 11:17:48 -05:00
|
|
|
"os/exec"
|
2015-01-13 13:46:32 -05:00
|
|
|
"strings"
|
|
|
|
"time"
|
2015-01-24 16:08:47 -05:00
|
|
|
|
2015-04-18 12:46:47 -04:00
|
|
|
"github.com/go-check/check"
|
2014-02-25 11:17:48 -05:00
|
|
|
)
|
|
|
|
|
2015-07-07 04:10:37 -04:00
|
|
|
// Pushing an image to a private registry.
|
2015-04-24 17:16:56 -04:00
|
|
|
func (s *DockerRegistrySuite) TestPushBusyboxImage(c *check.C) {
|
2015-01-13 13:46:32 -05:00
|
|
|
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
|
2015-02-26 21:23:50 -05:00
|
|
|
// tag the image to upload it to the private registry
|
2015-07-14 02:35:36 -04:00
|
|
|
dockerCmd(c, "tag", "busybox", repoName)
|
|
|
|
// push the image to the registry
|
|
|
|
dockerCmd(c, "push", repoName)
|
2014-02-25 11:17:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// pushing an image without a prefix should throw an error
|
2015-04-18 12:46:47 -04:00
|
|
|
func (s *DockerSuite) TestPushUnprefixedRepo(c *check.C) {
|
2015-07-27 14:13:25 -04:00
|
|
|
if out, _, err := dockerCmdWithError("push", "busybox"); err == nil {
|
2015-04-18 12:46:47 -04:00
|
|
|
c.Fatalf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out)
|
2014-02-25 11:17:48 -05:00
|
|
|
}
|
2015-01-13 13:46:32 -05:00
|
|
|
}
|
|
|
|
|
2015-04-24 17:16:56 -04:00
|
|
|
func (s *DockerRegistrySuite) TestPushUntagged(c *check.C) {
|
2015-01-13 13:46:32 -05:00
|
|
|
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
|
|
|
|
|
2015-03-04 15:05:17 -05:00
|
|
|
expected := "Repository does not exist"
|
2015-07-27 14:13:25 -04:00
|
|
|
if out, _, err := dockerCmdWithError("push", repoName); err == nil {
|
2015-04-27 16:33:30 -04:00
|
|
|
c.Fatalf("pushing the image to the private registry should have failed: output %q", out)
|
2015-01-13 13:46:32 -05:00
|
|
|
} else if !strings.Contains(out, expected) {
|
2015-04-18 12:46:47 -04:00
|
|
|
c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
|
2015-01-13 13:46:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-24 17:16:56 -04:00
|
|
|
func (s *DockerRegistrySuite) TestPushBadTag(c *check.C) {
|
2015-01-30 17:20:32 -05:00
|
|
|
repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL)
|
|
|
|
|
|
|
|
expected := "does not exist"
|
2015-07-14 02:35:36 -04:00
|
|
|
|
2015-07-27 14:13:25 -04:00
|
|
|
if out, _, err := dockerCmdWithError("push", repoName); err == nil {
|
2015-04-27 16:33:30 -04:00
|
|
|
c.Fatalf("pushing the image to the private registry should have failed: output %q", out)
|
2015-01-30 17:20:32 -05:00
|
|
|
} else if !strings.Contains(out, expected) {
|
2015-04-18 12:46:47 -04:00
|
|
|
c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
|
2015-01-30 17:20:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-24 17:16:56 -04:00
|
|
|
func (s *DockerRegistrySuite) TestPushMultipleTags(c *check.C) {
|
2015-01-30 17:20:32 -05:00
|
|
|
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
|
|
|
|
repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL)
|
|
|
|
repoTag2 := fmt.Sprintf("%v/dockercli/busybox:t2", privateRegistryURL)
|
2015-04-23 04:50:41 -04:00
|
|
|
// tag the image and upload it to the private registry
|
2015-07-14 02:35:36 -04:00
|
|
|
dockerCmd(c, "tag", "busybox", repoTag1)
|
2015-01-30 17:20:32 -05:00
|
|
|
|
2015-07-14 02:35:36 -04:00
|
|
|
dockerCmd(c, "tag", "busybox", repoTag2)
|
|
|
|
|
2015-08-12 21:32:23 -04:00
|
|
|
dockerCmd(c, "push", repoName)
|
2015-08-12 21:36:46 -04:00
|
|
|
|
|
|
|
// Ensure layer list is equivalent for repoTag1 and repoTag2
|
|
|
|
out1, _ := dockerCmd(c, "pull", repoTag1)
|
|
|
|
if strings.Contains(out1, "Tag t1 not found") {
|
|
|
|
c.Fatalf("Unable to pull pushed image: %s", out1)
|
|
|
|
}
|
|
|
|
imageAlreadyExists := ": Image already exists"
|
|
|
|
var out1Lines []string
|
|
|
|
for _, outputLine := range strings.Split(out1, "\n") {
|
|
|
|
if strings.Contains(outputLine, imageAlreadyExists) {
|
|
|
|
out1Lines = append(out1Lines, outputLine)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out2, _ := dockerCmd(c, "pull", repoTag2)
|
|
|
|
if strings.Contains(out2, "Tag t2 not found") {
|
|
|
|
c.Fatalf("Unable to pull pushed image: %s", out1)
|
|
|
|
}
|
|
|
|
var out2Lines []string
|
|
|
|
for _, outputLine := range strings.Split(out2, "\n") {
|
|
|
|
if strings.Contains(outputLine, imageAlreadyExists) {
|
|
|
|
out1Lines = append(out1Lines, outputLine)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(out1Lines) != len(out2Lines) {
|
|
|
|
c.Fatalf("Mismatched output length:\n%s\n%s", out1, out2)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range out1Lines {
|
|
|
|
if out1Lines[i] != out2Lines[i] {
|
|
|
|
c.Fatalf("Mismatched output line:\n%s\n%s", out1Lines[i], out2Lines[i])
|
|
|
|
}
|
|
|
|
}
|
2015-01-30 17:20:32 -05:00
|
|
|
}
|
|
|
|
|
2015-04-24 17:16:56 -04:00
|
|
|
func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) {
|
2015-01-24 16:08:47 -05:00
|
|
|
repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL)
|
|
|
|
emptyTarball, err := ioutil.TempFile("", "empty_tarball")
|
|
|
|
if err != nil {
|
2015-04-18 12:46:47 -04:00
|
|
|
c.Fatalf("Unable to create test file: %v", err)
|
2015-01-24 16:08:47 -05:00
|
|
|
}
|
|
|
|
tw := tar.NewWriter(emptyTarball)
|
|
|
|
err = tw.Close()
|
|
|
|
if err != nil {
|
2015-04-18 12:46:47 -04:00
|
|
|
c.Fatalf("Error creating empty tarball: %v", err)
|
2015-01-24 16:08:47 -05:00
|
|
|
}
|
|
|
|
freader, err := os.Open(emptyTarball.Name())
|
|
|
|
if err != nil {
|
2015-04-18 12:46:47 -04:00
|
|
|
c.Fatalf("Could not open test tarball: %v", err)
|
2015-01-24 16:08:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
importCmd := exec.Command(dockerBinary, "import", "-", repoName)
|
|
|
|
importCmd.Stdin = freader
|
|
|
|
out, _, err := runCommandWithOutput(importCmd)
|
|
|
|
if err != nil {
|
2015-04-18 12:46:47 -04:00
|
|
|
c.Errorf("import failed with errors: %v, output: %q", err, out)
|
2015-01-24 16:08:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now verify we can push it
|
2015-07-27 14:13:25 -04:00
|
|
|
if out, _, err := dockerCmdWithError("push", repoName); err != nil {
|
2015-04-18 12:46:47 -04:00
|
|
|
c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
|
2015-01-24 16:08:47 -05:00
|
|
|
}
|
|
|
|
}
|
2015-07-20 01:56:10 -04:00
|
|
|
|
|
|
|
func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
|
|
|
|
repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
|
|
|
|
// tag the image and upload it to the private registry
|
|
|
|
dockerCmd(c, "tag", "busybox", repoName)
|
|
|
|
|
|
|
|
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
|
|
|
s.trustedCmd(pushCmd)
|
|
|
|
out, _, err := runCommandWithOutput(pushCmd)
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error running trusted push: %s\n%s", err, out)
|
|
|
|
}
|
|
|
|
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
|
|
|
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
|
|
|
}
|
|
|
|
}
|
2015-07-21 23:36:22 -04:00
|
|
|
|
2015-07-22 14:39:35 -04:00
|
|
|
func (s *DockerTrustSuite) TestTrustedPushWithFaillingServer(c *check.C) {
|
2015-07-21 23:36:22 -04:00
|
|
|
repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
|
|
|
|
// tag the image and upload it to the private registry
|
|
|
|
dockerCmd(c, "tag", "busybox", repoName)
|
|
|
|
|
|
|
|
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
|
|
|
s.trustedCmdWithServer(pushCmd, "example/")
|
|
|
|
out, _, err := runCommandWithOutput(pushCmd)
|
|
|
|
if err == nil {
|
|
|
|
c.Fatalf("Missing error while running trusted push w/ no server")
|
|
|
|
}
|
|
|
|
|
2015-09-03 23:01:03 -04:00
|
|
|
if !strings.Contains(string(out), "error contacting notary server") {
|
2015-07-21 23:36:22 -04:00
|
|
|
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) {
|
|
|
|
repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
|
|
|
|
// tag the image and upload it to the private registry
|
|
|
|
dockerCmd(c, "tag", "busybox", repoName)
|
|
|
|
|
2015-07-24 04:59:42 -04:00
|
|
|
pushCmd := exec.Command(dockerBinary, "push", "--disable-content-trust", repoName)
|
2015-07-21 23:36:22 -04:00
|
|
|
s.trustedCmdWithServer(pushCmd, "example/")
|
|
|
|
out, _, err := runCommandWithOutput(pushCmd)
|
|
|
|
if err != nil {
|
2015-07-24 04:59:42 -04:00
|
|
|
c.Fatalf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out)
|
2015-07-21 23:36:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if strings.Contains(string(out), "Error establishing connection to notary repository") {
|
2015-07-24 04:59:42 -04:00
|
|
|
c.Fatalf("Missing expected output on trusted push with --disable-content-trust:\n%s", out)
|
2015-07-21 23:36:22 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) {
|
|
|
|
repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
|
|
|
|
// tag the image and upload it to the private registry
|
|
|
|
dockerCmd(c, "tag", "busybox", repoName)
|
|
|
|
dockerCmd(c, "push", repoName)
|
|
|
|
|
|
|
|
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
|
|
|
s.trustedCmd(pushCmd)
|
|
|
|
out, _, err := runCommandWithOutput(pushCmd)
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
|
|
|
c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-22 14:39:35 -04:00
|
|
|
func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) {
|
|
|
|
repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL)
|
2015-07-21 23:36:22 -04:00
|
|
|
// tag the image and upload it to the private registry
|
|
|
|
dockerCmd(c, "tag", "busybox", repoName)
|
|
|
|
|
2015-07-22 14:39:35 -04:00
|
|
|
// Do a trusted push
|
2015-07-21 23:36:22 -04:00
|
|
|
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
2015-07-22 14:39:35 -04:00
|
|
|
s.trustedCmd(pushCmd)
|
2015-07-21 23:36:22 -04:00
|
|
|
out, _, err := runCommandWithOutput(pushCmd)
|
2015-07-22 14:39:35 -04:00
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
2015-07-21 23:36:22 -04:00
|
|
|
}
|
|
|
|
|
2015-07-22 14:39:35 -04:00
|
|
|
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
|
|
|
c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out)
|
2015-07-21 23:36:22 -04:00
|
|
|
}
|
|
|
|
|
2015-07-22 14:39:35 -04:00
|
|
|
// Do another trusted push
|
|
|
|
pushCmd = exec.Command(dockerBinary, "push", repoName)
|
2015-07-21 23:36:22 -04:00
|
|
|
s.trustedCmd(pushCmd)
|
2015-07-22 14:39:35 -04:00
|
|
|
out, _, err = runCommandWithOutput(pushCmd)
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
|
|
|
}
|
2015-07-21 23:36:22 -04:00
|
|
|
|
2015-07-22 14:39:35 -04:00
|
|
|
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
|
|
|
c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
dockerCmd(c, "rmi", repoName)
|
|
|
|
|
|
|
|
// Try pull to ensure the double push did not break our ability to pull
|
|
|
|
pullCmd := exec.Command(dockerBinary, "pull", repoName)
|
|
|
|
s.trustedCmd(pullCmd)
|
|
|
|
out, _, err = runCommandWithOutput(pullCmd)
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error running trusted pull: %s\n%s", err, out)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(string(out), "Status: Downloaded") {
|
2015-07-24 04:59:42 -04:00
|
|
|
c.Fatalf("Missing expected output on trusted pull with --disable-content-trust:\n%s", out)
|
2015-07-22 14:39:35 -04:00
|
|
|
}
|
2015-07-21 23:36:22 -04:00
|
|
|
}
|
|
|
|
|
2015-07-22 14:39:35 -04:00
|
|
|
func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) {
|
|
|
|
repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL)
|
2015-07-21 23:36:22 -04:00
|
|
|
// tag the image and upload it to the private registry
|
|
|
|
dockerCmd(c, "tag", "busybox", repoName)
|
|
|
|
|
2015-07-22 14:39:35 -04:00
|
|
|
// Push with default passphrases
|
2015-07-21 23:36:22 -04:00
|
|
|
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
2015-07-22 14:39:35 -04:00
|
|
|
s.trustedCmd(pushCmd)
|
2015-07-21 23:36:22 -04:00
|
|
|
out, _, err := runCommandWithOutput(pushCmd)
|
2015-07-22 14:39:35 -04:00
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
|
|
|
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Push with wrong passphrases
|
|
|
|
pushCmd = exec.Command(dockerBinary, "push", repoName)
|
2015-07-31 18:01:50 -04:00
|
|
|
s.trustedCmdWithPassphrases(pushCmd, "12345678", "87654321")
|
2015-07-22 14:39:35 -04:00
|
|
|
out, _, err = runCommandWithOutput(pushCmd)
|
2015-07-21 23:36:22 -04:00
|
|
|
if err == nil {
|
2015-07-22 14:39:35 -04:00
|
|
|
c.Fatalf("Error missing from trusted push with short targets passphrase: \n%s", out)
|
2015-07-21 23:36:22 -04:00
|
|
|
}
|
|
|
|
|
2015-07-23 08:12:36 -04:00
|
|
|
if !strings.Contains(string(out), "password invalid, operation has failed") {
|
2015-07-21 23:36:22 -04:00
|
|
|
c.Fatalf("Missing expected output on trusted push with short targets/snapsnot passphrase:\n%s", out)
|
|
|
|
}
|
|
|
|
}
|
2015-07-22 21:46:59 -04:00
|
|
|
|
|
|
|
func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) {
|
2015-07-29 15:09:40 -04:00
|
|
|
c.Skip("Currently changes system time, causing instability")
|
2015-07-22 21:46:59 -04:00
|
|
|
repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL)
|
|
|
|
// tag the image and upload it to the private registry
|
|
|
|
dockerCmd(c, "tag", "busybox", repoName)
|
|
|
|
|
|
|
|
// Push with default passphrases
|
|
|
|
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
|
|
|
s.trustedCmd(pushCmd)
|
|
|
|
out, _, err := runCommandWithOutput(pushCmd)
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
|
|
|
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Snapshots last for three years. This should be expired
|
|
|
|
fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4)
|
|
|
|
|
|
|
|
runAtDifferentDate(fourYearsLater, func() {
|
|
|
|
// Push with wrong passphrases
|
|
|
|
pushCmd = exec.Command(dockerBinary, "push", repoName)
|
|
|
|
s.trustedCmd(pushCmd)
|
|
|
|
out, _, err = runCommandWithOutput(pushCmd)
|
|
|
|
if err == nil {
|
|
|
|
c.Fatalf("Error missing from trusted push with expired snapshot: \n%s", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(string(out), "repository out-of-date") {
|
|
|
|
c.Fatalf("Missing expected output on trusted push with expired snapshot:\n%s", out)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) {
|
2015-07-29 15:09:40 -04:00
|
|
|
c.Skip("Currently changes system time, causing instability")
|
2015-07-22 21:46:59 -04:00
|
|
|
repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppush/trusted:latest", privateRegistryURL)
|
|
|
|
// tag the image and upload it to the private registry
|
|
|
|
dockerCmd(c, "tag", "busybox", repoName)
|
|
|
|
|
|
|
|
// Push with default passphrases
|
|
|
|
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
|
|
|
s.trustedCmd(pushCmd)
|
|
|
|
out, _, err := runCommandWithOutput(pushCmd)
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("trusted push failed: %s\n%s", err, out)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
|
|
|
c.Fatalf("Missing expected output on trusted push:\n%s", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The timestamps expire in two weeks. Lets check three
|
|
|
|
threeWeeksLater := time.Now().Add(time.Hour * 24 * 21)
|
|
|
|
|
|
|
|
// Should succeed because the server transparently re-signs one
|
|
|
|
runAtDifferentDate(threeWeeksLater, func() {
|
|
|
|
pushCmd := exec.Command(dockerBinary, "push", repoName)
|
|
|
|
s.trustedCmd(pushCmd)
|
|
|
|
out, _, err := runCommandWithOutput(pushCmd)
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error running trusted push: %s\n%s", err, out)
|
|
|
|
}
|
|
|
|
if !strings.Contains(string(out), "Signing and pushing trust metadata") {
|
|
|
|
c.Fatalf("Missing expected output on trusted push with expired timestamp:\n%s", out)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|