docker_cli_pull_local_test.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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. }
  137. // TestPullIDStability verifies that pushing an image and pulling it back
  138. // preserves the image ID.
  139. func (s *DockerRegistrySuite) TestPullIDStability(c *check.C) {
  140. derivedImage := privateRegistryURL + "/dockercli/id-stability"
  141. baseImage := "busybox"
  142. _, err := buildImage(derivedImage, fmt.Sprintf(`
  143. FROM %s
  144. ENV derived true
  145. ENV asdf true
  146. RUN dd if=/dev/zero of=/file bs=1024 count=1024
  147. CMD echo %s
  148. `, baseImage, derivedImage), true)
  149. if err != nil {
  150. c.Fatal(err)
  151. }
  152. originalID, err := getIDByName(derivedImage)
  153. if err != nil {
  154. c.Fatalf("error inspecting: %v", err)
  155. }
  156. dockerCmd(c, "push", derivedImage)
  157. // Pull
  158. out, _ := dockerCmd(c, "pull", derivedImage)
  159. if strings.Contains(out, "Pull complete") {
  160. c.Fatalf("repull redownloaded a layer: %s", out)
  161. }
  162. derivedIDAfterPull, err := getIDByName(derivedImage)
  163. if err != nil {
  164. c.Fatalf("error inspecting: %v", err)
  165. }
  166. if derivedIDAfterPull != originalID {
  167. c.Fatal("image's ID unexpectedly changed after a repush/repull")
  168. }
  169. // Make sure the image runs correctly
  170. out, _ = dockerCmd(c, "run", "--rm", derivedImage)
  171. if strings.TrimSpace(out) != derivedImage {
  172. c.Fatalf("expected %s; got %s", derivedImage, out)
  173. }
  174. // Confirm that repushing and repulling does not change the computed ID
  175. dockerCmd(c, "push", derivedImage)
  176. dockerCmd(c, "rmi", derivedImage)
  177. dockerCmd(c, "pull", derivedImage)
  178. derivedIDAfterPull, err = getIDByName(derivedImage)
  179. if err != nil {
  180. c.Fatalf("error inspecting: %v", err)
  181. }
  182. if derivedIDAfterPull != originalID {
  183. c.Fatal("image's ID unexpectedly changed after a repush/repull")
  184. }
  185. if err != nil {
  186. c.Fatalf("error inspecting: %v", err)
  187. }
  188. // Make sure the image still runs
  189. out, _ = dockerCmd(c, "run", "--rm", derivedImage)
  190. if strings.TrimSpace(out) != derivedImage {
  191. c.Fatalf("expected %s; got %s", derivedImage, out)
  192. }
  193. }