github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/integration-cli/docker_cli_push_test.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/tar"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/docker/docker/cliconfig"
    14  	"github.com/docker/docker/pkg/integration/checker"
    15  	"github.com/go-check/check"
    16  )
    17  
    18  // Pushing an image to a private registry.
    19  func testPushBusyboxImage(c *check.C) {
    20  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    21  	// tag the image to upload it to the private registry
    22  	dockerCmd(c, "tag", "busybox", repoName)
    23  	// push the image to the registry
    24  	dockerCmd(c, "push", repoName)
    25  }
    26  
    27  func (s *DockerRegistrySuite) TestPushBusyboxImage(c *check.C) {
    28  	testPushBusyboxImage(c)
    29  }
    30  
    31  func (s *DockerSchema1RegistrySuite) TestPushBusyboxImage(c *check.C) {
    32  	testPushBusyboxImage(c)
    33  }
    34  
    35  // pushing an image without a prefix should throw an error
    36  func (s *DockerSuite) TestPushUnprefixedRepo(c *check.C) {
    37  	out, _, err := dockerCmdWithError("push", "busybox")
    38  	c.Assert(err, check.NotNil, check.Commentf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out))
    39  }
    40  
    41  func testPushUntagged(c *check.C) {
    42  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    43  	expected := "Repository does not exist"
    44  
    45  	out, _, err := dockerCmdWithError("push", repoName)
    46  	c.Assert(err, check.NotNil, check.Commentf("pushing the image to the private registry should have failed: output %q", out))
    47  	c.Assert(out, checker.Contains, expected, check.Commentf("pushing the image failed"))
    48  }
    49  
    50  func (s *DockerRegistrySuite) TestPushUntagged(c *check.C) {
    51  	testPushUntagged(c)
    52  }
    53  
    54  func (s *DockerSchema1RegistrySuite) TestPushUntagged(c *check.C) {
    55  	testPushUntagged(c)
    56  }
    57  
    58  func testPushBadTag(c *check.C) {
    59  	repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL)
    60  	expected := "does not exist"
    61  
    62  	out, _, err := dockerCmdWithError("push", repoName)
    63  	c.Assert(err, check.NotNil, check.Commentf("pushing the image to the private registry should have failed: output %q", out))
    64  	c.Assert(out, checker.Contains, expected, check.Commentf("pushing the image failed"))
    65  }
    66  
    67  func (s *DockerRegistrySuite) TestPushBadTag(c *check.C) {
    68  	testPushBadTag(c)
    69  }
    70  
    71  func (s *DockerSchema1RegistrySuite) TestPushBadTag(c *check.C) {
    72  	testPushBadTag(c)
    73  }
    74  
    75  func testPushMultipleTags(c *check.C) {
    76  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    77  	repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL)
    78  	repoTag2 := fmt.Sprintf("%v/dockercli/busybox:t2", privateRegistryURL)
    79  	// tag the image and upload it to the private registry
    80  	dockerCmd(c, "tag", "busybox", repoTag1)
    81  
    82  	dockerCmd(c, "tag", "busybox", repoTag2)
    83  
    84  	dockerCmd(c, "push", repoName)
    85  
    86  	// Ensure layer list is equivalent for repoTag1 and repoTag2
    87  	out1, _ := dockerCmd(c, "pull", repoTag1)
    88  
    89  	imageAlreadyExists := ": Image already exists"
    90  	var out1Lines []string
    91  	for _, outputLine := range strings.Split(out1, "\n") {
    92  		if strings.Contains(outputLine, imageAlreadyExists) {
    93  			out1Lines = append(out1Lines, outputLine)
    94  		}
    95  	}
    96  
    97  	out2, _ := dockerCmd(c, "pull", repoTag2)
    98  
    99  	var out2Lines []string
   100  	for _, outputLine := range strings.Split(out2, "\n") {
   101  		if strings.Contains(outputLine, imageAlreadyExists) {
   102  			out1Lines = append(out1Lines, outputLine)
   103  		}
   104  	}
   105  	c.Assert(out2Lines, checker.HasLen, len(out1Lines))
   106  
   107  	for i := range out1Lines {
   108  		c.Assert(out1Lines[i], checker.Equals, out2Lines[i])
   109  	}
   110  }
   111  
   112  func (s *DockerRegistrySuite) TestPushMultipleTags(c *check.C) {
   113  	testPushMultipleTags(c)
   114  }
   115  
   116  func (s *DockerSchema1RegistrySuite) TestPushMultipleTags(c *check.C) {
   117  	testPushMultipleTags(c)
   118  }
   119  
   120  func testPushEmptyLayer(c *check.C) {
   121  	repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL)
   122  	emptyTarball, err := ioutil.TempFile("", "empty_tarball")
   123  	c.Assert(err, check.IsNil, check.Commentf("Unable to create test file"))
   124  
   125  	tw := tar.NewWriter(emptyTarball)
   126  	err = tw.Close()
   127  	c.Assert(err, check.IsNil, check.Commentf("Error creating empty tarball"))
   128  
   129  	freader, err := os.Open(emptyTarball.Name())
   130  	c.Assert(err, check.IsNil, check.Commentf("Could not open test tarball"))
   131  
   132  	importCmd := exec.Command(dockerBinary, "import", "-", repoName)
   133  	importCmd.Stdin = freader
   134  	out, _, err := runCommandWithOutput(importCmd)
   135  	c.Assert(err, check.IsNil, check.Commentf("import failed: %q", out))
   136  
   137  	// Now verify we can push it
   138  	out, _, err = dockerCmdWithError("push", repoName)
   139  	c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out))
   140  }
   141  
   142  func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) {
   143  	testPushEmptyLayer(c)
   144  }
   145  
   146  func (s *DockerSchema1RegistrySuite) TestPushEmptyLayer(c *check.C) {
   147  	testPushEmptyLayer(c)
   148  }
   149  
   150  func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
   151  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   152  	// tag the image and upload it to the private registry
   153  	dockerCmd(c, "tag", "busybox", repoName)
   154  
   155  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   156  	s.trustedCmd(pushCmd)
   157  	out, _, err := runCommandWithOutput(pushCmd)
   158  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   159  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   160  
   161  	// Try pull after push
   162  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   163  	s.trustedCmd(pullCmd)
   164  	out, _, err = runCommandWithOutput(pullCmd)
   165  	c.Assert(err, check.IsNil, check.Commentf(out))
   166  	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
   167  }
   168  
   169  func (s *DockerTrustSuite) TestTrustedPushWithEnvPasswords(c *check.C) {
   170  	repoName := fmt.Sprintf("%v/dockerclienv/trusted:latest", privateRegistryURL)
   171  	// tag the image and upload it to the private registry
   172  	dockerCmd(c, "tag", "busybox", repoName)
   173  
   174  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   175  	s.trustedCmdWithPassphrases(pushCmd, "12345678", "12345678")
   176  	out, _, err := runCommandWithOutput(pushCmd)
   177  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   178  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   179  
   180  	// Try pull after push
   181  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   182  	s.trustedCmd(pullCmd)
   183  	out, _, err = runCommandWithOutput(pullCmd)
   184  	c.Assert(err, check.IsNil, check.Commentf(out))
   185  	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
   186  }
   187  
   188  // This test ensures backwards compatibility with old ENV variables. Should be
   189  // deprecated by 1.10
   190  func (s *DockerTrustSuite) TestTrustedPushWithDeprecatedEnvPasswords(c *check.C) {
   191  	repoName := fmt.Sprintf("%v/dockercli/trusteddeprecated:latest", privateRegistryURL)
   192  	// tag the image and upload it to the private registry
   193  	dockerCmd(c, "tag", "busybox", repoName)
   194  
   195  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   196  	s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "12345678")
   197  	out, _, err := runCommandWithOutput(pushCmd)
   198  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   199  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   200  }
   201  
   202  func (s *DockerTrustSuite) TestTrustedPushWithFailingServer(c *check.C) {
   203  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   204  	// tag the image and upload it to the private registry
   205  	dockerCmd(c, "tag", "busybox", repoName)
   206  
   207  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   208  	s.trustedCmdWithServer(pushCmd, "https://example.com:81/")
   209  	out, _, err := runCommandWithOutput(pushCmd)
   210  	c.Assert(err, check.NotNil, check.Commentf("Missing error while running trusted push w/ no server"))
   211  	c.Assert(out, checker.Contains, "error contacting notary server", check.Commentf("Missing expected output on trusted push"))
   212  }
   213  
   214  func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) {
   215  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   216  	// tag the image and upload it to the private registry
   217  	dockerCmd(c, "tag", "busybox", repoName)
   218  
   219  	pushCmd := exec.Command(dockerBinary, "push", "--disable-content-trust", repoName)
   220  	s.trustedCmdWithServer(pushCmd, "https://example.com/")
   221  	out, _, err := runCommandWithOutput(pushCmd)
   222  	c.Assert(err, check.IsNil, check.Commentf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out))
   223  	c.Assert(out, check.Not(checker.Contains), "Error establishing connection to notary repository", check.Commentf("Missing expected output on trusted push with --disable-content-trust:"))
   224  }
   225  
   226  func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) {
   227  	repoName := fmt.Sprintf("%v/dockerclitag/trusted:latest", privateRegistryURL)
   228  	// tag the image and upload it to the private registry
   229  	dockerCmd(c, "tag", "busybox", repoName)
   230  	dockerCmd(c, "push", repoName)
   231  
   232  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   233  	s.trustedCmd(pushCmd)
   234  	out, _, err := runCommandWithOutput(pushCmd)
   235  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   236  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   237  
   238  	// Try pull after push
   239  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   240  	s.trustedCmd(pullCmd)
   241  	out, _, err = runCommandWithOutput(pullCmd)
   242  	c.Assert(err, check.IsNil, check.Commentf(out))
   243  	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
   244  }
   245  
   246  func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) {
   247  	repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL)
   248  	// tag the image and upload it to the private registry
   249  	dockerCmd(c, "tag", "busybox", repoName)
   250  
   251  	// Do a trusted push
   252  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   253  	s.trustedCmd(pushCmd)
   254  	out, _, err := runCommandWithOutput(pushCmd)
   255  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   256  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   257  
   258  	// Do another trusted push
   259  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   260  	s.trustedCmd(pushCmd)
   261  	out, _, err = runCommandWithOutput(pushCmd)
   262  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   263  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   264  
   265  	dockerCmd(c, "rmi", repoName)
   266  
   267  	// Try pull to ensure the double push did not break our ability to pull
   268  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   269  	s.trustedCmd(pullCmd)
   270  	out, _, err = runCommandWithOutput(pullCmd)
   271  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted pull: %s\n%s", err, out))
   272  	c.Assert(out, checker.Contains, "Status: Downloaded", check.Commentf("Missing expected output on trusted pull with --disable-content-trust"))
   273  
   274  }
   275  
   276  func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) {
   277  	repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL)
   278  	// tag the image and upload it to the private registry
   279  	dockerCmd(c, "tag", "busybox", repoName)
   280  
   281  	// Push with default passphrases
   282  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   283  	s.trustedCmd(pushCmd)
   284  	out, _, err := runCommandWithOutput(pushCmd)
   285  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   286  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push:\n%s", out))
   287  
   288  	// Push with wrong passphrases
   289  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   290  	s.trustedCmdWithPassphrases(pushCmd, "12345678", "87654321")
   291  	out, _, err = runCommandWithOutput(pushCmd)
   292  	c.Assert(err, check.NotNil, check.Commentf("Error missing from trusted push with short targets passphrase: \n%s", out))
   293  	c.Assert(out, checker.Contains, "could not find necessary signing keys", check.Commentf("Missing expected output on trusted push with short targets/snapsnot passphrase"))
   294  }
   295  
   296  // This test ensures backwards compatibility with old ENV variables. Should be
   297  // deprecated by 1.10
   298  func (s *DockerTrustSuite) TestTrustedPushWithIncorrectDeprecatedPassphraseForNonRoot(c *check.C) {
   299  	repoName := fmt.Sprintf("%v/dockercliincorretdeprecatedpwd/trusted:latest", privateRegistryURL)
   300  	// tag the image and upload it to the private registry
   301  	dockerCmd(c, "tag", "busybox", repoName)
   302  
   303  	// Push with default passphrases
   304  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   305  	s.trustedCmd(pushCmd)
   306  	out, _, err := runCommandWithOutput(pushCmd)
   307  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   308  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   309  
   310  	// Push with wrong passphrases
   311  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   312  	s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "87654321")
   313  	out, _, err = runCommandWithOutput(pushCmd)
   314  	c.Assert(err, check.NotNil, check.Commentf("Error missing from trusted push with short targets passphrase: \n%s", out))
   315  	c.Assert(out, checker.Contains, "could not find necessary signing keys", check.Commentf("Missing expected output on trusted push with short targets/snapsnot passphrase"))
   316  }
   317  
   318  func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) {
   319  	c.Skip("Currently changes system time, causing instability")
   320  	repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL)
   321  	// tag the image and upload it to the private registry
   322  	dockerCmd(c, "tag", "busybox", repoName)
   323  
   324  	// Push with default passphrases
   325  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   326  	s.trustedCmd(pushCmd)
   327  	out, _, err := runCommandWithOutput(pushCmd)
   328  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   329  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   330  
   331  	// Snapshots last for three years. This should be expired
   332  	fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4)
   333  
   334  	runAtDifferentDate(fourYearsLater, func() {
   335  		// Push with wrong passphrases
   336  		pushCmd = exec.Command(dockerBinary, "push", repoName)
   337  		s.trustedCmd(pushCmd)
   338  		out, _, err = runCommandWithOutput(pushCmd)
   339  		c.Assert(err, check.NotNil, check.Commentf("Error missing from trusted push with expired snapshot: \n%s", out))
   340  		c.Assert(out, checker.Contains, "repository out-of-date", check.Commentf("Missing expected output on trusted push with expired snapshot"))
   341  	})
   342  }
   343  
   344  func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) {
   345  	c.Skip("Currently changes system time, causing instability")
   346  	repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppush/trusted:latest", privateRegistryURL)
   347  	// tag the image and upload it to the private registry
   348  	dockerCmd(c, "tag", "busybox", repoName)
   349  
   350  	// Push with default passphrases
   351  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   352  	s.trustedCmd(pushCmd)
   353  	out, _, err := runCommandWithOutput(pushCmd)
   354  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   355  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   356  
   357  	// The timestamps expire in two weeks. Lets check three
   358  	threeWeeksLater := time.Now().Add(time.Hour * 24 * 21)
   359  
   360  	// Should succeed because the server transparently re-signs one
   361  	runAtDifferentDate(threeWeeksLater, func() {
   362  		pushCmd := exec.Command(dockerBinary, "push", repoName)
   363  		s.trustedCmd(pushCmd)
   364  		out, _, err := runCommandWithOutput(pushCmd)
   365  		c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   366  		c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with expired timestamp"))
   367  	})
   368  }
   369  
   370  func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegation(c *check.C) {
   371  	repoName := fmt.Sprintf("%v/dockerclireleasedelegation/trusted", privateRegistryURL)
   372  	targetName := fmt.Sprintf("%s:latest", repoName)
   373  	pwd := "12345678"
   374  	s.setupDelegations(c, repoName, pwd)
   375  
   376  	// tag the image and upload it to the private registry
   377  	dockerCmd(c, "tag", "busybox", targetName)
   378  
   379  	pushCmd := exec.Command(dockerBinary, "-D", "push", targetName)
   380  	s.trustedCmdWithPassphrases(pushCmd, pwd, pwd)
   381  	out, _, err := runCommandWithOutput(pushCmd)
   382  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   383  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   384  
   385  	// Try pull after push
   386  	pullCmd := exec.Command(dockerBinary, "pull", targetName)
   387  	s.trustedCmd(pullCmd)
   388  	out, _, err = runCommandWithOutput(pullCmd)
   389  	c.Assert(err, check.IsNil, check.Commentf(out))
   390  	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
   391  
   392  	// check to make sure that the target has been added to targets/releases and not targets
   393  	contents, err := ioutil.ReadFile(filepath.Join(cliconfig.ConfigDir(), "trust/tuf", repoName, "metadata/targets.json"))
   394  	c.Assert(err, check.IsNil, check.Commentf("Unable to read targets metadata"))
   395  	c.Assert(strings.Contains(string(contents), `"latest"`), checker.False, check.Commentf(string(contents)))
   396  
   397  	contents, err = ioutil.ReadFile(filepath.Join(cliconfig.ConfigDir(), "trust/tuf", repoName, "metadata/targets/releases.json"))
   398  	c.Assert(err, check.IsNil, check.Commentf("Unable to read targets/releases metadata"))
   399  	c.Assert(string(contents), checker.Contains, `"latest"`, check.Commentf(string(contents)))
   400  }