|
@@ -4588,3 +4588,181 @@ func (s *DockerSuite) TestRunDuplicateMount(c *check.C) {
|
|
out = inspectFieldJSON(c, name, "Config.Volumes")
|
|
out = inspectFieldJSON(c, name, "Config.Volumes")
|
|
c.Assert(out, checker.Contains, "null")
|
|
c.Assert(out, checker.Contains, "null")
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+func (s *DockerSuite) TestRunMount(c *check.C) {
|
|
|
|
+ testRequires(c, DaemonIsLinux, SameHostDaemon, NotUserNamespace)
|
|
|
|
+
|
|
|
|
+ // mnt1, mnt2, and testCatFooBar are commonly used in multiple test cases
|
|
|
|
+ tmpDir, err := ioutil.TempDir("", "mount")
|
|
|
|
+ if err != nil {
|
|
|
|
+ c.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+ defer os.RemoveAll(tmpDir)
|
|
|
|
+ mnt1, mnt2 := path.Join(tmpDir, "mnt1"), path.Join(tmpDir, "mnt2")
|
|
|
|
+ if err := os.Mkdir(mnt1, 0755); err != nil {
|
|
|
|
+ c.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+ if err := os.Mkdir(mnt2, 0755); err != nil {
|
|
|
|
+ c.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+ if err := ioutil.WriteFile(path.Join(mnt1, "test1"), []byte("test1"), 0644); err != nil {
|
|
|
|
+ c.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+ if err := ioutil.WriteFile(path.Join(mnt2, "test2"), []byte("test2"), 0644); err != nil {
|
|
|
|
+ c.Fatal(err)
|
|
|
|
+ }
|
|
|
|
+ testCatFooBar := func(cName string) error {
|
|
|
|
+ out, _ := dockerCmd(c, "exec", cName, "cat", "/foo/test1")
|
|
|
|
+ if out != "test1" {
|
|
|
|
+ return fmt.Errorf("%s not mounted on /foo", mnt1)
|
|
|
|
+ }
|
|
|
|
+ out, _ = dockerCmd(c, "exec", cName, "cat", "/bar/test2")
|
|
|
|
+ if out != "test2" {
|
|
|
|
+ return fmt.Errorf("%s not mounted on /bar", mnt2)
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ type testCase struct {
|
|
|
|
+ equivalents [][]string
|
|
|
|
+ valid bool
|
|
|
|
+ // fn should be nil if valid==false
|
|
|
|
+ fn func(cName string) error
|
|
|
|
+ }
|
|
|
|
+ cases := []testCase{
|
|
|
|
+ {
|
|
|
|
+ equivalents: [][]string{
|
|
|
|
+ {
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,dst=/bar", mnt2),
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,target=/bar", mnt2),
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "--volume", fmt.Sprintf("%s:/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,target=/bar", mnt2),
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ valid: true,
|
|
|
|
+ fn: testCatFooBar,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ equivalents: [][]string{
|
|
|
|
+ {
|
|
|
|
+ "--mount", fmt.Sprintf("type=volume,src=%s,dst=/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=volume,src=%s,dst=/bar", mnt2),
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "--mount", fmt.Sprintf("type=volume,src=%s,dst=/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=volume,src=%s,target=/bar", mnt2),
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ valid: false,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ equivalents: [][]string{
|
|
|
|
+ {
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=volume,src=%s,dst=/bar", mnt2),
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "--volume", fmt.Sprintf("%s:/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=volume,src=%s,target=/bar", mnt2),
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ valid: false,
|
|
|
|
+ fn: testCatFooBar,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ equivalents: [][]string{
|
|
|
|
+ {
|
|
|
|
+ "--read-only",
|
|
|
|
+ "--mount", "type=volume,dst=/bar",
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ valid: true,
|
|
|
|
+ fn: func(cName string) error {
|
|
|
|
+ _, _, err := dockerCmdWithError("exec", cName, "touch", "/bar/icanwritehere")
|
|
|
|
+ return err
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ equivalents: [][]string{
|
|
|
|
+ {
|
|
|
|
+ "--read-only",
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
|
|
|
|
+ "--mount", "type=volume,dst=/bar",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "--read-only",
|
|
|
|
+ "--volume", fmt.Sprintf("%s:/foo", mnt1),
|
|
|
|
+ "--mount", "type=volume,dst=/bar",
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ valid: true,
|
|
|
|
+ fn: func(cName string) error {
|
|
|
|
+ out, _ := dockerCmd(c, "exec", cName, "cat", "/foo/test1")
|
|
|
|
+ if out != "test1" {
|
|
|
|
+ return fmt.Errorf("%s not mounted on /foo", mnt1)
|
|
|
|
+ }
|
|
|
|
+ _, _, err := dockerCmdWithError("exec", cName, "touch", "/bar/icanwritehere")
|
|
|
|
+ return err
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ equivalents: [][]string{
|
|
|
|
+ {
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt2),
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,target=/foo", mnt2),
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ "--volume", fmt.Sprintf("%s:/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=bind,src=%s,target=/foo", mnt2),
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ valid: false,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ equivalents: [][]string{
|
|
|
|
+ {
|
|
|
|
+ "--volume", fmt.Sprintf("%s:/foo", mnt1),
|
|
|
|
+ "--mount", fmt.Sprintf("type=volume,src=%s,target=/foo", mnt2),
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ valid: false,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ equivalents: [][]string{
|
|
|
|
+ {
|
|
|
|
+ "--mount", "type=volume,target=/foo",
|
|
|
|
+ "--mount", "type=volume,target=/foo",
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ valid: false,
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for i, testCase := range cases {
|
|
|
|
+ for j, opts := range testCase.equivalents {
|
|
|
|
+ cName := fmt.Sprintf("mount-%d-%d", i, j)
|
|
|
|
+ _, _, err := dockerCmdWithError(append([]string{"run", "-i", "-d", "--name", cName},
|
|
|
|
+ append(opts, []string{"busybox", "top"}...)...)...)
|
|
|
|
+ if testCase.valid {
|
|
|
|
+ c.Assert(err, check.IsNil,
|
|
|
|
+ check.Commentf("got error while creating a container with %v (%s)", opts, cName))
|
|
|
|
+ c.Assert(testCase.fn(cName), check.IsNil,
|
|
|
|
+ check.Commentf("got error while executing test for %v (%s)", opts, cName))
|
|
|
|
+ dockerCmd(c, "rm", "-f", cName)
|
|
|
|
+ } else {
|
|
|
|
+ c.Assert(err, checker.NotNil,
|
|
|
|
+ check.Commentf("got nil while creating a container with %v (%s)", opts, cName))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|