docker_cli_start_volume_driver_unix_test.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // +build !windows
  2. package main
  3. import (
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "net/http/httptest"
  9. "os"
  10. "path/filepath"
  11. "strings"
  12. "github.com/go-check/check"
  13. )
  14. func init() {
  15. check.Suite(&DockerExternalVolumeSuite{
  16. ds: &DockerSuite{},
  17. })
  18. }
  19. type eventCounter struct {
  20. activations int
  21. creations int
  22. removals int
  23. mounts int
  24. unmounts int
  25. paths int
  26. }
  27. type DockerExternalVolumeSuite struct {
  28. server *httptest.Server
  29. ds *DockerSuite
  30. d *Daemon
  31. ec *eventCounter
  32. }
  33. func (s *DockerExternalVolumeSuite) SetUpTest(c *check.C) {
  34. s.d = NewDaemon(c)
  35. s.ec = &eventCounter{}
  36. }
  37. func (s *DockerExternalVolumeSuite) TearDownTest(c *check.C) {
  38. s.d.Stop()
  39. s.ds.TearDownTest(c)
  40. }
  41. func (s *DockerExternalVolumeSuite) SetUpSuite(c *check.C) {
  42. mux := http.NewServeMux()
  43. s.server = httptest.NewServer(mux)
  44. type pluginRequest struct {
  45. name string
  46. }
  47. mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
  48. s.ec.activations++
  49. w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
  50. fmt.Fprintln(w, `{"Implements": ["VolumeDriver"]}`)
  51. })
  52. mux.HandleFunc("/VolumeDriver.Create", func(w http.ResponseWriter, r *http.Request) {
  53. s.ec.creations++
  54. w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
  55. fmt.Fprintln(w, `{}`)
  56. })
  57. mux.HandleFunc("/VolumeDriver.Remove", func(w http.ResponseWriter, r *http.Request) {
  58. s.ec.removals++
  59. w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
  60. fmt.Fprintln(w, `{}`)
  61. })
  62. mux.HandleFunc("/VolumeDriver.Path", func(w http.ResponseWriter, r *http.Request) {
  63. s.ec.paths++
  64. var pr pluginRequest
  65. if err := json.NewDecoder(r.Body).Decode(&pr); err != nil {
  66. http.Error(w, err.Error(), 500)
  67. }
  68. p := hostVolumePath(pr.name)
  69. w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
  70. fmt.Fprintln(w, fmt.Sprintf("{\"Mountpoint\": \"%s\"}", p))
  71. })
  72. mux.HandleFunc("/VolumeDriver.Mount", func(w http.ResponseWriter, r *http.Request) {
  73. s.ec.mounts++
  74. var pr pluginRequest
  75. if err := json.NewDecoder(r.Body).Decode(&pr); err != nil {
  76. http.Error(w, err.Error(), 500)
  77. }
  78. p := hostVolumePath(pr.name)
  79. if err := os.MkdirAll(p, 0755); err != nil {
  80. http.Error(w, err.Error(), 500)
  81. }
  82. if err := ioutil.WriteFile(filepath.Join(p, "test"), []byte(s.server.URL), 0644); err != nil {
  83. http.Error(w, err.Error(), 500)
  84. }
  85. w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
  86. fmt.Fprintln(w, fmt.Sprintf("{\"Mountpoint\": \"%s\"}", p))
  87. })
  88. mux.HandleFunc("/VolumeDriver.Unmount", func(w http.ResponseWriter, r *http.Request) {
  89. s.ec.unmounts++
  90. var pr pluginRequest
  91. if err := json.NewDecoder(r.Body).Decode(&pr); err != nil {
  92. http.Error(w, err.Error(), 500)
  93. }
  94. w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
  95. fmt.Fprintln(w, `{}`)
  96. })
  97. if err := os.MkdirAll("/etc/docker/plugins", 0755); err != nil {
  98. c.Fatal(err)
  99. }
  100. if err := ioutil.WriteFile("/etc/docker/plugins/test-external-volume-driver.spec", []byte(s.server.URL), 0644); err != nil {
  101. c.Fatal(err)
  102. }
  103. }
  104. func (s *DockerExternalVolumeSuite) TearDownSuite(c *check.C) {
  105. s.server.Close()
  106. if err := os.RemoveAll("/etc/docker/plugins"); err != nil {
  107. c.Fatal(err)
  108. }
  109. }
  110. func (s *DockerExternalVolumeSuite) TestStartExternalNamedVolumeDriver(c *check.C) {
  111. if err := s.d.StartWithBusybox(); err != nil {
  112. c.Fatal(err)
  113. }
  114. out, err := s.d.Cmd("run", "--rm", "--name", "test-data", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", "busybox:latest", "cat", "/tmp/external-volume-test/test")
  115. if err != nil {
  116. c.Fatal(out, err)
  117. }
  118. if !strings.Contains(out, s.server.URL) {
  119. c.Fatalf("External volume mount failed. Output: %s\n", out)
  120. }
  121. p := hostVolumePath("external-volume-test")
  122. _, err = os.Lstat(p)
  123. if err == nil {
  124. c.Fatalf("Expected error checking volume path in host: %s\n", p)
  125. }
  126. if !os.IsNotExist(err) {
  127. c.Fatalf("Expected volume path in host to not exist: %s, %v\n", p, err)
  128. }
  129. c.Assert(s.ec.activations, check.Equals, 1)
  130. c.Assert(s.ec.creations, check.Equals, 1)
  131. c.Assert(s.ec.removals, check.Equals, 1)
  132. c.Assert(s.ec.mounts, check.Equals, 1)
  133. c.Assert(s.ec.unmounts, check.Equals, 1)
  134. }
  135. func (s *DockerExternalVolumeSuite) TestStartExternalVolumeUnnamedDriver(c *check.C) {
  136. if err := s.d.StartWithBusybox(); err != nil {
  137. c.Fatal(err)
  138. }
  139. out, err := s.d.Cmd("run", "--rm", "--name", "test-data", "-v", "/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", "busybox:latest", "cat", "/tmp/external-volume-test/test")
  140. if err != nil {
  141. c.Fatal(err)
  142. }
  143. if !strings.Contains(out, s.server.URL) {
  144. c.Fatalf("External volume mount failed. Output: %s\n", out)
  145. }
  146. c.Assert(s.ec.activations, check.Equals, 1)
  147. c.Assert(s.ec.creations, check.Equals, 1)
  148. c.Assert(s.ec.removals, check.Equals, 1)
  149. c.Assert(s.ec.mounts, check.Equals, 1)
  150. c.Assert(s.ec.unmounts, check.Equals, 1)
  151. }
  152. func (s DockerExternalVolumeSuite) TestStartExternalVolumeDriverVolumesFrom(c *check.C) {
  153. if err := s.d.StartWithBusybox(); err != nil {
  154. c.Fatal(err)
  155. }
  156. out, err := s.d.Cmd("run", "-d", "--name", "vol-test1", "-v", "/foo", "--volume-driver", "test-external-volume-driver", "busybox:latest")
  157. c.Assert(err, check.IsNil, check.Commentf(out))
  158. out, err = s.d.Cmd("run", "--rm", "--volumes-from", "vol-test1", "--name", "vol-test2", "busybox", "ls", "/tmp")
  159. c.Assert(err, check.IsNil, check.Commentf(out))
  160. out, err = s.d.Cmd("rm", "-fv", "vol-test1")
  161. c.Assert(err, check.IsNil, check.Commentf(out))
  162. c.Assert(s.ec.activations, check.Equals, 1)
  163. c.Assert(s.ec.creations, check.Equals, 1)
  164. c.Assert(s.ec.removals, check.Equals, 1)
  165. c.Assert(s.ec.mounts, check.Equals, 2)
  166. c.Assert(s.ec.unmounts, check.Equals, 2)
  167. }
  168. func (s DockerExternalVolumeSuite) TestStartExternalVolumeDriverDeleteContainer(c *check.C) {
  169. if err := s.d.StartWithBusybox(); err != nil {
  170. c.Fatal(err)
  171. }
  172. if out, err := s.d.Cmd("run", "-d", "--name", "vol-test1", "-v", "/foo", "--volume-driver", "test-external-volume-driver", "busybox:latest"); err != nil {
  173. c.Fatal(out, err)
  174. }
  175. if out, err := s.d.Cmd("rm", "-fv", "vol-test1"); err != nil {
  176. c.Fatal(out, err)
  177. }
  178. c.Assert(s.ec.activations, check.Equals, 1)
  179. c.Assert(s.ec.creations, check.Equals, 1)
  180. c.Assert(s.ec.removals, check.Equals, 1)
  181. c.Assert(s.ec.mounts, check.Equals, 1)
  182. c.Assert(s.ec.unmounts, check.Equals, 1)
  183. }
  184. func hostVolumePath(name string) string {
  185. return fmt.Sprintf("/var/lib/docker/volumes/%s", name)
  186. }
  187. func (s *DockerExternalVolumeSuite) TestStartExternalNamedVolumeDriverCheckBindLocalVolume(c *check.C) {
  188. if err := s.d.StartWithBusybox(); err != nil {
  189. c.Fatal(err)
  190. }
  191. expected := s.server.URL
  192. dockerfile := fmt.Sprintf(`FROM busybox:latest
  193. RUN mkdir /nobindthenlocalvol
  194. RUN echo %s > /nobindthenlocalvol/test
  195. VOLUME ["/nobindthenlocalvol"]`, expected)
  196. img := "test-checkbindlocalvolume"
  197. args := []string{"--host", s.d.sock()}
  198. buildOut, err := buildImageArgs(args, img, dockerfile, true)
  199. fmt.Println(buildOut)
  200. out, err := s.d.Cmd("run", "--rm", "--name", "test-data-nobind", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", img, "cat", "/nobindthenlocalvol/test")
  201. if err != nil {
  202. fmt.Println(out)
  203. c.Fatal(err)
  204. }
  205. if !strings.Contains(out, expected) {
  206. c.Fatalf("External volume mount failed. Output: %s\n", out)
  207. }
  208. c.Assert(s.ec.activations, check.Equals, 1)
  209. c.Assert(s.ec.creations, check.Equals, 1)
  210. c.Assert(s.ec.removals, check.Equals, 1)
  211. c.Assert(s.ec.mounts, check.Equals, 1)
  212. c.Assert(s.ec.unmounts, check.Equals, 1)
  213. }