github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/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  	"strings"
    10  	"time"
    11  
    12  	"github.com/docker/docker/pkg/integration/checker"
    13  	"github.com/go-check/check"
    14  )
    15  
    16  // Pushing an image to a private registry.
    17  func (s *DockerRegistrySuite) TestPushBusyboxImage(c *check.C) {
    18  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    19  	// tag the image to upload it to the private registry
    20  	dockerCmd(c, "tag", "busybox", repoName)
    21  	// push the image to the registry
    22  	dockerCmd(c, "push", repoName)
    23  }
    24  
    25  // pushing an image without a prefix should throw an error
    26  func (s *DockerSuite) TestPushUnprefixedRepo(c *check.C) {
    27  	out, _, err := dockerCmdWithError("push", "busybox")
    28  	c.Assert(err, check.NotNil, check.Commentf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out))
    29  }
    30  
    31  func (s *DockerRegistrySuite) TestPushUntagged(c *check.C) {
    32  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    33  	expected := "Repository does not exist"
    34  
    35  	out, _, err := dockerCmdWithError("push", repoName)
    36  	c.Assert(err, check.NotNil, check.Commentf("pushing the image to the private registry should have failed: output %q", out))
    37  	c.Assert(out, checker.Contains, expected, check.Commentf("pushing the image failed"))
    38  }
    39  
    40  func (s *DockerRegistrySuite) TestPushBadTag(c *check.C) {
    41  	repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL)
    42  	expected := "does not exist"
    43  
    44  	out, _, err := dockerCmdWithError("push", repoName)
    45  	c.Assert(err, check.NotNil, check.Commentf("pushing the image to the private registry should have failed: output %q", out))
    46  	c.Assert(out, checker.Contains, expected, check.Commentf("pushing the image failed"))
    47  }
    48  
    49  func (s *DockerRegistrySuite) TestPushMultipleTags(c *check.C) {
    50  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    51  	repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL)
    52  	repoTag2 := fmt.Sprintf("%v/dockercli/busybox:t2", privateRegistryURL)
    53  	// tag the image and upload it to the private registry
    54  	dockerCmd(c, "tag", "busybox", repoTag1)
    55  
    56  	dockerCmd(c, "tag", "busybox", repoTag2)
    57  
    58  	dockerCmd(c, "push", repoName)
    59  
    60  	// Ensure layer list is equivalent for repoTag1 and repoTag2
    61  	out1, _ := dockerCmd(c, "pull", repoTag1)
    62  
    63  	imageAlreadyExists := ": Image already exists"
    64  	var out1Lines []string
    65  	for _, outputLine := range strings.Split(out1, "\n") {
    66  		if strings.Contains(outputLine, imageAlreadyExists) {
    67  			out1Lines = append(out1Lines, outputLine)
    68  		}
    69  	}
    70  
    71  	out2, _ := dockerCmd(c, "pull", repoTag2)
    72  
    73  	var out2Lines []string
    74  	for _, outputLine := range strings.Split(out2, "\n") {
    75  		if strings.Contains(outputLine, imageAlreadyExists) {
    76  			out1Lines = append(out1Lines, outputLine)
    77  		}
    78  	}
    79  	c.Assert(out2Lines, checker.HasLen, len(out1Lines))
    80  
    81  	for i := range out1Lines {
    82  		c.Assert(out1Lines[i], checker.Equals, out2Lines[i])
    83  	}
    84  }
    85  
    86  func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) {
    87  	repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL)
    88  	emptyTarball, err := ioutil.TempFile("", "empty_tarball")
    89  	c.Assert(err, check.IsNil, check.Commentf("Unable to create test file"))
    90  
    91  	tw := tar.NewWriter(emptyTarball)
    92  	err = tw.Close()
    93  	c.Assert(err, check.IsNil, check.Commentf("Error creating empty tarball"))
    94  
    95  	freader, err := os.Open(emptyTarball.Name())
    96  	c.Assert(err, check.IsNil, check.Commentf("Could not open test tarball"))
    97  
    98  	importCmd := exec.Command(dockerBinary, "import", "-", repoName)
    99  	importCmd.Stdin = freader
   100  	out, _, err := runCommandWithOutput(importCmd)
   101  	c.Assert(err, check.IsNil, check.Commentf("import failed: %q", out))
   102  
   103  	// Now verify we can push it
   104  	out, _, err = dockerCmdWithError("push", repoName)
   105  	c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out))
   106  }
   107  
   108  func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
   109  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   110  	// tag the image and upload it to the private registry
   111  	dockerCmd(c, "tag", "busybox", repoName)
   112  
   113  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   114  	s.trustedCmd(pushCmd)
   115  	out, _, err := runCommandWithOutput(pushCmd)
   116  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   117  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   118  }
   119  
   120  func (s *DockerTrustSuite) TestTrustedPushWithEnvPasswords(c *check.C) {
   121  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   122  	// tag the image and upload it to the private registry
   123  	dockerCmd(c, "tag", "busybox", repoName)
   124  
   125  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   126  	s.trustedCmdWithPassphrases(pushCmd, "12345678", "12345678")
   127  	out, _, err := runCommandWithOutput(pushCmd)
   128  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   129  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   130  }
   131  
   132  // This test ensures backwards compatibility with old ENV variables. Should be
   133  // deprecated by 1.10
   134  func (s *DockerTrustSuite) TestTrustedPushWithDeprecatedEnvPasswords(c *check.C) {
   135  	repoName := fmt.Sprintf("%v/dockercli/trusteddeprecated:latest", privateRegistryURL)
   136  	// tag the image and upload it to the private registry
   137  	dockerCmd(c, "tag", "busybox", repoName)
   138  
   139  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   140  	s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "12345678")
   141  	out, _, err := runCommandWithOutput(pushCmd)
   142  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %s\n%s", err, out))
   143  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   144  }
   145  
   146  func (s *DockerTrustSuite) TestTrustedPushWithFailingServer(c *check.C) {
   147  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   148  	// tag the image and upload it to the private registry
   149  	dockerCmd(c, "tag", "busybox", repoName)
   150  
   151  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   152  	s.trustedCmdWithServer(pushCmd, "https://example.com:81/")
   153  	out, _, err := runCommandWithOutput(pushCmd)
   154  	c.Assert(err, check.NotNil, check.Commentf("Missing error while running trusted push w/ no server"))
   155  	c.Assert(out, checker.Contains, "error contacting notary server", check.Commentf("Missing expected output on trusted push"))
   156  }
   157  
   158  func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) {
   159  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   160  	// tag the image and upload it to the private registry
   161  	dockerCmd(c, "tag", "busybox", repoName)
   162  
   163  	pushCmd := exec.Command(dockerBinary, "push", "--disable-content-trust", repoName)
   164  	s.trustedCmdWithServer(pushCmd, "https://example.com/")
   165  	out, _, err := runCommandWithOutput(pushCmd)
   166  	c.Assert(err, check.IsNil, check.Commentf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out))
   167  	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:"))
   168  }
   169  
   170  func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) {
   171  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   172  	// tag the image and upload it to the private registry
   173  	dockerCmd(c, "tag", "busybox", repoName)
   174  	dockerCmd(c, "push", repoName)
   175  
   176  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   177  	s.trustedCmd(pushCmd)
   178  	out, _, err := runCommandWithOutput(pushCmd)
   179  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   180  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   181  }
   182  
   183  func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) {
   184  	repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL)
   185  	// tag the image and upload it to the private registry
   186  	dockerCmd(c, "tag", "busybox", repoName)
   187  
   188  	// Do a trusted push
   189  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   190  	s.trustedCmd(pushCmd)
   191  	out, _, err := runCommandWithOutput(pushCmd)
   192  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   193  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   194  
   195  	// Do another trusted push
   196  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   197  	s.trustedCmd(pushCmd)
   198  	out, _, err = runCommandWithOutput(pushCmd)
   199  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   200  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
   201  
   202  	dockerCmd(c, "rmi", repoName)
   203  
   204  	// Try pull to ensure the double push did not break our ability to pull
   205  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   206  	s.trustedCmd(pullCmd)
   207  	out, _, err = runCommandWithOutput(pullCmd)
   208  	c.Assert(err, check.IsNil, check.Commentf("Error running trusted pull: %s\n%s", err, out))
   209  	c.Assert(out, checker.Contains, "Status: Downloaded", check.Commentf("Missing expected output on trusted pull with --disable-content-trust"))
   210  
   211  }
   212  
   213  func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) {
   214  	repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL)
   215  	// tag the image and upload it to the private registry
   216  	dockerCmd(c, "tag", "busybox", repoName)
   217  
   218  	// Push with default passphrases
   219  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   220  	s.trustedCmd(pushCmd)
   221  	out, _, err := runCommandWithOutput(pushCmd)
   222  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   223  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push:\n%s", out))
   224  
   225  	// Push with wrong passphrases
   226  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   227  	s.trustedCmdWithPassphrases(pushCmd, "12345678", "87654321")
   228  	out, _, err = runCommandWithOutput(pushCmd)
   229  	c.Assert(err, check.NotNil, check.Commentf("Error missing from trusted push with short targets passphrase: \n%s", out))
   230  	c.Assert(out, checker.Contains, "could not find necessary signing keys", check.Commentf("Missing expected output on trusted push with short targets/snapsnot passphrase"))
   231  }
   232  
   233  // This test ensures backwards compatibility with old ENV variables. Should be
   234  // deprecated by 1.10
   235  func (s *DockerTrustSuite) TestTrustedPushWithIncorrectDeprecatedPassphraseForNonRoot(c *check.C) {
   236  	repoName := fmt.Sprintf("%v/dockercliincorretdeprecatedpwd/trusted:latest", privateRegistryURL)
   237  	// tag the image and upload it to the private registry
   238  	dockerCmd(c, "tag", "busybox", repoName)
   239  
   240  	// Push with default passphrases
   241  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   242  	s.trustedCmd(pushCmd)
   243  	out, _, err := runCommandWithOutput(pushCmd)
   244  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %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  	// Push with wrong passphrases
   248  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   249  	s.trustedCmdWithDeprecatedEnvPassphrases(pushCmd, "12345678", "87654321")
   250  	out, _, err = runCommandWithOutput(pushCmd)
   251  	c.Assert(err, check.NotNil, check.Commentf("Error missing from trusted push with short targets passphrase: \n%s", out))
   252  	c.Assert(out, checker.Contains, "could not find necessary signing keys", check.Commentf("Missing expected output on trusted push with short targets/snapsnot passphrase"))
   253  }
   254  
   255  func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) {
   256  	c.Skip("Currently changes system time, causing instability")
   257  	repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL)
   258  	// tag the image and upload it to the private registry
   259  	dockerCmd(c, "tag", "busybox", repoName)
   260  
   261  	// Push with default passphrases
   262  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   263  	s.trustedCmd(pushCmd)
   264  	out, _, err := runCommandWithOutput(pushCmd)
   265  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %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  	// Snapshots last for three years. This should be expired
   269  	fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4)
   270  
   271  	runAtDifferentDate(fourYearsLater, func() {
   272  		// Push with wrong passphrases
   273  		pushCmd = exec.Command(dockerBinary, "push", repoName)
   274  		s.trustedCmd(pushCmd)
   275  		out, _, err = runCommandWithOutput(pushCmd)
   276  		c.Assert(err, check.NotNil, check.Commentf("Error missing from trusted push with expired snapshot: \n%s", out))
   277  		c.Assert(out, checker.Contains, "repository out-of-date", check.Commentf("Missing expected output on trusted push with expired snapshot"))
   278  	})
   279  }
   280  
   281  func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) {
   282  	c.Skip("Currently changes system time, causing instability")
   283  	repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppush/trusted:latest", privateRegistryURL)
   284  	// tag the image and upload it to the private registry
   285  	dockerCmd(c, "tag", "busybox", repoName)
   286  
   287  	// Push with default passphrases
   288  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   289  	s.trustedCmd(pushCmd)
   290  	out, _, err := runCommandWithOutput(pushCmd)
   291  	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
   292  	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push"))
   293  
   294  	// The timestamps expire in two weeks. Lets check three
   295  	threeWeeksLater := time.Now().Add(time.Hour * 24 * 21)
   296  
   297  	// Should succeed because the server transparently re-signs one
   298  	runAtDifferentDate(threeWeeksLater, func() {
   299  		pushCmd := exec.Command(dockerBinary, "push", repoName)
   300  		s.trustedCmd(pushCmd)
   301  		out, _, err := runCommandWithOutput(pushCmd)
   302  		c.Assert(err, check.IsNil, check.Commentf("Error running trusted push: %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 expired timestamp"))
   304  	})
   305  }