From 29f39ea24432d63c413cda75214db7eef8e409eb Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Tue, 24 Jan 2017 12:09:53 -0500 Subject: [PATCH] Support expanded mounts in Compose loader Add a test for loading expanded mount format. Signed-off-by: Daniel Nephin --- compose/loader/loader.go | 38 ++++++++++++++++++------------- compose/loader/loader_test.go | 42 +++++++++++++++++++++++++++++------ compose/types/types.go | 2 +- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/compose/loader/loader.go b/compose/loader/loader.go index 2ccef7198d..bdc837d9b6 100644 --- a/compose/loader/loader.go +++ b/compose/loader/loader.go @@ -251,6 +251,8 @@ func transformHook( return transformMappingOrList(data, "="), nil case reflect.TypeOf(types.MappingWithColon{}): return transformMappingOrList(data, ":"), nil + case reflect.TypeOf(types.ServiceVolumeConfig{}): + return transformServiceVolumeConfig(data) } return data, nil } @@ -329,10 +331,7 @@ func loadService(name string, serviceDict types.Dict, workingDir string) (*types return nil, err } - if err := resolveVolumePaths(serviceConfig.Volumes, workingDir); err != nil { - return nil, err - } - + resolveVolumePaths(serviceConfig.Volumes, workingDir) return serviceConfig, nil } @@ -365,22 +364,15 @@ func resolveEnvironment(serviceConfig *types.ServiceConfig, workingDir string) e return nil } -func resolveVolumePaths(volumes []string, workingDir string) error { - for i, mapping := range volumes { - parts := strings.SplitN(mapping, ":", 2) - if len(parts) == 1 { +func resolveVolumePaths(volumes []types.ServiceVolumeConfig, workingDir string) { + for i, volume := range volumes { + if volume.Type != "bind" { continue } - if strings.HasPrefix(parts[0], ".") { - parts[0] = absPath(workingDir, parts[0]) - } - parts[0] = expandUser(parts[0]) - - volumes[i] = strings.Join(parts, ":") + volume.Source = absPath(workingDir, expandUser(volume.Source)) + volumes[i] = volume } - - return nil } // TODO: make this more robust @@ -533,6 +525,20 @@ func transformServiceSecret(data interface{}) (interface{}, error) { } } +func transformServiceVolumeConfig(data interface{}) (interface{}, error) { + switch value := data.(type) { + case string: + return parseVolume(value) + case types.Dict: + return data, nil + case map[string]interface{}: + return data, nil + default: + return data, fmt.Errorf("invalid type %T for service volume", value) + } + +} + func transformServiceNetworkMap(value interface{}) (interface{}, error) { if list, ok := value.([]interface{}); ok { mapValue := map[interface{}]interface{}{} diff --git a/compose/loader/loader_test.go b/compose/loader/loader_test.go index 53f4280b64..126832a3b2 100644 --- a/compose/loader/loader_test.go +++ b/compose/loader/loader_test.go @@ -837,13 +837,13 @@ func TestFullExample(t *testing.T) { }, }, User: "someone", - Volumes: []string{ - "/var/lib/mysql", - "/opt/data:/var/lib/mysql", - fmt.Sprintf("%s:/code", workingDir), - fmt.Sprintf("%s/static:/var/www/html", workingDir), - fmt.Sprintf("%s/configs:/etc/configs/:ro", homeDir), - "datavolume:/var/lib/mysql", + Volumes: []types.ServiceVolumeConfig{ + {Target: "/var/lib/mysql", Type: "volume"}, + {Source: "/opt/data", Target: "/var/lib/mysql", Type: "bind"}, + {Source: workingDir, Target: "/code", Type: "bind"}, + {Source: workingDir + "/static", Target: "/var/www/html", Type: "bind"}, + {Source: homeDir + "/configs", Target: "/etc/configs/", Type: "bind", ReadOnly: true}, + {Source: "datavolume", Target: "/var/lib/mysql", Type: "volume"}, }, WorkingDir: "/code", } @@ -1041,3 +1041,31 @@ services: assert.Equal(t, 1, len(config.Services)) assert.Equal(t, expected, config.Services[0].Ports) } + +func TestLoadExpandedMountFormat(t *testing.T) { + config, err := loadYAML(` +version: "3.1" +services: + web: + image: busybox + volumes: + - type: volume + source: foo + target: /target + read_only: true +volumes: + foo: {} +`) + assert.NoError(t, err) + + expected := types.ServiceVolumeConfig{ + Type: "volume", + Source: "foo", + Target: "/target", + ReadOnly: true, + } + + assert.Equal(t, 1, len(config.Services)) + assert.Equal(t, 1, len(config.Services[0].Volumes)) + assert.Equal(t, expected, config.Services[0].Volumes[0]) +} diff --git a/compose/types/types.go b/compose/types/types.go index 307b5fd907..dce13c928a 100644 --- a/compose/types/types.go +++ b/compose/types/types.go @@ -228,7 +228,7 @@ type ServiceVolumeConfig struct { Type string Source string Target string - ReadOnly string `mapstructure:"read_only"` + ReadOnly bool `mapstructure:"read_only"` Bind *ServiceVolumeBind Volume *ServiceVolumeVolume }