Add Yaml validation

Fix #1292

Transform the Yaml struct to JSON and validate it against a JSON schema.

Signed-off-by: Thomas Gazagnaire <thomas@gazagnaire.org>
This commit is contained in:
Thomas Gazagnaire 2017-04-11 23:08:58 +02:00
parent c9c6d20a45
commit 02038f512d
2 changed files with 160 additions and 1 deletions

View File

@ -15,6 +15,7 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/docker/engine-api/types"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/xeipuuv/gojsonschema"
"gopkg.in/yaml.v2"
)
@ -80,11 +81,56 @@ type MobyImage struct {
Sysctl map[string]string
}
// recursively convert the map keys from `interface{}` to `string`
// this is needed to convert "yaml" interfaces to "JSON" interfaces
// see http://stackoverflow.com/questions/40737122/convert-yaml-to-json-without-struct-golang#answer-40737676
func convert(i interface{}) interface{} {
switch x := i.(type) {
case map[interface{}]interface{}:
m2 := map[string]interface{}{}
for k, v := range x {
m2[k.(string)] = convert(v)
}
return m2
case []interface{}:
for i, v := range x {
x[i] = convert(v)
}
}
return i
}
// NewConfig parses a config file
func NewConfig(config []byte) (*Moby, error) {
m := Moby{}
err := yaml.Unmarshal(config, &m)
// Parse raw yaml
var rawYaml interface{}
err := yaml.Unmarshal(config, &rawYaml)
if err != nil {
return &m, err
}
// Convert to raw JSON
rawJSON := convert(rawYaml)
// Validate raw yaml with JSON schema
schemaLoader := gojsonschema.NewStringLoader(schema)
documentLoader := gojsonschema.NewGoLoader(rawJSON)
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
if err != nil {
return &m, err
}
if !result.Valid() {
fmt.Printf("The configuration file is invalid:\n")
for _, desc := range result.Errors() {
fmt.Printf("- %s\n", desc)
}
return &m, fmt.Errorf("invalid configuration file")
}
// Parse yaml
err = yaml.Unmarshal(config, &m)
if err != nil {
return &m, err
}

113
src/cmd/moby/schema.go Normal file
View File

@ -0,0 +1,113 @@
package main
var schema = string(`
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Moby Config",
"additionalProperties": false,
"definitions": {
"kernel": {
"type": "object",
"additionalProperties": false,
"properties": {
"image": { "type": "string"},
"cmdline": { "type": "string"}
}
},
"file": {
"type": "object",
"additionalProperties": false,
"properties": {
"path": {"type": "string"},
"directory": {"type": "boolean"},
"contents": {"type": "string"}
}
},
"files": {
"type": "array",
"items": { "$ref": "#/definitions/file" }
},
"output": {
"type": "object",
"additionalProperties": false,
"properties": {
"format": {"type": "string"},
"project": {"type": "string"},
"bucket": {"type": "string"},
"family": {"type": "string"},
"keys": {"type": "string"},
"public": {"type": "boolean"},
"replace": {"type": "boolean"}
}
},
"outputs": {
"type": "array",
"items": { "$ref": "#/definitions/output" }
},
"trust": {
"type": "object",
"additionalProperties": false,
"properties": {
"image": { "$ref": "#/definitions/strings" },
"org": { "$ref": "#/definitions/strings" }
}
},
"strings": {
"type": "array",
"items": {"type": "string"}
},
"image": {
"type": "object",
"additionalProperties": false,
"required": ["name", "image"],
"properties": {
"name": {"type": "string"},
"image": {"type": "string"},
"capabilities": { "$ref": "#/definitions/strings" },
"mounts": { "$ref": "#/definitions/strings" },
"binds": { "$ref": "#/definitions/strings" },
"tmpfs": { "$ref": "#/definitions/strings" },
"command": { "$ref": "#/definitions/strings" },
"env": { "$ref": "#/definitions/strings" },
"cwd": { "type": "string"},
"net": { "type": "string"},
"pid": { "type": "string"},
"ipc": { "type": "string"},
"uts": { "type": "string"},
"readonly": { "type": "boolean"},
"maskedPaths": { "$ref": "#/definitions/strings" },
"readonlyPaths": { "$ref": "#/definitions/strings" },
"uid": {"type": "integer"},
"gid": {"type": "integer"},
"additionalGids": {
"type": "array",
"items": { "type": "integer" }
},
"noNewPrivileges": {"type": "boolean"},
"hostname": {"type": "string"},
"oomScoreAdj": {"type": "integer"},
"disableOOMKiller": {"type": "boolean"},
"rootfsPropagation": {"type": "string"},
"cgroupsPath": {"type": "string"},
"sysctl": {
"type": "array",
"items": { "$ref": "#/definitions/strings" }
}
}
},
"images": {
"type": "array",
"items": { "$ref": "#/definitions/image" }
}
},
"properties": {
"kernel": { "$ref": "#/definitions/kernel" },
"init": { "$ref": "#/definitions/strings" },
"onboot": { "$ref": "#/definitions/images" },
"services": { "$ref": "#/definitions/images" },
"trust": { "$ref": "#/definitions/trust" },
"files": { "$ref": "#/definitions/files" },
"outputs": { "$ref": "#/definitions/outputs" }
}
}
`)