Windows: Support RO volumes 14350+

Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
John Howard 2016-05-25 13:56:36 -07:00
parent ff3dc48966
commit 8d174a43ba
3 changed files with 60 additions and 34 deletions

View File

@ -3,6 +3,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"os"
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"
@ -209,8 +210,19 @@ func (s *DockerSuite) TestInspectContainerGraphDriver(c *check.C) {
} }
func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) { func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) {
testRequires(c, DaemonIsLinux) modifier := ",z"
dockerCmd(c, "run", "-d", "--name", "test", "-v", "/data:/data:ro,z", "busybox", "cat") 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") 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.Name, checker.Equals, "")
c.Assert(m.Driver, checker.Equals, "") c.Assert(m.Driver, checker.Equals, "")
c.Assert(m.Source, checker.Equals, "/data") c.Assert(m.Source, checker.Equals, prefix+slash+"data")
c.Assert(m.Destination, checker.Equals, "/data") c.Assert(m.Destination, checker.Equals, prefix+slash+"data")
c.Assert(m.Mode, checker.Equals, "ro,z") c.Assert(m.Mode, checker.Equals, "ro"+modifier)
c.Assert(m.RW, checker.Equals, false) c.Assert(m.RW, checker.Equals, false)
} }

View File

@ -442,18 +442,20 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir2(c *check.C) {
} }
func (s *DockerSuite) TestRunVolumesMountedAsReadonly(c *check.C) { func (s *DockerSuite) TestRunVolumesMountedAsReadonly(c *check.C) {
// TODO Windows (Post TP5): This test cannot run on a Windows daemon as // TODO Windows: Temporary check - remove once TP5 support is dropped
// Windows does not support read-only bind mounts. if daemonPlatform == "windows" && windowsDaemonKV < 14350 {
testRequires(c, DaemonIsLinux) 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 { 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) c.Fatalf("run should fail because volume is ro: exit code %d", code)
} }
} }
func (s *DockerSuite) TestRunVolumesFromInReadonlyModeFails(c *check.C) { func (s *DockerSuite) TestRunVolumesFromInReadonlyModeFails(c *check.C) {
// TODO Windows (Post TP5): This test cannot run on a Windows daemon as // TODO Windows: Temporary check - remove once TP5 support is dropped
// Windows does not support read-only bind mounts. Modified for when ro is supported. if daemonPlatform == "windows" && windowsDaemonKV < 14350 {
testRequires(c, DaemonIsLinux) c.Skip("Needs later Windows build for RO volumes")
}
var ( var (
volumeDir string volumeDir string
fileInVol string fileInVol string
@ -498,20 +500,23 @@ func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) {
} }
func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) { func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
// TODO Windows: This test cannot yet run on a Windows daemon as Windows does prefix, slash := getPrefixAndSlashFromDaemonPlatform()
// not support read-only bind mounts as at TP5
testRequires(c, DaemonIsLinux) // TODO Windows: Temporary check - remove once TP5 support is dropped
dockerCmd(c, "run", "--name", "parent", "-v", "/test:/test:ro", "busybox", "true") 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" // 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`") 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" // 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`") 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) testRequires(c, DaemonIsLinux, NotUserNamespace)
} }
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
tmpDir, err := ioutil.TempDir("", "docker-test-container") tmpDir, err := ioutil.TempDir("", "docker-test-container")
if err != nil { if err != nil {
c.Fatal(err) c.Fatal(err)
@ -1922,10 +1929,10 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) {
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
writeFile(path.Join(tmpDir, "touch-me"), "", c) writeFile(path.Join(tmpDir, "touch-me"), "", c)
// TODO Windows Post TP5. Windows does not yet support :ro binds // TODO Windows: Temporary check - remove once TP5 support is dropped
if daemonPlatform != "windows" { if daemonPlatform != "windows" || windowsDaemonKV >= 14350 {
// Test reading from a read-only bind mount // 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") { if !strings.Contains(out, "touch-me") {
c.Fatal("Container failed to read from bind mount") 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 // https://github.com/docker/docker/pull/14498
func (s *DockerSuite) TestVolumeFromMixedRWOptions(c *check.C) { 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() prefix, slash := getPrefixAndSlashFromDaemonPlatform()
dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "true") 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:ro", "--name", "test-volumes-1", "busybox", "true")
} }
dockerCmd(c, "run", "--volumes-from", "parent:rw", "--name", "test-volumes-2", "busybox", "true") dockerCmd(c, "run", "--volumes-from", "parent:rw", "--name", "test-volumes-2", "busybox", "true")

View File

@ -8,6 +8,7 @@ import (
"strings" "strings"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/system"
) )
// read-write modes // read-write modes
@ -68,18 +69,24 @@ const (
// - Variation on hostdir but can be a drive followed by colon as well // - Variation on hostdir but can be a drive followed by colon as well
// - If a path, must be absolute. Can include spaces // - If a path, must be absolute. Can include spaces
// - Drive cannot be c: (explicitly checked in code, not RegEx) // - Drive cannot be c: (explicitly checked in code, not RegEx)
//
// RXMode is the regex expression for the mode of the mount
RXMode = `(:(?P<mode>(?i)rw))?`
// Temporarily for TP4, disabling the use of ro as it's not supported yet
// in the platform. TODO Windows: `(:(?P<mode>(?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<mode>(?i)ro|rw))?`
} else {
RXMode = `(:(?P<mode>(?i)rw))?`
}
}
// BackwardsCompatible decides whether this mount point can be // BackwardsCompatible decides whether this mount point can be
// used in old versions of Docker or not. // used in old versions of Docker or not.
// Windows volumes are never backwards compatible. // Windows volumes are never backwards compatible.