-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is intended as a minor fix for 1.12.1 so that task creation doesn't do unexpected things when the user supplies erroneous paths. In particular, because we're currently using hostConfig.Binds to setup mounts, if a user uses an absolute path for a volume mount source, or a non-absolute path for a bind mount source, the engine will do the opposite of what the user requested since all absolute paths are treated as binds and all non-absolute paths are treated as named volumes. Fixes moby#25253 Signed-off-by: Brian Goff <cpuguy83@gmail.com>
- Loading branch information
Showing
5 changed files
with
173 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package container | ||
|
||
import ( | ||
"fmt" | ||
"path/filepath" | ||
|
||
"github.com/docker/swarmkit/api" | ||
) | ||
|
||
func validateMounts(mounts []api.Mount) error { | ||
for _, mount := range mounts { | ||
// Target must always be absolute | ||
if !filepath.IsAbs(mount.Target) { | ||
return fmt.Errorf("invalid mount target, must be an absolute path: %s", mount.Target) | ||
} | ||
|
||
switch mount.Type { | ||
// The checks on abs paths are required due to the container API confusing | ||
// volume mounts as bind mounts when the source is absolute (and vice-versa) | ||
// See #25253 | ||
// TODO: This is probably not neccessary once #22373 is merged | ||
case api.MountTypeBind: | ||
if !filepath.IsAbs(mount.Source) { | ||
return fmt.Errorf("invalid bind mount source, must be an absolute path: %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) | ||
} | ||
case api.MountTypeTmpfs: | ||
if mount.Source != "" { | ||
return fmt.Errorf("invalid tmpfs source, source must be empty") | ||
} | ||
default: | ||
return fmt.Errorf("invalid mount type: %s", mount.Type) | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package container | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"github.com/docker/docker/daemon" | ||
"github.com/docker/docker/pkg/stringid" | ||
"github.com/docker/swarmkit/api" | ||
) | ||
|
||
func newTestControllerWithMount(m api.Mount) (*controller, error) { | ||
return newController(&daemon.Daemon{}, &api.Task{ | ||
ID: stringid.GenerateRandomID(), | ||
ServiceID: stringid.GenerateRandomID(), | ||
Spec: api.TaskSpec{ | ||
Runtime: &api.TaskSpec_Container{ | ||
Container: &api.ContainerSpec{ | ||
Image: "image_name", | ||
Labels: map[string]string{ | ||
"com.docker.swarm.task.id": "id", | ||
}, | ||
Mounts: []api.Mount{m}, | ||
}, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestControllerValidateMountBind(t *testing.T) { | ||
// with improper source | ||
if _, err := newTestControllerWithMount(api.Mount{ | ||
Type: api.MountTypeBind, | ||
Source: "foo", | ||
Target: testAbsPath, | ||
}); err == nil || !strings.Contains(err.Error(), "invalid bind mount source") { | ||
t.Fatalf("expected error, got: %v", err) | ||
} | ||
|
||
// with proper source | ||
if _, err := newTestControllerWithMount(api.Mount{ | ||
Type: api.MountTypeBind, | ||
Source: testAbsPath, | ||
Target: testAbsPath, | ||
}); err != nil { | ||
t.Fatalf("expected error, got: %v", err) | ||
} | ||
} | ||
|
||
func TestControllerValidateMountVolume(t *testing.T) { | ||
// with improper source | ||
if _, err := newTestControllerWithMount(api.Mount{ | ||
Type: api.MountTypeVolume, | ||
Source: testAbsPath, | ||
Target: testAbsPath, | ||
}); err == nil || !strings.Contains(err.Error(), "invalid volume mount source") { | ||
t.Fatalf("expected error, got: %v", err) | ||
} | ||
|
||
// with proper source | ||
if _, err := newTestControllerWithMount(api.Mount{ | ||
Type: api.MountTypeVolume, | ||
Source: "foo", | ||
Target: testAbsPath, | ||
}); err != nil { | ||
t.Fatalf("expected error, got: %v", err) | ||
} | ||
} | ||
|
||
func TestControllerValidateMountTarget(t *testing.T) { | ||
// with improper target | ||
if _, err := newTestControllerWithMount(api.Mount{ | ||
Type: api.MountTypeBind, | ||
Source: testAbsPath, | ||
Target: "foo", | ||
}); err == nil || !strings.Contains(err.Error(), "invalid mount target") { | ||
t.Fatalf("expected error, got: %v", err) | ||
} | ||
|
||
// with proper target | ||
if _, err := newTestControllerWithMount(api.Mount{ | ||
Type: api.MountTypeBind, | ||
Source: testAbsPath, | ||
Target: testAbsPath, | ||
}); err != nil { | ||
t.Fatalf("expected no error, got: %v", err) | ||
} | ||
} | ||
|
||
func TestControllerValidateMountTmpfs(t *testing.T) { | ||
// with improper target | ||
if _, err := newTestControllerWithMount(api.Mount{ | ||
Type: api.MountTypeTmpfs, | ||
Source: "foo", | ||
Target: testAbsPath, | ||
}); err == nil || !strings.Contains(err.Error(), "invalid tmpfs source") { | ||
t.Fatalf("expected error, got: %v", err) | ||
} | ||
|
||
// with proper target | ||
if _, err := newTestControllerWithMount(api.Mount{ | ||
Type: api.MountTypeTmpfs, | ||
Target: testAbsPath, | ||
}); err != nil { | ||
t.Fatalf("expected no error, got: %v", err) | ||
} | ||
} | ||
|
||
func TestControllerValidateMountInvalidType(t *testing.T) { | ||
// with improper target | ||
if _, err := newTestControllerWithMount(api.Mount{ | ||
Type: api.Mount_MountType(9999), | ||
Source: "foo", | ||
Target: testAbsPath, | ||
}); err == nil || !strings.Contains(err.Error(), "invalid mount type") { | ||
t.Fatalf("expected error, got: %v", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// +build !windows | ||
|
||
package container | ||
|
||
const ( | ||
testAbsPath = "/foo" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package container | ||
|
||
const ( | ||
testAbsPath = `c:\foo` | ||
) |