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