From 36c0b59149a9ab4baee16eaad4ece1e980e96f2f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 3 Jan 2017 21:22:07 +0100 Subject: [PATCH 1/2] fix conversion of anonymous volumes in compose-file the `convertVolumeToMount()` function did not take anonymous volumes into account when converting volume specifications to bind-mounts. this resulted in the conversion to try to look up an empty "source" volume, which lead to an error; undefined volume: this patch distinguishes "anonymous" volumes from bind-mounts and named-volumes, and skips further processing if no source is defined (i.e. the volume is "anonymous"). Signed-off-by: Sebastiaan van Stijn --- cli/command/stack/deploy.go | 10 +++++++++- cli/command/stack/deploy_test.go | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 cli/command/stack/deploy_test.go diff --git a/cli/command/stack/deploy.go b/cli/command/stack/deploy.go index 00a7634a0a..4e7e1242b1 100644 --- a/cli/command/stack/deploy.go +++ b/cli/command/stack/deploy.go @@ -359,7 +359,15 @@ func convertVolumeToMount( case 1: target = parts[0] default: - return mount.Mount{}, fmt.Errorf("invald volume: %s", volumeSpec) + return mount.Mount{}, fmt.Errorf("invalid volume: %s", volumeSpec) + } + + if source == "" { + // Anonymous volume + return mount.Mount{ + Type: mount.TypeVolume, + Target: target, + }, nil } // TODO: catch Windows paths here diff --git a/cli/command/stack/deploy_test.go b/cli/command/stack/deploy_test.go new file mode 100644 index 0000000000..0ba27c8d0b --- /dev/null +++ b/cli/command/stack/deploy_test.go @@ -0,0 +1,21 @@ +package stack + +import ( + "testing" + + composetypes "github.com/aanand/compose-file/types" + "github.com/docker/docker/api/types/mount" + "github.com/docker/docker/pkg/testutil/assert" +) + +func TestConvertVolumeToMountAnonymousVolume(t *testing.T) { + stackVolumes := map[string]composetypes.VolumeConfig{} + namespace := namespace{name:"foo"} + expected := mount.Mount{ + Type: mount.TypeVolume, + Target: "/foo/bar", + } + mnt, err := convertVolumeToMount("/foo/bar", stackVolumes, namespace) + assert.NilError(t, err) + assert.DeepEqual(t, mnt, expected) +} From 1ca25a2e5e04e3acaef7834e374e74c0cd297680 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 3 Jan 2017 21:26:19 +0100 Subject: [PATCH 2/2] Improve validation for volume specs The current validation only checked for the number of elements in the volume-spec, however, did not validate if the elements were empty. Because of this, an empty volume-spec (""), or volume spec only containing separators ("::") would not be invalidated. This adds a simple check for empty elements in the volume-spec, and returns an error if the spec is invalid. A unit-test is also added to verify the behavior. Signed-off-by: Sebastiaan van Stijn --- cli/command/stack/deploy.go | 8 ++++++-- cli/command/stack/deploy_test.go | 11 ++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cli/command/stack/deploy.go b/cli/command/stack/deploy.go index 4e7e1242b1..8a18cff43a 100644 --- a/cli/command/stack/deploy.go +++ b/cli/command/stack/deploy.go @@ -348,6 +348,12 @@ func convertVolumeToMount( // TODO: split Windows path mappings properly parts := strings.SplitN(volumeSpec, ":", 3) + for _, part := range parts { + if strings.TrimSpace(part) == "" { + return mount.Mount{}, fmt.Errorf("invalid volume: %s", volumeSpec) + } + } + switch len(parts) { case 3: source = parts[0] @@ -358,8 +364,6 @@ func convertVolumeToMount( target = parts[1] case 1: target = parts[0] - default: - return mount.Mount{}, fmt.Errorf("invalid volume: %s", volumeSpec) } if source == "" { diff --git a/cli/command/stack/deploy_test.go b/cli/command/stack/deploy_test.go index 0ba27c8d0b..86ecf151d4 100644 --- a/cli/command/stack/deploy_test.go +++ b/cli/command/stack/deploy_test.go @@ -10,7 +10,7 @@ import ( func TestConvertVolumeToMountAnonymousVolume(t *testing.T) { stackVolumes := map[string]composetypes.VolumeConfig{} - namespace := namespace{name:"foo"} + namespace := namespace{name: "foo"} expected := mount.Mount{ Type: mount.TypeVolume, Target: "/foo/bar", @@ -19,3 +19,12 @@ func TestConvertVolumeToMountAnonymousVolume(t *testing.T) { assert.NilError(t, err) assert.DeepEqual(t, mnt, expected) } + +func TestConvertVolumeToMountInvalidFormat(t *testing.T) { + namespace := namespace{name: "foo"} + invalids := []string{"::", "::cc", ":bb:", "aa::", "aa::cc", "aa:bb:", " : : ", " : :cc", " :bb: ", "aa: : ", "aa: :cc", "aa:bb: "} + for _, vol := range invalids { + _, err := convertVolumeToMount(vol, map[string]composetypes.VolumeConfig{}, namespace) + assert.Error(t, err, "invalid volume: "+vol) + } +}