Pārlūkot izejas kodu

Add expanded mount syntax to Compose schema and types.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin 8 gadi atpakaļ
vecāks
revīzija
65c899bee5

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
cli/compose/schema/bindata.go


+ 31 - 1
cli/compose/schema/data/config_schema_v3.1.json

@@ -235,7 +235,37 @@
         },
         "user": {"type": "string"},
         "userns_mode": {"type": "string"},
-        "volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
+        "volumes": {
+          "type": "array",
+          "items": {
+            "oneOf": [
+              {"type": "string"},
+              {
+                "type": "object",
+                "required": ["type"],
+                "properties": {
+                  "type": {"type": "string"},
+                  "source": {"type": "string"},
+                  "target": {"type": "string"},
+                  "read_only": {"type": "boolean"},
+                  "bind": {
+                    "type": "object",
+                    "properties": {
+                      "propagation": {"type": "string"}
+                    }
+                  },
+                  "volume": {
+                    "type": "object",
+                    "properties": {
+                      "nocopy": {"type": "boolean"}
+                    }
+                  }
+                }
+              }
+            ],
+            "uniqueItems": true
+          }
+        },
         "working_dir": {"type": "string"}
       },
       "additionalProperties": false

+ 44 - 18
cli/compose/schema/schema.go

@@ -78,18 +78,22 @@ func Validate(config map[string]interface{}, version string) error {
 
 func toError(result *gojsonschema.Result) error {
 	err := getMostSpecificError(result.Errors())
-	description := getDescription(err)
-	return fmt.Errorf("%s %s", err.Field(), description)
+	return err
 }
 
-func getDescription(err gojsonschema.ResultError) string {
-	if err.Type() == "invalid_type" {
-		if expectedType, ok := err.Details()["expected"].(string); ok {
+func getDescription(err validationError) string {
+	switch err.parent.Type() {
+	case "invalid_type":
+		if expectedType, ok := err.parent.Details()["expected"].(string); ok {
 			return fmt.Sprintf("must be a %s", humanReadableType(expectedType))
 		}
+	case "number_one_of", "number_any_of":
+		if err.child == nil {
+			return err.parent.Description()
+		}
+		return err.child.Description()
 	}
-
-	return err.Description()
+	return err.parent.Description()
 }
 
 func humanReadableType(definition string) string {
@@ -113,23 +117,45 @@ func humanReadableType(definition string) string {
 	return definition
 }
 
-func getMostSpecificError(errors []gojsonschema.ResultError) gojsonschema.ResultError {
-	var mostSpecificError gojsonschema.ResultError
+type validationError struct {
+	parent gojsonschema.ResultError
+	child  gojsonschema.ResultError
+}
+
+func (err validationError) Error() string {
+	description := getDescription(err)
+	return fmt.Sprintf("%s %s", err.parent.Field(), description)
+}
+
+func getMostSpecificError(errors []gojsonschema.ResultError) validationError {
+	mostSpecificError := 0
+	for i, err := range errors {
+		if specificity(err) > specificity(errors[mostSpecificError]) {
+			mostSpecificError = i
+			continue
+		}
 
-	for _, err := range errors {
-		if mostSpecificError == nil {
-			mostSpecificError = err
-		} else if specificity(err) > specificity(mostSpecificError) {
-			mostSpecificError = err
-		} else if specificity(err) == specificity(mostSpecificError) {
+		if specificity(err) == specificity(errors[mostSpecificError]) {
 			// Invalid type errors win in a tie-breaker for most specific field name
-			if err.Type() == "invalid_type" && mostSpecificError.Type() != "invalid_type" {
-				mostSpecificError = err
+			if err.Type() == "invalid_type" && errors[mostSpecificError].Type() != "invalid_type" {
+				mostSpecificError = i
 			}
 		}
 	}
 
-	return mostSpecificError
+	if mostSpecificError+1 == len(errors) {
+		return validationError{parent: errors[mostSpecificError]}
+	}
+
+	switch errors[mostSpecificError].Type() {
+	case "number_one_of", "number_any_of":
+		return validationError{
+			parent: errors[mostSpecificError],
+			child:  errors[mostSpecificError+1],
+		}
+	default:
+		return validationError{parent: errors[mostSpecificError]}
+	}
 }
 
 func specificity(err gojsonschema.ResultError) int {

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

@@ -119,7 +119,7 @@ type ServiceConfig struct {
 	Tty             bool `mapstructure:"tty"`
 	Ulimits         map[string]*UlimitsConfig
 	User            string
-	Volumes         []string
+	Volumes         []ServiceVolumeConfig
 	WorkingDir      string `mapstructure:"working_dir"`
 }
 
@@ -223,6 +223,26 @@ type ServicePortConfig struct {
 	Protocol  string
 }
 
+// ServiceVolumeConfig are references to a volume used by a service
+type ServiceVolumeConfig struct {
+	Type     string
+	Source   string
+	Target   string
+	ReadOnly string `mapstructure:"read_only"`
+	Bind     *ServiceVolumeBind
+	Volume   *ServiceVolumeVolume
+}
+
+// ServiceVolumeBind are options for a service volume of type bind
+type ServiceVolumeBind struct {
+	Propogation string
+}
+
+// ServiceVolumeVolume are options for a service volume of type volume
+type ServiceVolumeVolume struct {
+	NoCopy bool `mapstructure:"nocopy"`
+}
+
 // ServiceSecretConfig is the secret configuration for a service
 type ServiceSecretConfig struct {
 	Source string

+ 1 - 1
opts/mount.go

@@ -100,7 +100,7 @@ func (m *MountOpt) Set(value string) error {
 		case "volume-nocopy":
 			volumeOptions().NoCopy, err = strconv.ParseBool(value)
 			if err != nil {
-				return fmt.Errorf("invalid value for populate: %s", value)
+				return fmt.Errorf("invalid value for volume-nocopy: %s", value)
 			}
 		case "volume-label":
 			setValueOnMap(volumeOptions().Labels, value)

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels