github.com/glycerine/docker@v1.8.2/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(c, "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(c, "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(c, "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) TestPushInterrupt(c *check.C) {
   101  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
   102  	// tag the image and upload it to the private registry
   103  	dockerCmd(c, "tag", "busybox", repoName)
   104  
   105  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   106  	if err := pushCmd.Start(); err != nil {
   107  		c.Fatalf("Failed to start pushing to private registry: %v", err)
   108  	}
   109  
   110  	// Interrupt push (yes, we have no idea at what point it will get killed).
   111  	time.Sleep(200 * time.Millisecond)
   112  	if err := pushCmd.Process.Kill(); err != nil {
   113  		c.Fatalf("Failed to kill push process: %v", err)
   114  	}
   115  	if out, _, err := dockerCmdWithError(c, "push", repoName); err == nil {
   116  		if !strings.Contains(out, "already in progress") {
   117  			c.Fatalf("Push should be continued on daemon side, but seems ok: %v, %s", err, out)
   118  		}
   119  	}
   120  	// now wait until all this pushes will complete
   121  	// if it failed with timeout - there would be some error,
   122  	// so no logic about it here
   123  	for exec.Command(dockerBinary, "push", repoName).Run() != nil {
   124  	}
   125  }
   126  
   127  func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) {
   128  	repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL)
   129  	emptyTarball, err := ioutil.TempFile("", "empty_tarball")
   130  	if err != nil {
   131  		c.Fatalf("Unable to create test file: %v", err)
   132  	}
   133  	tw := tar.NewWriter(emptyTarball)
   134  	err = tw.Close()
   135  	if err != nil {
   136  		c.Fatalf("Error creating empty tarball: %v", err)
   137  	}
   138  	freader, err := os.Open(emptyTarball.Name())
   139  	if err != nil {
   140  		c.Fatalf("Could not open test tarball: %v", err)
   141  	}
   142  
   143  	importCmd := exec.Command(dockerBinary, "import", "-", repoName)
   144  	importCmd.Stdin = freader
   145  	out, _, err := runCommandWithOutput(importCmd)
   146  	if err != nil {
   147  		c.Errorf("import failed with errors: %v, output: %q", err, out)
   148  	}
   149  
   150  	// Now verify we can push it
   151  	if out, _, err := dockerCmdWithError(c, "push", repoName); err != nil {
   152  		c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
   153  	}
   154  }
   155  
   156  func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
   157  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   158  	// tag the image and upload it to the private registry
   159  	dockerCmd(c, "tag", "busybox", repoName)
   160  
   161  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   162  	s.trustedCmd(pushCmd)
   163  	out, _, err := runCommandWithOutput(pushCmd)
   164  	if err != nil {
   165  		c.Fatalf("Error running trusted push: %s\n%s", err, out)
   166  	}
   167  	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   168  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   169  	}
   170  }
   171  
   172  func (s *DockerTrustSuite) TestTrustedPushWithFaillingServer(c *check.C) {
   173  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   174  	// tag the image and upload it to the private registry
   175  	dockerCmd(c, "tag", "busybox", repoName)
   176  
   177  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   178  	s.trustedCmdWithServer(pushCmd, "example/")
   179  	out, _, err := runCommandWithOutput(pushCmd)
   180  	if err == nil {
   181  		c.Fatalf("Missing error while running trusted push w/ no server")
   182  	}
   183  
   184  	if !strings.Contains(string(out), "Error establishing connection to notary repository") {
   185  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   186  	}
   187  }
   188  
   189  func (s *DockerTrustSuite) TestTrustedPushWithoutServerAndUntrusted(c *check.C) {
   190  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   191  	// tag the image and upload it to the private registry
   192  	dockerCmd(c, "tag", "busybox", repoName)
   193  
   194  	pushCmd := exec.Command(dockerBinary, "push", "--disable-content-trust", repoName)
   195  	s.trustedCmdWithServer(pushCmd, "example/")
   196  	out, _, err := runCommandWithOutput(pushCmd)
   197  	if err != nil {
   198  		c.Fatalf("trusted push with no server and --disable-content-trust failed: %s\n%s", err, out)
   199  	}
   200  
   201  	if strings.Contains(string(out), "Error establishing connection to notary repository") {
   202  		c.Fatalf("Missing expected output on trusted push with --disable-content-trust:\n%s", out)
   203  	}
   204  }
   205  
   206  func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) {
   207  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   208  	// tag the image and upload it to the private registry
   209  	dockerCmd(c, "tag", "busybox", repoName)
   210  	dockerCmd(c, "push", repoName)
   211  
   212  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   213  	s.trustedCmd(pushCmd)
   214  	out, _, err := runCommandWithOutput(pushCmd)
   215  	if err != nil {
   216  		c.Fatalf("trusted push failed: %s\n%s", err, out)
   217  	}
   218  
   219  	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   220  		c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out)
   221  	}
   222  }
   223  
   224  func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) {
   225  	repoName := fmt.Sprintf("%v/dockerclipushpush/trusted:latest", privateRegistryURL)
   226  	// tag the image and upload it to the private registry
   227  	dockerCmd(c, "tag", "busybox", repoName)
   228  
   229  	// Do a trusted push
   230  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   231  	s.trustedCmd(pushCmd)
   232  	out, _, err := runCommandWithOutput(pushCmd)
   233  	if err != nil {
   234  		c.Fatalf("trusted push failed: %s\n%s", err, out)
   235  	}
   236  
   237  	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   238  		c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out)
   239  	}
   240  
   241  	// Do another trusted push
   242  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   243  	s.trustedCmd(pushCmd)
   244  	out, _, err = runCommandWithOutput(pushCmd)
   245  	if err != nil {
   246  		c.Fatalf("trusted push failed: %s\n%s", err, out)
   247  	}
   248  
   249  	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   250  		c.Fatalf("Missing expected output on trusted push with existing tag:\n%s", out)
   251  	}
   252  
   253  	dockerCmd(c, "rmi", repoName)
   254  
   255  	// Try pull to ensure the double push did not break our ability to pull
   256  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   257  	s.trustedCmd(pullCmd)
   258  	out, _, err = runCommandWithOutput(pullCmd)
   259  	if err != nil {
   260  		c.Fatalf("Error running trusted pull: %s\n%s", err, out)
   261  	}
   262  
   263  	if !strings.Contains(string(out), "Status: Downloaded") {
   264  		c.Fatalf("Missing expected output on trusted pull with --disable-content-trust:\n%s", out)
   265  	}
   266  }
   267  
   268  func (s *DockerTrustSuite) TestTrustedPushWithIncorrectPassphraseForNonRoot(c *check.C) {
   269  	repoName := fmt.Sprintf("%v/dockercliincorretpwd/trusted:latest", privateRegistryURL)
   270  	// tag the image and upload it to the private registry
   271  	dockerCmd(c, "tag", "busybox", repoName)
   272  
   273  	// Push with default passphrases
   274  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   275  	s.trustedCmd(pushCmd)
   276  	out, _, err := runCommandWithOutput(pushCmd)
   277  	if err != nil {
   278  		c.Fatalf("trusted push failed: %s\n%s", err, out)
   279  	}
   280  
   281  	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   282  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   283  	}
   284  
   285  	// Push with wrong passphrases
   286  	pushCmd = exec.Command(dockerBinary, "push", repoName)
   287  	s.trustedCmdWithPassphrases(pushCmd, "12345678", "87654321")
   288  	out, _, err = runCommandWithOutput(pushCmd)
   289  	if err == nil {
   290  		c.Fatalf("Error missing from trusted push with short targets passphrase: \n%s", out)
   291  	}
   292  
   293  	if !strings.Contains(string(out), "password invalid, operation has failed") {
   294  		c.Fatalf("Missing expected output on trusted push with short targets/snapsnot passphrase:\n%s", out)
   295  	}
   296  }
   297  
   298  func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) {
   299  	c.Skip("Currently changes system time, causing instability")
   300  	repoName := fmt.Sprintf("%v/dockercliexpiredsnapshot/trusted:latest", privateRegistryURL)
   301  	// tag the image and upload it to the private registry
   302  	dockerCmd(c, "tag", "busybox", repoName)
   303  
   304  	// Push with default passphrases
   305  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   306  	s.trustedCmd(pushCmd)
   307  	out, _, err := runCommandWithOutput(pushCmd)
   308  	if err != nil {
   309  		c.Fatalf("trusted push failed: %s\n%s", err, out)
   310  	}
   311  
   312  	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   313  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   314  	}
   315  
   316  	// Snapshots last for three years. This should be expired
   317  	fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4)
   318  
   319  	runAtDifferentDate(fourYearsLater, func() {
   320  		// Push with wrong passphrases
   321  		pushCmd = exec.Command(dockerBinary, "push", repoName)
   322  		s.trustedCmd(pushCmd)
   323  		out, _, err = runCommandWithOutput(pushCmd)
   324  		if err == nil {
   325  			c.Fatalf("Error missing from trusted push with expired snapshot: \n%s", out)
   326  		}
   327  
   328  		if !strings.Contains(string(out), "repository out-of-date") {
   329  			c.Fatalf("Missing expected output on trusted push with expired snapshot:\n%s", out)
   330  		}
   331  	})
   332  }
   333  
   334  func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) {
   335  	c.Skip("Currently changes system time, causing instability")
   336  	repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppush/trusted:latest", privateRegistryURL)
   337  	// tag the image and upload it to the private registry
   338  	dockerCmd(c, "tag", "busybox", repoName)
   339  
   340  	// Push with default passphrases
   341  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   342  	s.trustedCmd(pushCmd)
   343  	out, _, err := runCommandWithOutput(pushCmd)
   344  	if err != nil {
   345  		c.Fatalf("trusted push failed: %s\n%s", err, out)
   346  	}
   347  
   348  	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   349  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   350  	}
   351  
   352  	// The timestamps expire in two weeks. Lets check three
   353  	threeWeeksLater := time.Now().Add(time.Hour * 24 * 21)
   354  
   355  	// Should succeed because the server transparently re-signs one
   356  	runAtDifferentDate(threeWeeksLater, func() {
   357  		pushCmd := exec.Command(dockerBinary, "push", repoName)
   358  		s.trustedCmd(pushCmd)
   359  		out, _, err := runCommandWithOutput(pushCmd)
   360  		if err != nil {
   361  			c.Fatalf("Error running trusted push: %s\n%s", err, out)
   362  		}
   363  		if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   364  			c.Fatalf("Missing expected output on trusted push with expired timestamp:\n%s", out)
   365  		}
   366  	})
   367  }