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  }