docker_cli_pull_local_test.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. if _, _, err := dockerCmdWithError("inspect", repo); err == nil {
  31. c.Fatalf("Image %v shouldn't have been pulled down", repo)
  32. }
  33. }
  34. }
  35. // TestConcurrentPullWholeRepo pulls the same repo concurrently.
  36. func (s *DockerRegistrySuite) TestConcurrentPullWholeRepo(c *check.C) {
  37. repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
  38. repos := []string{}
  39. for _, tag := range []string{"recent", "fresh", "todays"} {
  40. repo := fmt.Sprintf("%v:%v", repoName, tag)
  41. _, err := buildImage(repo, fmt.Sprintf(`
  42. FROM busybox
  43. ENTRYPOINT ["/bin/echo"]
  44. ENV FOO foo
  45. ENV BAR bar
  46. CMD echo %s
  47. `, repo), true)
  48. if err != nil {
  49. c.Fatal(err)
  50. }
  51. dockerCmd(c, "push", repo)
  52. repos = append(repos, repo)
  53. }
  54. // Clear local images store.
  55. args := append([]string{"rmi"}, repos...)
  56. dockerCmd(c, args...)
  57. // Run multiple re-pulls concurrently
  58. results := make(chan error)
  59. numPulls := 3
  60. for i := 0; i != numPulls; i++ {
  61. go func() {
  62. _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", "-a", repoName))
  63. results <- err
  64. }()
  65. }
  66. // These checks are separate from the loop above because the check
  67. // package is not goroutine-safe.
  68. for i := 0; i != numPulls; i++ {
  69. err := <-results
  70. c.Assert(err, check.IsNil, check.Commentf("concurrent pull failed with error: %v", err))
  71. }
  72. // Ensure all tags were pulled successfully
  73. for _, repo := range repos {
  74. dockerCmd(c, "inspect", repo)
  75. out, _ := dockerCmd(c, "run", "--rm", repo)
  76. if strings.TrimSpace(out) != "/bin/sh -c echo "+repo {
  77. c.Fatalf("CMD did not contain /bin/sh -c echo %s: %s", repo, out)
  78. }
  79. }
  80. }
  81. // TestConcurrentFailingPull tries a concurrent pull that doesn't succeed.
  82. func (s *DockerRegistrySuite) TestConcurrentFailingPull(c *check.C) {
  83. repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
  84. // Run multiple pulls concurrently
  85. results := make(chan error)
  86. numPulls := 3
  87. for i := 0; i != numPulls; i++ {
  88. go func() {
  89. _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repoName+":asdfasdf"))
  90. results <- err
  91. }()
  92. }
  93. // These checks are separate from the loop above because the check
  94. // package is not goroutine-safe.
  95. for i := 0; i != numPulls; i++ {
  96. err := <-results
  97. if err == nil {
  98. c.Fatal("expected pull to fail")
  99. }
  100. }
  101. }
  102. // TestConcurrentPullMultipleTags pulls multiple tags from the same repo
  103. // concurrently.
  104. func (s *DockerRegistrySuite) TestConcurrentPullMultipleTags(c *check.C) {
  105. repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
  106. repos := []string{}
  107. for _, tag := range []string{"recent", "fresh", "todays"} {
  108. repo := fmt.Sprintf("%v:%v", repoName, tag)
  109. _, err := buildImage(repo, fmt.Sprintf(`
  110. FROM busybox
  111. ENTRYPOINT ["/bin/echo"]
  112. ENV FOO foo
  113. ENV BAR bar
  114. CMD echo %s
  115. `, repo), true)
  116. if err != nil {
  117. c.Fatal(err)
  118. }
  119. dockerCmd(c, "push", repo)
  120. repos = append(repos, repo)
  121. }
  122. // Clear local images store.
  123. args := append([]string{"rmi"}, repos...)
  124. dockerCmd(c, args...)
  125. // Re-pull individual tags, in parallel
  126. results := make(chan error)
  127. for _, repo := range repos {
  128. go func(repo string) {
  129. _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repo))
  130. results <- err
  131. }(repo)
  132. }
  133. // These checks are separate from the loop above because the check
  134. // package is not goroutine-safe.
  135. for range repos {
  136. err := <-results
  137. c.Assert(err, check.IsNil, check.Commentf("concurrent pull failed with error: %v", err))
  138. }
  139. // Ensure all tags were pulled successfully
  140. for _, repo := range repos {
  141. dockerCmd(c, "inspect", repo)
  142. out, _ := dockerCmd(c, "run", "--rm", repo)
  143. if strings.TrimSpace(out) != "/bin/sh -c echo "+repo {
  144. c.Fatalf("CMD did not contain /bin/sh -c echo %s: %s", repo, out)
  145. }
  146. }
  147. }