Browse Source

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 <github@gone.nl>
Sebastiaan van Stijn 9 years ago
parent
commit
84d5ab96ef

+ 4 - 0
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)

+ 25 - 2
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 non-existing source
+	if _, err := newTestControllerWithMount(api.Mount{
+		Type:   api.MountTypeBind,
+		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: testAbsPath,
+		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)