Signed-off-by: John Howard <jhoward@microsoft.com>
| ... | ... |
@@ -595,7 +595,7 @@ func rewriteDockerfileFrom(dockerfileName string, translator func(string, regist |
| 595 | 595 |
|
| 596 | 596 |
repoInfo, err := registry.ParseRepositoryInfo(repo) |
| 597 | 597 |
if err != nil {
|
| 598 |
- return nil, nil, fmt.Errorf("unable to parse repository info: %v", err)
|
|
| 598 |
+ return nil, nil, fmt.Errorf("unable to parse repository info %q: %v", repo, err)
|
|
| 599 | 599 |
} |
| 600 | 600 |
|
| 601 | 601 |
ref := registry.ParseReference(tag) |
| ... | ... |
@@ -3,7 +3,7 @@ package main |
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 | 5 |
"net/http" |
| 6 |
- "path" |
|
| 6 |
+ "path/filepath" |
|
| 7 | 7 |
|
| 8 | 8 |
"github.com/docker/docker/api/types" |
| 9 | 9 |
"github.com/docker/docker/pkg/integration/checker" |
| ... | ... |
@@ -11,8 +11,12 @@ import ( |
| 11 | 11 |
) |
| 12 | 12 |
|
| 13 | 13 |
func (s *DockerSuite) TestVolumesApiList(c *check.C) {
|
| 14 |
- testRequires(c, DaemonIsLinux) |
|
| 15 |
- dockerCmd(c, "run", "-d", "-v", "/foo", "busybox") |
|
| 14 |
+ prefix := "" |
|
| 15 |
+ if daemonPlatform == "windows" {
|
|
| 16 |
+ prefix = "c:" |
|
| 17 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 18 |
+ } |
|
| 19 |
+ dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "busybox") |
|
| 16 | 20 |
|
| 17 | 21 |
status, b, err := sockRequest("GET", "/volumes", nil)
|
| 18 | 22 |
c.Assert(err, checker.IsNil) |
| ... | ... |
@@ -25,7 +29,9 @@ func (s *DockerSuite) TestVolumesApiList(c *check.C) {
|
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 | 27 |
func (s *DockerSuite) TestVolumesApiCreate(c *check.C) {
|
| 28 |
- testRequires(c, DaemonIsLinux) |
|
| 28 |
+ if daemonPlatform == "windows" {
|
|
| 29 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 30 |
+ } |
|
| 29 | 31 |
config := types.VolumeCreateRequest{
|
| 30 | 32 |
Name: "test", |
| 31 | 33 |
} |
| ... | ... |
@@ -37,12 +43,16 @@ func (s *DockerSuite) TestVolumesApiCreate(c *check.C) {
|
| 37 | 37 |
err = json.Unmarshal(b, &vol) |
| 38 | 38 |
c.Assert(err, checker.IsNil) |
| 39 | 39 |
|
| 40 |
- c.Assert(path.Base(path.Dir(vol.Mountpoint)), checker.Equals, config.Name) |
|
| 40 |
+ c.Assert(filepath.Base(filepath.Dir(vol.Mountpoint)), checker.Equals, config.Name) |
|
| 41 | 41 |
} |
| 42 | 42 |
|
| 43 | 43 |
func (s *DockerSuite) TestVolumesApiRemove(c *check.C) {
|
| 44 |
- testRequires(c, DaemonIsLinux) |
|
| 45 |
- dockerCmd(c, "run", "-d", "-v", "/foo", "--name=test", "busybox") |
|
| 44 |
+ prefix := "" |
|
| 45 |
+ if daemonPlatform == "windows" {
|
|
| 46 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 47 |
+ prefix = "c:" |
|
| 48 |
+ } |
|
| 49 |
+ dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "--name=test", "busybox") |
|
| 46 | 50 |
|
| 47 | 51 |
status, b, err := sockRequest("GET", "/volumes", nil)
|
| 48 | 52 |
c.Assert(err, checker.IsNil) |
| ... | ... |
@@ -65,7 +75,9 @@ func (s *DockerSuite) TestVolumesApiRemove(c *check.C) {
|
| 65 | 65 |
} |
| 66 | 66 |
|
| 67 | 67 |
func (s *DockerSuite) TestVolumesApiInspect(c *check.C) {
|
| 68 |
- testRequires(c, DaemonIsLinux) |
|
| 68 |
+ if daemonPlatform == "windows" {
|
|
| 69 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 70 |
+ } |
|
| 69 | 71 |
config := types.VolumeCreateRequest{
|
| 70 | 72 |
Name: "test", |
| 71 | 73 |
} |
| ... | ... |
@@ -425,7 +425,7 @@ func (s *DockerSuite) TestLinksPingLinkedContainersOnRename(c *check.C) {
|
| 425 | 425 |
} |
| 426 | 426 |
|
| 427 | 427 |
func (s *DockerSuite) TestRunExecDir(c *check.C) {
|
| 428 |
- testRequires(c, SameHostDaemon) |
|
| 428 |
+ testRequires(c, SameHostDaemon, DaemonIsLinux) |
|
| 429 | 429 |
|
| 430 | 430 |
out, _ := dockerCmd(c, "run", "-d", "busybox", "top") |
| 431 | 431 |
id := strings.TrimSpace(out) |
| ... | ... |
@@ -489,8 +489,7 @@ func (s *DockerSuite) TestRunExecDir(c *check.C) {
|
| 489 | 489 |
} |
| 490 | 490 |
|
| 491 | 491 |
func (s *DockerSuite) TestRunMutableNetworkFiles(c *check.C) {
|
| 492 |
- testRequires(c, SameHostDaemon) |
|
| 493 |
- |
|
| 492 |
+ testRequires(c, SameHostDaemon, DaemonIsLinux) |
|
| 494 | 493 |
for _, fn := range []string{"resolv.conf", "hosts"} {
|
| 495 | 494 |
deleteAllContainers() |
| 496 | 495 |
|
| ... | ... |
@@ -223,15 +223,29 @@ func (s *DockerSuite) TestRunWithDaemonFlags(c *check.C) {
|
| 223 | 223 |
|
| 224 | 224 |
// Regression test for #4979 |
| 225 | 225 |
func (s *DockerSuite) TestRunWithVolumesFromExited(c *check.C) {
|
| 226 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 227 |
- // not support volumes |
|
| 228 |
- testRequires(c, DaemonIsLinux) |
|
| 229 |
- out, exitCode := dockerCmd(c, "run", "--name", "test-data", "--volume", "/some/dir", "busybox", "touch", "/some/dir/file") |
|
| 226 |
+ |
|
| 227 |
+ var ( |
|
| 228 |
+ out string |
|
| 229 |
+ exitCode int |
|
| 230 |
+ ) |
|
| 231 |
+ |
|
| 232 |
+ // Create a file in a volume |
|
| 233 |
+ if daemonPlatform == "windows" {
|
|
| 234 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 235 |
+ out, exitCode = dockerCmd(c, "run", "--name", "test-data", "--volume", `c:\some\dir`, WindowsBaseImage, `cmd /c echo hello > c:\some\dir\file`) |
|
| 236 |
+ } else {
|
|
| 237 |
+ out, exitCode = dockerCmd(c, "run", "--name", "test-data", "--volume", "/some/dir", "busybox", "touch", "/some/dir/file") |
|
| 238 |
+ } |
|
| 230 | 239 |
if exitCode != 0 {
|
| 231 | 240 |
c.Fatal("1", out, exitCode)
|
| 232 | 241 |
} |
| 233 | 242 |
|
| 234 |
- out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", "busybox", "cat", "/some/dir/file") |
|
| 243 |
+ // Read the file from another container using --volumes-from to access the volume in the second container |
|
| 244 |
+ if daemonPlatform == "windows" {
|
|
| 245 |
+ out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", WindowsBaseImage, `cmd /c type c:\some\dir\file`) |
|
| 246 |
+ } else {
|
|
| 247 |
+ out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", "busybox", "cat", "/some/dir/file") |
|
| 248 |
+ } |
|
| 235 | 249 |
if exitCode != 0 {
|
| 236 | 250 |
c.Fatal("2", out, exitCode)
|
| 237 | 251 |
} |
| ... | ... |
@@ -240,9 +254,17 @@ func (s *DockerSuite) TestRunWithVolumesFromExited(c *check.C) {
|
| 240 | 240 |
// Volume path is a symlink which also exists on the host, and the host side is a file not a dir |
| 241 | 241 |
// But the volume call is just a normal volume, not a bind mount |
| 242 | 242 |
func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir(c *check.C) {
|
| 243 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 244 |
- // not support volumes |
|
| 245 |
- testRequires(c, DaemonIsLinux, SameHostDaemon, NativeExecDriver) |
|
| 243 |
+ var ( |
|
| 244 |
+ dockerFile string |
|
| 245 |
+ containerPath string |
|
| 246 |
+ cmd string |
|
| 247 |
+ ) |
|
| 248 |
+ if daemonPlatform == "windows" {
|
|
| 249 |
+ testRequires(c, SameHostDaemon, WindowsDaemonSupportsVolumes) |
|
| 250 |
+ } else {
|
|
| 251 |
+ testRequires(c, SameHostDaemon, NativeExecDriver) |
|
| 252 |
+ } |
|
| 253 |
+ |
|
| 246 | 254 |
name := "test-volume-symlink" |
| 247 | 255 |
|
| 248 | 256 |
dir, err := ioutil.TempDir("", name)
|
| ... | ... |
@@ -257,52 +279,84 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir(c *check.C) {
|
| 257 | 257 |
} |
| 258 | 258 |
f.Close() |
| 259 | 259 |
|
| 260 |
- dockerFile := fmt.Sprintf("FROM busybox\nRUN mkdir -p %s\nRUN ln -s %s /test", dir, dir)
|
|
| 260 |
+ if daemonPlatform == "windows" {
|
|
| 261 |
+ dockerFile = fmt.Sprintf("FROM %s\nRUN mkdir %s\nRUN mklink /D c:\\test %s", WindowsBaseImage, dir, dir)
|
|
| 262 |
+ containerPath = `c:\test\test` |
|
| 263 |
+ cmd = "tasklist" |
|
| 264 |
+ } else {
|
|
| 265 |
+ dockerFile = fmt.Sprintf("FROM busybox\nRUN mkdir -p %s\nRUN ln -s %s /test", dir, dir)
|
|
| 266 |
+ containerPath = "/test/test" |
|
| 267 |
+ cmd = "true" |
|
| 268 |
+ } |
|
| 261 | 269 |
if _, err := buildImage(name, dockerFile, false); err != nil {
|
| 262 | 270 |
c.Fatal(err) |
| 263 | 271 |
} |
| 264 | 272 |
|
| 265 |
- dockerCmd(c, "run", "-v", "/test/test", name) |
|
| 273 |
+ dockerCmd(c, "run", "-v", containerPath, name, cmd) |
|
| 266 | 274 |
} |
| 267 | 275 |
|
| 268 | 276 |
func (s *DockerSuite) TestRunVolumesMountedAsReadonly(c *check.C) {
|
| 269 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 270 |
- // not support volumes |
|
| 277 |
+ // TODO Windows (Post TP4): This test cannot run on a Windows daemon as |
|
| 278 |
+ // Windows does not support read-only bind mounts. |
|
| 271 | 279 |
testRequires(c, DaemonIsLinux) |
| 272 | 280 |
if _, code, err := dockerCmdWithError("run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile"); err == nil || code == 0 {
|
| 273 | 281 |
c.Fatalf("run should fail because volume is ro: exit code %d", code)
|
| 274 | 282 |
} |
| 275 | 283 |
} |
| 276 | 284 |
|
| 277 |
-func (s *DockerSuite) TestRunVolumesFromInReadonlyMode(c *check.C) {
|
|
| 278 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 279 |
- // not support volumes |
|
| 285 |
+func (s *DockerSuite) TestRunVolumesFromInReadonlyModeFails(c *check.C) {
|
|
| 286 |
+ // TODO Windows (Post TP4): This test cannot run on a Windows daemon as |
|
| 287 |
+ // Windows does not support read-only bind mounts. Modified for when ro is supported. |
|
| 280 | 288 |
testRequires(c, DaemonIsLinux) |
| 281 |
- dockerCmd(c, "run", "--name", "parent", "-v", "/test", "busybox", "true") |
|
| 289 |
+ var ( |
|
| 290 |
+ volumeDir string |
|
| 291 |
+ fileInVol string |
|
| 292 |
+ ) |
|
| 293 |
+ if daemonPlatform == "windows" {
|
|
| 294 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 295 |
+ volumeDir = `c:/test` // Forward-slash as using busybox |
|
| 296 |
+ fileInVol = `c:/test/file` |
|
| 297 |
+ } else {
|
|
| 298 |
+ testRequires(c, DaemonIsLinux) |
|
| 299 |
+ volumeDir = "/test" |
|
| 300 |
+ fileInVol = `/test/file` |
|
| 301 |
+ } |
|
| 302 |
+ dockerCmd(c, "run", "--name", "parent", "-v", volumeDir, "busybox", "true") |
|
| 282 | 303 |
|
| 283 |
- if _, code, err := dockerCmdWithError("run", "--volumes-from", "parent:ro", "busybox", "touch", "/test/file"); err == nil || code == 0 {
|
|
| 304 |
+ if _, code, err := dockerCmdWithError("run", "--volumes-from", "parent:ro", "busybox", "touch", fileInVol); err == nil || code == 0 {
|
|
| 284 | 305 |
c.Fatalf("run should fail because volume is ro: exit code %d", code)
|
| 285 | 306 |
} |
| 286 | 307 |
} |
| 287 | 308 |
|
| 288 | 309 |
// Regression test for #1201 |
| 289 | 310 |
func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) {
|
| 290 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 291 |
- // not support volumes |
|
| 292 |
- testRequires(c, DaemonIsLinux) |
|
| 293 |
- dockerCmd(c, "run", "--name", "parent", "-v", "/test", "busybox", "true") |
|
| 294 |
- dockerCmd(c, "run", "--volumes-from", "parent:rw", "busybox", "touch", "/test/file") |
|
| 311 |
+ var ( |
|
| 312 |
+ volumeDir string |
|
| 313 |
+ fileInVol string |
|
| 314 |
+ ) |
|
| 315 |
+ if daemonPlatform == "windows" {
|
|
| 316 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 317 |
+ volumeDir = `c:/test` // Forward-slash as using busybox |
|
| 318 |
+ fileInVol = `c:/test/file` |
|
| 319 |
+ } else {
|
|
| 320 |
+ testRequires(c, DaemonIsLinux) |
|
| 321 |
+ volumeDir = "/test" |
|
| 322 |
+ fileInVol = "/test/file" |
|
| 323 |
+ } |
|
| 324 |
+ |
|
| 325 |
+ dockerCmd(c, "run", "--name", "parent", "-v", volumeDir, "busybox", "true") |
|
| 326 |
+ dockerCmd(c, "run", "--volumes-from", "parent:rw", "busybox", "touch", fileInVol) |
|
| 295 | 327 |
|
| 296 |
- if out, _, err := dockerCmdWithError("run", "--volumes-from", "parent:bar", "busybox", "touch", "/test/file"); err == nil || !strings.Contains(out, "invalid mode: bar") {
|
|
| 297 |
- c.Fatalf("running --volumes-from foo:bar should have failed with invalid mode: %q", out)
|
|
| 328 |
+ if out, _, err := dockerCmdWithError("run", "--volumes-from", "parent:bar", "busybox", "touch", fileInVol); err == nil || !strings.Contains(out, "invalid mode: bar") {
|
|
| 329 |
+ c.Fatalf("running --volumes-from parent:bar should have failed with invalid mount mode: %q", out)
|
|
| 298 | 330 |
} |
| 299 | 331 |
|
| 300 |
- dockerCmd(c, "run", "--volumes-from", "parent", "busybox", "touch", "/test/file") |
|
| 332 |
+ dockerCmd(c, "run", "--volumes-from", "parent", "busybox", "touch", fileInVol) |
|
| 301 | 333 |
} |
| 302 | 334 |
|
| 303 | 335 |
func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
|
| 304 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 305 |
- // not support volumes |
|
| 336 |
+ // TODO Windows: This test cannot yet run on a Windows daemon as Windows does |
|
| 337 |
+ // not support read-only bind mounts as at TP4 |
|
| 306 | 338 |
testRequires(c, DaemonIsLinux) |
| 307 | 339 |
dockerCmd(c, "run", "--name", "parent", "-v", "/test:/test:ro", "busybox", "true") |
| 308 | 340 |
|
| ... | ... |
@@ -321,36 +375,54 @@ func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
|
| 321 | 321 |
|
| 322 | 322 |
// Test for GH#10618 |
| 323 | 323 |
func (s *DockerSuite) TestRunNoDupVolumes(c *check.C) {
|
| 324 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 325 |
- // not support volumes |
|
| 326 |
- testRequires(c, DaemonIsLinux) |
|
| 327 |
- mountstr1 := randomTmpDirPath("test1", daemonPlatform) + ":/someplace"
|
|
| 328 |
- mountstr2 := randomTmpDirPath("test2", daemonPlatform) + ":/someplace"
|
|
| 324 |
+ path1 := randomTmpDirPath("test1", daemonPlatform)
|
|
| 325 |
+ path2 := randomTmpDirPath("test2", daemonPlatform)
|
|
| 326 |
+ |
|
| 327 |
+ someplace := ":/someplace" |
|
| 328 |
+ if daemonPlatform == "windows" {
|
|
| 329 |
+ // Windows requires that the source directory exists before calling HCS |
|
| 330 |
+ testRequires(c, SameHostDaemon, WindowsDaemonSupportsVolumes) |
|
| 331 |
+ someplace = `:c:\someplace` |
|
| 332 |
+ if err := os.MkdirAll(path1, 0755); err != nil {
|
|
| 333 |
+ c.Fatalf("Failed to create %s: %q", path1, err)
|
|
| 334 |
+ } |
|
| 335 |
+ defer os.RemoveAll(path1) |
|
| 336 |
+ if err := os.MkdirAll(path2, 0755); err != nil {
|
|
| 337 |
+ c.Fatalf("Failed to create %s: %q", path1, err)
|
|
| 338 |
+ } |
|
| 339 |
+ defer os.RemoveAll(path2) |
|
| 340 |
+ } |
|
| 341 |
+ mountstr1 := path1 + someplace |
|
| 342 |
+ mountstr2 := path2 + someplace |
|
| 329 | 343 |
|
| 330 | 344 |
if out, _, err := dockerCmdWithError("run", "-v", mountstr1, "-v", mountstr2, "busybox", "true"); err == nil {
|
| 331 | 345 |
c.Fatal("Expected error about duplicate volume definitions")
|
| 332 | 346 |
} else {
|
| 333 | 347 |
if !strings.Contains(out, "Duplicate bind mount") {
|
| 334 |
- c.Fatalf("Expected 'duplicate volume' error, got %v", err)
|
|
| 348 |
+ c.Fatalf("Expected 'duplicate volume' error, got %v", out)
|
|
| 335 | 349 |
} |
| 336 | 350 |
} |
| 337 | 351 |
} |
| 338 | 352 |
|
| 339 | 353 |
// Test for #1351 |
| 340 | 354 |
func (s *DockerSuite) TestRunApplyVolumesFromBeforeVolumes(c *check.C) {
|
| 341 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 342 |
- // not support volumes |
|
| 343 |
- testRequires(c, DaemonIsLinux) |
|
| 344 |
- dockerCmd(c, "run", "--name", "parent", "-v", "/test", "busybox", "touch", "/test/foo") |
|
| 345 |
- dockerCmd(c, "run", "--volumes-from", "parent", "-v", "/test", "busybox", "cat", "/test/foo") |
|
| 355 |
+ prefix := "" |
|
| 356 |
+ if daemonPlatform == "windows" {
|
|
| 357 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 358 |
+ prefix = `c:` |
|
| 359 |
+ } |
|
| 360 |
+ dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "touch", prefix+"/test/foo") |
|
| 361 |
+ dockerCmd(c, "run", "--volumes-from", "parent", "-v", prefix+"/test", "busybox", "cat", prefix+"/test/foo") |
|
| 346 | 362 |
} |
| 347 | 363 |
|
| 348 | 364 |
func (s *DockerSuite) TestRunMultipleVolumesFrom(c *check.C) {
|
| 349 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 350 |
- // not support volumes |
|
| 351 |
- testRequires(c, DaemonIsLinux) |
|
| 352 |
- dockerCmd(c, "run", "--name", "parent1", "-v", "/test", "busybox", "touch", "/test/foo") |
|
| 353 |
- dockerCmd(c, "run", "--name", "parent2", "-v", "/other", "busybox", "touch", "/other/bar") |
|
| 365 |
+ prefix := "" |
|
| 366 |
+ if daemonPlatform == "windows" {
|
|
| 367 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 368 |
+ prefix = `c:` |
|
| 369 |
+ } |
|
| 370 |
+ dockerCmd(c, "run", "--name", "parent1", "-v", prefix+"/test", "busybox", "touch", prefix+"/test/foo") |
|
| 371 |
+ dockerCmd(c, "run", "--name", "parent2", "-v", prefix+"/other", "busybox", "touch", prefix+"/other/bar") |
|
| 354 | 372 |
dockerCmd(c, "run", "--volumes-from", "parent1", "--volumes-from", "parent2", "busybox", "sh", "-c", "cat /test/foo && cat /other/bar") |
| 355 | 373 |
} |
| 356 | 374 |
|
| ... | ... |
@@ -375,17 +447,18 @@ func (s *DockerSuite) TestRunVerifyContainerID(c *check.C) {
|
| 375 | 375 |
|
| 376 | 376 |
// Test that creating a container with a volume doesn't crash. Regression test for #995. |
| 377 | 377 |
func (s *DockerSuite) TestRunCreateVolume(c *check.C) {
|
| 378 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 379 |
- // not support volumes |
|
| 380 |
- testRequires(c, DaemonIsLinux) |
|
| 381 |
- dockerCmd(c, "run", "-v", "/var/lib/data", "busybox", "true") |
|
| 378 |
+ prefix := "" |
|
| 379 |
+ if daemonPlatform == "windows" {
|
|
| 380 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 381 |
+ prefix = `c:` |
|
| 382 |
+ } |
|
| 383 |
+ dockerCmd(c, "run", "-v", prefix+"/var/lib/data", "busybox", "true") |
|
| 382 | 384 |
} |
| 383 | 385 |
|
| 384 | 386 |
// Test that creating a volume with a symlink in its path works correctly. Test for #5152. |
| 385 | 387 |
// Note that this bug happens only with symlinks with a target that starts with '/'. |
| 386 | 388 |
func (s *DockerSuite) TestRunCreateVolumeWithSymlink(c *check.C) {
|
| 387 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 388 |
- // not support volumes |
|
| 389 |
+ // Cannot run on Windows as relies on Linux-specific functionality (sh -c mount...) |
|
| 389 | 390 |
testRequires(c, DaemonIsLinux) |
| 390 | 391 |
image := "docker-test-createvolumewithsymlink" |
| 391 | 392 |
|
| ... | ... |
@@ -421,27 +494,39 @@ func (s *DockerSuite) TestRunCreateVolumeWithSymlink(c *check.C) {
|
| 421 | 421 |
|
| 422 | 422 |
// Tests that a volume path that has a symlink exists in a container mounting it with `--volumes-from`. |
| 423 | 423 |
func (s *DockerSuite) TestRunVolumesFromSymlinkPath(c *check.C) {
|
| 424 |
- // TODO Windows: This test cannot run on a Windows daemon as Windows does |
|
| 425 |
- // not support volumes |
|
| 426 |
- testRequires(c, DaemonIsLinux) |
|
| 424 |
+ if daemonPlatform == "windows" {
|
|
| 425 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 426 |
+ } |
|
| 427 |
+ |
|
| 427 | 428 |
name := "docker-test-volumesfromsymlinkpath" |
| 429 |
+ prefix := "" |
|
| 430 |
+ dfContents := `FROM busybox |
|
| 431 |
+ RUN ln -s home /foo |
|
| 432 |
+ VOLUME ["/foo/bar"]` |
|
| 433 |
+ |
|
| 434 |
+ if daemonPlatform == "windows" {
|
|
| 435 |
+ prefix = `c:` |
|
| 436 |
+ dfContents = `FROM ` + WindowsBaseImage + ` |
|
| 437 |
+ RUN mkdir c:\home |
|
| 438 |
+ RUN mklink /D c:\foo c:\home |
|
| 439 |
+ VOLUME ["c:/foo/bar"] |
|
| 440 |
+ ENTRYPOINT c:\windows\system32\cmd.exe` |
|
| 441 |
+ } |
|
| 428 | 442 |
|
| 429 | 443 |
buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-") |
| 430 |
- buildCmd.Stdin = strings.NewReader(`FROM busybox |
|
| 431 |
- RUN ln -s home /foo |
|
| 432 |
- VOLUME ["/foo/bar"]`) |
|
| 444 |
+ buildCmd.Stdin = strings.NewReader(dfContents) |
|
| 433 | 445 |
buildCmd.Dir = workingDirectory |
| 434 | 446 |
err := buildCmd.Run() |
| 435 | 447 |
if err != nil {
|
| 436 | 448 |
c.Fatalf("could not build 'docker-test-volumesfromsymlinkpath': %v", err)
|
| 437 | 449 |
} |
| 438 | 450 |
|
| 439 |
- _, exitCode, err := dockerCmdWithError("run", "--name", "test-volumesfromsymlinkpath", name)
|
|
| 451 |
+ out, exitCode, err := dockerCmdWithError("run", "--name", "test-volumesfromsymlinkpath", name)
|
|
| 440 | 452 |
if err != nil || exitCode != 0 {
|
| 441 |
- c.Fatalf("[run] (volume) err: %v, exitcode: %d", err, exitCode)
|
|
| 453 |
+ c.Fatalf("[run] (volume) err: %v, exitcode: %d, out: %s", err, exitCode, out)
|
|
| 442 | 454 |
} |
| 443 | 455 |
|
| 444 |
- _, exitCode, err = dockerCmdWithError("run", "--volumes-from", "test-volumesfromsymlinkpath", "busybox", "sh", "-c", "ls /foo | grep -q bar")
|
|
| 456 |
+ _, exitCode, err = dockerCmdWithError("run", "--volumes-from", "test-volumesfromsymlinkpath", "busybox", "sh", "-c", "ls "+prefix+"/foo | grep -q bar")
|
|
| 445 | 457 |
if err != nil || exitCode != 0 {
|
| 446 | 458 |
c.Fatalf("[run] err: %v, exitcode: %d", err, exitCode)
|
| 447 | 459 |
} |
| ... | ... |
@@ -544,6 +629,15 @@ func (s *DockerSuite) TestRunUserNotFound(c *check.C) {
|
| 544 | 544 |
} |
| 545 | 545 |
|
| 546 | 546 |
func (s *DockerSuite) TestRunTwoConcurrentContainers(c *check.C) {
|
| 547 |
+ // TODO Windows. There are two bugs in TP4 which means this test cannot |
|
| 548 |
+ // be reliably enabled. The first is a race condition where sometimes |
|
| 549 |
+ // HCS CreateComputeSystem() will fail "Invalid class string". #4985252 and |
|
| 550 |
+ // #4493430. |
|
| 551 |
+ // |
|
| 552 |
+ // The second, which is seen more readily by increasing the number of concurrent |
|
| 553 |
+ // containers to 5 or more, is that CSRSS hangs. This may fixed in the TP4 ZDP. |
|
| 554 |
+ // #4898773. |
|
| 555 |
+ testRequires(c, DaemonIsLinux) |
|
| 547 | 556 |
sleepTime := "2" |
| 548 | 557 |
if daemonPlatform == "windows" {
|
| 549 | 558 |
sleepTime = "5" // Make more reliable on Windows |
| ... | ... |
@@ -1005,14 +1099,24 @@ func (s *DockerSuite) TestRunRootWorkdir(c *check.C) {
|
| 1005 | 1005 |
} |
| 1006 | 1006 |
|
| 1007 | 1007 |
func (s *DockerSuite) TestRunAllowBindMountingRoot(c *check.C) {
|
| 1008 |
- testRequires(c, DaemonIsLinux) |
|
| 1009 |
- dockerCmd(c, "run", "-v", "/:/host", "busybox", "ls", "/host") |
|
| 1008 |
+ if daemonPlatform == "windows" {
|
|
| 1009 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 1010 |
+ // Windows busybox will fail with Permission Denied on items such as pagefile.sys |
|
| 1011 |
+ dockerCmd(c, "run", "-v", `c:\:c:\host`, WindowsBaseImage, "cmd", "-c", "dir", `c:\host`) |
|
| 1012 |
+ } else {
|
|
| 1013 |
+ dockerCmd(c, "run", "-v", "/:/host", "busybox", "ls", "/host") |
|
| 1014 |
+ } |
|
| 1010 | 1015 |
} |
| 1011 | 1016 |
|
| 1012 | 1017 |
func (s *DockerSuite) TestRunDisallowBindMountingRootToRoot(c *check.C) {
|
| 1013 |
- // Not applicable on Windows as Windows does not support volumes |
|
| 1014 |
- testRequires(c, DaemonIsLinux) |
|
| 1015 |
- out, _, err := dockerCmdWithError("run", "-v", "/:/", "busybox", "ls", "/host")
|
|
| 1018 |
+ mount := "/:/" |
|
| 1019 |
+ targetDir := "/host" |
|
| 1020 |
+ if daemonPlatform == "windows" {
|
|
| 1021 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 1022 |
+ mount = `c:\:c\` |
|
| 1023 |
+ targetDir = "c:/host" // Forward slash as using busybox |
|
| 1024 |
+ } |
|
| 1025 |
+ out, _, err := dockerCmdWithError("run", "-v", mount, "busybox", "ls", targetDir)
|
|
| 1016 | 1026 |
if err == nil {
|
| 1017 | 1027 |
c.Fatal(out, err) |
| 1018 | 1028 |
} |
| ... | ... |
@@ -1466,7 +1570,7 @@ func (s *DockerSuite) TestRunState(c *check.C) {
|
| 1466 | 1466 |
|
| 1467 | 1467 |
// Test for #1737 |
| 1468 | 1468 |
func (s *DockerSuite) TestRunCopyVolumeUidGid(c *check.C) {
|
| 1469 |
- // Not applicable on Windows as it does not support volumes, uid or gid |
|
| 1469 |
+ // Not applicable on Windows as it does not support uid or gid in this way |
|
| 1470 | 1470 |
testRequires(c, DaemonIsLinux) |
| 1471 | 1471 |
name := "testrunvolumesuidgid" |
| 1472 | 1472 |
_, err := buildImage(name, |
| ... | ... |
@@ -1489,7 +1593,8 @@ func (s *DockerSuite) TestRunCopyVolumeUidGid(c *check.C) {
|
| 1489 | 1489 |
|
| 1490 | 1490 |
// Test for #1582 |
| 1491 | 1491 |
func (s *DockerSuite) TestRunCopyVolumeContent(c *check.C) {
|
| 1492 |
- // Not applicable on Windows as it does not support volumes |
|
| 1492 |
+ // TODO Windows, post TP4. Windows does not yet support volume functionality |
|
| 1493 |
+ // that copies from the image to the volume. |
|
| 1493 | 1494 |
testRequires(c, DaemonIsLinux) |
| 1494 | 1495 |
name := "testruncopyvolumecontent" |
| 1495 | 1496 |
_, err := buildImage(name, |
| ... | ... |
@@ -1712,10 +1817,12 @@ func (s *DockerSuite) TestRunEntrypoint(c *check.C) {
|
| 1712 | 1712 |
} |
| 1713 | 1713 |
|
| 1714 | 1714 |
func (s *DockerSuite) TestRunBindMounts(c *check.C) {
|
| 1715 |
- // /tmp gets permission denied |
|
| 1716 |
- testRequires(c, NotUserNamespace) |
|
| 1717 |
- // Cannot run on Windows as Windows does not support volumes |
|
| 1718 |
- testRequires(c, DaemonIsLinux, SameHostDaemon) |
|
| 1715 |
+ testRequires(c, SameHostDaemon) |
|
| 1716 |
+ if daemonPlatform == "windows" {
|
|
| 1717 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 1718 |
+ } else {
|
|
| 1719 |
+ testRequires(c, DaemonIsLinux, NotUserNamespace) |
|
| 1720 |
+ } |
|
| 1719 | 1721 |
|
| 1720 | 1722 |
tmpDir, err := ioutil.TempDir("", "docker-test-container")
|
| 1721 | 1723 |
if err != nil {
|
| ... | ... |
@@ -1725,14 +1832,21 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) {
|
| 1725 | 1725 |
defer os.RemoveAll(tmpDir) |
| 1726 | 1726 |
writeFile(path.Join(tmpDir, "touch-me"), "", c) |
| 1727 | 1727 |
|
| 1728 |
- // Test reading from a read-only bind mount |
|
| 1729 |
- out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox", "ls", "/tmp")
|
|
| 1730 |
- if !strings.Contains(out, "touch-me") {
|
|
| 1731 |
- c.Fatal("Container failed to read from bind mount")
|
|
| 1728 |
+ // TODO Windows Post TP4. Windows does not yet support :ro binds |
|
| 1729 |
+ if daemonPlatform != "windows" {
|
|
| 1730 |
+ // Test reading from a read-only bind mount |
|
| 1731 |
+ out, _ := dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox", "ls", "/tmp")
|
|
| 1732 |
+ if !strings.Contains(out, "touch-me") {
|
|
| 1733 |
+ c.Fatal("Container failed to read from bind mount")
|
|
| 1734 |
+ } |
|
| 1732 | 1735 |
} |
| 1733 | 1736 |
|
| 1734 | 1737 |
// test writing to bind mount |
| 1735 |
- dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:rw", tmpDir), "busybox", "touch", "/tmp/holla")
|
|
| 1738 |
+ if daemonPlatform == "windows" {
|
|
| 1739 |
+ dockerCmd(c, "run", "-v", fmt.Sprintf(`%s:c:\tmp:rw`, tmpDir), "busybox", "touch", "c:/tmp/holla") |
|
| 1740 |
+ } else {
|
|
| 1741 |
+ dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:rw", tmpDir), "busybox", "touch", "/tmp/holla")
|
|
| 1742 |
+ } |
|
| 1736 | 1743 |
|
| 1737 | 1744 |
readFile(path.Join(tmpDir, "holla"), c) // Will fail if the file doesn't exist |
| 1738 | 1745 |
|
| ... | ... |
@@ -1742,12 +1856,15 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) {
|
| 1742 | 1742 |
c.Fatal("Container bind mounted illegal directory")
|
| 1743 | 1743 |
} |
| 1744 | 1744 |
|
| 1745 |
- // test mount a file |
|
| 1746 |
- dockerCmd(c, "run", "-v", fmt.Sprintf("%s/holla:/tmp/holla:rw", tmpDir), "busybox", "sh", "-c", "echo -n 'yotta' > /tmp/holla")
|
|
| 1747 |
- content := readFile(path.Join(tmpDir, "holla"), c) // Will fail if the file doesn't exist |
|
| 1748 |
- expected := "yotta" |
|
| 1749 |
- if content != expected {
|
|
| 1750 |
- c.Fatalf("Output should be %q, actual out: %q", expected, content)
|
|
| 1745 |
+ // Windows does not (and likely never will) support mounting a single file |
|
| 1746 |
+ if daemonPlatform != "windows" {
|
|
| 1747 |
+ // test mount a file |
|
| 1748 |
+ dockerCmd(c, "run", "-v", fmt.Sprintf("%s/holla:/tmp/holla:rw", tmpDir), "busybox", "sh", "-c", "echo -n 'yotta' > /tmp/holla")
|
|
| 1749 |
+ content := readFile(path.Join(tmpDir, "holla"), c) // Will fail if the file doesn't exist |
|
| 1750 |
+ expected := "yotta" |
|
| 1751 |
+ if content != expected {
|
|
| 1752 |
+ c.Fatalf("Output should be %q, actual out: %q", expected, content)
|
|
| 1753 |
+ } |
|
| 1751 | 1754 |
} |
| 1752 | 1755 |
} |
| 1753 | 1756 |
|
| ... | ... |
@@ -1806,16 +1923,11 @@ func (s *DockerSuite) TestRunCidFileCheckIDLength(c *check.C) {
|
| 1806 | 1806 |
} |
| 1807 | 1807 |
|
| 1808 | 1808 |
func (s *DockerSuite) TestRunSetMacAddress(c *check.C) {
|
| 1809 |
- // TODO Windows. Test modified to be theoretically Windows compatible, |
|
| 1810 |
- // but the version of busybox being used on Windows doesn't handle |
|
| 1811 |
- // sh -c ipconfig -all (or /all). It ignores the *all bit. This could |
|
| 1812 |
- // be a bug in busybox. |
|
| 1813 |
- testRequires(c, DaemonIsLinux) |
|
| 1814 | 1809 |
mac := "12:34:56:78:9a:bc" |
| 1815 |
- |
|
| 1816 | 1810 |
var out string |
| 1817 | 1811 |
if daemonPlatform == "windows" {
|
| 1818 | 1812 |
out, _ = dockerCmd(c, "run", "-i", "--rm", fmt.Sprintf("--mac-address=%s", mac), "busybox", "sh", "-c", "ipconfig /all | grep 'Physical Address' | awk '{print $12}'")
|
| 1813 |
+ mac = strings.Replace(strings.ToUpper(mac), ":", "-", -1) // To Windows-style MACs |
|
| 1819 | 1814 |
} else {
|
| 1820 | 1815 |
out, _ = dockerCmd(c, "run", "-i", "--rm", fmt.Sprintf("--mac-address=%s", mac), "busybox", "/bin/sh", "-c", "ip link show eth0 | tail -1 | awk '{print $2}'")
|
| 1821 | 1816 |
} |
| ... | ... |
@@ -1912,10 +2024,13 @@ func (s *DockerSuite) TestRunAllocatePortInReservedRange(c *check.C) {
|
| 1912 | 1912 |
|
| 1913 | 1913 |
// Regression test for #7792 |
| 1914 | 1914 |
func (s *DockerSuite) TestRunMountOrdering(c *check.C) {
|
| 1915 |
- // tmp gets permission denied |
|
| 1916 |
- testRequires(c, NotUserNamespace) |
|
| 1917 |
- // Not applicable on Windows as Windows does not support volumes |
|
| 1918 |
- testRequires(c, SameHostDaemon, DaemonIsLinux) |
|
| 1915 |
+ // TODO Windows: Post TP4. Updated, but Windows does not support nested mounts currently. |
|
| 1916 |
+ testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) |
|
| 1917 |
+ prefix := "" |
|
| 1918 |
+ if daemonPlatform == "windows" {
|
|
| 1919 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 1920 |
+ prefix = "c:" |
|
| 1921 |
+ } |
|
| 1919 | 1922 |
|
| 1920 | 1923 |
tmpDir, err := ioutil.TempDir("", "docker_nested_mount_test")
|
| 1921 | 1924 |
if err != nil {
|
| ... | ... |
@@ -1948,20 +2063,23 @@ func (s *DockerSuite) TestRunMountOrdering(c *check.C) {
|
| 1948 | 1948 |
} |
| 1949 | 1949 |
|
| 1950 | 1950 |
dockerCmd(c, "run", |
| 1951 |
- "-v", fmt.Sprintf("%s:/tmp", tmpDir),
|
|
| 1952 |
- "-v", fmt.Sprintf("%s:/tmp/foo", fooDir),
|
|
| 1953 |
- "-v", fmt.Sprintf("%s:/tmp/tmp2", tmpDir2),
|
|
| 1954 |
- "-v", fmt.Sprintf("%s:/tmp/tmp2/foo", fooDir),
|
|
| 1951 |
+ "-v", fmt.Sprintf("%s:"+prefix+"/tmp", tmpDir),
|
|
| 1952 |
+ "-v", fmt.Sprintf("%s:"+prefix+"/tmp/foo", fooDir),
|
|
| 1953 |
+ "-v", fmt.Sprintf("%s:"+prefix+"/tmp/tmp2", tmpDir2),
|
|
| 1954 |
+ "-v", fmt.Sprintf("%s:"+prefix+"/tmp/tmp2/foo", fooDir),
|
|
| 1955 | 1955 |
"busybox:latest", "sh", "-c", |
| 1956 |
- "ls /tmp/touch-me && ls /tmp/foo/touch-me && ls /tmp/tmp2/touch-me && ls /tmp/tmp2/foo/touch-me") |
|
| 1956 |
+ "ls "+prefix+"/tmp/touch-me && ls "+prefix+"/tmp/foo/touch-me && ls "+prefix+"/tmp/tmp2/touch-me && ls "+prefix+"/tmp/tmp2/foo/touch-me") |
|
| 1957 | 1957 |
} |
| 1958 | 1958 |
|
| 1959 | 1959 |
// Regression test for https://github.com/docker/docker/issues/8259 |
| 1960 | 1960 |
func (s *DockerSuite) TestRunReuseBindVolumeThatIsSymlink(c *check.C) {
|
| 1961 |
- // /tmp gets permission denied |
|
| 1962 |
- testRequires(c, NotUserNamespace) |
|
| 1963 | 1961 |
// Not applicable on Windows as Windows does not support volumes |
| 1964 |
- testRequires(c, SameHostDaemon, DaemonIsLinux) |
|
| 1962 |
+ testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace) |
|
| 1963 |
+ prefix := "" |
|
| 1964 |
+ if daemonPlatform == "windows" {
|
|
| 1965 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 1966 |
+ prefix = "c:" |
|
| 1967 |
+ } |
|
| 1965 | 1968 |
|
| 1966 | 1969 |
tmpDir, err := ioutil.TempDir(os.TempDir(), "testlink") |
| 1967 | 1970 |
if err != nil {
|
| ... | ... |
@@ -1976,16 +2094,17 @@ func (s *DockerSuite) TestRunReuseBindVolumeThatIsSymlink(c *check.C) {
|
| 1976 | 1976 |
defer os.RemoveAll(linkPath) |
| 1977 | 1977 |
|
| 1978 | 1978 |
// Create first container |
| 1979 |
- dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp/test", linkPath), "busybox", "ls", "-lh", "/tmp/test")
|
|
| 1979 |
+ dockerCmd(c, "run", "-v", fmt.Sprintf("%s:"+prefix+"/tmp/test", linkPath), "busybox", "ls", prefix+"/tmp/test")
|
|
| 1980 | 1980 |
|
| 1981 | 1981 |
// Create second container with same symlinked path |
| 1982 | 1982 |
// This will fail if the referenced issue is hit with a "Volume exists" error |
| 1983 |
- dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp/test", linkPath), "busybox", "ls", "-lh", "/tmp/test")
|
|
| 1983 |
+ dockerCmd(c, "run", "-v", fmt.Sprintf("%s:"+prefix+"/tmp/test", linkPath), "busybox", "ls", prefix+"/tmp/test")
|
|
| 1984 | 1984 |
} |
| 1985 | 1985 |
|
| 1986 | 1986 |
//GH#10604: Test an "/etc" volume doesn't overlay special bind mounts in container |
| 1987 | 1987 |
func (s *DockerSuite) TestRunCreateVolumeEtc(c *check.C) {
|
| 1988 |
- // Not applicable on Windows as Windows does not support volumes |
|
| 1988 |
+ // While Windows supports volumes, it does not support --add-host hence |
|
| 1989 |
+ // this test is not applicable on Windows. |
|
| 1989 | 1990 |
testRequires(c, DaemonIsLinux) |
| 1990 | 1991 |
out, _ := dockerCmd(c, "run", "--dns=127.0.0.1", "-v", "/etc", "busybox", "cat", "/etc/resolv.conf") |
| 1991 | 1992 |
if !strings.Contains(out, "nameserver 127.0.0.1") {
|
| ... | ... |
@@ -2005,7 +2124,8 @@ func (s *DockerSuite) TestRunCreateVolumeEtc(c *check.C) {
|
| 2005 | 2005 |
} |
| 2006 | 2006 |
|
| 2007 | 2007 |
func (s *DockerSuite) TestVolumesNoCopyData(c *check.C) {
|
| 2008 |
- // Not applicable on Windows as Windows does not support volumes |
|
| 2008 |
+ // TODO Windows (Post TP4). Windows does not support volumes which |
|
| 2009 |
+ // are pre-populated such as is built in the dockerfile used in this test. |
|
| 2009 | 2010 |
testRequires(c, DaemonIsLinux) |
| 2010 | 2011 |
if _, err := buildImage("dataimage",
|
| 2011 | 2012 |
`FROM busybox |
| ... | ... |
@@ -2041,37 +2161,42 @@ func (s *DockerSuite) TestRunNoOutputFromPullInStdout(c *check.C) {
|
| 2041 | 2041 |
} |
| 2042 | 2042 |
|
| 2043 | 2043 |
func (s *DockerSuite) TestRunVolumesCleanPaths(c *check.C) {
|
| 2044 |
- // Not applicable on Windows as Windows does not support volumes |
|
| 2045 |
- testRequires(c, DaemonIsLinux) |
|
| 2044 |
+ prefix := "" |
|
| 2045 |
+ slash := `/` |
|
| 2046 |
+ if daemonPlatform == "windows" {
|
|
| 2047 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 2048 |
+ prefix = "c:" |
|
| 2049 |
+ slash = `\` |
|
| 2050 |
+ } |
|
| 2046 | 2051 |
if _, err := buildImage("run_volumes_clean_paths",
|
| 2047 | 2052 |
`FROM busybox |
| 2048 |
- VOLUME /foo/`, |
|
| 2053 |
+ VOLUME `+prefix+`/foo/`, |
|
| 2049 | 2054 |
true); err != nil {
|
| 2050 | 2055 |
c.Fatal(err) |
| 2051 | 2056 |
} |
| 2052 | 2057 |
|
| 2053 |
- dockerCmd(c, "run", "-v", "/foo", "-v", "/bar/", "--name", "dark_helmet", "run_volumes_clean_paths") |
|
| 2058 |
+ dockerCmd(c, "run", "-v", prefix+"/foo", "-v", prefix+"/bar/", "--name", "dark_helmet", "run_volumes_clean_paths") |
|
| 2054 | 2059 |
|
| 2055 |
- out, err := inspectMountSourceField("dark_helmet", "/foo/")
|
|
| 2060 |
+ out, err := inspectMountSourceField("dark_helmet", prefix+slash+"foo"+slash)
|
|
| 2056 | 2061 |
if err != errMountNotFound {
|
| 2057 |
- c.Fatalf("Found unexpected volume entry for '/foo/' in volumes\n%q", out)
|
|
| 2062 |
+ c.Fatalf("Found unexpected volume entry for '%s/foo/' in volumes\n%q", prefix, out)
|
|
| 2058 | 2063 |
} |
| 2059 | 2064 |
|
| 2060 |
- out, err = inspectMountSourceField("dark_helmet", "/foo")
|
|
| 2065 |
+ out, err = inspectMountSourceField("dark_helmet", prefix+slash+`foo`)
|
|
| 2061 | 2066 |
c.Assert(err, check.IsNil) |
| 2062 |
- if !strings.Contains(out, volumesConfigPath) {
|
|
| 2063 |
- c.Fatalf("Volume was not defined for /foo\n%q", out)
|
|
| 2067 |
+ if !strings.Contains(strings.ToLower(out), strings.ToLower(volumesConfigPath)) {
|
|
| 2068 |
+ c.Fatalf("Volume was not defined for %s/foo\n%q", prefix, out)
|
|
| 2064 | 2069 |
} |
| 2065 | 2070 |
|
| 2066 |
- out, err = inspectMountSourceField("dark_helmet", "/bar/")
|
|
| 2071 |
+ out, err = inspectMountSourceField("dark_helmet", prefix+slash+"bar"+slash)
|
|
| 2067 | 2072 |
if err != errMountNotFound {
|
| 2068 |
- c.Fatalf("Found unexpected volume entry for '/bar/' in volumes\n%q", out)
|
|
| 2073 |
+ c.Fatalf("Found unexpected volume entry for '%s/bar/' in volumes\n%q", prefix, out)
|
|
| 2069 | 2074 |
} |
| 2070 | 2075 |
|
| 2071 |
- out, err = inspectMountSourceField("dark_helmet", "/bar")
|
|
| 2076 |
+ out, err = inspectMountSourceField("dark_helmet", prefix+slash+"bar")
|
|
| 2072 | 2077 |
c.Assert(err, check.IsNil) |
| 2073 |
- if !strings.Contains(out, volumesConfigPath) {
|
|
| 2074 |
- c.Fatalf("Volume was not defined for /bar\n%q", out)
|
|
| 2078 |
+ if !strings.Contains(strings.ToLower(out), strings.ToLower(volumesConfigPath)) {
|
|
| 2079 |
+ c.Fatalf("Volume was not defined for %s/bar\n%q", prefix, out)
|
|
| 2075 | 2080 |
} |
| 2076 | 2081 |
} |
| 2077 | 2082 |
|
| ... | ... |
@@ -2409,7 +2534,7 @@ func (s *DockerSuite) TestRunNonLocalMacAddress(c *check.C) {
|
| 2409 | 2409 |
if daemonPlatform == "windows" {
|
| 2410 | 2410 |
cmd = "ipconfig /all" |
| 2411 | 2411 |
image = WindowsBaseImage |
| 2412 |
- expected = strings.Replace(addr, ":", "-", -1) |
|
| 2412 |
+ expected = strings.Replace(strings.ToUpper(addr), ":", "-", -1) |
|
| 2413 | 2413 |
|
| 2414 | 2414 |
} |
| 2415 | 2415 |
|
| ... | ... |
@@ -2614,11 +2739,13 @@ func (s *DockerSuite) TestRunContainerWithReadonlyRootfsWithAddHostFlag(c *check |
| 2614 | 2614 |
} |
| 2615 | 2615 |
|
| 2616 | 2616 |
func (s *DockerSuite) TestRunVolumesFromRestartAfterRemoved(c *check.C) {
|
| 2617 |
- // TODO Windows. Not applicable on Windows which does not support volumes. |
|
| 2618 |
- // This may be possible to add in the future. |
|
| 2619 |
- testRequires(c, DaemonIsLinux) |
|
| 2620 |
- dockerCmd(c, "run", "-d", "--name", "voltest", "-v", "/foo", "busybox") |
|
| 2621 |
- dockerCmd(c, "run", "-d", "--name", "restarter", "--volumes-from", "voltest", "busybox", "top") |
|
| 2617 |
+ prefix := "" |
|
| 2618 |
+ if daemonPlatform == "windows" {
|
|
| 2619 |
+ prefix = "c:" |
|
| 2620 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 2621 |
+ } |
|
| 2622 |
+ dockerCmd(c, "run", "-d", "--name", "voltest", "-v", prefix+"/foo", "busybox", "sleep", "60") |
|
| 2623 |
+ dockerCmd(c, "run", "-d", "--name", "restarter", "--volumes-from", "voltest", "busybox", "sleep", "60") |
|
| 2622 | 2624 |
|
| 2623 | 2625 |
// Remove the main volume container and restart the consuming container |
| 2624 | 2626 |
dockerCmd(c, "rm", "-f", "voltest") |
| ... | ... |
@@ -2844,19 +2971,31 @@ func (s *DockerSuite) TestRunCapAddCHOWN(c *check.C) {
|
| 2844 | 2844 |
|
| 2845 | 2845 |
// https://github.com/docker/docker/pull/14498 |
| 2846 | 2846 |
func (s *DockerSuite) TestVolumeFromMixedRWOptions(c *check.C) {
|
| 2847 |
- // Not applicable on Windows as volumes are not supported on Winodws |
|
| 2848 |
- testRequires(c, DaemonIsLinux) |
|
| 2849 |
- dockerCmd(c, "run", "--name", "parent", "-v", "/test", "busybox", "true") |
|
| 2850 |
- dockerCmd(c, "run", "--volumes-from", "parent:ro", "--name", "test-volumes-1", "busybox", "true") |
|
| 2847 |
+ // TODO Windows post TP4. Enable the read-only bits once they are |
|
| 2848 |
+ // supported on the platform. |
|
| 2849 |
+ prefix := "" |
|
| 2850 |
+ slash := `/` |
|
| 2851 |
+ if daemonPlatform == "windows" {
|
|
| 2852 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 2853 |
+ prefix = "c:" |
|
| 2854 |
+ slash = `\` |
|
| 2855 |
+ } |
|
| 2856 |
+ |
|
| 2857 |
+ dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "true") |
|
| 2858 |
+ if daemonPlatform != "windows" {
|
|
| 2859 |
+ dockerCmd(c, "run", "--volumes-from", "parent:ro", "--name", "test-volumes-1", "busybox", "true") |
|
| 2860 |
+ } |
|
| 2851 | 2861 |
dockerCmd(c, "run", "--volumes-from", "parent:rw", "--name", "test-volumes-2", "busybox", "true") |
| 2852 | 2862 |
|
| 2853 |
- mRO, err := inspectMountPoint("test-volumes-1", "/test")
|
|
| 2854 |
- c.Assert(err, check.IsNil) |
|
| 2855 |
- if mRO.RW {
|
|
| 2856 |
- c.Fatalf("Expected RO volume was RW")
|
|
| 2863 |
+ if daemonPlatform != "windows" {
|
|
| 2864 |
+ mRO, err := inspectMountPoint("test-volumes-1", prefix+slash+"test")
|
|
| 2865 |
+ c.Assert(err, check.IsNil) |
|
| 2866 |
+ if mRO.RW {
|
|
| 2867 |
+ c.Fatalf("Expected RO volume was RW")
|
|
| 2868 |
+ } |
|
| 2857 | 2869 |
} |
| 2858 | 2870 |
|
| 2859 |
- mRW, err := inspectMountPoint("test-volumes-2", "/test")
|
|
| 2871 |
+ mRW, err := inspectMountPoint("test-volumes-2", prefix+slash+"test")
|
|
| 2860 | 2872 |
c.Assert(err, check.IsNil) |
| 2861 | 2873 |
if !mRW.RW {
|
| 2862 | 2874 |
c.Fatalf("Expected RW volume was RO")
|
| ... | ... |
@@ -3189,14 +3328,20 @@ func (s *DockerSuite) TestRunCreateContainerFailedCleanUp(c *check.C) {
|
| 3189 | 3189 |
} |
| 3190 | 3190 |
|
| 3191 | 3191 |
func (s *DockerSuite) TestRunNamedVolume(c *check.C) {
|
| 3192 |
- // TODO Windows: This may be possible to modify once Windows supports volumes |
|
| 3192 |
+ prefix := "" |
|
| 3193 |
+ slash := `/` |
|
| 3194 |
+ if daemonPlatform == "windows" {
|
|
| 3195 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 3196 |
+ prefix = "c:" |
|
| 3197 |
+ slash = `\` |
|
| 3198 |
+ } |
|
| 3193 | 3199 |
testRequires(c, DaemonIsLinux) |
| 3194 |
- dockerCmd(c, "run", "--name=test", "-v", "testing:/foo", "busybox", "sh", "-c", "echo hello > /foo/bar") |
|
| 3200 |
+ dockerCmd(c, "run", "--name=test", "-v", "testing:"+prefix+slash+"foo", "busybox", "sh", "-c", "echo hello > "+prefix+"/foo/bar") |
|
| 3195 | 3201 |
|
| 3196 |
- out, _ := dockerCmd(c, "run", "--volumes-from", "test", "busybox", "sh", "-c", "cat /foo/bar") |
|
| 3202 |
+ out, _ := dockerCmd(c, "run", "--volumes-from", "test", "busybox", "sh", "-c", "cat "+prefix+"/foo/bar") |
|
| 3197 | 3203 |
c.Assert(strings.TrimSpace(out), check.Equals, "hello") |
| 3198 | 3204 |
|
| 3199 |
- out, _ = dockerCmd(c, "run", "-v", "testing:/foo", "busybox", "sh", "-c", "cat /foo/bar") |
|
| 3205 |
+ out, _ = dockerCmd(c, "run", "-v", "testing:"+prefix+slash+"foo", "busybox", "sh", "-c", "cat "+prefix+"/foo/bar") |
|
| 3200 | 3206 |
c.Assert(strings.TrimSpace(out), check.Equals, "hello") |
| 3201 | 3207 |
} |
| 3202 | 3208 |
|
| ... | ... |
@@ -3598,6 +3743,8 @@ func (s *DockerSuite) TestRunStdinBlockedAfterContainerExit(c *check.C) {
|
| 3598 | 3598 |
} |
| 3599 | 3599 |
|
| 3600 | 3600 |
func (s *DockerSuite) TestRunWrongCpusetCpusFlagValue(c *check.C) {
|
| 3601 |
+ // TODO Windows: This needs validation (error out) in the daemon. |
|
| 3602 |
+ testRequires(c, DaemonIsLinux) |
|
| 3601 | 3603 |
out, _, err := dockerCmdWithError("run", "--cpuset-cpus", "1-10,11--", "busybox", "true")
|
| 3602 | 3604 |
c.Assert(err, check.NotNil) |
| 3603 | 3605 |
expected := "Error response from daemon: Invalid value 1-10,11-- for cpuset cpus.\n" |
| ... | ... |
@@ -3605,6 +3752,8 @@ func (s *DockerSuite) TestRunWrongCpusetCpusFlagValue(c *check.C) {
|
| 3605 | 3605 |
} |
| 3606 | 3606 |
|
| 3607 | 3607 |
func (s *DockerSuite) TestRunWrongCpusetMemsFlagValue(c *check.C) {
|
| 3608 |
+ // TODO Windows: This needs validation (error out) in the daemon. |
|
| 3609 |
+ testRequires(c, DaemonIsLinux) |
|
| 3608 | 3610 |
out, _, err := dockerCmdWithError("run", "--cpuset-mems", "1-42--", "busybox", "true")
|
| 3609 | 3611 |
c.Assert(err, check.NotNil) |
| 3610 | 3612 |
expected := "Error response from daemon: Invalid value 1-42-- for cpuset mems.\n" |
| ... | ... |
@@ -11,7 +11,9 @@ import ( |
| 11 | 11 |
) |
| 12 | 12 |
|
| 13 | 13 |
func (s *DockerSuite) TestVolumeCliCreate(c *check.C) {
|
| 14 |
- testRequires(c, DaemonIsLinux) |
|
| 14 |
+ if daemonPlatform == "windows" {
|
|
| 15 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 16 |
+ } |
|
| 15 | 17 |
dockerCmd(c, "volume", "create") |
| 16 | 18 |
|
| 17 | 19 |
_, err := runCommand(exec.Command(dockerBinary, "volume", "create", "-d", "nosuchdriver")) |
| ... | ... |
@@ -23,6 +25,9 @@ func (s *DockerSuite) TestVolumeCliCreate(c *check.C) {
|
| 23 | 23 |
} |
| 24 | 24 |
|
| 25 | 25 |
func (s *DockerSuite) TestVolumeCliCreateOptionConflict(c *check.C) {
|
| 26 |
+ if daemonPlatform == "windows" {
|
|
| 27 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 28 |
+ } |
|
| 26 | 29 |
dockerCmd(c, "volume", "create", "--name=test") |
| 27 | 30 |
out, _, err := dockerCmdWithError("volume", "create", "--name", "test", "--driver", "nosuchdriver")
|
| 28 | 31 |
c.Assert(err, check.NotNil, check.Commentf("volume create exception name already in use with another driver"))
|
| ... | ... |
@@ -35,7 +40,9 @@ func (s *DockerSuite) TestVolumeCliCreateOptionConflict(c *check.C) {
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
func (s *DockerSuite) TestVolumeCliInspect(c *check.C) {
|
| 38 |
- testRequires(c, DaemonIsLinux) |
|
| 38 |
+ if daemonPlatform == "windows" {
|
|
| 39 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 40 |
+ } |
|
| 39 | 41 |
c.Assert( |
| 40 | 42 |
exec.Command(dockerBinary, "volume", "inspect", "doesntexist").Run(), |
| 41 | 43 |
check.Not(check.IsNil), |
| ... | ... |
@@ -53,33 +60,40 @@ func (s *DockerSuite) TestVolumeCliInspect(c *check.C) {
|
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 | 55 |
func (s *DockerSuite) TestVolumeCliLs(c *check.C) {
|
| 56 |
- testRequires(c, DaemonIsLinux) |
|
| 56 |
+ prefix := "" |
|
| 57 |
+ if daemonPlatform == "windows" {
|
|
| 58 |
+ prefix = "c:" |
|
| 59 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 60 |
+ } |
|
| 57 | 61 |
out, _ := dockerCmd(c, "volume", "create") |
| 58 | 62 |
id := strings.TrimSpace(out) |
| 59 | 63 |
|
| 60 | 64 |
dockerCmd(c, "volume", "create", "--name", "test") |
| 61 |
- dockerCmd(c, "run", "-v", "/foo", "busybox", "ls", "/") |
|
| 65 |
+ dockerCmd(c, "run", "-v", prefix+"/foo", "busybox", "ls", "/") |
|
| 62 | 66 |
|
| 63 | 67 |
out, _ = dockerCmd(c, "volume", "ls") |
| 64 | 68 |
outArr := strings.Split(strings.TrimSpace(out), "\n") |
| 65 | 69 |
c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out))
|
| 66 | 70 |
|
| 67 |
- // Since there is no guarentee of ordering of volumes, we just make sure the names are in the output |
|
| 71 |
+ // Since there is no guarantee of ordering of volumes, we just make sure the names are in the output |
|
| 68 | 72 |
c.Assert(strings.Contains(out, id+"\n"), check.Equals, true) |
| 69 | 73 |
c.Assert(strings.Contains(out, "test\n"), check.Equals, true) |
| 70 | 74 |
} |
| 71 | 75 |
|
| 72 | 76 |
func (s *DockerSuite) TestVolumeCliLsFilterDangling(c *check.C) {
|
| 73 |
- testRequires(c, DaemonIsLinux) |
|
| 74 |
- |
|
| 77 |
+ prefix := "" |
|
| 78 |
+ if daemonPlatform == "windows" {
|
|
| 79 |
+ prefix = "c:" |
|
| 80 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 81 |
+ } |
|
| 75 | 82 |
dockerCmd(c, "volume", "create", "--name", "testnotinuse1") |
| 76 | 83 |
dockerCmd(c, "volume", "create", "--name", "testisinuse1") |
| 77 | 84 |
dockerCmd(c, "volume", "create", "--name", "testisinuse2") |
| 78 | 85 |
|
| 79 | 86 |
// Make sure both "created" (but not started), and started |
| 80 | 87 |
// containers are included in reference counting |
| 81 |
- dockerCmd(c, "run", "--name", "volume-test1", "-v", "testisinuse1:/foo", "busybox", "true") |
|
| 82 |
- dockerCmd(c, "create", "--name", "volume-test2", "-v", "testisinuse2:/foo", "busybox", "true") |
|
| 88 |
+ dockerCmd(c, "run", "--name", "volume-test1", "-v", "testisinuse1:"+prefix+"/foo", "busybox", "true") |
|
| 89 |
+ dockerCmd(c, "create", "--name", "volume-test2", "-v", "testisinuse2:"+prefix+"/foo", "busybox", "true") |
|
| 83 | 90 |
|
| 84 | 91 |
out, _ := dockerCmd(c, "volume", "ls") |
| 85 | 92 |
|
| ... | ... |
@@ -104,7 +118,11 @@ func (s *DockerSuite) TestVolumeCliLsFilterDangling(c *check.C) {
|
| 104 | 104 |
} |
| 105 | 105 |
|
| 106 | 106 |
func (s *DockerSuite) TestVolumeCliRm(c *check.C) {
|
| 107 |
- testRequires(c, DaemonIsLinux) |
|
| 107 |
+ prefix := "" |
|
| 108 |
+ if daemonPlatform == "windows" {
|
|
| 109 |
+ prefix = "c:" |
|
| 110 |
+ testRequires(c, WindowsDaemonSupportsVolumes) |
|
| 111 |
+ } |
|
| 108 | 112 |
out, _ := dockerCmd(c, "volume", "create") |
| 109 | 113 |
id := strings.TrimSpace(out) |
| 110 | 114 |
|
| ... | ... |
@@ -117,7 +135,7 @@ func (s *DockerSuite) TestVolumeCliRm(c *check.C) {
|
| 117 | 117 |
c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
|
| 118 | 118 |
|
| 119 | 119 |
volumeID := "testing" |
| 120 |
- dockerCmd(c, "run", "-v", volumeID+":/foo", "--name=test", "busybox", "sh", "-c", "echo hello > /foo/bar") |
|
| 120 |
+ dockerCmd(c, "run", "-v", volumeID+":"+prefix+"/foo", "--name=test", "busybox", "sh", "-c", "echo hello > /foo/bar") |
|
| 121 | 121 |
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "volume", "rm", "testing")) |
| 122 | 122 |
c.Assert( |
| 123 | 123 |
err, |
| ... | ... |
@@ -130,7 +148,7 @@ func (s *DockerSuite) TestVolumeCliRm(c *check.C) {
|
| 130 | 130 |
dockerCmd(c, "volume", "inspect", volumeID) |
| 131 | 131 |
dockerCmd(c, "rm", "-f", "test") |
| 132 | 132 |
|
| 133 |
- out, _ = dockerCmd(c, "run", "--name=test2", "-v", volumeID+":/foo", "busybox", "sh", "-c", "cat /foo/bar") |
|
| 133 |
+ out, _ = dockerCmd(c, "run", "--name=test2", "-v", volumeID+":"+prefix+"/foo", "busybox", "sh", "-c", "cat /foo/bar") |
|
| 134 | 134 |
c.Assert(strings.TrimSpace(out), check.Equals, "hello", check.Commentf("volume data was removed"))
|
| 135 | 135 |
dockerCmd(c, "rm", "test2") |
| 136 | 136 |
|
| ... | ... |
@@ -34,6 +34,12 @@ var ( |
| 34 | 34 |
// a version call to the daemon and examining the response header. |
| 35 | 35 |
daemonPlatform string |
| 36 | 36 |
|
| 37 |
+ // windowsDaemonKV is used on Windows to distinguish between different |
|
| 38 |
+ // versions. This is necessary to enable certain tests based on whether |
|
| 39 |
+ // the platform supports it. For example, Windows Server 2016 TP3 does |
|
| 40 |
+ // not support volumes, but TP4 does. |
|
| 41 |
+ windowsDaemonKV int |
|
| 42 |
+ |
|
| 37 | 43 |
// daemonDefaultImage is the name of the default image to use when running |
| 38 | 44 |
// tests. This is platform dependent. |
| 39 | 45 |
daemonDefaultImage string |
| ... | ... |
@@ -637,6 +637,29 @@ func init() {
|
| 637 | 637 |
if daemonPlatform != "linux" && daemonPlatform != "windows" {
|
| 638 | 638 |
panic("Cannot run tests against platform: " + daemonPlatform)
|
| 639 | 639 |
} |
| 640 |
+ |
|
| 641 |
+ // On Windows, extract out the version as we need to make selective |
|
| 642 |
+ // decisions during integration testing as and when features are implemented. |
|
| 643 |
+ if daemonPlatform == "windows" {
|
|
| 644 |
+ if body, err := ioutil.ReadAll(res.Body); err == nil {
|
|
| 645 |
+ var server types.Version |
|
| 646 |
+ if err := json.Unmarshal(body, &server); err == nil {
|
|
| 647 |
+ // eg in "10.0 10550 (10550.1000.amd64fre.branch.date-time)" we want 10550 |
|
| 648 |
+ windowsDaemonKV, _ = strconv.Atoi(strings.Split(server.KernelVersion, " ")[1]) |
|
| 649 |
+ } |
|
| 650 |
+ } |
|
| 651 |
+ } |
|
| 652 |
+ |
|
| 653 |
+ // Now we know the daemon platform, can set paths used by tests. |
|
| 654 |
+ if daemonPlatform == "windows" {
|
|
| 655 |
+ dockerBasePath = `c:\programdata\docker` |
|
| 656 |
+ volumesConfigPath = dockerBasePath + `\volumes` |
|
| 657 |
+ containerStoragePath = dockerBasePath + `\containers` |
|
| 658 |
+ } else {
|
|
| 659 |
+ dockerBasePath = "/var/lib/docker" |
|
| 660 |
+ volumesConfigPath = dockerBasePath + "/volumes" |
|
| 661 |
+ containerStoragePath = dockerBasePath + "/containers" |
|
| 662 |
+ } |
|
| 640 | 663 |
} |
| 641 | 664 |
|
| 642 | 665 |
func deleteAllImages() error {
|
| ... | ... |
@@ -29,6 +29,18 @@ var ( |
| 29 | 29 |
func() bool { return daemonPlatform == "windows" },
|
| 30 | 30 |
"Test requires a Windows daemon", |
| 31 | 31 |
} |
| 32 |
+ WindowsDaemonSupportsVolumes = testRequirement{
|
|
| 33 |
+ func() bool {
|
|
| 34 |
+ if daemonPlatform != "windows" {
|
|
| 35 |
+ return false |
|
| 36 |
+ } |
|
| 37 |
+ if windowsDaemonKV == 0 {
|
|
| 38 |
+ panic("windowsDaemonKV is not set")
|
|
| 39 |
+ } |
|
| 40 |
+ return windowsDaemonKV >= 10559 |
|
| 41 |
+ }, |
|
| 42 |
+ "Test requires a Windows daemon that supports volumes", |
|
| 43 |
+ } |
|
| 32 | 44 |
DaemonIsLinux = testRequirement{
|
| 33 | 45 |
func() bool { return daemonPlatform == "linux" },
|
| 34 | 46 |
"Test requires a Linux daemon", |