From 84d5ab96ef33355e65f5c31210eb1777db372c52 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 8 Aug 2016 17:24:00 +0200 Subject: [PATCH] fix validation of non-existing bind-mount source Unlike `docker run -v..`, `docker service create --mount` does not allow bind-mounting non-existing host paths. This adds validation for the specified `source`, and produces an error if the path is not found on the host. Signed-off-by: Sebastiaan van Stijn --- daemon/cluster/executor/container/validate.go | 4 +++ .../executor/container/validate_test.go | 29 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/daemon/cluster/executor/container/validate.go b/daemon/cluster/executor/container/validate.go index db348fe953..dad1524a6d 100644 --- a/daemon/cluster/executor/container/validate.go +++ b/daemon/cluster/executor/container/validate.go @@ -2,6 +2,7 @@ package container import ( "fmt" + "os" "path/filepath" "github.com/docker/swarmkit/api" @@ -23,6 +24,9 @@ func validateMounts(mounts []api.Mount) error { if !filepath.IsAbs(mount.Source) { return fmt.Errorf("invalid bind mount source, must be an absolute path: %s", mount.Source) } + if _, err := os.Stat(mount.Source); os.IsNotExist(err) { + return fmt.Errorf("invalid bind mount source, source path not found: %s", mount.Source) + } case api.MountTypeVolume: if filepath.IsAbs(mount.Source) { return fmt.Errorf("invalid volume mount source, must not be an absolute path: %s", mount.Source) diff --git a/daemon/cluster/executor/container/validate_test.go b/daemon/cluster/executor/container/validate_test.go index acbe558f2e..d911c1ebec 100644 --- a/daemon/cluster/executor/container/validate_test.go +++ b/daemon/cluster/executor/container/validate_test.go @@ -1,6 +1,8 @@ package container import ( + "io/ioutil" + "os" "strings" "testing" @@ -37,10 +39,25 @@ func TestControllerValidateMountBind(t *testing.T) { t.Fatalf("expected error, got: %v", err) } - // with proper source + // with non-existing source if _, err := newTestControllerWithMount(api.Mount{ Type: api.MountTypeBind, - Source: testAbsPath, + Source: "/some-non-existing-host-path/", + Target: testAbsPath, + }); err == nil || !strings.Contains(err.Error(), "invalid bind mount source") { + t.Fatalf("expected error, got: %v", err) + } + + // with proper source + tmpdir, err := ioutil.TempDir("", "TestControllerValidateMountBind") + if err != nil { + t.Fatalf("failed to create temp dir: %v", err) + } + defer os.Remove(tmpdir) + + if _, err := newTestControllerWithMount(api.Mount{ + Type: api.MountTypeBind, + Source: tmpdir, Target: testAbsPath, }); err != nil { t.Fatalf("expected error, got: %v", err) @@ -68,6 +85,12 @@ func TestControllerValidateMountVolume(t *testing.T) { } func TestControllerValidateMountTarget(t *testing.T) { + tmpdir, err := ioutil.TempDir("", "TestControllerValidateMountTarget") + if err != nil { + t.Fatalf("failed to create temp dir: %v", err) + } + defer os.Remove(tmpdir) + // with improper target if _, err := newTestControllerWithMount(api.Mount{ Type: api.MountTypeBind, @@ -80,7 +103,7 @@ func TestControllerValidateMountTarget(t *testing.T) { // with proper target if _, err := newTestControllerWithMount(api.Mount{ Type: api.MountTypeBind, - Source: testAbsPath, + Source: tmpdir, Target: testAbsPath, }); err != nil { t.Fatalf("expected no error, got: %v", err)