docker_cli_volume_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. package main
  2. import (
  3. "os/exec"
  4. "strings"
  5. "github.com/docker/docker/pkg/integration/checker"
  6. "github.com/go-check/check"
  7. )
  8. func (s *DockerSuite) TestVolumeCliCreate(c *check.C) {
  9. dockerCmd(c, "volume", "create")
  10. _, err := runCommand(exec.Command(dockerBinary, "volume", "create", "-d", "nosuchdriver"))
  11. c.Assert(err, check.Not(check.IsNil))
  12. out, _ := dockerCmd(c, "volume", "create", "--name=test")
  13. name := strings.TrimSpace(out)
  14. c.Assert(name, check.Equals, "test")
  15. }
  16. func (s *DockerSuite) TestVolumeCliCreateOptionConflict(c *check.C) {
  17. dockerCmd(c, "volume", "create", "--name=test")
  18. out, _, err := dockerCmdWithError("volume", "create", "--name", "test", "--driver", "nosuchdriver")
  19. c.Assert(err, check.NotNil, check.Commentf("volume create exception name already in use with another driver"))
  20. c.Assert(out, checker.Contains, "A volume named test already exists")
  21. out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Driver }}", "test")
  22. _, _, err = dockerCmdWithError("volume", "create", "--name", "test", "--driver", strings.TrimSpace(out))
  23. c.Assert(err, check.IsNil)
  24. }
  25. func (s *DockerSuite) TestVolumeCliInspect(c *check.C) {
  26. c.Assert(
  27. exec.Command(dockerBinary, "volume", "inspect", "doesntexist").Run(),
  28. check.Not(check.IsNil),
  29. check.Commentf("volume inspect should error on non-existent volume"),
  30. )
  31. out, _ := dockerCmd(c, "volume", "create")
  32. name := strings.TrimSpace(out)
  33. out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Name }}", name)
  34. c.Assert(strings.TrimSpace(out), check.Equals, name)
  35. dockerCmd(c, "volume", "create", "--name", "test")
  36. out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Name }}", "test")
  37. c.Assert(strings.TrimSpace(out), check.Equals, "test")
  38. }
  39. func (s *DockerSuite) TestVolumeCliInspectMulti(c *check.C) {
  40. dockerCmd(c, "volume", "create", "--name", "test1")
  41. dockerCmd(c, "volume", "create", "--name", "test2")
  42. dockerCmd(c, "volume", "create", "--name", "not-shown")
  43. out, _, err := dockerCmdWithError("volume", "inspect", "--format='{{ .Name }}'", "test1", "test2", "doesntexist", "not-shown")
  44. c.Assert(err, checker.NotNil)
  45. outArr := strings.Split(strings.TrimSpace(out), "\n")
  46. c.Assert(len(outArr), check.Equals, 3, check.Commentf("\n%s", out))
  47. c.Assert(out, checker.Contains, "test1")
  48. c.Assert(out, checker.Contains, "test2")
  49. c.Assert(out, checker.Contains, "Error: No such volume: doesntexist")
  50. c.Assert(out, checker.Not(checker.Contains), "not-shown")
  51. }
  52. func (s *DockerSuite) TestVolumeCliLs(c *check.C) {
  53. prefix, _ := getPrefixAndSlashFromDaemonPlatform()
  54. out, _ := dockerCmd(c, "volume", "create", "--name", "aaa")
  55. dockerCmd(c, "volume", "create", "--name", "test")
  56. dockerCmd(c, "volume", "create", "--name", "soo")
  57. dockerCmd(c, "run", "-v", "soo:"+prefix+"/foo", "busybox", "ls", "/")
  58. out, _ = dockerCmd(c, "volume", "ls")
  59. outArr := strings.Split(strings.TrimSpace(out), "\n")
  60. c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out))
  61. assertVolList(c, out, []string{"aaa", "soo", "test"})
  62. }
  63. // assertVolList checks volume retrieved with ls command
  64. // equals to expected volume list
  65. // note: out should be `volume ls [option]` result
  66. func assertVolList(c *check.C, out string, expectVols []string) {
  67. lines := strings.Split(out, "\n")
  68. var volList []string
  69. for _, line := range lines[1 : len(lines)-1] {
  70. volFields := strings.Fields(line)
  71. // wrap all volume name in volList
  72. volList = append(volList, volFields[1])
  73. }
  74. // volume ls should contains all expected volumes
  75. c.Assert(volList, checker.DeepEquals, expectVols)
  76. }
  77. func (s *DockerSuite) TestVolumeCliLsFilterDangling(c *check.C) {
  78. prefix, _ := getPrefixAndSlashFromDaemonPlatform()
  79. dockerCmd(c, "volume", "create", "--name", "testnotinuse1")
  80. dockerCmd(c, "volume", "create", "--name", "testisinuse1")
  81. dockerCmd(c, "volume", "create", "--name", "testisinuse2")
  82. // Make sure both "created" (but not started), and started
  83. // containers are included in reference counting
  84. dockerCmd(c, "run", "--name", "volume-test1", "-v", "testisinuse1:"+prefix+"/foo", "busybox", "true")
  85. dockerCmd(c, "create", "--name", "volume-test2", "-v", "testisinuse2:"+prefix+"/foo", "busybox", "true")
  86. out, _ := dockerCmd(c, "volume", "ls")
  87. // No filter, all volumes should show
  88. c.Assert(out, checker.Contains, "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output"))
  89. c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output"))
  90. c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output"))
  91. out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=false")
  92. // Explicitly disabling dangling
  93. c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output"))
  94. c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output"))
  95. c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output"))
  96. out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=true")
  97. // Filter "dangling" volumes; only "dangling" (unused) volumes should be in the output
  98. c.Assert(out, checker.Contains, "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output"))
  99. c.Assert(out, check.Not(checker.Contains), "testisinuse1\n", check.Commentf("volume 'testisinuse1' in output, but not expected"))
  100. c.Assert(out, check.Not(checker.Contains), "testisinuse2\n", check.Commentf("volume 'testisinuse2' in output, but not expected"))
  101. out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=1")
  102. // Filter "dangling" volumes; only "dangling" (unused) volumes should be in the output, dangling also accept 1
  103. c.Assert(out, checker.Contains, "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output"))
  104. c.Assert(out, check.Not(checker.Contains), "testisinuse1\n", check.Commentf("volume 'testisinuse1' in output, but not expected"))
  105. c.Assert(out, check.Not(checker.Contains), "testisinuse2\n", check.Commentf("volume 'testisinuse2' in output, but not expected"))
  106. out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=0")
  107. // dangling=0 is same as dangling=false case
  108. c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output"))
  109. c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output"))
  110. c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output"))
  111. out, _ = dockerCmd(c, "volume", "ls", "--filter", "name=testisin")
  112. c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output"))
  113. c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("execpeted volume 'testisinuse1' in output"))
  114. c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output"))
  115. out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=invalidDriver")
  116. outArr := strings.Split(strings.TrimSpace(out), "\n")
  117. c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
  118. out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=local")
  119. outArr = strings.Split(strings.TrimSpace(out), "\n")
  120. c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out))
  121. out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=loc")
  122. outArr = strings.Split(strings.TrimSpace(out), "\n")
  123. c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out))
  124. }
  125. func (s *DockerSuite) TestVolumeCliLsErrorWithInvalidFilterName(c *check.C) {
  126. out, _, err := dockerCmdWithError("volume", "ls", "-f", "FOO=123")
  127. c.Assert(err, checker.NotNil)
  128. c.Assert(out, checker.Contains, "Invalid filter")
  129. }
  130. func (s *DockerSuite) TestVolumeCliLsWithIncorrectFilterValue(c *check.C) {
  131. out, _, err := dockerCmdWithError("volume", "ls", "-f", "dangling=invalid")
  132. c.Assert(err, check.NotNil)
  133. c.Assert(out, checker.Contains, "Invalid filter")
  134. }
  135. func (s *DockerSuite) TestVolumeCliRm(c *check.C) {
  136. prefix, _ := getPrefixAndSlashFromDaemonPlatform()
  137. out, _ := dockerCmd(c, "volume", "create")
  138. id := strings.TrimSpace(out)
  139. dockerCmd(c, "volume", "create", "--name", "test")
  140. dockerCmd(c, "volume", "rm", id)
  141. dockerCmd(c, "volume", "rm", "test")
  142. out, _ = dockerCmd(c, "volume", "ls")
  143. outArr := strings.Split(strings.TrimSpace(out), "\n")
  144. c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
  145. volumeID := "testing"
  146. dockerCmd(c, "run", "-v", volumeID+":"+prefix+"/foo", "--name=test", "busybox", "sh", "-c", "echo hello > /foo/bar")
  147. out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "volume", "rm", "testing"))
  148. c.Assert(
  149. err,
  150. check.Not(check.IsNil),
  151. check.Commentf("Should not be able to remove volume that is in use by a container\n%s", out))
  152. out, _ = dockerCmd(c, "run", "--volumes-from=test", "--name=test2", "busybox", "sh", "-c", "cat /foo/bar")
  153. c.Assert(strings.TrimSpace(out), check.Equals, "hello")
  154. dockerCmd(c, "rm", "-fv", "test2")
  155. dockerCmd(c, "volume", "inspect", volumeID)
  156. dockerCmd(c, "rm", "-f", "test")
  157. out, _ = dockerCmd(c, "run", "--name=test2", "-v", volumeID+":"+prefix+"/foo", "busybox", "sh", "-c", "cat /foo/bar")
  158. c.Assert(strings.TrimSpace(out), check.Equals, "hello", check.Commentf("volume data was removed"))
  159. dockerCmd(c, "rm", "test2")
  160. dockerCmd(c, "volume", "rm", volumeID)
  161. c.Assert(
  162. exec.Command("volume", "rm", "doesntexist").Run(),
  163. check.Not(check.IsNil),
  164. check.Commentf("volume rm should fail with non-existent volume"),
  165. )
  166. }
  167. func (s *DockerSuite) TestVolumeCliNoArgs(c *check.C) {
  168. out, _ := dockerCmd(c, "volume")
  169. // no args should produce the cmd usage output
  170. usage := "Usage: docker volume COMMAND"
  171. c.Assert(out, checker.Contains, usage)
  172. // invalid arg should error and show the command usage on stderr
  173. _, stderr, _, err := runCommandWithStdoutStderr(exec.Command(dockerBinary, "volume", "somearg"))
  174. c.Assert(err, check.NotNil, check.Commentf(stderr))
  175. c.Assert(stderr, checker.Contains, usage)
  176. // invalid flag should error and show the flag error and cmd usage
  177. _, stderr, _, err = runCommandWithStdoutStderr(exec.Command(dockerBinary, "volume", "--no-such-flag"))
  178. c.Assert(err, check.NotNil, check.Commentf(stderr))
  179. c.Assert(stderr, checker.Contains, usage)
  180. c.Assert(stderr, checker.Contains, "unknown flag: --no-such-flag")
  181. }
  182. func (s *DockerSuite) TestVolumeCliInspectTmplError(c *check.C) {
  183. out, _ := dockerCmd(c, "volume", "create")
  184. name := strings.TrimSpace(out)
  185. out, exitCode, err := dockerCmdWithError("volume", "inspect", "--format='{{ .FooBar }}'", name)
  186. c.Assert(err, checker.NotNil, check.Commentf("Output: %s", out))
  187. c.Assert(exitCode, checker.Equals, 1, check.Commentf("Output: %s", out))
  188. c.Assert(out, checker.Contains, "Template parsing error")
  189. }
  190. func (s *DockerSuite) TestVolumeCliCreateWithOpts(c *check.C) {
  191. testRequires(c, DaemonIsLinux)
  192. dockerCmd(c, "volume", "create", "-d", "local", "--name", "test", "--opt=type=tmpfs", "--opt=device=tmpfs", "--opt=o=size=1m,uid=1000")
  193. out, _ := dockerCmd(c, "run", "-v", "test:/foo", "busybox", "mount")
  194. mounts := strings.Split(out, "\n")
  195. var found bool
  196. for _, m := range mounts {
  197. if strings.Contains(m, "/foo") {
  198. found = true
  199. info := strings.Fields(m)
  200. // tmpfs on <path> type tmpfs (rw,relatime,size=1024k,uid=1000)
  201. c.Assert(info[0], checker.Equals, "tmpfs")
  202. c.Assert(info[2], checker.Equals, "/foo")
  203. c.Assert(info[4], checker.Equals, "tmpfs")
  204. c.Assert(info[5], checker.Contains, "uid=1000")
  205. c.Assert(info[5], checker.Contains, "size=1024k")
  206. }
  207. }
  208. c.Assert(found, checker.Equals, true)
  209. }
  210. func (s *DockerSuite) TestVolumeCliCreateLabel(c *check.C) {
  211. testVol := "testvolcreatelabel"
  212. testLabel := "foo"
  213. testValue := "bar"
  214. out, _, err := dockerCmdWithError("volume", "create", "--label", testLabel+"="+testValue, "--name", testVol)
  215. c.Assert(err, check.IsNil)
  216. out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Labels."+testLabel+" }}", testVol)
  217. c.Assert(strings.TrimSpace(out), check.Equals, testValue)
  218. }
  219. func (s *DockerSuite) TestVolumeCliCreateLabelMultiple(c *check.C) {
  220. testVol := "testvolcreatelabel"
  221. testLabels := map[string]string{
  222. "foo": "bar",
  223. "baz": "foo",
  224. }
  225. args := []string{
  226. "volume",
  227. "create",
  228. "--name",
  229. testVol,
  230. }
  231. for k, v := range testLabels {
  232. args = append(args, "--label", k+"="+v)
  233. }
  234. out, _, err := dockerCmdWithError(args...)
  235. c.Assert(err, check.IsNil)
  236. for k, v := range testLabels {
  237. out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Labels."+k+" }}", testVol)
  238. c.Assert(strings.TrimSpace(out), check.Equals, v)
  239. }
  240. }