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