github.com/mssola/docker@v1.8.1/integration-cli/docker_cli_pull_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os/exec"
     6  	"strings"
     7  	"time"
     8  
     9  	"io/ioutil"
    10  
    11  	"github.com/go-check/check"
    12  )
    13  
    14  // See issue docker/docker#8141
    15  func (s *DockerRegistrySuite) TestPullImageWithAliases(c *check.C) {
    16  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    17  
    18  	repos := []string{}
    19  	for _, tag := range []string{"recent", "fresh"} {
    20  		repos = append(repos, fmt.Sprintf("%v:%v", repoName, tag))
    21  	}
    22  
    23  	// Tag and push the same image multiple times.
    24  	for _, repo := range repos {
    25  		dockerCmd(c, "tag", "busybox", repo)
    26  		dockerCmd(c, "push", repo)
    27  	}
    28  
    29  	// Clear local images store.
    30  	args := append([]string{"rmi"}, repos...)
    31  	dockerCmd(c, args...)
    32  
    33  	// Pull a single tag and verify it doesn't bring down all aliases.
    34  	dockerCmd(c, "pull", repos[0])
    35  	dockerCmd(c, "inspect", repos[0])
    36  	for _, repo := range repos[1:] {
    37  		if _, _, err := dockerCmdWithError(c, "inspect", repo); err == nil {
    38  			c.Fatalf("Image %v shouldn't have been pulled down", repo)
    39  		}
    40  	}
    41  }
    42  
    43  // pulling library/hello-world should show verified message
    44  func (s *DockerSuite) TestPullVerified(c *check.C) {
    45  	c.Skip("Skipping hub dependent test")
    46  
    47  	// Image must be pulled from central repository to get verified message
    48  	// unless keychain is manually updated to contain the daemon's sign key.
    49  
    50  	verifiedName := "hello-world"
    51  
    52  	// pull it
    53  	expected := "The image you are pulling has been verified"
    54  	if out, exitCode, err := dockerCmdWithError(c, "pull", verifiedName); err != nil || !strings.Contains(out, expected) {
    55  		if err != nil || exitCode != 0 {
    56  			c.Skip(fmt.Sprintf("pulling the '%s' image from the registry has failed: %v", verifiedName, err))
    57  		}
    58  		c.Fatalf("pulling a verified image failed. expected: %s\ngot: %s, %v", expected, out, err)
    59  	}
    60  
    61  	// pull it again
    62  	if out, exitCode, err := dockerCmdWithError(c, "pull", verifiedName); err != nil || strings.Contains(out, expected) {
    63  		if err != nil || exitCode != 0 {
    64  			c.Skip(fmt.Sprintf("pulling the '%s' image from the registry has failed: %v", verifiedName, err))
    65  		}
    66  		c.Fatalf("pulling a verified image failed. unexpected verify message\ngot: %s, %v", out, err)
    67  	}
    68  
    69  }
    70  
    71  // pulling an image from the central registry should work
    72  func (s *DockerSuite) TestPullImageFromCentralRegistry(c *check.C) {
    73  	testRequires(c, Network)
    74  
    75  	dockerCmd(c, "pull", "hello-world")
    76  }
    77  
    78  // pulling a non-existing image from the central registry should return a non-zero exit code
    79  func (s *DockerSuite) TestPullNonExistingImage(c *check.C) {
    80  	testRequires(c, Network)
    81  
    82  	name := "sadfsadfasdf"
    83  	out, _, err := dockerCmdWithError(c, "pull", name)
    84  
    85  	if err == nil || !strings.Contains(out, fmt.Sprintf("Error: image library/%s:latest not found", name)) {
    86  		c.Fatalf("expected non-zero exit status when pulling non-existing image: %s", out)
    87  	}
    88  }
    89  
    90  // pulling an image from the central registry using official names should work
    91  // ensure all pulls result in the same image
    92  func (s *DockerSuite) TestPullImageOfficialNames(c *check.C) {
    93  	testRequires(c, Network)
    94  
    95  	names := []string{
    96  		"library/hello-world",
    97  		"docker.io/library/hello-world",
    98  		"index.docker.io/library/hello-world",
    99  	}
   100  	for _, name := range names {
   101  		out, exitCode, err := dockerCmdWithError(c, "pull", name)
   102  		if err != nil || exitCode != 0 {
   103  			c.Errorf("pulling the '%s' image from the registry has failed: %s", name, err)
   104  			continue
   105  		}
   106  
   107  		// ensure we don't have multiple image names.
   108  		out, _ = dockerCmd(c, "images")
   109  		if strings.Contains(out, name) {
   110  			c.Errorf("images should not have listed '%s'", name)
   111  		}
   112  	}
   113  }
   114  
   115  func (s *DockerSuite) TestPullScratchNotAllowed(c *check.C) {
   116  	testRequires(c, Network)
   117  
   118  	out, exitCode, err := dockerCmdWithError(c, "pull", "scratch")
   119  	if err == nil {
   120  		c.Fatal("expected pull of scratch to fail, but it didn't")
   121  	}
   122  	if exitCode != 1 {
   123  		c.Fatalf("pulling scratch expected exit code 1, got %d", exitCode)
   124  	}
   125  	if strings.Contains(out, "Pulling repository scratch") {
   126  		c.Fatalf("pulling scratch should not have begun: %s", out)
   127  	}
   128  	if !strings.Contains(out, "'scratch' is a reserved name") {
   129  		c.Fatalf("unexpected output pulling scratch: %s", out)
   130  	}
   131  }
   132  
   133  // pulling an image with --all-tags=true
   134  func (s *DockerSuite) TestPullImageWithAllTagFromCentralRegistry(c *check.C) {
   135  	testRequires(c, Network)
   136  
   137  	dockerCmd(c, "pull", "busybox")
   138  
   139  	outImageCmd, _ := dockerCmd(c, "images", "busybox")
   140  
   141  	dockerCmd(c, "pull", "--all-tags=true", "busybox")
   142  
   143  	outImageAllTagCmd, _ := dockerCmd(c, "images", "busybox")
   144  
   145  	if strings.Count(outImageCmd, "busybox") >= strings.Count(outImageAllTagCmd, "busybox") {
   146  		c.Fatalf("Pulling with all tags should get more images")
   147  	}
   148  
   149  	// FIXME has probably no effect (tags already pushed)
   150  	dockerCmd(c, "pull", "-a", "busybox")
   151  
   152  	outImageAllTagCmd, _ = dockerCmd(c, "images", "busybox")
   153  
   154  	if strings.Count(outImageCmd, "busybox") >= strings.Count(outImageAllTagCmd, "busybox") {
   155  		c.Fatalf("Pulling with all tags should get more images")
   156  	}
   157  }
   158  
   159  func (s *DockerTrustSuite) TestTrustedPull(c *check.C) {
   160  	repoName := s.setupTrustedImage(c, "trusted-pull")
   161  
   162  	// Try pull
   163  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   164  	s.trustedCmd(pullCmd)
   165  	out, _, err := runCommandWithOutput(pullCmd)
   166  	if err != nil {
   167  		c.Fatalf("Error running trusted pull: %s\n%s", err, out)
   168  	}
   169  
   170  	if !strings.Contains(string(out), "Tagging") {
   171  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   172  	}
   173  
   174  	dockerCmd(c, "rmi", repoName)
   175  
   176  	// Try untrusted pull to ensure we pushed the tag to the registry
   177  	pullCmd = exec.Command(dockerBinary, "pull", "--disable-content-trust=true", repoName)
   178  	s.trustedCmd(pullCmd)
   179  	out, _, err = runCommandWithOutput(pullCmd)
   180  	if err != nil {
   181  		c.Fatalf("Error running trusted pull: %s\n%s", err, out)
   182  	}
   183  
   184  	if !strings.Contains(string(out), "Status: Downloaded") {
   185  		c.Fatalf("Missing expected output on trusted pull with --disable-content-trust:\n%s", out)
   186  	}
   187  }
   188  
   189  func (s *DockerTrustSuite) TestTrustedIsolatedPull(c *check.C) {
   190  	repoName := s.setupTrustedImage(c, "trusted-isolatd-pull")
   191  
   192  	// Try pull (run from isolated directory without trust information)
   193  	pullCmd := exec.Command(dockerBinary, "--config", "/tmp/docker-isolated", "pull", repoName)
   194  	s.trustedCmd(pullCmd)
   195  	out, _, err := runCommandWithOutput(pullCmd)
   196  	if err != nil {
   197  		c.Fatalf("Error running trusted pull: %s\n%s", err, out)
   198  	}
   199  
   200  	if !strings.Contains(string(out), "Tagging") {
   201  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   202  	}
   203  
   204  	dockerCmd(c, "rmi", repoName)
   205  }
   206  
   207  func (s *DockerTrustSuite) TestUntrustedPull(c *check.C) {
   208  	repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL)
   209  	// tag the image and upload it to the private registry
   210  	dockerCmd(c, "tag", "busybox", repoName)
   211  	dockerCmd(c, "push", repoName)
   212  	dockerCmd(c, "rmi", repoName)
   213  
   214  	// Try trusted pull on untrusted tag
   215  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   216  	s.trustedCmd(pullCmd)
   217  	out, _, err := runCommandWithOutput(pullCmd)
   218  	if err == nil {
   219  		c.Fatalf("Error expected when running trusted pull with:\n%s", out)
   220  	}
   221  
   222  	if !strings.Contains(string(out), "no trust data available") {
   223  		c.Fatalf("Missing expected output on trusted pull:\n%s", out)
   224  	}
   225  }
   226  
   227  func (s *DockerTrustSuite) TestPullWhenCertExpired(c *check.C) {
   228  	c.Skip("Currently changes system time, causing instability")
   229  	repoName := s.setupTrustedImage(c, "trusted-cert-expired")
   230  
   231  	// Certificates have 10 years of expiration
   232  	elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11)
   233  
   234  	runAtDifferentDate(elevenYearsFromNow, func() {
   235  		// Try pull
   236  		pullCmd := exec.Command(dockerBinary, "pull", repoName)
   237  		s.trustedCmd(pullCmd)
   238  		out, _, err := runCommandWithOutput(pullCmd)
   239  		if err == nil {
   240  			c.Fatalf("Error running trusted pull in the distant future: %s\n%s", err, out)
   241  		}
   242  
   243  		if !strings.Contains(string(out), "could not validate the path to a trusted root") {
   244  			c.Fatalf("Missing expected output on trusted pull in the distant future:\n%s", out)
   245  		}
   246  	})
   247  
   248  	runAtDifferentDate(elevenYearsFromNow, func() {
   249  		// Try pull
   250  		pullCmd := exec.Command(dockerBinary, "pull", "--disable-content-trust", repoName)
   251  		s.trustedCmd(pullCmd)
   252  		out, _, err := runCommandWithOutput(pullCmd)
   253  		if err != nil {
   254  			c.Fatalf("Error running untrusted pull in the distant future: %s\n%s", err, out)
   255  		}
   256  
   257  		if !strings.Contains(string(out), "Status: Downloaded") {
   258  			c.Fatalf("Missing expected output on untrusted pull in the distant future:\n%s", out)
   259  		}
   260  	})
   261  }
   262  
   263  func (s *DockerTrustSuite) TestTrustedPullFromBadTrustServer(c *check.C) {
   264  	repoName := fmt.Sprintf("%v/dockerclievilpull/trusted:latest", privateRegistryURL)
   265  	evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir")
   266  	if err != nil {
   267  		c.Fatalf("Failed to create local temp dir")
   268  	}
   269  
   270  	// tag the image and upload it to the private registry
   271  	dockerCmd(c, "tag", "busybox", repoName)
   272  
   273  	pushCmd := exec.Command(dockerBinary, "push", repoName)
   274  	s.trustedCmd(pushCmd)
   275  	out, _, err := runCommandWithOutput(pushCmd)
   276  	if err != nil {
   277  		c.Fatalf("Error running trusted push: %s\n%s", err, out)
   278  	}
   279  	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   280  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   281  	}
   282  
   283  	dockerCmd(c, "rmi", repoName)
   284  
   285  	// Try pull
   286  	pullCmd := exec.Command(dockerBinary, "pull", repoName)
   287  	s.trustedCmd(pullCmd)
   288  	out, _, err = runCommandWithOutput(pullCmd)
   289  	if err != nil {
   290  		c.Fatalf("Error running trusted pull: %s\n%s", err, out)
   291  	}
   292  
   293  	if !strings.Contains(string(out), "Tagging") {
   294  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   295  	}
   296  
   297  	dockerCmd(c, "rmi", repoName)
   298  
   299  	// Kill the notary server, start a new "evil" one.
   300  	s.not.Close()
   301  	s.not, err = newTestNotary(c)
   302  	if err != nil {
   303  		c.Fatalf("Restarting notary server failed.")
   304  	}
   305  
   306  	// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
   307  	// tag an image and upload it to the private registry
   308  	dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
   309  
   310  	// Push up to the new server
   311  	pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName)
   312  	s.trustedCmd(pushCmd)
   313  	out, _, err = runCommandWithOutput(pushCmd)
   314  	if err != nil {
   315  		c.Fatalf("Error running trusted push: %s\n%s", err, out)
   316  	}
   317  	if !strings.Contains(string(out), "Signing and pushing trust metadata") {
   318  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   319  	}
   320  
   321  	// Now, try pulling with the original client from this new trust server. This should fail.
   322  	pullCmd = exec.Command(dockerBinary, "pull", repoName)
   323  	s.trustedCmd(pullCmd)
   324  	out, _, err = runCommandWithOutput(pullCmd)
   325  	if err == nil {
   326  		c.Fatalf("Expected to fail on this pull due to different remote data: %s\n%s", err, out)
   327  	}
   328  
   329  	if !strings.Contains(string(out), "failed to validate data with current trusted certificates") {
   330  		c.Fatalf("Missing expected output on trusted push:\n%s", out)
   331  	}
   332  }
   333  
   334  func (s *DockerTrustSuite) TestTrustedPullWithExpiredSnapshot(c *check.C) {
   335  	c.Skip("Currently changes system time, causing instability")
   336  	repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppull/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  	dockerCmd(c, "rmi", repoName)
   353  
   354  	// Snapshots last for three years. This should be expired
   355  	fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4)
   356  
   357  	// Should succeed because the server transparently re-signs one
   358  	runAtDifferentDate(fourYearsLater, func() {
   359  		// Try pull
   360  		pullCmd := exec.Command(dockerBinary, "pull", repoName)
   361  		s.trustedCmd(pullCmd)
   362  		out, _, err = runCommandWithOutput(pullCmd)
   363  		if err == nil {
   364  			c.Fatalf("Missing expected error running trusted pull with expired snapshots")
   365  		}
   366  
   367  		if !strings.Contains(string(out), "repository out-of-date") {
   368  			c.Fatalf("Missing expected output on trusted pull with expired snapshot:\n%s", out)
   369  		}
   370  	})
   371  }