docker_cli_pull_local_test.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package main
  2. import (
  3. "fmt"
  4. "os/exec"
  5. "strings"
  6. "github.com/go-check/check"
  7. )
  8. // TestPullImageWithAliases pulls a specific image tag and verifies that any aliases (i.e., other
  9. // tags for the same image) are not also pulled down.
  10. //
  11. // Ref: docker/docker#8141
  12. func (s *DockerRegistrySuite) TestPullImageWithAliases(c *check.C) {
  13. repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
  14. repos := []string{}
  15. for _, tag := range []string{"recent", "fresh"} {
  16. repos = append(repos, fmt.Sprintf("%v:%v", repoName, tag))
  17. }
  18. // Tag and push the same image multiple times.
  19. for _, repo := range repos {
  20. dockerCmd(c, "tag", "busybox", repo)
  21. dockerCmd(c, "push", repo)
  22. }
  23. // Clear local images store.
  24. args := append([]string{"rmi"}, repos...)
  25. dockerCmd(c, args...)
  26. // Pull a single tag and verify it doesn't bring down all aliases.
  27. dockerCmd(c, "pull", repos[0])
  28. dockerCmd(c, "inspect", repos[0])
  29. for _, repo := range repos[1:] {
  30. _, _, err := dockerCmdWithError("inspect", repo)
  31. c.Assert(err, check.NotNil, check.Commentf("Image %v shouldn't have been pulled down", repo))
  32. }
  33. }
  34. // TestConcurrentPullWholeRepo pulls the same repo concurrently.
  35. func (s *DockerRegistrySuite) TestConcurrentPullWholeRepo(c *check.C) {
  36. repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
  37. repos := []string{}
  38. for _, tag := range []string{"recent", "fresh", "todays"} {
  39. repo := fmt.Sprintf("%v:%v", repoName, tag)
  40. _, err := buildImage(repo, fmt.Sprintf(`
  41. FROM busybox
  42. ENTRYPOINT ["/bin/echo"]
  43. ENV FOO foo
  44. ENV BAR bar
  45. CMD echo %s
  46. `, repo), true)
  47. c.Assert(err, check.IsNil)
  48. dockerCmd(c, "push", repo)
  49. repos = append(repos, repo)
  50. }
  51. // Clear local images store.
  52. args := append([]string{"rmi"}, repos...)
  53. dockerCmd(c, args...)
  54. // Run multiple re-pulls concurrently
  55. results := make(chan error)
  56. numPulls := 3
  57. for i := 0; i != numPulls; i++ {
  58. go func() {
  59. _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", "-a", repoName))
  60. results <- err
  61. }()
  62. }
  63. // These checks are separate from the loop above because the check
  64. // package is not goroutine-safe.
  65. for i := 0; i != numPulls; i++ {
  66. err := <-results
  67. c.Assert(err, check.IsNil, check.Commentf("concurrent pull failed with error: %v", err))
  68. }
  69. // Ensure all tags were pulled successfully
  70. for _, repo := range repos {
  71. dockerCmd(c, "inspect", repo)
  72. out, _ := dockerCmd(c, "run", "--rm", repo)
  73. 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))
  74. }
  75. }
  76. // TestConcurrentFailingPull tries a concurrent pull that doesn't succeed.
  77. func (s *DockerRegistrySuite) TestConcurrentFailingPull(c *check.C) {
  78. repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
  79. // Run multiple pulls concurrently
  80. results := make(chan error)
  81. numPulls := 3
  82. for i := 0; i != numPulls; i++ {
  83. go func() {
  84. _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repoName+":asdfasdf"))
  85. results <- err
  86. }()
  87. }
  88. // These checks are separate from the loop above because the check
  89. // package is not goroutine-safe.
  90. for i := 0; i != numPulls; i++ {
  91. err := <-results
  92. c.Assert(err, check.NotNil, check.Commentf("expected pull to fail"))
  93. }
  94. }
  95. // TestConcurrentPullMultipleTags pulls multiple tags from the same repo
  96. // concurrently.
  97. func (s *DockerRegistrySuite) TestConcurrentPullMultipleTags(c *check.C) {
  98. repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
  99. repos := []string{}
  100. for _, tag := range []string{"recent", "fresh", "todays"} {
  101. repo := fmt.Sprintf("%v:%v", repoName, tag)
  102. _, err := buildImage(repo, fmt.Sprintf(`
  103. FROM busybox
  104. ENTRYPOINT ["/bin/echo"]
  105. ENV FOO foo
  106. ENV BAR bar
  107. CMD echo %s
  108. `, repo), true)
  109. c.Assert(err, check.IsNil)
  110. dockerCmd(c, "push", repo)
  111. repos = append(repos, repo)
  112. }
  113. // Clear local images store.
  114. args := append([]string{"rmi"}, repos...)
  115. dockerCmd(c, args...)
  116. // Re-pull individual tags, in parallel
  117. results := make(chan error)
  118. for _, repo := range repos {
  119. go func(repo string) {
  120. _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repo))
  121. results <- err
  122. }(repo)
  123. }
  124. // These checks are separate from the loop above because the check
  125. // package is not goroutine-safe.
  126. for range repos {
  127. err := <-results
  128. c.Assert(err, check.IsNil, check.Commentf("concurrent pull failed with error: %v", err))
  129. }
  130. // Ensure all tags were pulled successfully
  131. for _, repo := range repos {
  132. dockerCmd(c, "inspect", repo)
  133. out, _ := dockerCmd(c, "run", "--rm", repo)
  134. 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))
  135. }
  136. }