github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/integration-cli/docker_cli_pull_local_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os/exec"
     6  	"strings"
     7  
     8  	"github.com/docker/docker/pkg/integration/checker"
     9  	"github.com/go-check/check"
    10  )
    11  
    12  // TestPullImageWithAliases pulls a specific image tag and verifies that any aliases (i.e., other
    13  // tags for the same image) are not also pulled down.
    14  //
    15  // Ref: docker/docker#8141
    16  func (s *DockerRegistrySuite) TestPullImageWithAliases(c *check.C) {
    17  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    18  
    19  	repos := []string{}
    20  	for _, tag := range []string{"recent", "fresh"} {
    21  		repos = append(repos, fmt.Sprintf("%v:%v", repoName, tag))
    22  	}
    23  
    24  	// Tag and push the same image multiple times.
    25  	for _, repo := range repos {
    26  		dockerCmd(c, "tag", "busybox", repo)
    27  		dockerCmd(c, "push", repo)
    28  	}
    29  
    30  	// Clear local images store.
    31  	args := append([]string{"rmi"}, repos...)
    32  	dockerCmd(c, args...)
    33  
    34  	// Pull a single tag and verify it doesn't bring down all aliases.
    35  	dockerCmd(c, "pull", repos[0])
    36  	dockerCmd(c, "inspect", repos[0])
    37  	for _, repo := range repos[1:] {
    38  		_, _, err := dockerCmdWithError("inspect", repo)
    39  		c.Assert(err, checker.NotNil, check.Commentf("Image %v shouldn't have been pulled down", repo))
    40  	}
    41  }
    42  
    43  // TestConcurrentPullWholeRepo pulls the same repo concurrently.
    44  func (s *DockerRegistrySuite) TestConcurrentPullWholeRepo(c *check.C) {
    45  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    46  
    47  	repos := []string{}
    48  	for _, tag := range []string{"recent", "fresh", "todays"} {
    49  		repo := fmt.Sprintf("%v:%v", repoName, tag)
    50  		_, err := buildImage(repo, fmt.Sprintf(`
    51  		    FROM busybox
    52  		    ENTRYPOINT ["/bin/echo"]
    53  		    ENV FOO foo
    54  		    ENV BAR bar
    55  		    CMD echo %s
    56  		`, repo), true)
    57  		c.Assert(err, checker.IsNil)
    58  		dockerCmd(c, "push", repo)
    59  		repos = append(repos, repo)
    60  	}
    61  
    62  	// Clear local images store.
    63  	args := append([]string{"rmi"}, repos...)
    64  	dockerCmd(c, args...)
    65  
    66  	// Run multiple re-pulls concurrently
    67  	results := make(chan error)
    68  	numPulls := 3
    69  
    70  	for i := 0; i != numPulls; i++ {
    71  		go func() {
    72  			_, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", "-a", repoName))
    73  			results <- err
    74  		}()
    75  	}
    76  
    77  	// These checks are separate from the loop above because the check
    78  	// package is not goroutine-safe.
    79  	for i := 0; i != numPulls; i++ {
    80  		err := <-results
    81  		c.Assert(err, checker.IsNil, check.Commentf("concurrent pull failed with error: %v", err))
    82  	}
    83  
    84  	// Ensure all tags were pulled successfully
    85  	for _, repo := range repos {
    86  		dockerCmd(c, "inspect", repo)
    87  		out, _ := dockerCmd(c, "run", "--rm", repo)
    88  		c.Assert(strings.TrimSpace(out), checker.Equals, "/bin/sh -c echo "+repo)
    89  	}
    90  }
    91  
    92  // TestConcurrentFailingPull tries a concurrent pull that doesn't succeed.
    93  func (s *DockerRegistrySuite) TestConcurrentFailingPull(c *check.C) {
    94  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
    95  
    96  	// Run multiple pulls concurrently
    97  	results := make(chan error)
    98  	numPulls := 3
    99  
   100  	for i := 0; i != numPulls; i++ {
   101  		go func() {
   102  			_, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repoName+":asdfasdf"))
   103  			results <- err
   104  		}()
   105  	}
   106  
   107  	// These checks are separate from the loop above because the check
   108  	// package is not goroutine-safe.
   109  	for i := 0; i != numPulls; i++ {
   110  		err := <-results
   111  		c.Assert(err, checker.NotNil, check.Commentf("expected pull to fail"))
   112  	}
   113  }
   114  
   115  // TestConcurrentPullMultipleTags pulls multiple tags from the same repo
   116  // concurrently.
   117  func (s *DockerRegistrySuite) TestConcurrentPullMultipleTags(c *check.C) {
   118  	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
   119  
   120  	repos := []string{}
   121  	for _, tag := range []string{"recent", "fresh", "todays"} {
   122  		repo := fmt.Sprintf("%v:%v", repoName, tag)
   123  		_, err := buildImage(repo, fmt.Sprintf(`
   124  		    FROM busybox
   125  		    ENTRYPOINT ["/bin/echo"]
   126  		    ENV FOO foo
   127  		    ENV BAR bar
   128  		    CMD echo %s
   129  		`, repo), true)
   130  		c.Assert(err, checker.IsNil)
   131  		dockerCmd(c, "push", repo)
   132  		repos = append(repos, repo)
   133  	}
   134  
   135  	// Clear local images store.
   136  	args := append([]string{"rmi"}, repos...)
   137  	dockerCmd(c, args...)
   138  
   139  	// Re-pull individual tags, in parallel
   140  	results := make(chan error)
   141  
   142  	for _, repo := range repos {
   143  		go func(repo string) {
   144  			_, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repo))
   145  			results <- err
   146  		}(repo)
   147  	}
   148  
   149  	// These checks are separate from the loop above because the check
   150  	// package is not goroutine-safe.
   151  	for range repos {
   152  		err := <-results
   153  		c.Assert(err, checker.IsNil, check.Commentf("concurrent pull failed with error: %v", err))
   154  	}
   155  
   156  	// Ensure all tags were pulled successfully
   157  	for _, repo := range repos {
   158  		dockerCmd(c, "inspect", repo)
   159  		out, _ := dockerCmd(c, "run", "--rm", repo)
   160  		c.Assert(strings.TrimSpace(out), checker.Equals, "/bin/sh -c echo "+repo)
   161  	}
   162  }
   163  
   164  // TestPullIDStability verifies that pushing an image and pulling it back
   165  // preserves the image ID.
   166  func (s *DockerRegistrySuite) TestPullIDStability(c *check.C) {
   167  	derivedImage := privateRegistryURL + "/dockercli/id-stability"
   168  	baseImage := "busybox"
   169  
   170  	_, err := buildImage(derivedImage, fmt.Sprintf(`
   171  	    FROM %s
   172  	    ENV derived true
   173  	    ENV asdf true
   174  	    RUN dd if=/dev/zero of=/file bs=1024 count=1024
   175  	    CMD echo %s
   176  	`, baseImage, derivedImage), true)
   177  	if err != nil {
   178  		c.Fatal(err)
   179  	}
   180  
   181  	originalID, err := getIDByName(derivedImage)
   182  	if err != nil {
   183  		c.Fatalf("error inspecting: %v", err)
   184  	}
   185  	dockerCmd(c, "push", derivedImage)
   186  
   187  	// Pull
   188  	out, _ := dockerCmd(c, "pull", derivedImage)
   189  	if strings.Contains(out, "Pull complete") {
   190  		c.Fatalf("repull redownloaded a layer: %s", out)
   191  	}
   192  
   193  	derivedIDAfterPull, err := getIDByName(derivedImage)
   194  	if err != nil {
   195  		c.Fatalf("error inspecting: %v", err)
   196  	}
   197  
   198  	if derivedIDAfterPull != originalID {
   199  		c.Fatal("image's ID unexpectedly changed after a repush/repull")
   200  	}
   201  
   202  	// Make sure the image runs correctly
   203  	out, _ = dockerCmd(c, "run", "--rm", derivedImage)
   204  	if strings.TrimSpace(out) != derivedImage {
   205  		c.Fatalf("expected %s; got %s", derivedImage, out)
   206  	}
   207  
   208  	// Confirm that repushing and repulling does not change the computed ID
   209  	dockerCmd(c, "push", derivedImage)
   210  	dockerCmd(c, "rmi", derivedImage)
   211  	dockerCmd(c, "pull", derivedImage)
   212  
   213  	derivedIDAfterPull, err = getIDByName(derivedImage)
   214  	if err != nil {
   215  		c.Fatalf("error inspecting: %v", err)
   216  	}
   217  
   218  	if derivedIDAfterPull != originalID {
   219  		c.Fatal("image's ID unexpectedly changed after a repush/repull")
   220  	}
   221  	if err != nil {
   222  		c.Fatalf("error inspecting: %v", err)
   223  	}
   224  
   225  	// Make sure the image still runs
   226  	out, _ = dockerCmd(c, "run", "--rm", derivedImage)
   227  	if strings.TrimSpace(out) != derivedImage {
   228  		c.Fatalf("expected %s; got %s", derivedImage, out)
   229  	}
   230  }