Browse code

Merge pull request #23002 from Microsoft/jjh/readonly

Windows: Support RO volumes 14350+

Michael Crosby authored on 2016/06/09 03:18:48
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
 
... ...
@@ -443,18 +443,20 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir2(c *check.C) {
443 443
 }
444 444
 
445 445
 func (s *DockerSuite) TestRunVolumesMountedAsReadonly(c *check.C) {
446
-	// TODO Windows (Post TP5): This test cannot run on a Windows daemon as
447
-	// Windows does not support read-only bind mounts.
448
-	testRequires(c, DaemonIsLinux)
446
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
447
+	if daemonPlatform == "windows" && windowsDaemonKV < 14350 {
448
+		c.Skip("Needs later Windows build for RO volumes")
449
+	}
449 450
 	if _, code, err := dockerCmdWithError("run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile"); err == nil || code == 0 {
450 451
 		c.Fatalf("run should fail because volume is ro: exit code %d", code)
451 452
 	}
452 453
 }
453 454
 
454 455
 func (s *DockerSuite) TestRunVolumesFromInReadonlyModeFails(c *check.C) {
455
-	// TODO Windows (Post TP5): This test cannot run on a Windows daemon as
456
-	// Windows does not support read-only bind mounts. Modified for when ro is supported.
457
-	testRequires(c, DaemonIsLinux)
456
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
457
+	if daemonPlatform == "windows" && windowsDaemonKV < 14350 {
458
+		c.Skip("Needs later Windows build for RO volumes")
459
+	}
458 460
 	var (
459 461
 		volumeDir string
460 462
 		fileInVol string
... ...
@@ -499,20 +501,23 @@ func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) {
499 499
 }
500 500
 
501 501
 func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
502
-	// TODO Windows: This test cannot yet run on a Windows daemon as Windows does
503
-	// not support read-only bind mounts as at TP5
504
-	testRequires(c, DaemonIsLinux)
505
-	dockerCmd(c, "run", "--name", "parent", "-v", "/test:/test:ro", "busybox", "true")
502
+	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
503
+
504
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
505
+	if daemonPlatform == "windows" && windowsDaemonKV < 14350 {
506
+		c.Skip("Needs later Windows build for RO volumes")
507
+	}
508
+	dockerCmd(c, "run", "--name", "parent", "-v", prefix+slash+"test:"+prefix+slash+"test:ro", "busybox", "true")
506 509
 
507 510
 	// Expect this "rw" mode to be be ignored since the inherited volume is "ro"
508
-	if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent:rw", "busybox", "touch", "/test/file"); err == nil {
511
+	if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent:rw", "busybox", "touch", prefix+slash+"test"+slash+"file"); err == nil {
509 512
 		c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `rw`")
510 513
 	}
511 514
 
512
-	dockerCmd(c, "run", "--name", "parent2", "-v", "/test:/test:ro", "busybox", "true")
515
+	dockerCmd(c, "run", "--name", "parent2", "-v", prefix+slash+"test:"+prefix+slash+"test:ro", "busybox", "true")
513 516
 
514 517
 	// Expect this to be read-only since both are "ro"
515
-	if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent2:ro", "busybox", "touch", "/test/file"); err == nil {
518
+	if _, _, err := dockerCmdWithError("run", "--volumes-from", "parent2:ro", "busybox", "touch", prefix+slash+"test"+slash+"file"); err == nil {
516 519
 		c.Fatal("Expected volumes-from to inherit read-only volume even when passing in `ro`")
517 520
 	}
518 521
 }
... ...
@@ -1936,6 +1941,8 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) {
1936 1936
 		testRequires(c, DaemonIsLinux, NotUserNamespace)
1937 1937
 	}
1938 1938
 
1939
+	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
1940
+
1939 1941
 	tmpDir, err := ioutil.TempDir("", "docker-test-container")
1940 1942
 	if err != nil {
1941 1943
 		c.Fatal(err)
... ...
@@ -1944,10 +1951,10 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) {
1944 1944
 	defer os.RemoveAll(tmpDir)
1945 1945
 	writeFile(path.Join(tmpDir, "touch-me"), "", c)
1946 1946
 
1947
-	// TODO Windows Post TP5. Windows does not yet support :ro binds
1948
-	if daemonPlatform != "windows" {
1947
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
1948
+	if daemonPlatform != "windows" || windowsDaemonKV >= 14350 {
1949 1949
 		// Test reading from a read-only bind mount
1950
-		out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox", "ls", "/tmp")
1950
+		out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:%s/tmp:ro", tmpDir, prefix), "busybox", "ls", prefix+"/tmp")
1951 1951
 		if !strings.Contains(out, "touch-me") {
1952 1952
 			c.Fatal("Container failed to read from bind mount")
1953 1953
 		}
... ...
@@ -3147,12 +3154,12 @@ func (s *DockerSuite) TestRunCapAddCHOWN(c *check.C) {
3147 3147
 
3148 3148
 // https://github.com/docker/docker/pull/14498
3149 3149
 func (s *DockerSuite) TestVolumeFromMixedRWOptions(c *check.C) {
3150
-	// TODO Windows post TP5. Enable the read-only bits once they are
3151
-	// supported on the platform.
3152 3150
 	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
3153 3151
 
3154 3152
 	dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "true")
3155
-	if daemonPlatform != "windows" {
3153
+
3154
+	// TODO Windows: Temporary check - remove once TP5 support is dropped
3155
+	if daemonPlatform != "windows" || windowsDaemonKV >= 14350 {
3156 3156
 		dockerCmd(c, "run", "--volumes-from", "parent:ro", "--name", "test-volumes-1", "busybox", "true")
3157 3157
 	}
3158 3158
 	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.