add check for local volume option

Description:
When using local volume option such as size=10G, type=tmpfs, if we provide wrong options, we could create volume successfully.
But when we are ready to use it, it will fail to start container by failing to mount the local volume(invalid option).

We should check the options at when we create it.

Signed-off-by: Wentao Zhang <zhangwentao234@huawei.com>
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Vincent Demeester 2018-04-09 10:09:30 +02:00 committed by Sebastiaan van Stijn
parent 2cb26cfe9c
commit d5b271c155
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
4 changed files with 72 additions and 10 deletions

View File

@ -1835,14 +1835,62 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *check.C) {
Image: "busybox", Image: "busybox",
}, },
hostConfig: containertypes.HostConfig{ hostConfig: containertypes.HostConfig{
Mounts: []mounttypes.Mount{{ Mounts: []mounttypes.Mount{
Type: "volume", {
Source: "hello3", Type: "volume",
Target: destPath, Source: "missing-device-opt",
VolumeOptions: &mounttypes.VolumeOptions{ Target: destPath,
DriverConfig: &mounttypes.Driver{ VolumeOptions: &mounttypes.VolumeOptions{
Name: "local", DriverConfig: &mounttypes.Driver{
Options: map[string]string{"o": "size=1"}}}}}}, Name: "local",
Options: map[string]string{"type": "tmpfs"},
},
},
},
},
},
msg: `missing required option: "device"`,
},
{
config: containertypes.Config{
Image: "busybox",
},
hostConfig: containertypes.HostConfig{
Mounts: []mounttypes.Mount{
{
Type: "volume",
Source: "missing-type-opt",
Target: destPath,
VolumeOptions: &mounttypes.VolumeOptions{
DriverConfig: &mounttypes.Driver{
Name: "local",
Options: map[string]string{"device": "tmpfs"},
},
},
},
},
},
msg: `missing required option: "type"`,
},
{
config: containertypes.Config{
Image: "busybox",
},
hostConfig: containertypes.HostConfig{
Mounts: []mounttypes.Mount{
{
Type: "volume",
Source: "hello4",
Target: destPath,
VolumeOptions: &mounttypes.VolumeOptions{
DriverConfig: &mounttypes.Driver{
Name: "local",
Options: map[string]string{"o": "size=1", "type": "tmpfs", "device": "tmpfs"},
},
},
},
},
},
msg: "", msg: "",
}, },
{ {
@ -1869,7 +1917,6 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *check.C) {
}}}}, }}}},
msg: "", msg: "",
}, },
{ {
config: containertypes.Config{ config: containertypes.Config{
Image: "busybox", Image: "busybox",

View File

@ -353,11 +353,19 @@ func (v *localVolume) unmount() error {
} }
func validateOpts(opts map[string]string) error { func validateOpts(opts map[string]string) error {
if len(opts) == 0 {
return nil
}
for opt := range opts { for opt := range opts {
if !validOpts[opt] { if !validOpts[opt] {
return validationError(fmt.Sprintf("invalid option key: %q", opt)) return validationError(fmt.Sprintf("invalid option key: %q", opt))
} }
} }
for opt := range mandatoryOpts {
if _, ok := opts[opt]; !ok {
return errdefs.InvalidParameter(errors.Errorf("missing required option: %q", opt))
}
}
return nil return nil
} }

View File

@ -27,6 +27,10 @@ var (
"o": true, // generic mount options "o": true, // generic mount options
"device": true, // device to mount from "device": true, // device to mount from
} }
mandatoryOpts = map[string]struct{}{
"device": {},
"type": {},
}
) )
type optsConfig struct { type optsConfig struct {

View File

@ -14,7 +14,10 @@ import (
type optsConfig struct{} type optsConfig struct{}
var validOpts map[string]bool var (
validOpts map[string]bool
mandatoryOpts map[string]struct{}
)
// scopedPath verifies that the path where the volume is located // scopedPath verifies that the path where the volume is located
// is under Docker's root and the valid local paths. // is under Docker's root and the valid local paths.