Browse code

Windows: Support RO volumes 14350+

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2016/05/26 05:56:36
Showing 3 changed files
... ...
@@ -3,6 +3,7 @@ package main
3 3
 import (
4 4
 	"encoding/json"
5 5
 	"fmt"
6
+	"os"
6 7
 	"os/exec"
7 8
 	"strconv"
8 9
 	"strings"
... ...
@@ -209,8 +210,19 @@ func (s *DockerSuite) TestInspectContainerGraphDriver(c *check.C) {
209 209
 }
210 210
 
211 211
 func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) {
212
-	testRequires(c, DaemonIsLinux)
213
-	dockerCmd(c, "run", "-d", "--name", "test", "-v", "/data:/data:ro,z", "busybox", "cat")
212
+	modifier := ",z"
213
+	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
214
+	if daemonPlatform == "windows" {
215
+		modifier = ""
216
+		// TODO Windows: Temporary check - remove once TP5 support is dropped
217
+		if windowsDaemonKV < 14350 {
218
+			c.Skip("Needs later Windows build for RO volumes")
219
+		}
220
+		// Linux creates the host directory if it doesn't exist. Windows does not.
221
+		os.Mkdir(`c:\data`, os.ModeDir)
222
+	}
223
+
224
+	dockerCmd(c, "run", "-d", "--name", "test", "-v", prefix+slash+"data:"+prefix+slash+"data:ro"+modifier, "busybox", "cat")
214 225
 
215 226
 	vol := inspectFieldJSON(c, "test", "Mounts")
216 227
 
... ...
@@ -225,9 +237,9 @@ func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) {
225 225
 
226 226
 	c.Assert(m.Name, checker.Equals, "")
227 227
 	c.Assert(m.Driver, checker.Equals, "")
228
-	c.Assert(m.Source, checker.Equals, "/data")
229
-	c.Assert(m.Destination, checker.Equals, "/data")
230
-	c.Assert(m.Mode, checker.Equals, "ro,z")
228
+	c.Assert(m.Source, checker.Equals, prefix+slash+"data")
229
+	c.Assert(m.Destination, checker.Equals, prefix+slash+"data")
230
+	c.Assert(m.Mode, checker.Equals, "ro"+modifier)
231 231
 	c.Assert(m.RW, checker.Equals, false)
232 232
 }
233 233
 
... ...
@@ -442,18 +442,20 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir2(c *check.C) {
442 442
 }
443 443
 
444 444
 func (s *DockerSuite) TestRunVolumesMountedAsReadonly(c *check.C) {
445
-	// TODO Windows (Post TP5): This test cannot run on a Windows daemon as
446
-	// Windows does not support read-only bind mounts.
447
-	testRequires(c, DaemonIsLinux)
445
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
446
+	if daemonPlatform == "windows" && windowsDaemonKV < 14350 {
447
+		c.Skip("Needs later Windows build for RO volumes")
448
+	}
448 449
 	if _, code, err := dockerCmdWithError("run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile"); err == nil || code == 0 {
449 450
 		c.Fatalf("run should fail because volume is ro: exit code %d", code)
450 451
 	}
451 452
 }
452 453
 
453 454
 func (s *DockerSuite) TestRunVolumesFromInReadonlyModeFails(c *check.C) {
454
-	// TODO Windows (Post TP5): This test cannot run on a Windows daemon as
455
-	// Windows does not support read-only bind mounts. Modified for when ro is supported.
456
-	testRequires(c, DaemonIsLinux)
455
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
456
+	if daemonPlatform == "windows" && windowsDaemonKV < 14350 {
457
+		c.Skip("Needs later Windows build for RO volumes")
458
+	}
457 459
 	var (
458 460
 		volumeDir string
459 461
 		fileInVol string
... ...
@@ -498,20 +500,23 @@ func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) {
498 498
 }
499 499
 
500 500
 func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
501
-	// TODO Windows: This test cannot yet run on a Windows daemon as Windows does
502
-	// not support read-only bind mounts as at TP5
503
-	testRequires(c, DaemonIsLinux)
504
-	dockerCmd(c, "run", "--name", "parent", "-v", "/test:/test:ro", "busybox", "true")
501
+	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
502
+
503
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
504
+	if daemonPlatform == "windows" && windowsDaemonKV < 14350 {
505
+		c.Skip("Needs later Windows build for RO volumes")
506
+	}
507
+	dockerCmd(c, "run", "--name", "parent", "-v", prefix+slash+"test:"+prefix+slash+"test:ro", "busybox", "true")
505 508
 
506 509
 	// Expect this "rw" mode to be be ignored since the inherited volume is "ro"
507
-	if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent:rw", "busybox", "touch", "/test/file"); err == nil {
510
+	if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent:rw", "busybox", "touch", prefix+slash+"test"+slash+"file"); err == nil {
508 511
 		c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `rw`")
509 512
 	}
510 513
 
511
-	dockerCmd(c, "run", "--name", "parent2", "-v", "/test:/test:ro", "busybox", "true")
514
+	dockerCmd(c, "run", "--name", "parent2", "-v", prefix+slash+"test:"+prefix+slash+"test:ro", "busybox", "true")
512 515
 
513 516
 	// Expect this to be read-only since both are "ro"
514
-	if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent2:ro", "busybox", "touch", "/test/file"); err == nil {
517
+	if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent2:ro", "busybox", "touch", prefix+slash+"test"+slash+"file"); err == nil {
515 518
 		c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `ro`")
516 519
 	}
517 520
 }
... ...
@@ -1914,6 +1919,8 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) {
1914 1914
 		testRequires(c, DaemonIsLinux, NotUserNamespace)
1915 1915
 	}
1916 1916
 
1917
+	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
1918
+
1917 1919
 	tmpDir, err := ioutil.TempDir("", "docker-test-container")
1918 1920
 	if err != nil {
1919 1921
 		c.Fatal(err)
... ...
@@ -1922,10 +1929,10 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) {
1922 1922
 	defer os.RemoveAll(tmpDir)
1923 1923
 	writeFile(path.Join(tmpDir, "touch-me"), "", c)
1924 1924
 
1925
-	// TODO Windows Post TP5. Windows does not yet support :ro binds
1926
-	if daemonPlatform != "windows" {
1925
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
1926
+	if daemonPlatform != "windows" || windowsDaemonKV >= 14350 {
1927 1927
 		// Test reading from a read-only bind mount
1928
-		out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox", "ls", "/tmp")
1928
+		out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:%s/tmp:ro", tmpDir, prefix), "busybox", "ls", prefix+"/tmp")
1929 1929
 		if !strings.Contains(out, "touch-me") {
1930 1930
 			c.Fatal("Container failed to read from bind mount")
1931 1931
 		}
... ...
@@ -3122,12 +3129,12 @@ func (s *DockerSuite) TestRunCapAddCHOWN(c *check.C) {
3122 3122
 
3123 3123
 // https://github.com/docker/docker/pull/14498
3124 3124
 func (s *DockerSuite) TestVolumeFromMixedRWOptions(c *check.C) {
3125
-	// TODO Windows post TP5. Enable the read-only bits once they are
3126
-	// supported on the platform.
3127 3125
 	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
3128 3126
 
3129 3127
 	dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "true")
3130
-	if daemonPlatform != "windows" {
3128
+
3129
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
3130
+	if daemonPlatform != "windows" || windowsDaemonKV >= 14350 {
3131 3131
 		dockerCmd(c, "run", "--volumes-from", "parent:ro", "--name", "test-volumes-1", "busybox", "true")
3132 3132
 	}
3133 3133
 	dockerCmd(c, "run", "--volumes-from", "parent:rw", "--name", "test-volumes-2", "busybox", "true")
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"strings"
9 9
 
10 10
 	"github.com/Sirupsen/logrus"
11
+	"github.com/docker/docker/pkg/system"
11 12
 )
12 13
 
13 14
 // read-write modes
... ...
@@ -68,17 +69,23 @@ const (
68 68
 	//    -  Variation on hostdir but can be a drive followed by colon as well
69 69
 	//    -  If a path, must be absolute. Can include spaces
70 70
 	//    -  Drive cannot be c: (explicitly checked in code, not RegEx)
71
-	//
71
+)
72 72
 
73
-	// RXMode is the regex expression for the mode of the mount
74
-	RXMode = `(:(?P<mode>(?i)rw))?`
75
-	// Temporarily for TP4, disabling the use of ro as it's not supported yet
76
-	// in the platform. TODO Windows: `(:(?P<mode>(?i)ro|rw))?`
77
-	// mode (optional)
78
-	//    -  Hopefully self explanatory in comparison to above.
73
+// RXMode is the regex expression for the mode of the mount
74
+var RXMode string
75
+
76
+func init() {
77
+	osv := system.GetOSVersion()
78
+	// Read-only volumes supported from 14350 onwards (post Windows Server 2016 TP5)
79
+	// Mode (optional):
80
+	//    -  Hopefully self explanatory in comparison to above regex's.
79 81
 	//    -  Colon is not in the capture group
80
-	//
81
-)
82
+	if osv.Build >= 14350 {
83
+		RXMode = `(:(?P<mode>(?i)ro|rw))?`
84
+	} else {
85
+		RXMode = `(:(?P<mode>(?i)rw))?`
86
+	}
87
+}
82 88
 
83 89
 // BackwardsCompatible decides whether this mount point can be
84 90
 // used in old versions of Docker or not.