Просмотр исходного кода

Support expanded mounts in Compose loader

Add a test for loading expanded mount format.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin 8 лет назад
Родитель
Сommit
190dc5a40a
3 измененных файлов с 58 добавлено и 24 удалено
  1. 22 16
      cli/compose/loader/loader.go
  2. 35 7
      cli/compose/loader/loader_test.go
  3. 1 1
      cli/compose/types/types.go

+ 22 - 16
cli/compose/loader/loader.go

@@ -251,6 +251,8 @@ func transformHook(
 		return transformMappingOrList(data, "="), nil
 		return transformMappingOrList(data, "="), nil
 	case reflect.TypeOf(types.MappingWithColon{}):
 	case reflect.TypeOf(types.MappingWithColon{}):
 		return transformMappingOrList(data, ":"), nil
 		return transformMappingOrList(data, ":"), nil
+	case reflect.TypeOf(types.ServiceVolumeConfig{}):
+		return transformServiceVolumeConfig(data)
 	}
 	}
 	return data, nil
 	return data, nil
 }
 }
@@ -329,10 +331,7 @@ func loadService(name string, serviceDict types.Dict, workingDir string) (*types
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	if err := resolveVolumePaths(serviceConfig.Volumes, workingDir); err != nil {
-		return nil, err
-	}
-
+	resolveVolumePaths(serviceConfig.Volumes, workingDir)
 	return serviceConfig, nil
 	return serviceConfig, nil
 }
 }
 
 
@@ -365,22 +364,15 @@ func resolveEnvironment(serviceConfig *types.ServiceConfig, workingDir string) e
 	return nil
 	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
 			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
 // 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) {
 func transformServiceNetworkMap(value interface{}) (interface{}, error) {
 	if list, ok := value.([]interface{}); ok {
 	if list, ok := value.([]interface{}); ok {
 		mapValue := map[interface{}]interface{}{}
 		mapValue := map[interface{}]interface{}{}

+ 35 - 7
cli/compose/loader/loader_test.go

@@ -837,13 +837,13 @@ func TestFullExample(t *testing.T) {
 			},
 			},
 		},
 		},
 		User: "someone",
 		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",
 		WorkingDir: "/code",
 	}
 	}
@@ -1041,3 +1041,31 @@ services:
 	assert.Equal(t, 1, len(config.Services))
 	assert.Equal(t, 1, len(config.Services))
 	assert.Equal(t, expected, config.Services[0].Ports)
 	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])
+}

+ 1 - 1
cli/compose/types/types.go

@@ -228,7 +228,7 @@ type ServiceVolumeConfig struct {
 	Type     string
 	Type     string
 	Source   string
 	Source   string
 	Target   string
 	Target   string
-	ReadOnly string `mapstructure:"read_only"`
+	ReadOnly bool `mapstructure:"read_only"`
 	Bind     *ServiceVolumeBind
 	Bind     *ServiceVolumeBind
 	Volume   *ServiceVolumeVolume
 	Volume   *ServiceVolumeVolume
 }
 }