1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Handle bind options and volume options

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2016-11-10 11:33:00 -05:00
parent bd8de8d8be
commit ef90081d44

View file

@ -259,47 +259,64 @@ func convertVolumes(
) ([]mount.Mount, error) { ) ([]mount.Mount, error) {
var mounts []mount.Mount var mounts []mount.Mount
for _, volumeString := range serviceVolumes { for _, volumeSpec := range serviceVolumes {
var ( mount, err := convertVolumeToMount(volumeSpec, stackVolumes, namespace)
source, target string if err != nil {
mountType mount.Type return nil, err
readOnly bool }
volumeOptions *mount.VolumeOptions mounts = append(mounts, mount)
) }
return mounts, nil
}
func convertVolumeToMount(
volumeSpec string,
stackVolumes map[string]composetypes.VolumeConfig,
namespace namespace,
) (mount.Mount, error) {
var source, target string
var mode []string
// TODO: split Windows path mappings properly // TODO: split Windows path mappings properly
parts := strings.SplitN(volumeString, ":", 3) parts := strings.SplitN(volumeSpec, ":", 3)
if len(parts) == 3 { switch len(parts) {
case 3:
source = parts[0] source = parts[0]
target = parts[1] target = parts[1]
if parts[2] == "ro" { mode = strings.Split(parts[2], ",")
readOnly = true case 2:
}
} else if len(parts) == 2 {
source = parts[0] source = parts[0]
target = parts[1] target = parts[1]
} else if len(parts) == 1 { case 1:
target = parts[0] target = parts[0]
default:
return mount.Mount{}, fmt.Errorf("invald volume: %s", volumeSpec)
} }
// TODO: catch Windows paths here // TODO: catch Windows paths here
if strings.HasPrefix(source, "/") { if strings.HasPrefix(source, "/") {
mountType = mount.TypeBind return mount.Mount{
} else { Type: mount.TypeBind,
mountType = mount.TypeVolume Source: source,
Target: target,
ReadOnly: isReadOnly(mode),
BindOptions: getBindOptions(mode),
}, nil
}
stackVolume, exists := stackVolumes[source] stackVolume, exists := stackVolumes[source]
if !exists { if !exists {
// TODO: better error message (include service name) return mount.Mount{}, fmt.Errorf("undefined volume: %s", source)
return nil, fmt.Errorf("Undefined volume: %s", source)
} }
var volumeOptions *mount.VolumeOptions
if stackVolume.External.Name != "" { if stackVolume.External.Name != "" {
source = stackVolume.External.Name source = stackVolume.External.Name
} else { } else {
volumeOptions = &mount.VolumeOptions{ volumeOptions = &mount.VolumeOptions{
Labels: stackVolume.Labels, Labels: stackVolume.Labels,
NoCopy: isNoCopy(mode),
} }
if stackVolume.Driver != "" { if stackVolume.Driver != "" {
@ -308,21 +325,41 @@ func convertVolumes(
Options: stackVolume.DriverOpts, Options: stackVolume.DriverOpts,
} }
} }
source = namespace.scope(source) source = namespace.scope(source)
} }
} return mount.Mount{
Type: mount.TypeVolume,
mounts = append(mounts, mount.Mount{
Type: mountType,
Source: source, Source: source,
Target: target, Target: target,
ReadOnly: readOnly, ReadOnly: isReadOnly(mode),
VolumeOptions: volumeOptions, VolumeOptions: volumeOptions,
}) }, nil
} }
return mounts, nil func modeHas(mode []string, field string) bool {
for _, item := range mode {
if item == field {
return true
}
}
return false
}
func isReadOnly(mode []string) bool {
return modeHas(mode, "ro")
}
func isNoCopy(mode []string) bool {
return modeHas(mode, "nocopy")
}
func getBindOptions(mode []string) *mount.BindOptions {
for _, item := range mode {
if strings.Contains(item, "private") || strings.Contains(item, "shared") || strings.Contains(item, "slave") {
return &mount.BindOptions{Propagation: mount.Propagation(item)}
}
}
return nil
} }
func deployServices( func deployServices(
@ -429,6 +466,7 @@ func convertService(
mounts, err := convertVolumes(service.Volumes, volumes, namespace) mounts, err := convertVolumes(service.Volumes, volumes, namespace)
if err != nil { if err != nil {
// TODO: better error message (include service name)
return swarm.ServiceSpec{}, err return swarm.ServiceSpec{}, err
} }