mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 17:26:28 +00:00
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:
parent
c9c6d20a45
commit
02038f512d
@ -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
113
src/cmd/moby/schema.go
Normal 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" }
|
||||
}
|
||||
}
|
||||
`)
|
Loading…
Reference in New Issue
Block a user