github.com/SamWhited/moby@v1.13.1/integration-cli/docker_cli_volume_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "strings" 10 11 "github.com/docker/docker/pkg/integration/checker" 12 icmd "github.com/docker/docker/pkg/integration/cmd" 13 "github.com/go-check/check" 14 ) 15 16 func (s *DockerSuite) TestVolumeCLICreate(c *check.C) { 17 dockerCmd(c, "volume", "create") 18 19 _, err := runCommand(exec.Command(dockerBinary, "volume", "create", "-d", "nosuchdriver")) 20 c.Assert(err, check.Not(check.IsNil)) 21 22 // test using hidden --name option 23 out, _ := dockerCmd(c, "volume", "create", "--name=test") 24 name := strings.TrimSpace(out) 25 c.Assert(name, check.Equals, "test") 26 27 out, _ = dockerCmd(c, "volume", "create", "test2") 28 name = strings.TrimSpace(out) 29 c.Assert(name, check.Equals, "test2") 30 } 31 32 func (s *DockerSuite) TestVolumeCLIInspect(c *check.C) { 33 c.Assert( 34 exec.Command(dockerBinary, "volume", "inspect", "doesntexist").Run(), 35 check.Not(check.IsNil), 36 check.Commentf("volume inspect should error on non-existent volume"), 37 ) 38 39 out, _ := dockerCmd(c, "volume", "create") 40 name := strings.TrimSpace(out) 41 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Name }}", name) 42 c.Assert(strings.TrimSpace(out), check.Equals, name) 43 44 dockerCmd(c, "volume", "create", "test") 45 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Name }}", "test") 46 c.Assert(strings.TrimSpace(out), check.Equals, "test") 47 } 48 49 func (s *DockerSuite) TestVolumeCLIInspectMulti(c *check.C) { 50 dockerCmd(c, "volume", "create", "test1") 51 dockerCmd(c, "volume", "create", "test2") 52 dockerCmd(c, "volume", "create", "not-shown") 53 54 result := dockerCmdWithResult("volume", "inspect", "--format={{ .Name }}", "test1", "test2", "doesntexist", "not-shown") 55 c.Assert(result, icmd.Matches, icmd.Expected{ 56 ExitCode: 1, 57 Err: "No such volume: doesntexist", 58 }) 59 60 out := result.Stdout() 61 outArr := strings.Split(strings.TrimSpace(out), "\n") 62 c.Assert(len(outArr), check.Equals, 2, check.Commentf("\n%s", out)) 63 64 c.Assert(out, checker.Contains, "test1") 65 c.Assert(out, checker.Contains, "test2") 66 c.Assert(out, checker.Not(checker.Contains), "not-shown") 67 } 68 69 func (s *DockerSuite) TestVolumeCLILs(c *check.C) { 70 prefix, _ := getPrefixAndSlashFromDaemonPlatform() 71 dockerCmd(c, "volume", "create", "aaa") 72 73 dockerCmd(c, "volume", "create", "test") 74 75 dockerCmd(c, "volume", "create", "soo") 76 dockerCmd(c, "run", "-v", "soo:"+prefix+"/foo", "busybox", "ls", "/") 77 78 out, _ := dockerCmd(c, "volume", "ls") 79 outArr := strings.Split(strings.TrimSpace(out), "\n") 80 c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out)) 81 82 assertVolList(c, out, []string{"aaa", "soo", "test"}) 83 } 84 85 func (s *DockerSuite) TestVolumeLsFormat(c *check.C) { 86 dockerCmd(c, "volume", "create", "aaa") 87 dockerCmd(c, "volume", "create", "test") 88 dockerCmd(c, "volume", "create", "soo") 89 90 out, _ := dockerCmd(c, "volume", "ls", "--format", "{{.Name}}") 91 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 92 93 expected := []string{"aaa", "soo", "test"} 94 var names []string 95 names = append(names, lines...) 96 c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names)) 97 } 98 99 func (s *DockerSuite) TestVolumeLsFormatDefaultFormat(c *check.C) { 100 dockerCmd(c, "volume", "create", "aaa") 101 dockerCmd(c, "volume", "create", "test") 102 dockerCmd(c, "volume", "create", "soo") 103 104 config := `{ 105 "volumesFormat": "{{ .Name }} default" 106 }` 107 d, err := ioutil.TempDir("", "integration-cli-") 108 c.Assert(err, checker.IsNil) 109 defer os.RemoveAll(d) 110 111 err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644) 112 c.Assert(err, checker.IsNil) 113 114 out, _ := dockerCmd(c, "--config", d, "volume", "ls") 115 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 116 117 expected := []string{"aaa default", "soo default", "test default"} 118 var names []string 119 names = append(names, lines...) 120 c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names)) 121 } 122 123 // assertVolList checks volume retrieved with ls command 124 // equals to expected volume list 125 // note: out should be `volume ls [option]` result 126 func assertVolList(c *check.C, out string, expectVols []string) { 127 lines := strings.Split(out, "\n") 128 var volList []string 129 for _, line := range lines[1 : len(lines)-1] { 130 volFields := strings.Fields(line) 131 // wrap all volume name in volList 132 volList = append(volList, volFields[1]) 133 } 134 135 // volume ls should contains all expected volumes 136 c.Assert(volList, checker.DeepEquals, expectVols) 137 } 138 139 func (s *DockerSuite) TestVolumeCLILsFilterDangling(c *check.C) { 140 prefix, _ := getPrefixAndSlashFromDaemonPlatform() 141 dockerCmd(c, "volume", "create", "testnotinuse1") 142 dockerCmd(c, "volume", "create", "testisinuse1") 143 dockerCmd(c, "volume", "create", "testisinuse2") 144 145 // Make sure both "created" (but not started), and started 146 // containers are included in reference counting 147 dockerCmd(c, "run", "--name", "volume-test1", "-v", "testisinuse1:"+prefix+"/foo", "busybox", "true") 148 dockerCmd(c, "create", "--name", "volume-test2", "-v", "testisinuse2:"+prefix+"/foo", "busybox", "true") 149 150 out, _ := dockerCmd(c, "volume", "ls") 151 152 // No filter, all volumes should show 153 c.Assert(out, checker.Contains, "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 154 c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output")) 155 c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output")) 156 157 out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=false") 158 159 // Explicitly disabling dangling 160 c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 161 c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output")) 162 c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output")) 163 164 out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=true") 165 166 // Filter "dangling" volumes; only "dangling" (unused) volumes should be in the output 167 c.Assert(out, checker.Contains, "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 168 c.Assert(out, check.Not(checker.Contains), "testisinuse1\n", check.Commentf("volume 'testisinuse1' in output, but not expected")) 169 c.Assert(out, check.Not(checker.Contains), "testisinuse2\n", check.Commentf("volume 'testisinuse2' in output, but not expected")) 170 171 out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=1") 172 // Filter "dangling" volumes; only "dangling" (unused) volumes should be in the output, dangling also accept 1 173 c.Assert(out, checker.Contains, "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 174 c.Assert(out, check.Not(checker.Contains), "testisinuse1\n", check.Commentf("volume 'testisinuse1' in output, but not expected")) 175 c.Assert(out, check.Not(checker.Contains), "testisinuse2\n", check.Commentf("volume 'testisinuse2' in output, but not expected")) 176 177 out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=0") 178 // dangling=0 is same as dangling=false case 179 c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 180 c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output")) 181 c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output")) 182 183 out, _ = dockerCmd(c, "volume", "ls", "--filter", "name=testisin") 184 c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 185 c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("execpeted volume 'testisinuse1' in output")) 186 c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output")) 187 188 out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=invalidDriver") 189 outArr := strings.Split(strings.TrimSpace(out), "\n") 190 c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out)) 191 192 out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=local") 193 outArr = strings.Split(strings.TrimSpace(out), "\n") 194 c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out)) 195 196 out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=loc") 197 outArr = strings.Split(strings.TrimSpace(out), "\n") 198 c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out)) 199 200 } 201 202 func (s *DockerSuite) TestVolumeCLILsErrorWithInvalidFilterName(c *check.C) { 203 out, _, err := dockerCmdWithError("volume", "ls", "-f", "FOO=123") 204 c.Assert(err, checker.NotNil) 205 c.Assert(out, checker.Contains, "Invalid filter") 206 } 207 208 func (s *DockerSuite) TestVolumeCLILsWithIncorrectFilterValue(c *check.C) { 209 out, _, err := dockerCmdWithError("volume", "ls", "-f", "dangling=invalid") 210 c.Assert(err, check.NotNil) 211 c.Assert(out, checker.Contains, "Invalid filter") 212 } 213 214 func (s *DockerSuite) TestVolumeCLIRm(c *check.C) { 215 prefix, _ := getPrefixAndSlashFromDaemonPlatform() 216 out, _ := dockerCmd(c, "volume", "create") 217 id := strings.TrimSpace(out) 218 219 dockerCmd(c, "volume", "create", "test") 220 dockerCmd(c, "volume", "rm", id) 221 dockerCmd(c, "volume", "rm", "test") 222 223 out, _ = dockerCmd(c, "volume", "ls") 224 outArr := strings.Split(strings.TrimSpace(out), "\n") 225 c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out)) 226 227 volumeID := "testing" 228 dockerCmd(c, "run", "-v", volumeID+":"+prefix+"/foo", "--name=test", "busybox", "sh", "-c", "echo hello > /foo/bar") 229 out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "volume", "rm", "testing")) 230 c.Assert( 231 err, 232 check.Not(check.IsNil), 233 check.Commentf("Should not be able to remove volume that is in use by a container\n%s", out)) 234 235 out, _ = dockerCmd(c, "run", "--volumes-from=test", "--name=test2", "busybox", "sh", "-c", "cat /foo/bar") 236 c.Assert(strings.TrimSpace(out), check.Equals, "hello") 237 dockerCmd(c, "rm", "-fv", "test2") 238 dockerCmd(c, "volume", "inspect", volumeID) 239 dockerCmd(c, "rm", "-f", "test") 240 241 out, _ = dockerCmd(c, "run", "--name=test2", "-v", volumeID+":"+prefix+"/foo", "busybox", "sh", "-c", "cat /foo/bar") 242 c.Assert(strings.TrimSpace(out), check.Equals, "hello", check.Commentf("volume data was removed")) 243 dockerCmd(c, "rm", "test2") 244 245 dockerCmd(c, "volume", "rm", volumeID) 246 c.Assert( 247 exec.Command("volume", "rm", "doesntexist").Run(), 248 check.Not(check.IsNil), 249 check.Commentf("volume rm should fail with non-existent volume"), 250 ) 251 } 252 253 func (s *DockerSuite) TestVolumeCLINoArgs(c *check.C) { 254 out, _ := dockerCmd(c, "volume") 255 // no args should produce the cmd usage output 256 usage := "Usage: docker volume COMMAND" 257 c.Assert(out, checker.Contains, usage) 258 259 // invalid arg should error and show the command usage on stderr 260 _, stderr, _, err := runCommandWithStdoutStderr(exec.Command(dockerBinary, "volume", "somearg")) 261 c.Assert(err, check.NotNil, check.Commentf(stderr)) 262 c.Assert(stderr, checker.Contains, usage) 263 264 // invalid flag should error and show the flag error and cmd usage 265 _, stderr, _, err = runCommandWithStdoutStderr(exec.Command(dockerBinary, "volume", "--no-such-flag")) 266 c.Assert(err, check.NotNil, check.Commentf(stderr)) 267 c.Assert(stderr, checker.Contains, usage) 268 c.Assert(stderr, checker.Contains, "unknown flag: --no-such-flag") 269 } 270 271 func (s *DockerSuite) TestVolumeCLIInspectTmplError(c *check.C) { 272 out, _ := dockerCmd(c, "volume", "create") 273 name := strings.TrimSpace(out) 274 275 out, exitCode, err := dockerCmdWithError("volume", "inspect", "--format='{{ .FooBar }}'", name) 276 c.Assert(err, checker.NotNil, check.Commentf("Output: %s", out)) 277 c.Assert(exitCode, checker.Equals, 1, check.Commentf("Output: %s", out)) 278 c.Assert(out, checker.Contains, "Template parsing error") 279 } 280 281 func (s *DockerSuite) TestVolumeCLICreateWithOpts(c *check.C) { 282 testRequires(c, DaemonIsLinux) 283 284 dockerCmd(c, "volume", "create", "-d", "local", "test", "--opt=type=tmpfs", "--opt=device=tmpfs", "--opt=o=size=1m,uid=1000") 285 out, _ := dockerCmd(c, "run", "-v", "test:/foo", "busybox", "mount") 286 287 mounts := strings.Split(out, "\n") 288 var found bool 289 for _, m := range mounts { 290 if strings.Contains(m, "/foo") { 291 found = true 292 info := strings.Fields(m) 293 // tmpfs on <path> type tmpfs (rw,relatime,size=1024k,uid=1000) 294 c.Assert(info[0], checker.Equals, "tmpfs") 295 c.Assert(info[2], checker.Equals, "/foo") 296 c.Assert(info[4], checker.Equals, "tmpfs") 297 c.Assert(info[5], checker.Contains, "uid=1000") 298 c.Assert(info[5], checker.Contains, "size=1024k") 299 } 300 } 301 c.Assert(found, checker.Equals, true) 302 } 303 304 func (s *DockerSuite) TestVolumeCLICreateLabel(c *check.C) { 305 testVol := "testvolcreatelabel" 306 testLabel := "foo" 307 testValue := "bar" 308 309 out, _, err := dockerCmdWithError("volume", "create", "--label", testLabel+"="+testValue, testVol) 310 c.Assert(err, check.IsNil) 311 312 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Labels."+testLabel+" }}", testVol) 313 c.Assert(strings.TrimSpace(out), check.Equals, testValue) 314 } 315 316 func (s *DockerSuite) TestVolumeCLICreateLabelMultiple(c *check.C) { 317 testVol := "testvolcreatelabel" 318 319 testLabels := map[string]string{ 320 "foo": "bar", 321 "baz": "foo", 322 } 323 324 args := []string{ 325 "volume", 326 "create", 327 testVol, 328 } 329 330 for k, v := range testLabels { 331 args = append(args, "--label", k+"="+v) 332 } 333 334 out, _, err := dockerCmdWithError(args...) 335 c.Assert(err, check.IsNil) 336 337 for k, v := range testLabels { 338 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Labels."+k+" }}", testVol) 339 c.Assert(strings.TrimSpace(out), check.Equals, v) 340 } 341 } 342 343 func (s *DockerSuite) TestVolumeCLILsFilterLabels(c *check.C) { 344 testVol1 := "testvolcreatelabel-1" 345 out, _, err := dockerCmdWithError("volume", "create", "--label", "foo=bar1", testVol1) 346 c.Assert(err, check.IsNil) 347 348 testVol2 := "testvolcreatelabel-2" 349 out, _, err = dockerCmdWithError("volume", "create", "--label", "foo=bar2", testVol2) 350 c.Assert(err, check.IsNil) 351 352 out, _ = dockerCmd(c, "volume", "ls", "--filter", "label=foo") 353 354 // filter with label=key 355 c.Assert(out, checker.Contains, "testvolcreatelabel-1\n", check.Commentf("expected volume 'testvolcreatelabel-1' in output")) 356 c.Assert(out, checker.Contains, "testvolcreatelabel-2\n", check.Commentf("expected volume 'testvolcreatelabel-2' in output")) 357 358 out, _ = dockerCmd(c, "volume", "ls", "--filter", "label=foo=bar1") 359 360 // filter with label=key=value 361 c.Assert(out, checker.Contains, "testvolcreatelabel-1\n", check.Commentf("expected volume 'testvolcreatelabel-1' in output")) 362 c.Assert(out, check.Not(checker.Contains), "testvolcreatelabel-2\n", check.Commentf("expected volume 'testvolcreatelabel-2 in output")) 363 364 out, _ = dockerCmd(c, "volume", "ls", "--filter", "label=non-exist") 365 outArr := strings.Split(strings.TrimSpace(out), "\n") 366 c.Assert(len(outArr), check.Equals, 1, check.Commentf("\n%s", out)) 367 368 out, _ = dockerCmd(c, "volume", "ls", "--filter", "label=foo=non-exist") 369 outArr = strings.Split(strings.TrimSpace(out), "\n") 370 c.Assert(len(outArr), check.Equals, 1, check.Commentf("\n%s", out)) 371 } 372 373 func (s *DockerSuite) TestVolumeCLIRmForceUsage(c *check.C) { 374 out, _ := dockerCmd(c, "volume", "create") 375 id := strings.TrimSpace(out) 376 377 dockerCmd(c, "volume", "rm", "-f", id) 378 dockerCmd(c, "volume", "rm", "--force", "nonexist") 379 380 out, _ = dockerCmd(c, "volume", "ls") 381 outArr := strings.Split(strings.TrimSpace(out), "\n") 382 c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out)) 383 } 384 385 func (s *DockerSuite) TestVolumeCLIRmForce(c *check.C) { 386 testRequires(c, SameHostDaemon, DaemonIsLinux) 387 388 name := "test" 389 out, _ := dockerCmd(c, "volume", "create", name) 390 id := strings.TrimSpace(out) 391 c.Assert(id, checker.Equals, name) 392 393 out, _ = dockerCmd(c, "volume", "inspect", "--format", "{{.Mountpoint}}", name) 394 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 395 // Mountpoint is in the form of "/var/lib/docker/volumes/.../_data", removing `/_data` 396 path := strings.TrimSuffix(strings.TrimSpace(out), "/_data") 397 out, _, err := runCommandWithOutput(exec.Command("rm", "-rf", path)) 398 c.Assert(err, check.IsNil) 399 400 dockerCmd(c, "volume", "rm", "-f", "test") 401 out, _ = dockerCmd(c, "volume", "ls") 402 c.Assert(out, checker.Not(checker.Contains), name) 403 dockerCmd(c, "volume", "create", "test") 404 out, _ = dockerCmd(c, "volume", "ls") 405 c.Assert(out, checker.Contains, name) 406 } 407 408 func (s *DockerSuite) TestVolumeCliInspectWithVolumeOpts(c *check.C) { 409 testRequires(c, DaemonIsLinux) 410 411 // Without options 412 name := "test1" 413 dockerCmd(c, "volume", "create", "-d", "local", name) 414 out, _ := dockerCmd(c, "volume", "inspect", "--format={{ .Options }}", name) 415 c.Assert(strings.TrimSpace(out), checker.Contains, "map[]") 416 417 // With options 418 name = "test2" 419 k1, v1 := "type", "tmpfs" 420 k2, v2 := "device", "tmpfs" 421 k3, v3 := "o", "size=1m,uid=1000" 422 dockerCmd(c, "volume", "create", "-d", "local", name, "--opt", fmt.Sprintf("%s=%s", k1, v1), "--opt", fmt.Sprintf("%s=%s", k2, v2), "--opt", fmt.Sprintf("%s=%s", k3, v3)) 423 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Options }}", name) 424 c.Assert(strings.TrimSpace(out), checker.Contains, fmt.Sprintf("%s:%s", k1, v1)) 425 c.Assert(strings.TrimSpace(out), checker.Contains, fmt.Sprintf("%s:%s", k2, v2)) 426 c.Assert(strings.TrimSpace(out), checker.Contains, fmt.Sprintf("%s:%s", k3, v3)) 427 }