| package main |
| |
| import ( |
| "fmt" |
| "os/exec" |
| "strings" |
| |
| "github.com/go-check/check" |
| ) |
| |
| // TestPullImageWithAliases pulls a specific image tag and verifies that any aliases (i.e., other |
| // tags for the same image) are not also pulled down. |
| // |
| // Ref: docker/docker#8141 |
| func (s *DockerRegistrySuite) TestPullImageWithAliases(c *check.C) { |
| repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) |
| |
| repos := []string{} |
| for _, tag := range []string{"recent", "fresh"} { |
| repos = append(repos, fmt.Sprintf("%v:%v", repoName, tag)) |
| } |
| |
| // Tag and push the same image multiple times. |
| for _, repo := range repos { |
| dockerCmd(c, "tag", "busybox", repo) |
| dockerCmd(c, "push", repo) |
| } |
| |
| // Clear local images store. |
| args := append([]string{"rmi"}, repos...) |
| dockerCmd(c, args...) |
| |
| // Pull a single tag and verify it doesn't bring down all aliases. |
| dockerCmd(c, "pull", repos[0]) |
| dockerCmd(c, "inspect", repos[0]) |
| for _, repo := range repos[1:] { |
| _, _, err := dockerCmdWithError("inspect", repo) |
| c.Assert(err, check.NotNil, check.Commentf("Image %v shouldn't have been pulled down", repo)) |
| } |
| } |
| |
| // TestConcurrentPullWholeRepo pulls the same repo concurrently. |
| func (s *DockerRegistrySuite) TestConcurrentPullWholeRepo(c *check.C) { |
| repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) |
| |
| repos := []string{} |
| for _, tag := range []string{"recent", "fresh", "todays"} { |
| repo := fmt.Sprintf("%v:%v", repoName, tag) |
| _, err := buildImage(repo, fmt.Sprintf(` |
| FROM busybox |
| ENTRYPOINT ["/bin/echo"] |
| ENV FOO foo |
| ENV BAR bar |
| CMD echo %s |
| `, repo), true) |
| c.Assert(err, check.IsNil) |
| dockerCmd(c, "push", repo) |
| repos = append(repos, repo) |
| } |
| |
| // Clear local images store. |
| args := append([]string{"rmi"}, repos...) |
| dockerCmd(c, args...) |
| |
| // Run multiple re-pulls concurrently |
| results := make(chan error) |
| numPulls := 3 |
| |
| for i := 0; i != numPulls; i++ { |
| go func() { |
| _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", "-a", repoName)) |
| results <- err |
| }() |
| } |
| |
| // These checks are separate from the loop above because the check |
| // package is not goroutine-safe. |
| for i := 0; i != numPulls; i++ { |
| err := <-results |
| c.Assert(err, check.IsNil, check.Commentf("concurrent pull failed with error: %v", err)) |
| } |
| |
| // Ensure all tags were pulled successfully |
| for _, repo := range repos { |
| dockerCmd(c, "inspect", repo) |
| out, _ := dockerCmd(c, "run", "--rm", repo) |
| c.Assert(strings.TrimSpace(out), check.Equals, "/bin/sh -c echo "+repo, check.Commentf("CMD did not contain /bin/sh -c echo %s: %s", repo, out)) |
| } |
| } |
| |
| // TestConcurrentFailingPull tries a concurrent pull that doesn't succeed. |
| func (s *DockerRegistrySuite) TestConcurrentFailingPull(c *check.C) { |
| repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) |
| |
| // Run multiple pulls concurrently |
| results := make(chan error) |
| numPulls := 3 |
| |
| for i := 0; i != numPulls; i++ { |
| go func() { |
| _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repoName+":asdfasdf")) |
| results <- err |
| }() |
| } |
| |
| // These checks are separate from the loop above because the check |
| // package is not goroutine-safe. |
| for i := 0; i != numPulls; i++ { |
| err := <-results |
| c.Assert(err, check.NotNil, check.Commentf("expected pull to fail")) |
| } |
| } |
| |
| // TestConcurrentPullMultipleTags pulls multiple tags from the same repo |
| // concurrently. |
| func (s *DockerRegistrySuite) TestConcurrentPullMultipleTags(c *check.C) { |
| repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) |
| |
| repos := []string{} |
| for _, tag := range []string{"recent", "fresh", "todays"} { |
| repo := fmt.Sprintf("%v:%v", repoName, tag) |
| _, err := buildImage(repo, fmt.Sprintf(` |
| FROM busybox |
| ENTRYPOINT ["/bin/echo"] |
| ENV FOO foo |
| ENV BAR bar |
| CMD echo %s |
| `, repo), true) |
| c.Assert(err, check.IsNil) |
| dockerCmd(c, "push", repo) |
| repos = append(repos, repo) |
| } |
| |
| // Clear local images store. |
| args := append([]string{"rmi"}, repos...) |
| dockerCmd(c, args...) |
| |
| // Re-pull individual tags, in parallel |
| results := make(chan error) |
| |
| for _, repo := range repos { |
| go func(repo string) { |
| _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repo)) |
| results <- err |
| }(repo) |
| } |
| |
| // These checks are separate from the loop above because the check |
| // package is not goroutine-safe. |
| for range repos { |
| err := <-results |
| c.Assert(err, check.IsNil, check.Commentf("concurrent pull failed with error: %v", err)) |
| } |
| |
| // Ensure all tags were pulled successfully |
| for _, repo := range repos { |
| dockerCmd(c, "inspect", repo) |
| out, _ := dockerCmd(c, "run", "--rm", repo) |
| c.Assert(strings.TrimSpace(out), check.Equals, "/bin/sh -c echo "+repo, check.Commentf("CMD did not contain /bin/sh -c echo %s; %s", repo, out)) |
| } |
| } |