github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/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/api/types/container" 12 "github.com/docker/docker/api/types/mount" 13 "github.com/docker/docker/api/types/network" 14 "github.com/docker/docker/client" 15 "github.com/docker/docker/integration-cli/checker" 16 "github.com/docker/docker/integration-cli/cli/build" 17 "github.com/go-check/check" 18 "github.com/gotestyourself/gotestyourself/icmd" 19 "golang.org/x/net/context" 20 ) 21 22 func (s *DockerSuite) TestVolumeCLICreate(c *check.C) { 23 dockerCmd(c, "volume", "create") 24 25 _, _, err := dockerCmdWithError("volume", "create", "-d", "nosuchdriver") 26 c.Assert(err, check.NotNil) 27 28 // test using hidden --name option 29 out, _ := dockerCmd(c, "volume", "create", "--name=test") 30 name := strings.TrimSpace(out) 31 c.Assert(name, check.Equals, "test") 32 33 out, _ = dockerCmd(c, "volume", "create", "test2") 34 name = strings.TrimSpace(out) 35 c.Assert(name, check.Equals, "test2") 36 } 37 38 func (s *DockerSuite) TestVolumeCLIInspect(c *check.C) { 39 c.Assert( 40 exec.Command(dockerBinary, "volume", "inspect", "doesnotexist").Run(), 41 check.Not(check.IsNil), 42 check.Commentf("volume inspect should error on non-existent volume"), 43 ) 44 45 out, _ := dockerCmd(c, "volume", "create") 46 name := strings.TrimSpace(out) 47 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Name }}", name) 48 c.Assert(strings.TrimSpace(out), check.Equals, name) 49 50 dockerCmd(c, "volume", "create", "test") 51 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Name }}", "test") 52 c.Assert(strings.TrimSpace(out), check.Equals, "test") 53 } 54 55 func (s *DockerSuite) TestVolumeCLIInspectMulti(c *check.C) { 56 dockerCmd(c, "volume", "create", "test1") 57 dockerCmd(c, "volume", "create", "test2") 58 dockerCmd(c, "volume", "create", "test3") 59 60 result := dockerCmdWithResult("volume", "inspect", "--format={{ .Name }}", "test1", "test2", "doesnotexist", "test3") 61 result.Assert(c, icmd.Expected{ 62 ExitCode: 1, 63 Err: "No such volume: doesnotexist", 64 }) 65 66 out := result.Stdout() 67 c.Assert(out, checker.Contains, "test1") 68 c.Assert(out, checker.Contains, "test2") 69 c.Assert(out, checker.Contains, "test3") 70 } 71 72 func (s *DockerSuite) TestVolumeCLILs(c *check.C) { 73 prefix, _ := getPrefixAndSlashFromDaemonPlatform() 74 dockerCmd(c, "volume", "create", "aaa") 75 76 dockerCmd(c, "volume", "create", "test") 77 78 dockerCmd(c, "volume", "create", "soo") 79 dockerCmd(c, "run", "-v", "soo:"+prefix+"/foo", "busybox", "ls", "/") 80 81 out, _ := dockerCmd(c, "volume", "ls", "-q") 82 assertVolumesInList(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 assertVolumesInList(c, out, []string{"aaa", "soo", "test"}) 92 } 93 94 func (s *DockerSuite) TestVolumeLsFormatDefaultFormat(c *check.C) { 95 dockerCmd(c, "volume", "create", "aaa") 96 dockerCmd(c, "volume", "create", "test") 97 dockerCmd(c, "volume", "create", "soo") 98 99 config := `{ 100 "volumesFormat": "{{ .Name }} default" 101 }` 102 d, err := ioutil.TempDir("", "integration-cli-") 103 c.Assert(err, checker.IsNil) 104 defer os.RemoveAll(d) 105 106 err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644) 107 c.Assert(err, checker.IsNil) 108 109 out, _ := dockerCmd(c, "--config", d, "volume", "ls") 110 assertVolumesInList(c, out, []string{"aaa default", "soo default", "test default"}) 111 } 112 113 // assertVolList checks volume retrieved with ls command 114 // equals to expected volume list 115 // note: out should be `volume ls [option]` result 116 func assertVolList(c *check.C, out string, expectVols []string) { 117 lines := strings.Split(out, "\n") 118 var volList []string 119 for _, line := range lines[1 : len(lines)-1] { 120 volFields := strings.Fields(line) 121 // wrap all volume name in volList 122 volList = append(volList, volFields[1]) 123 } 124 125 // volume ls should contains all expected volumes 126 c.Assert(volList, checker.DeepEquals, expectVols) 127 } 128 129 func assertVolumesInList(c *check.C, out string, expected []string) { 130 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 131 for _, expect := range expected { 132 found := false 133 for _, v := range lines { 134 found = v == expect 135 if found { 136 break 137 } 138 } 139 c.Assert(found, checker.Equals, true, check.Commentf("Expected volume not found: %v, got: %v", expect, lines)) 140 } 141 } 142 143 func (s *DockerSuite) TestVolumeCLILsFilterDangling(c *check.C) { 144 prefix, _ := getPrefixAndSlashFromDaemonPlatform() 145 dockerCmd(c, "volume", "create", "testnotinuse1") 146 dockerCmd(c, "volume", "create", "testisinuse1") 147 dockerCmd(c, "volume", "create", "testisinuse2") 148 149 // Make sure both "created" (but not started), and started 150 // containers are included in reference counting 151 dockerCmd(c, "run", "--name", "volume-test1", "-v", "testisinuse1:"+prefix+"/foo", "busybox", "true") 152 dockerCmd(c, "create", "--name", "volume-test2", "-v", "testisinuse2:"+prefix+"/foo", "busybox", "true") 153 154 out, _ := dockerCmd(c, "volume", "ls") 155 156 // No filter, all volumes should show 157 c.Assert(out, checker.Contains, "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 158 c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output")) 159 c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output")) 160 161 out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=false") 162 163 // Explicitly disabling dangling 164 c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 165 c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output")) 166 c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output")) 167 168 out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=true") 169 170 // Filter "dangling" volumes; only "dangling" (unused) volumes should be in the output 171 c.Assert(out, checker.Contains, "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 172 c.Assert(out, check.Not(checker.Contains), "testisinuse1\n", check.Commentf("volume 'testisinuse1' in output, but not expected")) 173 c.Assert(out, check.Not(checker.Contains), "testisinuse2\n", check.Commentf("volume 'testisinuse2' in output, but not expected")) 174 175 out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=1") 176 // Filter "dangling" volumes; only "dangling" (unused) volumes should be in the output, dangling also accept 1 177 c.Assert(out, checker.Contains, "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 178 c.Assert(out, check.Not(checker.Contains), "testisinuse1\n", check.Commentf("volume 'testisinuse1' in output, but not expected")) 179 c.Assert(out, check.Not(checker.Contains), "testisinuse2\n", check.Commentf("volume 'testisinuse2' in output, but not expected")) 180 181 out, _ = dockerCmd(c, "volume", "ls", "--filter", "dangling=0") 182 // dangling=0 is same as dangling=false case 183 c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 184 c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output")) 185 c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output")) 186 187 out, _ = dockerCmd(c, "volume", "ls", "--filter", "name=testisin") 188 c.Assert(out, check.Not(checker.Contains), "testnotinuse1\n", check.Commentf("expected volume 'testnotinuse1' in output")) 189 c.Assert(out, checker.Contains, "testisinuse1\n", check.Commentf("expected volume 'testisinuse1' in output")) 190 c.Assert(out, checker.Contains, "testisinuse2\n", check.Commentf("expected volume 'testisinuse2' in output")) 191 } 192 193 func (s *DockerSuite) TestVolumeCLILsErrorWithInvalidFilterName(c *check.C) { 194 out, _, err := dockerCmdWithError("volume", "ls", "-f", "FOO=123") 195 c.Assert(err, checker.NotNil) 196 c.Assert(out, checker.Contains, "Invalid filter") 197 } 198 199 func (s *DockerSuite) TestVolumeCLILsWithIncorrectFilterValue(c *check.C) { 200 out, _, err := dockerCmdWithError("volume", "ls", "-f", "dangling=invalid") 201 c.Assert(err, check.NotNil) 202 c.Assert(out, checker.Contains, "Invalid filter") 203 } 204 205 func (s *DockerSuite) TestVolumeCLIRm(c *check.C) { 206 prefix, _ := getPrefixAndSlashFromDaemonPlatform() 207 out, _ := dockerCmd(c, "volume", "create") 208 id := strings.TrimSpace(out) 209 210 dockerCmd(c, "volume", "create", "test") 211 dockerCmd(c, "volume", "rm", id) 212 dockerCmd(c, "volume", "rm", "test") 213 214 volumeID := "testing" 215 dockerCmd(c, "run", "-v", volumeID+":"+prefix+"/foo", "--name=test", "busybox", "sh", "-c", "echo hello > /foo/bar") 216 217 icmd.RunCommand(dockerBinary, "volume", "rm", "testing").Assert(c, icmd.Expected{ 218 ExitCode: 1, 219 Error: "exit status 1", 220 }) 221 222 out, _ = dockerCmd(c, "run", "--volumes-from=test", "--name=test2", "busybox", "sh", "-c", "cat /foo/bar") 223 c.Assert(strings.TrimSpace(out), check.Equals, "hello") 224 dockerCmd(c, "rm", "-fv", "test2") 225 dockerCmd(c, "volume", "inspect", volumeID) 226 dockerCmd(c, "rm", "-f", "test") 227 228 out, _ = dockerCmd(c, "run", "--name=test2", "-v", volumeID+":"+prefix+"/foo", "busybox", "sh", "-c", "cat /foo/bar") 229 c.Assert(strings.TrimSpace(out), check.Equals, "hello", check.Commentf("volume data was removed")) 230 dockerCmd(c, "rm", "test2") 231 232 dockerCmd(c, "volume", "rm", volumeID) 233 c.Assert( 234 exec.Command("volume", "rm", "doesnotexist").Run(), 235 check.Not(check.IsNil), 236 check.Commentf("volume rm should fail with non-existent volume"), 237 ) 238 } 239 240 // FIXME(vdemeester) should be a unit test in cli/command/volume package 241 func (s *DockerSuite) TestVolumeCLINoArgs(c *check.C) { 242 out, _ := dockerCmd(c, "volume") 243 // no args should produce the cmd usage output 244 usage := "Usage: docker volume COMMAND" 245 c.Assert(out, checker.Contains, usage) 246 247 // invalid arg should error and show the command usage on stderr 248 icmd.RunCommand(dockerBinary, "volume", "somearg").Assert(c, icmd.Expected{ 249 ExitCode: 1, 250 Error: "exit status 1", 251 Err: usage, 252 }) 253 254 // invalid flag should error and show the flag error and cmd usage 255 result := icmd.RunCommand(dockerBinary, "volume", "--no-such-flag") 256 result.Assert(c, icmd.Expected{ 257 ExitCode: 125, 258 Error: "exit status 125", 259 Err: usage, 260 }) 261 c.Assert(result.Stderr(), checker.Contains, "unknown flag: --no-such-flag") 262 } 263 264 func (s *DockerSuite) TestVolumeCLIInspectTmplError(c *check.C) { 265 out, _ := dockerCmd(c, "volume", "create") 266 name := strings.TrimSpace(out) 267 268 out, exitCode, err := dockerCmdWithError("volume", "inspect", "--format='{{ .FooBar }}'", name) 269 c.Assert(err, checker.NotNil, check.Commentf("Output: %s", out)) 270 c.Assert(exitCode, checker.Equals, 1, check.Commentf("Output: %s", out)) 271 c.Assert(out, checker.Contains, "Template parsing error") 272 } 273 274 func (s *DockerSuite) TestVolumeCLICreateWithOpts(c *check.C) { 275 testRequires(c, DaemonIsLinux) 276 277 dockerCmd(c, "volume", "create", "-d", "local", "test", "--opt=type=tmpfs", "--opt=device=tmpfs", "--opt=o=size=1m,uid=1000") 278 out, _ := dockerCmd(c, "run", "-v", "test:/foo", "busybox", "mount") 279 280 mounts := strings.Split(out, "\n") 281 var found bool 282 for _, m := range mounts { 283 if strings.Contains(m, "/foo") { 284 found = true 285 info := strings.Fields(m) 286 // tmpfs on <path> type tmpfs (rw,relatime,size=1024k,uid=1000) 287 c.Assert(info[0], checker.Equals, "tmpfs") 288 c.Assert(info[2], checker.Equals, "/foo") 289 c.Assert(info[4], checker.Equals, "tmpfs") 290 c.Assert(info[5], checker.Contains, "uid=1000") 291 c.Assert(info[5], checker.Contains, "size=1024k") 292 break 293 } 294 } 295 c.Assert(found, checker.Equals, true) 296 } 297 298 func (s *DockerSuite) TestVolumeCLICreateLabel(c *check.C) { 299 testVol := "testvolcreatelabel" 300 testLabel := "foo" 301 testValue := "bar" 302 303 out, _, err := dockerCmdWithError("volume", "create", "--label", testLabel+"="+testValue, testVol) 304 c.Assert(err, check.IsNil) 305 306 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Labels."+testLabel+" }}", testVol) 307 c.Assert(strings.TrimSpace(out), check.Equals, testValue) 308 } 309 310 func (s *DockerSuite) TestVolumeCLICreateLabelMultiple(c *check.C) { 311 testVol := "testvolcreatelabel" 312 313 testLabels := map[string]string{ 314 "foo": "bar", 315 "baz": "foo", 316 } 317 318 args := []string{ 319 "volume", 320 "create", 321 testVol, 322 } 323 324 for k, v := range testLabels { 325 args = append(args, "--label", k+"="+v) 326 } 327 328 out, _, err := dockerCmdWithError(args...) 329 c.Assert(err, check.IsNil) 330 331 for k, v := range testLabels { 332 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Labels."+k+" }}", testVol) 333 c.Assert(strings.TrimSpace(out), check.Equals, v) 334 } 335 } 336 337 func (s *DockerSuite) TestVolumeCLILsFilterLabels(c *check.C) { 338 testVol1 := "testvolcreatelabel-1" 339 out, _, err := dockerCmdWithError("volume", "create", "--label", "foo=bar1", testVol1) 340 c.Assert(err, check.IsNil) 341 342 testVol2 := "testvolcreatelabel-2" 343 out, _, err = dockerCmdWithError("volume", "create", "--label", "foo=bar2", testVol2) 344 c.Assert(err, check.IsNil) 345 346 out, _ = dockerCmd(c, "volume", "ls", "--filter", "label=foo") 347 348 // filter with label=key 349 c.Assert(out, checker.Contains, "testvolcreatelabel-1\n", check.Commentf("expected volume 'testvolcreatelabel-1' in output")) 350 c.Assert(out, checker.Contains, "testvolcreatelabel-2\n", check.Commentf("expected volume 'testvolcreatelabel-2' in output")) 351 352 out, _ = dockerCmd(c, "volume", "ls", "--filter", "label=foo=bar1") 353 354 // filter with label=key=value 355 c.Assert(out, checker.Contains, "testvolcreatelabel-1\n", check.Commentf("expected volume 'testvolcreatelabel-1' in output")) 356 c.Assert(out, check.Not(checker.Contains), "testvolcreatelabel-2\n", check.Commentf("expected volume 'testvolcreatelabel-2 in output")) 357 358 out, _ = dockerCmd(c, "volume", "ls", "--filter", "label=non-exist") 359 outArr := strings.Split(strings.TrimSpace(out), "\n") 360 c.Assert(len(outArr), check.Equals, 1, check.Commentf("\n%s", out)) 361 362 out, _ = dockerCmd(c, "volume", "ls", "--filter", "label=foo=non-exist") 363 outArr = strings.Split(strings.TrimSpace(out), "\n") 364 c.Assert(len(outArr), check.Equals, 1, check.Commentf("\n%s", out)) 365 } 366 367 func (s *DockerSuite) TestVolumeCLILsFilterDrivers(c *check.C) { 368 // using default volume driver local to create volumes 369 testVol1 := "testvol-1" 370 out, _, err := dockerCmdWithError("volume", "create", testVol1) 371 c.Assert(err, check.IsNil) 372 373 testVol2 := "testvol-2" 374 out, _, err = dockerCmdWithError("volume", "create", testVol2) 375 c.Assert(err, check.IsNil) 376 377 // filter with driver=local 378 out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=local") 379 c.Assert(out, checker.Contains, "testvol-1\n", check.Commentf("expected volume 'testvol-1' in output")) 380 c.Assert(out, checker.Contains, "testvol-2\n", check.Commentf("expected volume 'testvol-2' in output")) 381 382 // filter with driver=invaliddriver 383 out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=invaliddriver") 384 outArr := strings.Split(strings.TrimSpace(out), "\n") 385 c.Assert(len(outArr), check.Equals, 1, check.Commentf("\n%s", out)) 386 387 // filter with driver=loca 388 out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=loca") 389 outArr = strings.Split(strings.TrimSpace(out), "\n") 390 c.Assert(len(outArr), check.Equals, 1, check.Commentf("\n%s", out)) 391 392 // filter with driver= 393 out, _ = dockerCmd(c, "volume", "ls", "--filter", "driver=") 394 outArr = strings.Split(strings.TrimSpace(out), "\n") 395 c.Assert(len(outArr), check.Equals, 1, check.Commentf("\n%s", out)) 396 } 397 398 func (s *DockerSuite) TestVolumeCLIRmForceUsage(c *check.C) { 399 out, _ := dockerCmd(c, "volume", "create") 400 id := strings.TrimSpace(out) 401 402 dockerCmd(c, "volume", "rm", "-f", id) 403 dockerCmd(c, "volume", "rm", "--force", "nonexist") 404 } 405 406 func (s *DockerSuite) TestVolumeCLIRmForce(c *check.C) { 407 testRequires(c, SameHostDaemon, DaemonIsLinux) 408 409 name := "test" 410 out, _ := dockerCmd(c, "volume", "create", name) 411 id := strings.TrimSpace(out) 412 c.Assert(id, checker.Equals, name) 413 414 out, _ = dockerCmd(c, "volume", "inspect", "--format", "{{.Mountpoint}}", name) 415 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 416 // Mountpoint is in the form of "/var/lib/docker/volumes/.../_data", removing `/_data` 417 path := strings.TrimSuffix(strings.TrimSpace(out), "/_data") 418 icmd.RunCommand("rm", "-rf", path).Assert(c, icmd.Success) 419 420 dockerCmd(c, "volume", "rm", "-f", name) 421 out, _ = dockerCmd(c, "volume", "ls") 422 c.Assert(out, checker.Not(checker.Contains), name) 423 dockerCmd(c, "volume", "create", name) 424 out, _ = dockerCmd(c, "volume", "ls") 425 c.Assert(out, checker.Contains, name) 426 } 427 428 // TestVolumeCLIRmForceInUse verifies that repeated `docker volume rm -f` calls does not remove a volume 429 // if it is in use. Test case for https://github.com/docker/docker/issues/31446 430 func (s *DockerSuite) TestVolumeCLIRmForceInUse(c *check.C) { 431 name := "testvolume" 432 out, _ := dockerCmd(c, "volume", "create", name) 433 id := strings.TrimSpace(out) 434 c.Assert(id, checker.Equals, name) 435 436 prefix, slash := getPrefixAndSlashFromDaemonPlatform() 437 out, e := dockerCmd(c, "create", "-v", "testvolume:"+prefix+slash+"foo", "busybox") 438 cid := strings.TrimSpace(out) 439 440 _, _, err := dockerCmdWithError("volume", "rm", "-f", name) 441 c.Assert(err, check.NotNil) 442 c.Assert(err.Error(), checker.Contains, "volume is in use") 443 out, _ = dockerCmd(c, "volume", "ls") 444 c.Assert(out, checker.Contains, name) 445 446 // The original issue did not _remove_ the volume from the list 447 // the first time. But a second call to `volume rm` removed it. 448 // Calling `volume rm` a second time to confirm it's not removed 449 // when calling twice. 450 _, _, err = dockerCmdWithError("volume", "rm", "-f", name) 451 c.Assert(err, check.NotNil) 452 c.Assert(err.Error(), checker.Contains, "volume is in use") 453 out, _ = dockerCmd(c, "volume", "ls") 454 c.Assert(out, checker.Contains, name) 455 456 // Verify removing the volume after the container is removed works 457 _, e = dockerCmd(c, "rm", cid) 458 c.Assert(e, check.Equals, 0) 459 460 _, e = dockerCmd(c, "volume", "rm", "-f", name) 461 c.Assert(e, check.Equals, 0) 462 463 out, e = dockerCmd(c, "volume", "ls") 464 c.Assert(e, check.Equals, 0) 465 c.Assert(out, checker.Not(checker.Contains), name) 466 } 467 468 func (s *DockerSuite) TestVolumeCliInspectWithVolumeOpts(c *check.C) { 469 testRequires(c, DaemonIsLinux) 470 471 // Without options 472 name := "test1" 473 dockerCmd(c, "volume", "create", "-d", "local", name) 474 out, _ := dockerCmd(c, "volume", "inspect", "--format={{ .Options }}", name) 475 c.Assert(strings.TrimSpace(out), checker.Contains, "map[]") 476 477 // With options 478 name = "test2" 479 k1, v1 := "type", "tmpfs" 480 k2, v2 := "device", "tmpfs" 481 k3, v3 := "o", "size=1m,uid=1000" 482 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)) 483 out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Options }}", name) 484 c.Assert(strings.TrimSpace(out), checker.Contains, fmt.Sprintf("%s:%s", k1, v1)) 485 c.Assert(strings.TrimSpace(out), checker.Contains, fmt.Sprintf("%s:%s", k2, v2)) 486 c.Assert(strings.TrimSpace(out), checker.Contains, fmt.Sprintf("%s:%s", k3, v3)) 487 } 488 489 // Test case (1) for 21845: duplicate targets for --volumes-from 490 func (s *DockerSuite) TestDuplicateMountpointsForVolumesFrom(c *check.C) { 491 testRequires(c, DaemonIsLinux) 492 493 image := "vimage" 494 buildImageSuccessfully(c, image, build.WithDockerfile(` 495 FROM busybox 496 VOLUME ["/tmp/data"]`)) 497 498 dockerCmd(c, "run", "--name=data1", image, "true") 499 dockerCmd(c, "run", "--name=data2", image, "true") 500 501 out, _ := dockerCmd(c, "inspect", "--format", "{{(index .Mounts 0).Name}}", "data1") 502 data1 := strings.TrimSpace(out) 503 c.Assert(data1, checker.Not(checker.Equals), "") 504 505 out, _ = dockerCmd(c, "inspect", "--format", "{{(index .Mounts 0).Name}}", "data2") 506 data2 := strings.TrimSpace(out) 507 c.Assert(data2, checker.Not(checker.Equals), "") 508 509 // Both volume should exist 510 out, _ = dockerCmd(c, "volume", "ls", "-q") 511 c.Assert(strings.TrimSpace(out), checker.Contains, data1) 512 c.Assert(strings.TrimSpace(out), checker.Contains, data2) 513 514 out, _, err := dockerCmdWithError("run", "--name=app", "--volumes-from=data1", "--volumes-from=data2", "-d", "busybox", "top") 515 c.Assert(err, checker.IsNil, check.Commentf("Out: %s", out)) 516 517 // Only the second volume will be referenced, this is backward compatible 518 out, _ = dockerCmd(c, "inspect", "--format", "{{(index .Mounts 0).Name}}", "app") 519 c.Assert(strings.TrimSpace(out), checker.Equals, data2) 520 521 dockerCmd(c, "rm", "-f", "-v", "app") 522 dockerCmd(c, "rm", "-f", "-v", "data1") 523 dockerCmd(c, "rm", "-f", "-v", "data2") 524 525 // Both volume should not exist 526 out, _ = dockerCmd(c, "volume", "ls", "-q") 527 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data1) 528 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data2) 529 } 530 531 // Test case (2) for 21845: duplicate targets for --volumes-from and -v (bind) 532 func (s *DockerSuite) TestDuplicateMountpointsForVolumesFromAndBind(c *check.C) { 533 testRequires(c, DaemonIsLinux) 534 535 image := "vimage" 536 buildImageSuccessfully(c, image, build.WithDockerfile(` 537 FROM busybox 538 VOLUME ["/tmp/data"]`)) 539 540 dockerCmd(c, "run", "--name=data1", image, "true") 541 dockerCmd(c, "run", "--name=data2", image, "true") 542 543 out, _ := dockerCmd(c, "inspect", "--format", "{{(index .Mounts 0).Name}}", "data1") 544 data1 := strings.TrimSpace(out) 545 c.Assert(data1, checker.Not(checker.Equals), "") 546 547 out, _ = dockerCmd(c, "inspect", "--format", "{{(index .Mounts 0).Name}}", "data2") 548 data2 := strings.TrimSpace(out) 549 c.Assert(data2, checker.Not(checker.Equals), "") 550 551 // Both volume should exist 552 out, _ = dockerCmd(c, "volume", "ls", "-q") 553 c.Assert(strings.TrimSpace(out), checker.Contains, data1) 554 c.Assert(strings.TrimSpace(out), checker.Contains, data2) 555 556 // /tmp/data is automatically created, because we are not using the modern mount API here 557 out, _, err := dockerCmdWithError("run", "--name=app", "--volumes-from=data1", "--volumes-from=data2", "-v", "/tmp/data:/tmp/data", "-d", "busybox", "top") 558 c.Assert(err, checker.IsNil, check.Commentf("Out: %s", out)) 559 560 // No volume will be referenced (mount is /tmp/data), this is backward compatible 561 out, _ = dockerCmd(c, "inspect", "--format", "{{(index .Mounts 0).Name}}", "app") 562 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data1) 563 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data2) 564 565 dockerCmd(c, "rm", "-f", "-v", "app") 566 dockerCmd(c, "rm", "-f", "-v", "data1") 567 dockerCmd(c, "rm", "-f", "-v", "data2") 568 569 // Both volume should not exist 570 out, _ = dockerCmd(c, "volume", "ls", "-q") 571 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data1) 572 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data2) 573 } 574 575 // Test case (3) for 21845: duplicate targets for --volumes-from and `Mounts` (API only) 576 func (s *DockerSuite) TestDuplicateMountpointsForVolumesFromAndMounts(c *check.C) { 577 testRequires(c, SameHostDaemon, DaemonIsLinux) 578 579 image := "vimage" 580 buildImageSuccessfully(c, image, build.WithDockerfile(` 581 FROM busybox 582 VOLUME ["/tmp/data"]`)) 583 584 dockerCmd(c, "run", "--name=data1", image, "true") 585 dockerCmd(c, "run", "--name=data2", image, "true") 586 587 out, _ := dockerCmd(c, "inspect", "--format", "{{(index .Mounts 0).Name}}", "data1") 588 data1 := strings.TrimSpace(out) 589 c.Assert(data1, checker.Not(checker.Equals), "") 590 591 out, _ = dockerCmd(c, "inspect", "--format", "{{(index .Mounts 0).Name}}", "data2") 592 data2 := strings.TrimSpace(out) 593 c.Assert(data2, checker.Not(checker.Equals), "") 594 595 // Both volume should exist 596 out, _ = dockerCmd(c, "volume", "ls", "-q") 597 c.Assert(strings.TrimSpace(out), checker.Contains, data1) 598 c.Assert(strings.TrimSpace(out), checker.Contains, data2) 599 600 err := os.MkdirAll("/tmp/data", 0755) 601 c.Assert(err, checker.IsNil) 602 // Mounts is available in API 603 cli, err := client.NewEnvClient() 604 c.Assert(err, checker.IsNil) 605 defer cli.Close() 606 607 config := container.Config{ 608 Cmd: []string{"top"}, 609 Image: "busybox", 610 } 611 612 hostConfig := container.HostConfig{ 613 VolumesFrom: []string{"data1", "data2"}, 614 Mounts: []mount.Mount{ 615 { 616 Type: "bind", 617 Source: "/tmp/data", 618 Target: "/tmp/data", 619 }, 620 }, 621 } 622 _, err = cli.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, "app") 623 624 c.Assert(err, checker.IsNil) 625 626 // No volume will be referenced (mount is /tmp/data), this is backward compatible 627 out, _ = dockerCmd(c, "inspect", "--format", "{{(index .Mounts 0).Name}}", "app") 628 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data1) 629 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data2) 630 631 dockerCmd(c, "rm", "-f", "-v", "app") 632 dockerCmd(c, "rm", "-f", "-v", "data1") 633 dockerCmd(c, "rm", "-f", "-v", "data2") 634 635 // Both volume should not exist 636 out, _ = dockerCmd(c, "volume", "ls", "-q") 637 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data1) 638 c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), data2) 639 }