mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-21 01:59:07 +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"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/engine-api/types"
|
"github.com/docker/engine-api/types"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/xeipuuv/gojsonschema"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -80,11 +81,56 @@ type MobyImage struct {
|
|||||||
Sysctl map[string]string
|
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
|
// NewConfig parses a config file
|
||||||
func NewConfig(config []byte) (*Moby, error) {
|
func NewConfig(config []byte) (*Moby, error) {
|
||||||
m := Moby{}
|
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 {
|
if err != nil {
|
||||||
return &m, err
|
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