From 8d174a43babd19e8c1166338b5aa5f1128914a96 Mon Sep 17 00:00:00 2001 From: John Howard Date: Wed, 25 May 2016 13:56:36 -0700 Subject: [PATCH] Windows: Support RO volumes 14350+ Signed-off-by: John Howard --- integration-cli/docker_cli_inspect_test.go | 22 ++++++++--- integration-cli/docker_cli_run_test.go | 45 +++++++++++++--------- volume/volume_windows.go | 27 ++++++++----- 3 files changed, 60 insertions(+), 34 deletions(-) diff --git a/integration-cli/docker_cli_inspect_test.go b/integration-cli/docker_cli_inspect_test.go index 29614537d6..e4343fa5ff 100644 --- a/integration-cli/docker_cli_inspect_test.go +++ b/integration-cli/docker_cli_inspect_test.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "os" "os/exec" "strconv" "strings" @@ -209,8 +210,19 @@ func (s *DockerSuite) TestInspectContainerGraphDriver(c *check.C) { } func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) { - testRequires(c, DaemonIsLinux) - dockerCmd(c, "run", "-d", "--name", "test", "-v", "/data:/data:ro,z", "busybox", "cat") + modifier := ",z" + prefix, slash := getPrefixAndSlashFromDaemonPlatform() + if daemonPlatform == "windows" { + modifier = "" + // TODO Windows: Temporary check - remove once TP5 support is dropped + if windowsDaemonKV < 14350 { + c.Skip("Needs later Windows build for RO volumes") + } + // Linux creates the host directory if it doesn't exist. Windows does not. + os.Mkdir(`c:\data`, os.ModeDir) + } + + dockerCmd(c, "run", "-d", "--name", "test", "-v", prefix+slash+"data:"+prefix+slash+"data:ro"+modifier, "busybox", "cat") vol := inspectFieldJSON(c, "test", "Mounts") @@ -225,9 +237,9 @@ func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) { c.Assert(m.Name, checker.Equals, "") c.Assert(m.Driver, checker.Equals, "") - c.Assert(m.Source, checker.Equals, "/data") - c.Assert(m.Destination, checker.Equals, "/data") - c.Assert(m.Mode, checker.Equals, "ro,z") + c.Assert(m.Source, checker.Equals, prefix+slash+"data") + c.Assert(m.Destination, checker.Equals, prefix+slash+"data") + c.Assert(m.Mode, checker.Equals, "ro"+modifier) c.Assert(m.RW, checker.Equals, false) } diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 1145f3bc21..71287506f4 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -442,18 +442,20 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir2(c *check.C) { } func (s *DockerSuite) TestRunVolumesMountedAsReadonly(c *check.C) { - // TODO Windows (Post TP5): This test cannot run on a Windows daemon as - // Windows does not support read-only bind mounts. - testRequires(c, DaemonIsLinux) + // TODO Windows: Temporary check - remove once TP5 support is dropped + if daemonPlatform == "windows" && windowsDaemonKV < 14350 { + c.Skip("Needs later Windows build for RO volumes") + } if _, code, err := dockerCmdWithError("run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile"); err == nil || code == 0 { c.Fatalf("run should fail because volume is ro: exit code %d", code) } } func (s *DockerSuite) TestRunVolumesFromInReadonlyModeFails(c *check.C) { - // TODO Windows (Post TP5): This test cannot run on a Windows daemon as - // Windows does not support read-only bind mounts. Modified for when ro is supported. - testRequires(c, DaemonIsLinux) + // TODO Windows: Temporary check - remove once TP5 support is dropped + if daemonPlatform == "windows" && windowsDaemonKV < 14350 { + c.Skip("Needs later Windows build for RO volumes") + } var ( volumeDir string fileInVol string @@ -498,20 +500,23 @@ func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) { } func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) { - // TODO Windows: This test cannot yet run on a Windows daemon as Windows does - // not support read-only bind mounts as at TP5 - testRequires(c, DaemonIsLinux) - dockerCmd(c, "run", "--name", "parent", "-v", "/test:/test:ro", "busybox", "true") + prefix, slash := getPrefixAndSlashFromDaemonPlatform() + + // TODO Windows: Temporary check - remove once TP5 support is dropped + if daemonPlatform == "windows" && windowsDaemonKV < 14350 { + c.Skip("Needs later Windows build for RO volumes") + } + dockerCmd(c, "run", "--name", "parent", "-v", prefix+slash+"test:"+prefix+slash+"test:ro", "busybox", "true") // Expect this "rw" mode to be be ignored since the inherited volume is "ro" - if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent:rw", "busybox", "touch", "/test/file"); err == nil { + if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent:rw", "busybox", "touch", prefix+slash+"test"+slash+"file"); err == nil { c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `rw`") } - dockerCmd(c, "run", "--name", "parent2", "-v", "/test:/test:ro", "busybox", "true") + dockerCmd(c, "run", "--name", "parent2", "-v", prefix+slash+"test:"+prefix+slash+"test:ro", "busybox", "true") // Expect this to be read-only since both are "ro" - if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent2:ro", "busybox", "touch", "/test/file"); err == nil { + if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent2:ro", "busybox", "touch", prefix+slash+"test"+slash+"file"); err == nil { c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `ro`") } } @@ -1914,6 +1919,8 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) { testRequires(c, DaemonIsLinux, NotUserNamespace) } + prefix, _ := getPrefixAndSlashFromDaemonPlatform() + tmpDir, err := ioutil.TempDir("", "docker-test-container") if err != nil { c.Fatal(err) @@ -1922,10 +1929,10 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) { defer os.RemoveAll(tmpDir) writeFile(path.Join(tmpDir, "touch-me"), "", c) - // TODO Windows Post TP5. Windows does not yet support :ro binds - if daemonPlatform != "windows" { + // TODO Windows: Temporary check - remove once TP5 support is dropped + if daemonPlatform != "windows" || windowsDaemonKV >= 14350 { // Test reading from a read-only bind mount - out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox", "ls", "/tmp") + out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:%s/tmp:ro", tmpDir, prefix), "busybox", "ls", prefix+"/tmp") if !strings.Contains(out, "touch-me") { c.Fatal("Container failed to read from bind mount") } @@ -3122,12 +3129,12 @@ func (s *DockerSuite) TestRunCapAddCHOWN(c *check.C) { // https://github.com/docker/docker/pull/14498 func (s *DockerSuite) TestVolumeFromMixedRWOptions(c *check.C) { - // TODO Windows post TP5. Enable the read-only bits once they are - // supported on the platform. prefix, slash := getPrefixAndSlashFromDaemonPlatform() dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "true") - if daemonPlatform != "windows" { + + // TODO Windows: Temporary check - remove once TP5 support is dropped + if daemonPlatform != "windows" || windowsDaemonKV >= 14350 { dockerCmd(c, "run", "--volumes-from", "parent:ro", "--name", "test-volumes-1", "busybox", "true") } dockerCmd(c, "run", "--volumes-from", "parent:rw", "--name", "test-volumes-2", "busybox", "true") diff --git a/volume/volume_windows.go b/volume/volume_windows.go index d01d10d671..7aa6983d2c 100644 --- a/volume/volume_windows.go +++ b/volume/volume_windows.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/Sirupsen/logrus" + "github.com/docker/docker/pkg/system" ) // read-write modes @@ -68,18 +69,24 @@ const ( // - Variation on hostdir but can be a drive followed by colon as well // - If a path, must be absolute. Can include spaces // - Drive cannot be c: (explicitly checked in code, not RegEx) - // - - // RXMode is the regex expression for the mode of the mount - RXMode = `(:(?P(?i)rw))?` - // Temporarily for TP4, disabling the use of ro as it's not supported yet - // in the platform. TODO Windows: `(:(?P(?i)ro|rw))?` - // mode (optional) - // - Hopefully self explanatory in comparison to above. - // - Colon is not in the capture group - // ) +// RXMode is the regex expression for the mode of the mount +var RXMode string + +func init() { + osv := system.GetOSVersion() + // Read-only volumes supported from 14350 onwards (post Windows Server 2016 TP5) + // Mode (optional): + // - Hopefully self explanatory in comparison to above regex's. + // - Colon is not in the capture group + if osv.Build >= 14350 { + RXMode = `(:(?P(?i)ro|rw))?` + } else { + RXMode = `(:(?P(?i)rw))?` + } +} + // BackwardsCompatible decides whether this mount point can be // used in old versions of Docker or not. // Windows volumes are never backwards compatible.