github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/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  // testConcurrentPush pushes multiple tags to the same repo
   152  // concurrently.
   153  func testConcurrentPush(c *check.C) {
   154  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
   155  
   156  	repos := []string{}
   157  	for _, tag := range []string{"push1", "push2", "push3"} {
   158  		repo := fmt.Sprintf("%v:%v", repoName, tag)
   159  		_, err := buildImage(repo, fmt.Sprintf(`
   160  	FROM busybox
   161  	ENTRYPOINT ["/bin/echo"]
   162  	ENV FOO foo
   163  	ENV BAR bar
   164  	CMD echo %s
   165  `, repo), true)
   166  		c.Assert(err, checker.IsNil)
   167  		repos = append(repos, repo)
   168  	}
   169  
   170  	// Push tags, in parallel
   171  	results := make(chan error)
   172  
   173  	for _, repo := range repos {
   174  		go func(repo string) {
   175  			_, _, err := runCommandWithOutput(exec.Command(dockerBinary, "push", repo))
   176  			results <- err
   177  		}(repo)
   178  	}
   179  
   180  	for range repos {
   181  		err := <-results
   182  		c.Assert(err, checker.IsNil, check.Commentf("concurrent push failed with error: %v", err))
   183  	}
   184  
   185  	// Clear local images store.
   186  	args := append([]string{"rmi"}, repos...)
   187  	dockerCmd(c, args...)
   188  
   189  	// Re-pull and run individual tags, to make sure pushes succeeded
   190  	for _, repo := range repos {
   191  		dockerCmd(c, "pull", repo)
   192  		dockerCmd(c, "inspect", repo)
   193  		out, _ := dockerCmd(c, "run", "--rm", repo)
   194  		c.Assert(strings.TrimSpace(out), checker.Equals, "/bin/sh -c echo "+repo)
   195  	}
   196  }
   197  
   198  func (s *DockerRegistrySuite) TestConcurrentPush(c *check.C) {
   199  	testConcurrentPush(c)
   200  }
   201  
   202  func (s *DockerSchema1RegistrySuite) TestConcurrentPush(c *check.C) {
   203  	testConcurrentPush(c)
   204  }
   205  
   206  func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *check.C) {
   207  	sourceRepoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
   208  	// tag the image to upload it to the private registry
   209  	dockerCmd(c, "tag", "busybox", sourceRepoName)
   210  	// push the image to the registry
   211  	out1, _, err := dockerCmdWithError("push", sourceRepoName)
   212  	c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out1))
   213  	// ensure that none of the layers were mounted from another repository during push
   214  	c.Assert(strings.Contains(out1, "Mounted from"), check.Equals, false)
   215  
   216  	digest1 := digest.DigestRegexp.FindString(out1)
   217  	c.Assert(len(digest1), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest"))
   218  
   219  	destRepoName := fmt.Sprintf("%v/dockercli/crossrepopush", privateRegistryURL)
   220  	// retag the image to upload the same layers to another repo in the same registry
   221  	dockerCmd(c, "tag", "busybox", destRepoName)
   222  	// push the image to the registry
   223  	out2, _, err := dockerCmdWithError("push", destRepoName)
   224  	c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out2))
   225  	// ensure that layers were mounted from the first repo during push
   226  	c.Assert(strings.Contains(out2, "Mounted from dockercli/busybox"), check.Equals, true)
   227  
   228  	digest2 := digest.DigestRegexp.FindString(out2)
   229  	c.Assert(len(digest2), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest"))
   230  	c.Assert(digest1, check.Equals, digest2)
   231  
   232  	// ensure that we can pull and run the cross-repo-pushed repository
   233  	dockerCmd(c, "rmi", destRepoName)
   234  	dockerCmd(c, "pull", destRepoName)
   235  	out3, _ := dockerCmd(c, "run", destRepoName, "echo", "-n", "hello world")
   236  	c.Assert(out3, check.Equals, "hello world")
   237  }
   238  
   239  func (s *DockerSchema1RegistrySuite) TestCrossRepositoryLayerPushNotSupported(c *check.C) {
   240  	sourceRepoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
   241  	// tag the image to upload it to the private registry
   242  	dockerCmd(c, "tag", "busybox", sourceRepoName)
   243  	// push the image to the registry
   244  	out1, _, err := dockerCmdWithError("push", sourceRepoName)
   245  	c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out1))
   246  	// ensure that none of the layers were mounted from another repository during push
   247  	c.Assert(strings.Contains(out1, "Mounted from"), check.Equals, false)
   248  
   249  	digest1 := digest.DigestRegexp.FindString(out1)
   250  	c.Assert(len(digest1), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest"))
   251  
   252  	destRepoName := fmt.Sprintf("%v/dockercli/crossrepopush", privateRegistryURL)
   253  	// retag the image to upload the same layers to another repo in the same registry
   254  	dockerCmd(c, "tag", "busybox", destRepoName)
   255  	// push the image to the registry
   256  	out2, _, err := dockerCmdWithError("push", destRepoName)
   257  	c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out2))
   258  	// schema1 registry should not support cross-repo layer mounts, so ensure that this does not happen
   259  	c.Assert(strings.Contains(out2, "Mounted from"), check.Equals, false)
   260  
   261  	digest2 := digest.DigestRegexp.FindString(out2)
   262  	c.Assert(len(digest2), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest"))
   263  	c.Assert(digest1, check.Equals, digest2)
   264  
   265  	// ensure that we can pull and run the second pushed repository
   266  	dockerCmd(c, "rmi", destRepoName)
   267  	dockerCmd(c, "pull", destRepoName)
   268  	out3, _ := dockerCmd(c, "run", destRepoName, "echo", "-n", "hello world")
   269  	c.Assert(out3, check.Equals, "hello world")
   270  }
   271  
   272  func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
   273  	repoName := fmt.Sprintf("%v/dockerclitrusted/pushtest:latest", privateRegistryURL)
   274  	// tag the image and upload it to the private registry
   275  	dockerCmd(c, "tag", "busybox", repoName)
   276  
   277  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   278  	s.trustedCmd(pushCmd)
   279  	out, _, err := runCommandWithOutput(pushCmd)
   280  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   281  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   282  
   283  	// Try pull after push
   284  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   285  	s.trustedCmd(pullCmd)
   286  	out, _, err = runCommandWithOutput(pullCmd)
   287  	c.Assert(err, check.IsNil, check.Commentf(out))
   288  	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
   289  
   290  	// Assert that we rotated the snapshot key to the server by checking our local keystore
   291  	contents, err := ioutil.ReadDir(filepath.Join(cliconfig.ConfigDir(), "trust/private/tuf_keys", privateRegistryURL, "dockerclitrusted/pushtest"))
   292  	c.Assert(err, check.IsNil, check.Commentf("Unable to read local tuf key files"))
   293  	// Check that we only have 1 key (targets key)
   294  	c.Assert(contents, checker.HasLen, 1)
   295  }
   296  
   297  func (s *DockerTrustSuite) TestTrustedPushWithEnvPasswords(c *check.C) {
   298  	repoName := fmt.Sprintf("%v/dockerclienv/trusted:latest", privateRegistryURL)
   299  	// tag the image and upload it to the private registry
   300  	dockerCmd(c, "tag", "busybox", repoName)
   301  
   302  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   303  	s.trustedCmdWithPassphrases(pushCmd, "12345678", "12345678")
   304  	out, _, err := runCommandWithOutput(pushCmd)
   305  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   306  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   307  
   308  	// Try pull after push
   309  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   310  	s.trustedCmd(pullCmd)
   311  	out, _, err = runCommandWithOutput(pullCmd)
   312  	c.Assert(err, check.IsNil, check.Commentf(out))
   313  	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
   314  }
   315  
   316  // This test ensures backwards compatibility with old ENV variables. Should be
   317  // deprecated by 1.10
   318  func (s *DockerTrustSuite) TestTrustedPushWithDeprecatedEnvPasswords(c *check.C) {
   319  	repoName := fmt.Sprintf("%v/dockercli/trusteddeprecated:latest", privateRegistryURL)
   320  	// tag the image and upload it to the private registry
   321  	dockerCmd(c, "tag", "busybox", repoName)
   322  
   323  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   324  	s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "12345678")
   325  	out, _, err := runCommandWithOutput(pushCmd)
   326  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   327  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   328  }
   329  
   330  func (s *DockerTrustSuite) TestTrustedPushWithFailingServer(c *check.C) {
   331  	repoName := fmt.Sprintf("%v/dockerclitrusted/failingserver:latest", privateRegistryURL)
   332  	// tag the image and upload it to the private registry
   333  	dockerCmd(c, "tag", "busybox", repoName)
   334  
   335  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   336  	s.trustedCmdWithServer(pushCmd, "https://example.com:81/")
   337  	out, _, err := runCommandWithOutput(pushCmd)
   338  	c.Assert(err, check.NotNil, check.Commentf("Missing error while running trusted push w/ no server"))
   339  	c.Assert(out, checker.Contains, "error contacting notary server", check.Commentf("Missing expected output on trusted push"))
   340  }
   341  
   342  func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) {
   343  	repoName := fmt.Sprintf("%v/dockerclitrusted/trustedandnot:latest", privateRegistryURL)
   344  	// tag the image and upload it to the private registry
   345  	dockerCmd(c, "tag", "busybox", repoName)
   346  
   347  	pushCmd := exec.Command(dockerBinary, "push", "--disable-content-trust", repoName)
   348  	s.trustedCmdWithServer(pushCmd, "https://example.com/")
   349  	out, _, err := runCommandWithOutput(pushCmd)
   350  	c.Assert(err, check.IsNil, check.Commentf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out))
   351  	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:"))
   352  }
   353  
   354  func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) {
   355  	repoName := fmt.Sprintf("%v/dockerclitag/trusted:latest", privateRegistryURL)
   356  	// tag the image and upload it to the private registry
   357  	dockerCmd(c, "tag", "busybox", repoName)
   358  	dockerCmd(c, "push", repoName)
   359  
   360  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   361  	s.trustedCmd(pushCmd)
   362  	out, _, err := runCommandWithOutput(pushCmd)
   363  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   364  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   365  
   366  	// Try pull after push
   367  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   368  	s.trustedCmd(pullCmd)
   369  	out, _, err = runCommandWithOutput(pullCmd)
   370  	c.Assert(err, check.IsNil, check.Commentf(out))
   371  	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
   372  }
   373  
   374  func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) {
   375  	repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL)
   376  	// tag the image and upload it to the private registry
   377  	dockerCmd(c, "tag", "busybox", repoName)
   378  
   379  	// Do a trusted push
   380  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   381  	s.trustedCmd(pushCmd)
   382  	out, _, err := runCommandWithOutput(pushCmd)
   383  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   384  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   385  
   386  	// Do another trusted push
   387  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   388  	s.trustedCmd(pushCmd)
   389  	out, _, err = runCommandWithOutput(pushCmd)
   390  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   391  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   392  
   393  	dockerCmd(c, "rmi", repoName)
   394  
   395  	// Try pull to ensure the double push did not break our ability to pull
   396  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   397  	s.trustedCmd(pullCmd)
   398  	out, _, err = runCommandWithOutput(pullCmd)
   399  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted pull: %s\n%s", err, out))
   400  	c.Assert(out, checker.Contains, "Status: Downloaded", check.Commentf("Missing expected output on trusted pull with --disable-content-trust"))
   401  
   402  }
   403  
   404  func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) {
   405  	repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL)
   406  	// tag the image and upload it to the private registry
   407  	dockerCmd(c, "tag", "busybox", repoName)
   408  
   409  	// Push with default passphrases
   410  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   411  	s.trustedCmd(pushCmd)
   412  	out, _, err := runCommandWithOutput(pushCmd)
   413  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   414  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push:\n%s", out))
   415  
   416  	// Push with wrong passphrases
   417  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   418  	s.trustedCmdWithPassphrases(pushCmd, "12345678", "87654321")
   419  	out, _, err = runCommandWithOutput(pushCmd)
   420  	c.Assert(err, check.NotNil, check.Commentf("Error missing from trusted push with short targets passphrase: \n%s", out))
   421  	c.Assert(out, checker.Contains, "could not find necessary signing keys", check.Commentf("Missing expected output on trusted push with short targets/snapsnot passphrase"))
   422  }
   423  
   424  // This test ensures backwards compatibility with old ENV variables. Should be
   425  // deprecated by 1.10
   426  func (s *DockerTrustSuite) TestTrustedPushWithIncorrectDeprecatedPassphraseForNonRoot(c *check.C) {
   427  	repoName := fmt.Sprintf("%v/dockercliincorretdeprecatedpwd/trusted:latest", privateRegistryURL)
   428  	// tag the image and upload it to the private registry
   429  	dockerCmd(c, "tag", "busybox", repoName)
   430  
   431  	// Push with default passphrases
   432  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   433  	s.trustedCmd(pushCmd)
   434  	out, _, err := runCommandWithOutput(pushCmd)
   435  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   436  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   437  
   438  	// Push with wrong passphrases
   439  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   440  	s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "87654321")
   441  	out, _, err = runCommandWithOutput(pushCmd)
   442  	c.Assert(err, check.NotNil, check.Commentf("Error missing from trusted push with short targets passphrase: \n%s", out))
   443  	c.Assert(out, checker.Contains, "could not find necessary signing keys", check.Commentf("Missing expected output on trusted push with short targets/snapsnot passphrase"))
   444  }
   445  
   446  func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) {
   447  	c.Skip("Currently changes system time, causing instability")
   448  	repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL)
   449  	// tag the image and upload it to the private registry
   450  	dockerCmd(c, "tag", "busybox", repoName)
   451  
   452  	// Push with default passphrases
   453  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   454  	s.trustedCmd(pushCmd)
   455  	out, _, err := runCommandWithOutput(pushCmd)
   456  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   457  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   458  
   459  	// Snapshots last for three years. This should be expired
   460  	fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4)
   461  
   462  	runAtDifferentDate(fourYearsLater, func() {
   463  		// Push with wrong passphrases
   464  		pushCmd = exec.Command(dockerBinary, "push", repoName)
   465  		s.trustedCmd(pushCmd)
   466  		out, _, err = runCommandWithOutput(pushCmd)
   467  		c.Assert(err, check.NotNil, check.Commentf("Error missing from trusted push with expired snapshot: \n%s", out))
   468  		c.Assert(out, checker.Contains, "repository out-of-date", check.Commentf("Missing expected output on trusted push with expired snapshot"))
   469  	})
   470  }
   471  
   472  func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) {
   473  	c.Skip("Currently changes system time, causing instability")
   474  	repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppush/trusted:latest", privateRegistryURL)
   475  	// tag the image and upload it to the private registry
   476  	dockerCmd(c, "tag", "busybox", repoName)
   477  
   478  	// Push with default passphrases
   479  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   480  	s.trustedCmd(pushCmd)
   481  	out, _, err := runCommandWithOutput(pushCmd)
   482  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   483  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   484  
   485  	// The timestamps expire in two weeks. Lets check three
   486  	threeWeeksLater := time.Now().Add(time.Hour * 24 * 21)
   487  
   488  	// Should succeed because the server transparently re-signs one
   489  	runAtDifferentDate(threeWeeksLater, func() {
   490  		pushCmd := exec.Command(dockerBinary, "push", repoName)
   491  		s.trustedCmd(pushCmd)
   492  		out, _, err := runCommandWithOutput(pushCmd)
   493  		c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   494  		c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with expired timestamp"))
   495  	})
   496  }
   497  
   498  func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegation(c *check.C) {
   499  	repoName := fmt.Sprintf("%v/dockerclireleasedelegation/trusted", privateRegistryURL)
   500  	targetName := fmt.Sprintf("%s:latest", repoName)
   501  	pwd := "12345678"
   502  	s.setupDelegations(c, repoName, pwd)
   503  
   504  	// tag the image and upload it to the private registry
   505  	dockerCmd(c, "tag", "busybox", targetName)
   506  
   507  	pushCmd := exec.Command(dockerBinary, "-D", "push", targetName)
   508  	s.trustedCmdWithPassphrases(pushCmd, pwd, pwd)
   509  	out, _, err := runCommandWithOutput(pushCmd)
   510  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   511  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   512  
   513  	// Try pull after push
   514  	pullCmd := exec.Command(dockerBinary, "pull", targetName)
   515  	s.trustedCmd(pullCmd)
   516  	out, _, err = runCommandWithOutput(pullCmd)
   517  	c.Assert(err, check.IsNil, check.Commentf(out))
   518  	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
   519  
   520  	// check to make sure that the target has been added to targets/releases and not targets
   521  	contents, err := ioutil.ReadFile(filepath.Join(cliconfig.ConfigDir(), "trust/tuf", repoName, "metadata/targets.json"))
   522  	c.Assert(err, check.IsNil, check.Commentf("Unable to read targets metadata"))
   523  	c.Assert(strings.Contains(string(contents), `"latest"`), checker.False, check.Commentf(string(contents)))
   524  
   525  	contents, err = ioutil.ReadFile(filepath.Join(cliconfig.ConfigDir(), "trust/tuf", repoName, "metadata/targets/releases.json"))
   526  	c.Assert(err, check.IsNil, check.Commentf("Unable to read targets/releases metadata"))
   527  	c.Assert(string(contents), checker.Contains, `"latest"`, check.Commentf(string(contents)))
   528  }