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