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:
parent
bd8de8d8be
commit
ef90081d44
1 changed files with 96 additions and 58 deletions
|
@ -259,70 +259,107 @@ 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
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: split Windows path mappings properly
|
|
||||||
parts := strings.SplitN(volumeString, ":", 3)
|
|
||||||
|
|
||||||
if len(parts) == 3 {
|
|
||||||
source = parts[0]
|
|
||||||
target = parts[1]
|
|
||||||
if parts[2] == "ro" {
|
|
||||||
readOnly = true
|
|
||||||
}
|
|
||||||
} else if len(parts) == 2 {
|
|
||||||
source = parts[0]
|
|
||||||
target = parts[1]
|
|
||||||
} else if len(parts) == 1 {
|
|
||||||
target = parts[0]
|
|
||||||
}
|
}
|
||||||
|
mounts = append(mounts, mount)
|
||||||
|
}
|
||||||
|
return mounts, nil
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: catch Windows paths here
|
func convertVolumeToMount(
|
||||||
if strings.HasPrefix(source, "/") {
|
volumeSpec string,
|
||||||
mountType = mount.TypeBind
|
stackVolumes map[string]composetypes.VolumeConfig,
|
||||||
} else {
|
namespace namespace,
|
||||||
mountType = mount.TypeVolume
|
) (mount.Mount, error) {
|
||||||
|
var source, target string
|
||||||
|
var mode []string
|
||||||
|
|
||||||
stackVolume, exists := stackVolumes[source]
|
// TODO: split Windows path mappings properly
|
||||||
if !exists {
|
parts := strings.SplitN(volumeSpec, ":", 3)
|
||||||
// TODO: better error message (include service name)
|
|
||||||
return nil, fmt.Errorf("Undefined volume: %s", source)
|
|
||||||
}
|
|
||||||
|
|
||||||
if stackVolume.External.Name != "" {
|
switch len(parts) {
|
||||||
source = stackVolume.External.Name
|
case 3:
|
||||||
} else {
|
source = parts[0]
|
||||||
volumeOptions = &mount.VolumeOptions{
|
target = parts[1]
|
||||||
Labels: stackVolume.Labels,
|
mode = strings.Split(parts[2], ",")
|
||||||
}
|
case 2:
|
||||||
|
source = parts[0]
|
||||||
if stackVolume.Driver != "" {
|
target = parts[1]
|
||||||
volumeOptions.DriverConfig = &mount.Driver{
|
case 1:
|
||||||
Name: stackVolume.Driver,
|
target = parts[0]
|
||||||
Options: stackVolume.DriverOpts,
|
default:
|
||||||
}
|
return mount.Mount{}, fmt.Errorf("invald volume: %s", volumeSpec)
|
||||||
}
|
|
||||||
|
|
||||||
source = namespace.scope(source)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mounts = append(mounts, mount.Mount{
|
|
||||||
Type: mountType,
|
|
||||||
Source: source,
|
|
||||||
Target: target,
|
|
||||||
ReadOnly: readOnly,
|
|
||||||
VolumeOptions: volumeOptions,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mounts, nil
|
// TODO: catch Windows paths here
|
||||||
|
if strings.HasPrefix(source, "/") {
|
||||||
|
return mount.Mount{
|
||||||
|
Type: mount.TypeBind,
|
||||||
|
Source: source,
|
||||||
|
Target: target,
|
||||||
|
ReadOnly: isReadOnly(mode),
|
||||||
|
BindOptions: getBindOptions(mode),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
stackVolume, exists := stackVolumes[source]
|
||||||
|
if !exists {
|
||||||
|
return mount.Mount{}, fmt.Errorf("undefined volume: %s", source)
|
||||||
|
}
|
||||||
|
|
||||||
|
var volumeOptions *mount.VolumeOptions
|
||||||
|
if stackVolume.External.Name != "" {
|
||||||
|
source = stackVolume.External.Name
|
||||||
|
} else {
|
||||||
|
volumeOptions = &mount.VolumeOptions{
|
||||||
|
Labels: stackVolume.Labels,
|
||||||
|
NoCopy: isNoCopy(mode),
|
||||||
|
}
|
||||||
|
|
||||||
|
if stackVolume.Driver != "" {
|
||||||
|
volumeOptions.DriverConfig = &mount.Driver{
|
||||||
|
Name: stackVolume.Driver,
|
||||||
|
Options: stackVolume.DriverOpts,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
source = namespace.scope(source)
|
||||||
|
}
|
||||||
|
return mount.Mount{
|
||||||
|
Type: mount.TypeVolume,
|
||||||
|
Source: source,
|
||||||
|
Target: target,
|
||||||
|
ReadOnly: isReadOnly(mode),
|
||||||
|
VolumeOptions: volumeOptions,
|
||||||
|
}, 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue