Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit 65374488f92512cf34667cb71ea6d62985310f65)
Signed-off-by: Victor Vieux <vieux@docker.com>
| ... | ... |
@@ -62,16 +62,11 @@ func Load(configDetails types.ConfigDetails) (*types.Config, error) {
|
| 62 | 62 |
} |
| 63 | 63 |
} |
| 64 | 64 |
|
| 65 |
- if err := schema.Validate(configDict); err != nil {
|
|
| 65 |
+ if err := schema.Validate(configDict, schema.Version(configDict)); err != nil {
|
|
| 66 | 66 |
return nil, err |
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 | 69 |
cfg := types.Config{}
|
| 70 |
- version := configDict["version"].(string) |
|
| 71 |
- if version != "3" && version != "3.0" {
|
|
| 72 |
- return nil, fmt.Errorf(`Unsupported Compose file version: %#v. The only version supported is "3" (or "3.0")`, version) |
|
| 73 |
- } |
|
| 74 |
- |
|
| 75 | 70 |
if services, ok := configDict["services"]; ok {
|
| 76 | 71 |
servicesConfig, err := interpolation.Interpolate(services.(types.Dict), "service", os.LookupEnv) |
| 77 | 72 |
if err != nil {
|
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
// Code generated by go-bindata. |
| 2 | 2 |
// sources: |
| 3 | 3 |
// data/config_schema_v3.0.json |
| 4 |
+// data/config_schema_v3.1.json |
|
| 4 | 5 |
// DO NOT EDIT! |
| 5 | 6 |
|
| 6 | 7 |
package schema |
| ... | ... |
@@ -88,6 +89,26 @@ func dataConfig_schema_v30Json() (*asset, error) {
|
| 88 | 88 |
return a, nil |
| 89 | 89 |
} |
| 90 | 90 |
|
| 91 |
+var _dataConfig_schema_v31Json = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xec\x1a\x4d\x93\xdb\xa8\xf2\xee\x5f\xa1\x52\x72\x8b\x67\x26\xaf\x5e\xea\x55\xbd\xdc\xde\xf1\x9d\x76\xcf\x3b\xe5\xa8\xb0\xd4\x96\xc9\x20\x20\x80\x9c\x71\x52\xfe\xef\x5b\xe8\xcb\x80\x41\x60\x5b\xd9\xa4\x6a\xf7\x34\x63\xd1\xdd\xf4\x77\x37\x0d\xdf\x57\x59\x96\xbf\x95\xe5\x1e\x1a\x94\x7f\xcc\xf2\xbd\x52\xfc\xe3\xd3\xd3\x67\xc9\xe8\x43\xff\xf5\x91\x89\xfa\xa9\x12\x68\xa7\x1e\xde\x7f\x78\xea\xbf\xbd\xc9\xd7\x1a\x0f\x57\x1a\xa5\x64\x74\x87\xeb\xa2\x5f\x29\x0e\xff\x7e\xfc\xd7\xa3\x46\xef\x41\xd4\x91\x83\x06\x62\xdb\xcf\x50\xaa\xfe\x9b\x80\x2f\x2d\x16\xa0\x91\x9f\xf3\x03\x08\x89\x19\xcd\x37\xeb\x95\x5e\xe3\x82\x71\x10\x0a\x83\xcc\x3f\x66\x9a\xb9\x2c\x9b\x40\xc6\x0f\x06\x59\xa9\x04\xa6\x75\xde\x7d\x3e\x75\x14\xb2\x2c\x97\x20\x0e\xb8\x34\x28\x4c\xac\xbe\x79\x3a\xd3\x7f\x9a\xc0\xd6\x2e\x55\x83\xd9\xee\x3b\x47\x4a\x81\xa0\xbf\x5f\xf2\xd6\x2d\x7f\x7a\x46\x0f\xdf\xfe\xf7\xf0\xc7\xfb\x87\xff\x3e\x16\x0f\x9b\x77\x6f\xad\x65\xad\x5f\x01\xbb\x7e\xfb\x0a\x76\x98\x62\x85\x19\x9d\xf6\xcf\x27\xc8\xd3\xf0\xdf\x69\xda\x18\x55\x55\x07\x8c\x88\xb5\xf7\x0e\x11\x09\xb6\xcc\x14\xd4\x57\x26\x5e\x62\x32\x4f\x60\x3f\x49\xe6\x61\x7f\x8f\xcc\xb6\x38\x07\x46\xda\x26\x6a\xc1\x11\xea\x27\x09\xd3\x6f\xbf\x8c\xfd\x24\x94\x02\x54\xdc\x65\x7b\xa8\x9f\xe6\xb1\x7a\xfb\xfb\x04\x5e\x8d\x42\xcf\xc2\xf6\x10\xc6\xde\x1d\x83\x56\x78\xfb\x54\xe5\x0b\xaf\xb0\xae\x26\x65\x05\xb4\x54\x01\x27\xec\xa8\xbf\x05\xf4\xd1\x03\x34\x40\x55\x3e\xa9\x20\xcb\xf2\x6d\x8b\x49\xe5\x6a\x94\x51\xf8\x4d\x93\x78\x36\x3e\x66\xd9\x77\x37\x93\x19\x74\xba\x75\xeb\x57\xd8\xe0\xd3\x7a\x40\x96\x69\xbd\x64\x54\xc1\xab\xea\x84\x9a\xdf\xba\x57\x01\x2b\x5f\x40\xec\x30\x81\x54\x0c\x24\x6a\x39\xa3\x32\x82\xa5\x2a\x98\x28\x2a\x5c\xaa\xfc\xe4\xa0\x5f\xd0\x8b\xfb\xd3\x84\x6a\xfc\xda\xac\x3c\x04\xf3\x12\xf1\x02\x55\x95\x25\x07\x12\x02\x1d\xf3\x75\x96\x63\x05\x8d\xf4\x8b\x98\xe5\x2d\xc5\x5f\x5a\xf8\xff\x00\xa2\x44\x0b\x2e\xdd\x4a\x30\xbe\x3c\xe1\x5a\xb0\x96\x17\x1c\x09\xed\x60\xf3\xea\xcf\x4b\xd6\x34\x88\x2e\xe5\x75\xd7\xc8\x91\xa0\x79\x46\x15\xc2\x14\x44\x41\x51\x13\x73\x24\x1d\x75\x40\x2b\x59\xf4\x05\x7f\xd6\x8d\x76\x45\x8f\x2f\x1d\x02\x53\xf5\x5f\xd4\x1e\x15\x9d\x73\xec\x9e\x8c\x76\x6d\xcd\x5b\xee\x20\x16\x12\x90\x28\xf7\x37\xe2\xb3\x06\x61\x9a\xa2\x3b\xa0\x4a\x1c\x39\xc3\xbd\xbf\xfc\x72\x8e\x00\xf4\x50\x4c\xb9\xe4\x6a\x35\x00\x3d\x60\xc1\x68\x33\x46\x43\x4a\x82\x99\x92\xbc\xc6\x7f\xe5\x4c\x82\xab\x18\x47\x40\x73\x69\x12\xd5\xd2\xc9\x88\xf1\x3c\x0a\xbe\xce\x72\xda\x36\x5b\x10\xba\x87\xb5\x20\x77\x4c\x34\x48\x33\x3b\xee\x6d\x2c\x5b\x9a\xf6\x78\x9e\xa9\x40\x53\x06\x5d\xd6\x11\x29\x08\xa6\x2f\xcb\xbb\x38\xbc\x2a\x81\x8a\x3d\x93\x2a\x3d\x87\x1b\xe8\x7b\x40\x44\xed\xcb\x3d\x94\x2f\x33\xe8\x26\x94\x85\xcd\xa4\x4a\x71\x72\xdc\xa0\x3a\x0e\xc4\xcb\x18\x08\x41\x5b\x20\x37\xc9\xb9\xa8\xf2\x0d\xb2\xac\xae\x35\x68\xc8\xe3\x2e\x3a\x97\x61\x39\x56\xf3\x2b\x81\x0f\x20\x52\x0b\x38\xe3\xe7\x86\xcb\x5d\x8c\x37\x20\x59\xbc\xfb\xb4\x40\x3f\x3d\xf6\xcd\xe7\x4c\x54\x75\xff\x11\x92\x6f\xdc\x76\x21\x73\xea\xbe\xef\x8b\x23\x61\x5a\x43\x61\x59\xa5\x41\xa5\xee\x1b\x04\xc8\x80\x5d\xcf\xa0\xc3\xe9\xa6\x68\x58\x15\x72\xd0\x0b\x60\x57\x37\xc1\x4c\x7d\x75\x21\xcc\x6e\xea\x1f\x93\x4c\x17\x3d\x40\x44\xa4\x09\xb1\x97\xca\xe6\x99\xdd\xb8\x8b\x75\x70\x88\x60\x24\x21\x1e\xec\x41\x45\x5a\xd4\x30\x3f\x7c\x48\xf4\x09\x1f\xee\x7f\x66\x71\x03\xa8\x41\x9a\xe9\x3d\x72\x84\xd4\x99\x95\x2e\xdc\x7c\x8c\x6c\x22\xd1\xf6\x83\x5b\x78\x8e\xab\x70\xae\xe8\x32\x84\x19\x60\x9c\x09\x75\x11\x5d\x7f\x4d\xb9\xef\xb7\xbe\xbb\xda\x73\x81\x0f\x98\x40\x0d\xf6\xa9\x65\xcb\x18\x01\x44\xad\xd4\x23\x00\x55\x05\xa3\xe4\x98\x00\x29\x15\x12\xd1\x03\x85\x84\xb2\x15\x58\x1d\x0b\xc6\xd5\xe2\x7d\x86\xdc\x37\x85\xc4\xdf\xc0\xb6\xe6\x39\xdf\x0f\x84\x36\x0e\x43\xce\x84\xe4\x46\x83\x86\x52\x52\x3c\x8c\x3d\x89\x30\x9a\xa8\xe2\x29\x2a\x97\xac\x15\x65\xea\x01\x5b\xef\x89\x44\x0d\xa9\x47\x78\xed\x6e\x76\xd8\xcc\x03\xd7\xd7\x00\x5f\x14\xba\xc1\x84\xb1\xaa\xec\xfe\x36\xf3\xca\xc9\x1b\xfa\xf2\x28\x4b\x75\x5b\xb7\x26\x55\x85\x69\xc1\x38\xd0\x68\x6c\x48\xc5\x78\x21\x71\x4d\x11\x89\xc6\x87\x06\xad\x05\x2a\xa1\xe0\x20\x30\xf3\x6a\x6d\x6d\x26\x85\xaa\x15\x48\xb3\x6a\x91\x51\x0d\xdf\xdd\x78\xac\x54\x2a\x1e\xec\x2d\xc1\x0d\x0e\x07\x8d\xc7\x6b\x13\x3a\x80\xbe\xfa\xfb\x8b\xfe\x4c\xc1\x3f\x73\x8a\xa9\x82\x5a\xbb\xc9\xa5\x53\xcd\xf4\x9c\xf3\x2d\x67\x42\xaf\xb9\x47\xc2\xb6\xd2\x0c\x1f\x59\x1f\x98\x3b\xe5\x47\xf0\x75\xa2\x5e\xbe\xac\xbb\x8e\x8e\xde\x7a\x60\x64\xe3\x85\xbf\xaa\x98\xbb\x6c\x6c\x82\xf5\xd4\x1f\x54\xad\x8c\x1e\x0b\x3a\x18\x2a\xe7\x5a\xda\x09\xd4\x18\xda\x2f\x5a\x2d\x74\x9b\xac\x83\xa0\xc2\x7e\x6e\x57\x8e\x64\x57\x8c\xdd\x9d\x13\xeb\x48\xc0\x37\x4f\x36\x41\xdd\x99\xf2\xf3\xe4\x9b\x63\x27\x72\x9e\xc4\x07\x86\xcb\xda\x95\xc4\xc1\xca\x33\x3e\x9d\x2a\xdc\x00\x6b\x55\x04\x4a\x80\x12\xd8\xd1\xfc\x98\x8a\x4d\x62\x20\x7f\xcd\xc1\x50\x85\x25\xda\x3a\x33\xe6\x29\x9d\xdd\x64\xde\xec\x3c\xc0\x1f\x07\x46\x73\xc6\x35\x20\x17\xb0\x6d\x4a\xb0\x08\xe0\x04\x97\x48\xc6\x12\xd2\x1d\x63\x8a\x96\x57\x48\x41\xd1\xdf\xcf\x5e\x55\x02\x66\x72\x3f\x47\x02\x11\x02\x04\xcb\x26\x25\x97\xe6\x15\x10\x74\xbc\xa9\x36\x76\xe8\x3b\x84\x49\x2b\xa0\x40\xa5\x1a\xae\x80\x23\x9e\x99\x37\x8c\x62\xc5\xbc\x99\x22\x6d\xcb\x06\xbd\x16\xe3\xb6\x1d\x48\xac\xc3\xb1\x9b\xfb\xd4\x09\x83\xe1\x09\x7d\x03\x78\x5d\x95\x9e\x31\xd1\xb9\xe6\x07\x3c\x66\xdc\xf1\x42\x74\x01\x52\x27\xa5\x69\x00\x14\xc5\x8f\x96\x98\xe1\xb4\x51\x70\x46\x70\x79\x5c\x4a\xc2\x92\xd1\x5e\xc9\x29\x0e\x71\xa7\x07\x6a\x77\xd0\x2d\x51\xc3\x55\x34\x58\x3b\x84\xaf\x98\x56\xec\xeb\x15\x1b\x2e\xe7\x4a\x9c\xa0\x12\x9c\x7c\x77\xaf\xa2\xa5\x12\x08\x53\x75\x75\x59\xbf\x57\xac\x3b\xaa\xfa\xe4\x9f\x91\xac\x3f\xc1\xc5\xef\xd3\x03\x99\xbe\xe4\x6d\x74\x2a\xd8\x40\xc3\x84\xd7\x01\x17\x78\xf0\x11\x13\x71\x04\x5b\xa0\xaa\x25\x8d\x91\x07\xa8\x82\xf1\xe5\x4f\x1d\xf1\x51\xf1\x26\x9e\x90\x30\x47\xcd\x52\xd1\x91\x3c\x58\xcf\xbd\x35\x38\x9b\x9f\x5f\x64\xe1\x19\x46\x8c\xeb\x38\xef\x03\x84\x6c\xb7\x34\x30\x4a\xb8\x3c\x6d\xf8\x6e\xfb\xd3\x8f\x2b\xa7\xf0\xe1\xe4\xbe\xa4\x37\xde\x89\x05\xac\xfa\x3c\x75\x92\xeb\x49\x57\x9b\x64\x13\x07\x2f\xa4\x96\xe3\xff\xca\x06\xef\x8e\x9c\x31\x3c\x58\x8a\xa4\x8c\x01\xea\x9f\x8c\xf1\xcb\xf8\xd7\x4c\x51\xbc\xf1\x74\x70\xf5\xcb\xb4\x98\xd3\x0c\x50\x37\x17\xd2\x84\x27\x46\x7f\x7b\x43\xd8\xa3\x40\xc3\x20\x97\x67\xf8\x39\x3d\x26\xdf\x80\x0d\x18\x1b\x9b\x0d\x17\xcc\xf3\x2a\xd7\xae\x65\x73\xa3\x9f\x11\x24\x70\x23\xe2\x6c\x3a\x28\x6f\x5e\xf2\x05\xf3\xc7\xe3\xbb\x99\x8a\x3d\x77\x53\xfd\x83\x4a\xdd\x02\x63\x35\xbf\x4d\x9d\x36\x7f\xd4\xee\xe5\x4b\xcb\x40\xf4\x1b\xf8\x17\xef\x2e\xb5\x9c\xf4\x78\x31\x63\xfa\x6e\x8f\x46\xfb\x37\x93\x1b\x4b\x3f\x0e\x48\xff\xee\xc3\x48\xd8\x1b\xf3\xe4\x13\x32\xa3\xf7\x35\xa6\x3b\x98\x1d\x5f\x45\x06\xee\x21\x56\xe6\xdf\xee\x05\xeb\xea\xb4\xfa\x33\x00\x00\xff\xff\xb7\x14\xdd\xc9\x3a\x2f\x00\x00")
|
|
| 92 |
+ |
|
| 93 |
+func dataConfig_schema_v31JsonBytes() ([]byte, error) {
|
|
| 94 |
+ return bindataRead( |
|
| 95 |
+ _dataConfig_schema_v31Json, |
|
| 96 |
+ "data/config_schema_v3.1.json", |
|
| 97 |
+ ) |
|
| 98 |
+} |
|
| 99 |
+ |
|
| 100 |
+func dataConfig_schema_v31Json() (*asset, error) {
|
|
| 101 |
+ bytes, err := dataConfig_schema_v31JsonBytes() |
|
| 102 |
+ if err != nil {
|
|
| 103 |
+ return nil, err |
|
| 104 |
+ } |
|
| 105 |
+ |
|
| 106 |
+ info := bindataFileInfo{name: "data/config_schema_v3.1.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
|
| 107 |
+ a := &asset{bytes: bytes, info: info}
|
|
| 108 |
+ return a, nil |
|
| 109 |
+} |
|
| 110 |
+ |
|
| 91 | 111 |
// Asset loads and returns the asset for the given name. |
| 92 | 112 |
// It returns an error if the asset could not be found or |
| 93 | 113 |
// could not be loaded. |
| ... | ... |
@@ -141,6 +162,7 @@ func AssetNames() []string {
|
| 141 | 141 |
// _bindata is a table, holding each asset generator, mapped to its name. |
| 142 | 142 |
var _bindata = map[string]func() (*asset, error){
|
| 143 | 143 |
"data/config_schema_v3.0.json": dataConfig_schema_v30Json, |
| 144 |
+ "data/config_schema_v3.1.json": dataConfig_schema_v31Json, |
|
| 144 | 145 |
} |
| 145 | 146 |
|
| 146 | 147 |
// AssetDir returns the file names below a certain |
| ... | ... |
@@ -183,8 +205,9 @@ type bintree struct {
|
| 183 | 183 |
Children map[string]*bintree |
| 184 | 184 |
} |
| 185 | 185 |
var _bintree = &bintree{nil, map[string]*bintree{
|
| 186 |
- "data": &bintree{nil, map[string]*bintree{
|
|
| 187 |
- "config_schema_v3.0.json": &bintree{dataConfig_schema_v30Json, map[string]*bintree{}},
|
|
| 186 |
+ "data": {nil, map[string]*bintree{
|
|
| 187 |
+ "config_schema_v3.0.json": {dataConfig_schema_v30Json, map[string]*bintree{}},
|
|
| 188 |
+ "config_schema_v3.1.json": {dataConfig_schema_v31Json, map[string]*bintree{}},
|
|
| 188 | 189 |
}}, |
| 189 | 190 |
}} |
| 190 | 191 |
|
| 191 | 192 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,426 @@ |
| 0 |
+{
|
|
| 1 |
+ "$schema": "http://json-schema.org/draft-04/schema#", |
|
| 2 |
+ "id": "config_schema_v3.1.json", |
|
| 3 |
+ "type": "object", |
|
| 4 |
+ "required": ["version"], |
|
| 5 |
+ |
|
| 6 |
+ "properties": {
|
|
| 7 |
+ "version": {
|
|
| 8 |
+ "type": "string" |
|
| 9 |
+ }, |
|
| 10 |
+ |
|
| 11 |
+ "services": {
|
|
| 12 |
+ "id": "#/properties/services", |
|
| 13 |
+ "type": "object", |
|
| 14 |
+ "patternProperties": {
|
|
| 15 |
+ "^[a-zA-Z0-9._-]+$": {
|
|
| 16 |
+ "$ref": "#/definitions/service" |
|
| 17 |
+ } |
|
| 18 |
+ }, |
|
| 19 |
+ "additionalProperties": false |
|
| 20 |
+ }, |
|
| 21 |
+ |
|
| 22 |
+ "networks": {
|
|
| 23 |
+ "id": "#/properties/networks", |
|
| 24 |
+ "type": "object", |
|
| 25 |
+ "patternProperties": {
|
|
| 26 |
+ "^[a-zA-Z0-9._-]+$": {
|
|
| 27 |
+ "$ref": "#/definitions/network" |
|
| 28 |
+ } |
|
| 29 |
+ } |
|
| 30 |
+ }, |
|
| 31 |
+ |
|
| 32 |
+ "volumes": {
|
|
| 33 |
+ "id": "#/properties/volumes", |
|
| 34 |
+ "type": "object", |
|
| 35 |
+ "patternProperties": {
|
|
| 36 |
+ "^[a-zA-Z0-9._-]+$": {
|
|
| 37 |
+ "$ref": "#/definitions/volume" |
|
| 38 |
+ } |
|
| 39 |
+ }, |
|
| 40 |
+ "additionalProperties": false |
|
| 41 |
+ }, |
|
| 42 |
+ |
|
| 43 |
+ "secrets": {
|
|
| 44 |
+ "id": "#/properties/secrets", |
|
| 45 |
+ "type": "object", |
|
| 46 |
+ "patternProperties": {
|
|
| 47 |
+ "^[a-zA-Z0-9._-]+$": {
|
|
| 48 |
+ "$ref": "#/definitions/secret" |
|
| 49 |
+ } |
|
| 50 |
+ }, |
|
| 51 |
+ "additionalProperties": false |
|
| 52 |
+ } |
|
| 53 |
+ }, |
|
| 54 |
+ |
|
| 55 |
+ "additionalProperties": false, |
|
| 56 |
+ |
|
| 57 |
+ "definitions": {
|
|
| 58 |
+ |
|
| 59 |
+ "service": {
|
|
| 60 |
+ "id": "#/definitions/service", |
|
| 61 |
+ "type": "object", |
|
| 62 |
+ |
|
| 63 |
+ "properties": {
|
|
| 64 |
+ "deploy": {"$ref": "#/definitions/deployment"},
|
|
| 65 |
+ "build": {
|
|
| 66 |
+ "oneOf": [ |
|
| 67 |
+ {"type": "string"},
|
|
| 68 |
+ {
|
|
| 69 |
+ "type": "object", |
|
| 70 |
+ "properties": {
|
|
| 71 |
+ "context": {"type": "string"},
|
|
| 72 |
+ "dockerfile": {"type": "string"},
|
|
| 73 |
+ "args": {"$ref": "#/definitions/list_or_dict"}
|
|
| 74 |
+ }, |
|
| 75 |
+ "additionalProperties": false |
|
| 76 |
+ } |
|
| 77 |
+ ] |
|
| 78 |
+ }, |
|
| 79 |
+ "cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
| 80 |
+ "cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
| 81 |
+ "cgroup_parent": {"type": "string"},
|
|
| 82 |
+ "command": {
|
|
| 83 |
+ "oneOf": [ |
|
| 84 |
+ {"type": "string"},
|
|
| 85 |
+ {"type": "array", "items": {"type": "string"}}
|
|
| 86 |
+ ] |
|
| 87 |
+ }, |
|
| 88 |
+ "container_name": {"type": "string"},
|
|
| 89 |
+ "depends_on": {"$ref": "#/definitions/list_of_strings"},
|
|
| 90 |
+ "devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
| 91 |
+ "dns": {"$ref": "#/definitions/string_or_list"},
|
|
| 92 |
+ "dns_search": {"$ref": "#/definitions/string_or_list"},
|
|
| 93 |
+ "domainname": {"type": "string"},
|
|
| 94 |
+ "entrypoint": {
|
|
| 95 |
+ "oneOf": [ |
|
| 96 |
+ {"type": "string"},
|
|
| 97 |
+ {"type": "array", "items": {"type": "string"}}
|
|
| 98 |
+ ] |
|
| 99 |
+ }, |
|
| 100 |
+ "env_file": {"$ref": "#/definitions/string_or_list"},
|
|
| 101 |
+ "environment": {"$ref": "#/definitions/list_or_dict"},
|
|
| 102 |
+ |
|
| 103 |
+ "expose": {
|
|
| 104 |
+ "type": "array", |
|
| 105 |
+ "items": {
|
|
| 106 |
+ "type": ["string", "number"], |
|
| 107 |
+ "format": "expose" |
|
| 108 |
+ }, |
|
| 109 |
+ "uniqueItems": true |
|
| 110 |
+ }, |
|
| 111 |
+ |
|
| 112 |
+ "external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
| 113 |
+ "extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
|
| 114 |
+ "healthcheck": {"$ref": "#/definitions/healthcheck"},
|
|
| 115 |
+ "hostname": {"type": "string"},
|
|
| 116 |
+ "image": {"type": "string"},
|
|
| 117 |
+ "ipc": {"type": "string"},
|
|
| 118 |
+ "labels": {"$ref": "#/definitions/list_or_dict"},
|
|
| 119 |
+ "links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
| 120 |
+ |
|
| 121 |
+ "logging": {
|
|
| 122 |
+ "type": "object", |
|
| 123 |
+ |
|
| 124 |
+ "properties": {
|
|
| 125 |
+ "driver": {"type": "string"},
|
|
| 126 |
+ "options": {
|
|
| 127 |
+ "type": "object", |
|
| 128 |
+ "patternProperties": {
|
|
| 129 |
+ "^.+$": {"type": ["string", "number", "null"]}
|
|
| 130 |
+ } |
|
| 131 |
+ } |
|
| 132 |
+ }, |
|
| 133 |
+ "additionalProperties": false |
|
| 134 |
+ }, |
|
| 135 |
+ |
|
| 136 |
+ "mac_address": {"type": "string"},
|
|
| 137 |
+ "network_mode": {"type": "string"},
|
|
| 138 |
+ |
|
| 139 |
+ "networks": {
|
|
| 140 |
+ "oneOf": [ |
|
| 141 |
+ {"$ref": "#/definitions/list_of_strings"},
|
|
| 142 |
+ {
|
|
| 143 |
+ "type": "object", |
|
| 144 |
+ "patternProperties": {
|
|
| 145 |
+ "^[a-zA-Z0-9._-]+$": {
|
|
| 146 |
+ "oneOf": [ |
|
| 147 |
+ {
|
|
| 148 |
+ "type": "object", |
|
| 149 |
+ "properties": {
|
|
| 150 |
+ "aliases": {"$ref": "#/definitions/list_of_strings"},
|
|
| 151 |
+ "ipv4_address": {"type": "string"},
|
|
| 152 |
+ "ipv6_address": {"type": "string"}
|
|
| 153 |
+ }, |
|
| 154 |
+ "additionalProperties": false |
|
| 155 |
+ }, |
|
| 156 |
+ {"type": "null"}
|
|
| 157 |
+ ] |
|
| 158 |
+ } |
|
| 159 |
+ }, |
|
| 160 |
+ "additionalProperties": false |
|
| 161 |
+ } |
|
| 162 |
+ ] |
|
| 163 |
+ }, |
|
| 164 |
+ "pid": {"type": ["string", "null"]},
|
|
| 165 |
+ |
|
| 166 |
+ "ports": {
|
|
| 167 |
+ "type": "array", |
|
| 168 |
+ "items": {
|
|
| 169 |
+ "type": ["string", "number"], |
|
| 170 |
+ "format": "ports" |
|
| 171 |
+ }, |
|
| 172 |
+ "uniqueItems": true |
|
| 173 |
+ }, |
|
| 174 |
+ |
|
| 175 |
+ "privileged": {"type": "boolean"},
|
|
| 176 |
+ "read_only": {"type": "boolean"},
|
|
| 177 |
+ "restart": {"type": "string"},
|
|
| 178 |
+ "security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
| 179 |
+ "shm_size": {"type": ["number", "string"]},
|
|
| 180 |
+ "secrets": {
|
|
| 181 |
+ "type": "array", |
|
| 182 |
+ "items": {
|
|
| 183 |
+ "oneOf": [ |
|
| 184 |
+ {"type": "string"},
|
|
| 185 |
+ {
|
|
| 186 |
+ "type": "object", |
|
| 187 |
+ "properties": {
|
|
| 188 |
+ "source": {"type": "string"},
|
|
| 189 |
+ "target": {"type": "string"},
|
|
| 190 |
+ "uid": {"type": "string"},
|
|
| 191 |
+ "gid": {"type": "string"},
|
|
| 192 |
+ "mode": {"type": "number"}
|
|
| 193 |
+ } |
|
| 194 |
+ } |
|
| 195 |
+ ] |
|
| 196 |
+ } |
|
| 197 |
+ }, |
|
| 198 |
+ "sysctls": {"$ref": "#/definitions/list_or_dict"},
|
|
| 199 |
+ "stdin_open": {"type": "boolean"},
|
|
| 200 |
+ "stop_signal": {"type": "string"},
|
|
| 201 |
+ "stop_grace_period": {"type": "string", "format": "duration"},
|
|
| 202 |
+ "tmpfs": {"$ref": "#/definitions/string_or_list"},
|
|
| 203 |
+ "tty": {"type": "boolean"},
|
|
| 204 |
+ "ulimits": {
|
|
| 205 |
+ "type": "object", |
|
| 206 |
+ "patternProperties": {
|
|
| 207 |
+ "^[a-z]+$": {
|
|
| 208 |
+ "oneOf": [ |
|
| 209 |
+ {"type": "integer"},
|
|
| 210 |
+ {
|
|
| 211 |
+ "type":"object", |
|
| 212 |
+ "properties": {
|
|
| 213 |
+ "hard": {"type": "integer"},
|
|
| 214 |
+ "soft": {"type": "integer"}
|
|
| 215 |
+ }, |
|
| 216 |
+ "required": ["soft", "hard"], |
|
| 217 |
+ "additionalProperties": false |
|
| 218 |
+ } |
|
| 219 |
+ ] |
|
| 220 |
+ } |
|
| 221 |
+ } |
|
| 222 |
+ }, |
|
| 223 |
+ "user": {"type": "string"},
|
|
| 224 |
+ "userns_mode": {"type": "string"},
|
|
| 225 |
+ "volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
|
| 226 |
+ "working_dir": {"type": "string"}
|
|
| 227 |
+ }, |
|
| 228 |
+ "additionalProperties": false |
|
| 229 |
+ }, |
|
| 230 |
+ |
|
| 231 |
+ "healthcheck": {
|
|
| 232 |
+ "id": "#/definitions/healthcheck", |
|
| 233 |
+ "type": ["object", "null"], |
|
| 234 |
+ "properties": {
|
|
| 235 |
+ "interval": {"type":"string"},
|
|
| 236 |
+ "timeout": {"type":"string"},
|
|
| 237 |
+ "retries": {"type": "number"},
|
|
| 238 |
+ "test": {
|
|
| 239 |
+ "oneOf": [ |
|
| 240 |
+ {"type": "string"},
|
|
| 241 |
+ {"type": "array", "items": {"type": "string"}}
|
|
| 242 |
+ ] |
|
| 243 |
+ }, |
|
| 244 |
+ "disable": {"type": "boolean"}
|
|
| 245 |
+ }, |
|
| 246 |
+ "additionalProperties": false |
|
| 247 |
+ }, |
|
| 248 |
+ "deployment": {
|
|
| 249 |
+ "id": "#/definitions/deployment", |
|
| 250 |
+ "type": ["object", "null"], |
|
| 251 |
+ "properties": {
|
|
| 252 |
+ "mode": {"type": "string"},
|
|
| 253 |
+ "replicas": {"type": "integer"},
|
|
| 254 |
+ "labels": {"$ref": "#/definitions/list_or_dict"},
|
|
| 255 |
+ "update_config": {
|
|
| 256 |
+ "type": "object", |
|
| 257 |
+ "properties": {
|
|
| 258 |
+ "parallelism": {"type": "integer"},
|
|
| 259 |
+ "delay": {"type": "string", "format": "duration"},
|
|
| 260 |
+ "failure_action": {"type": "string"},
|
|
| 261 |
+ "monitor": {"type": "string", "format": "duration"},
|
|
| 262 |
+ "max_failure_ratio": {"type": "number"}
|
|
| 263 |
+ }, |
|
| 264 |
+ "additionalProperties": false |
|
| 265 |
+ }, |
|
| 266 |
+ "resources": {
|
|
| 267 |
+ "type": "object", |
|
| 268 |
+ "properties": {
|
|
| 269 |
+ "limits": {"$ref": "#/definitions/resource"},
|
|
| 270 |
+ "reservations": {"$ref": "#/definitions/resource"}
|
|
| 271 |
+ } |
|
| 272 |
+ }, |
|
| 273 |
+ "restart_policy": {
|
|
| 274 |
+ "type": "object", |
|
| 275 |
+ "properties": {
|
|
| 276 |
+ "condition": {"type": "string"},
|
|
| 277 |
+ "delay": {"type": "string", "format": "duration"},
|
|
| 278 |
+ "max_attempts": {"type": "integer"},
|
|
| 279 |
+ "window": {"type": "string", "format": "duration"}
|
|
| 280 |
+ }, |
|
| 281 |
+ "additionalProperties": false |
|
| 282 |
+ }, |
|
| 283 |
+ "placement": {
|
|
| 284 |
+ "type": "object", |
|
| 285 |
+ "properties": {
|
|
| 286 |
+ "constraints": {"type": "array", "items": {"type": "string"}}
|
|
| 287 |
+ }, |
|
| 288 |
+ "additionalProperties": false |
|
| 289 |
+ } |
|
| 290 |
+ }, |
|
| 291 |
+ "additionalProperties": false |
|
| 292 |
+ }, |
|
| 293 |
+ |
|
| 294 |
+ "resource": {
|
|
| 295 |
+ "id": "#/definitions/resource", |
|
| 296 |
+ "type": "object", |
|
| 297 |
+ "properties": {
|
|
| 298 |
+ "cpus": {"type": "string"},
|
|
| 299 |
+ "memory": {"type": "string"}
|
|
| 300 |
+ }, |
|
| 301 |
+ "additionalProperties": false |
|
| 302 |
+ }, |
|
| 303 |
+ |
|
| 304 |
+ "network": {
|
|
| 305 |
+ "id": "#/definitions/network", |
|
| 306 |
+ "type": ["object", "null"], |
|
| 307 |
+ "properties": {
|
|
| 308 |
+ "driver": {"type": "string"},
|
|
| 309 |
+ "driver_opts": {
|
|
| 310 |
+ "type": "object", |
|
| 311 |
+ "patternProperties": {
|
|
| 312 |
+ "^.+$": {"type": ["string", "number"]}
|
|
| 313 |
+ } |
|
| 314 |
+ }, |
|
| 315 |
+ "ipam": {
|
|
| 316 |
+ "type": "object", |
|
| 317 |
+ "properties": {
|
|
| 318 |
+ "driver": {"type": "string"},
|
|
| 319 |
+ "config": {
|
|
| 320 |
+ "type": "array", |
|
| 321 |
+ "items": {
|
|
| 322 |
+ "type": "object", |
|
| 323 |
+ "properties": {
|
|
| 324 |
+ "subnet": {"type": "string"}
|
|
| 325 |
+ }, |
|
| 326 |
+ "additionalProperties": false |
|
| 327 |
+ } |
|
| 328 |
+ } |
|
| 329 |
+ }, |
|
| 330 |
+ "additionalProperties": false |
|
| 331 |
+ }, |
|
| 332 |
+ "external": {
|
|
| 333 |
+ "type": ["boolean", "object"], |
|
| 334 |
+ "properties": {
|
|
| 335 |
+ "name": {"type": "string"}
|
|
| 336 |
+ }, |
|
| 337 |
+ "additionalProperties": false |
|
| 338 |
+ }, |
|
| 339 |
+ "labels": {"$ref": "#/definitions/list_or_dict"}
|
|
| 340 |
+ }, |
|
| 341 |
+ "additionalProperties": false |
|
| 342 |
+ }, |
|
| 343 |
+ |
|
| 344 |
+ "volume": {
|
|
| 345 |
+ "id": "#/definitions/volume", |
|
| 346 |
+ "type": ["object", "null"], |
|
| 347 |
+ "properties": {
|
|
| 348 |
+ "driver": {"type": "string"},
|
|
| 349 |
+ "driver_opts": {
|
|
| 350 |
+ "type": "object", |
|
| 351 |
+ "patternProperties": {
|
|
| 352 |
+ "^.+$": {"type": ["string", "number"]}
|
|
| 353 |
+ } |
|
| 354 |
+ }, |
|
| 355 |
+ "external": {
|
|
| 356 |
+ "type": ["boolean", "object"], |
|
| 357 |
+ "properties": {
|
|
| 358 |
+ "name": {"type": "string"}
|
|
| 359 |
+ } |
|
| 360 |
+ } |
|
| 361 |
+ }, |
|
| 362 |
+ "labels": {"$ref": "#/definitions/list_or_dict"},
|
|
| 363 |
+ "additionalProperties": false |
|
| 364 |
+ }, |
|
| 365 |
+ |
|
| 366 |
+ "secret": {
|
|
| 367 |
+ "id": "#/definitions/secret", |
|
| 368 |
+ "type": "object", |
|
| 369 |
+ "properties": {
|
|
| 370 |
+ "file": {"type": "string"},
|
|
| 371 |
+ "external": {
|
|
| 372 |
+ "type": ["boolean", "object"], |
|
| 373 |
+ "properties": {
|
|
| 374 |
+ "name": {"type": "string"}
|
|
| 375 |
+ } |
|
| 376 |
+ } |
|
| 377 |
+ }, |
|
| 378 |
+ "labels": {"$ref": "#/definitions/list_or_dict"},
|
|
| 379 |
+ "additionalProperties": false |
|
| 380 |
+ }, |
|
| 381 |
+ |
|
| 382 |
+ "string_or_list": {
|
|
| 383 |
+ "oneOf": [ |
|
| 384 |
+ {"type": "string"},
|
|
| 385 |
+ {"$ref": "#/definitions/list_of_strings"}
|
|
| 386 |
+ ] |
|
| 387 |
+ }, |
|
| 388 |
+ |
|
| 389 |
+ "list_of_strings": {
|
|
| 390 |
+ "type": "array", |
|
| 391 |
+ "items": {"type": "string"},
|
|
| 392 |
+ "uniqueItems": true |
|
| 393 |
+ }, |
|
| 394 |
+ |
|
| 395 |
+ "list_or_dict": {
|
|
| 396 |
+ "oneOf": [ |
|
| 397 |
+ {
|
|
| 398 |
+ "type": "object", |
|
| 399 |
+ "patternProperties": {
|
|
| 400 |
+ ".+": {
|
|
| 401 |
+ "type": ["string", "number", "null"] |
|
| 402 |
+ } |
|
| 403 |
+ }, |
|
| 404 |
+ "additionalProperties": false |
|
| 405 |
+ }, |
|
| 406 |
+ {"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
|
| 407 |
+ ] |
|
| 408 |
+ }, |
|
| 409 |
+ |
|
| 410 |
+ "constraints": {
|
|
| 411 |
+ "service": {
|
|
| 412 |
+ "id": "#/definitions/constraints/service", |
|
| 413 |
+ "anyOf": [ |
|
| 414 |
+ {"required": ["build"]},
|
|
| 415 |
+ {"required": ["image"]}
|
|
| 416 |
+ ], |
|
| 417 |
+ "properties": {
|
|
| 418 |
+ "build": {
|
|
| 419 |
+ "required": ["context"] |
|
| 420 |
+ } |
|
| 421 |
+ } |
|
| 422 |
+ } |
|
| 423 |
+ } |
|
| 424 |
+ } |
|
| 425 |
+} |
| ... | ... |
@@ -7,9 +7,15 @@ import ( |
| 7 | 7 |
"strings" |
| 8 | 8 |
"time" |
| 9 | 9 |
|
| 10 |
+ "github.com/pkg/errors" |
|
| 10 | 11 |
"github.com/xeipuuv/gojsonschema" |
| 11 | 12 |
) |
| 12 | 13 |
|
| 14 |
+const ( |
|
| 15 |
+ defaultVersion = "1.0" |
|
| 16 |
+ versionField = "version" |
|
| 17 |
+) |
|
| 18 |
+ |
|
| 13 | 19 |
type portsFormatChecker struct{}
|
| 14 | 20 |
|
| 15 | 21 |
func (checker portsFormatChecker) IsFormat(input string) bool {
|
| ... | ... |
@@ -30,11 +36,29 @@ func init() {
|
| 30 | 30 |
gojsonschema.FormatCheckers.Add("duration", durationFormatChecker{})
|
| 31 | 31 |
} |
| 32 | 32 |
|
| 33 |
+// Version returns the version of the config, defaulting to version 1.0 |
|
| 34 |
+func Version(config map[string]interface{}) string {
|
|
| 35 |
+ version, ok := config[versionField] |
|
| 36 |
+ if !ok {
|
|
| 37 |
+ return defaultVersion |
|
| 38 |
+ } |
|
| 39 |
+ return normalizeVersion(fmt.Sprintf("%v", version))
|
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+func normalizeVersion(version string) string {
|
|
| 43 |
+ switch version {
|
|
| 44 |
+ case "3": |
|
| 45 |
+ return "3.0" |
|
| 46 |
+ default: |
|
| 47 |
+ return version |
|
| 48 |
+ } |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 33 | 51 |
// Validate uses the jsonschema to validate the configuration |
| 34 |
-func Validate(config map[string]interface{}) error {
|
|
| 35 |
- schemaData, err := Asset("data/config_schema_v3.0.json")
|
|
| 52 |
+func Validate(config map[string]interface{}, version string) error {
|
|
| 53 |
+ schemaData, err := Asset(fmt.Sprintf("data/config_schema_v%s.json", version))
|
|
| 36 | 54 |
if err != nil {
|
| 37 |
- return err |
|
| 55 |
+ return errors.Errorf("unsupported Compose file version: %s", version)
|
|
| 38 | 56 |
} |
| 39 | 57 |
|
| 40 | 58 |
schemaLoader := gojsonschema.NewStringLoader(string(schemaData)) |
| ... | ... |
@@ -8,9 +8,9 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
type dict map[string]interface{}
|
| 10 | 10 |
|
| 11 |
-func TestValid(t *testing.T) {
|
|
| 11 |
+func TestValidate(t *testing.T) {
|
|
| 12 | 12 |
config := dict{
|
| 13 |
- "version": "2.1", |
|
| 13 |
+ "version": "3.0", |
|
| 14 | 14 |
"services": dict{
|
| 15 | 15 |
"foo": dict{
|
| 16 | 16 |
"image": "busybox", |
| ... | ... |
@@ -18,12 +18,12 @@ func TestValid(t *testing.T) {
|
| 18 | 18 |
}, |
| 19 | 19 |
} |
| 20 | 20 |
|
| 21 |
- assert.NoError(t, Validate(config)) |
|
| 21 |
+ assert.NoError(t, Validate(config, "3.0")) |
|
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 |
-func TestUndefinedTopLevelOption(t *testing.T) {
|
|
| 24 |
+func TestValidateUndefinedTopLevelOption(t *testing.T) {
|
|
| 25 | 25 |
config := dict{
|
| 26 |
- "version": "2.1", |
|
| 26 |
+ "version": "3.0", |
|
| 27 | 27 |
"helicopters": dict{
|
| 28 | 28 |
"foo": dict{
|
| 29 | 29 |
"image": "busybox", |
| ... | ... |
@@ -31,5 +31,22 @@ func TestUndefinedTopLevelOption(t *testing.T) {
|
| 31 | 31 |
}, |
| 32 | 32 |
} |
| 33 | 33 |
|
| 34 |
- assert.Error(t, Validate(config)) |
|
| 34 |
+ err := Validate(config, "3.0") |
|
| 35 |
+ assert.Error(t, err) |
|
| 36 |
+ assert.Contains(t, err.Error(), "Additional property helicopters is not allowed") |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+func TestValidateInvalidVersion(t *testing.T) {
|
|
| 40 |
+ config := dict{
|
|
| 41 |
+ "version": "2.1", |
|
| 42 |
+ "services": dict{
|
|
| 43 |
+ "foo": dict{
|
|
| 44 |
+ "image": "busybox", |
|
| 45 |
+ }, |
|
| 46 |
+ }, |
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 49 |
+ err := Validate(config, "2.1") |
|
| 50 |
+ assert.Error(t, err) |
|
| 51 |
+ assert.Contains(t, err.Error(), "unsupported Compose file version: 2.1") |
|
| 35 | 52 |
} |