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