Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit 5295494

Browse files
committed
Validation for v2 services
Signed-off-by: Josh Curl <[email protected]>
1 parent c7c4bb7 commit 5295494

File tree

12 files changed

+244
-103
lines changed

12 files changed

+244
-103
lines changed

config/merge_v2.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ func MergeServicesV2(existingServices *ServiceConfigs, environmentLookup Environ
3232
}
3333
}
3434

35+
if options.Validate {
36+
if err := validateV2(datas); err != nil {
37+
return nil, err
38+
}
39+
}
40+
3541
for name, data := range datas {
3642
data, err := parseV2(resourceLookup, environmentLookup, file, data, datas, options)
3743
if err != nil {
@@ -155,6 +161,12 @@ func parseV2(resourceLookup ResourceLookup, environmentLookup EnvironmentLookup,
155161
}
156162
}
157163

164+
if options.Validate {
165+
if err := validate(baseRawServices); err != nil {
166+
return nil, err
167+
}
168+
}
169+
158170
baseService, ok = baseRawServices[service]
159171
if !ok {
160172
return nil, fmt.Errorf("Failed to find service %s in file %s", service, file)

config/schema.go

Lines changed: 11 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package config
22

3-
var schemaV1 = `{
3+
var schemaDataV1 = `{
44
"$schema": "http://json-schema.org/draft-04/schema#",
55
"id": "config_schema_v1.json",
66
@@ -87,6 +87,7 @@ var schemaV1 = `{
8787
"mac_address": {"type": "string"},
8888
"mem_limit": {"type": ["number", "string"]},
8989
"memswap_limit": {"type": ["number", "string"]},
90+
"mem_swappiness": {"type": "integer"},
9091
"net": {"type": "string"},
9192
"pid": {"type": ["string", "null"]},
9293
@@ -189,46 +190,14 @@ var schemaV1 = `{
189190
}
190191
`
191192

192-
var schemaV2 = `{
193+
var servicesSchemaDataV2 = `{
193194
"$schema": "http://json-schema.org/draft-04/schema#",
194195
"id": "config_schema_v2.0.json",
195196
"type": "object",
196197
197-
"properties": {
198-
"version": {
199-
"type": "string"
200-
},
201-
202-
"services": {
203-
"id": "#/properties/services",
204-
"type": "object",
205-
"patternProperties": {
206-
"^[a-zA-Z0-9._-]+$": {
207-
"$ref": "#/definitions/service"
208-
}
209-
},
210-
"additionalProperties": false
211-
},
212-
213-
"networks": {
214-
"id": "#/properties/networks",
215-
"type": "object",
216-
"patternProperties": {
217-
"^[a-zA-Z0-9._-]+$": {
218-
"$ref": "#/definitions/network"
219-
}
220-
}
221-
},
222-
223-
"volumes": {
224-
"id": "#/properties/volumes",
225-
"type": "object",
226-
"patternProperties": {
227-
"^[a-zA-Z0-9._-]+$": {
228-
"$ref": "#/definitions/volume"
229-
}
230-
},
231-
"additionalProperties": false
198+
"patternProperties": {
199+
"^[a-zA-Z0-9._-]+$": {
200+
"$ref": "#/definitions/service"
232201
}
233202
},
234203
@@ -330,6 +299,7 @@ var schemaV2 = `{
330299
"mac_address": {"type": "string"},
331300
"mem_limit": {"type": ["number", "string"]},
332301
"memswap_limit": {"type": ["number", "string"]},
302+
"mem_swappiness": {"type": "integer"},
333303
"network_mode": {"type": "string"},
334304
335305
"networks": {
@@ -357,6 +327,7 @@ var schemaV2 = `{
357327
}
358328
]
359329
},
330+
"oom_score_adj": {"type": "integer", "minimum": -1000, "maximum": 1000},
360331
"pid": {"type": ["string", "null"]},
361332
362333
"ports": {
@@ -436,7 +407,8 @@ var schemaV2 = `{
436407
"name": {"type": "string"}
437408
},
438409
"additionalProperties": false
439-
}
410+
},
411+
"internal": {"type": "boolean"}
440412
},
441413
"additionalProperties": false
442414
},
@@ -457,8 +429,7 @@ var schemaV2 = `{
457429
"properties": {
458430
"name": {"type": "string"}
459431
}
460-
},
461-
"additionalProperties": false
432+
}
462433
},
463434
"additionalProperties": false
464435
},

config/schema_helpers.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ import (
99
)
1010

1111
var (
12-
schemaLoader gojsonschema.JSONLoader
13-
constraintSchemaLoader gojsonschema.JSONLoader
14-
schema map[string]interface{}
12+
schemaLoaderV1 gojsonschema.JSONLoader
13+
constraintSchemaLoaderV1 gojsonschema.JSONLoader
14+
schemaLoaderV2 gojsonschema.JSONLoader
15+
constraintSchemaLoaderV2 gojsonschema.JSONLoader
16+
schemaV1 map[string]interface{}
17+
schemaV2 map[string]interface{}
1518
)
1619

1720
type (
@@ -31,28 +34,28 @@ func (checker portsFormatChecker) IsFormat(input string) bool {
3134
return err == nil
3235
}
3336

34-
func setupSchemaLoaders() error {
35-
if schema != nil {
37+
func setupSchemaLoaders(schemaData string, schema *map[string]interface{}, schemaLoader, constraintSchemaLoader *gojsonschema.JSONLoader) error {
38+
if *schema != nil {
3639
return nil
3740
}
3841

3942
var schemaRaw interface{}
40-
err := json.Unmarshal([]byte(schemaV1), &schemaRaw)
43+
err := json.Unmarshal([]byte(schemaData), &schemaRaw)
4144
if err != nil {
4245
return err
4346
}
4447

45-
schema = schemaRaw.(map[string]interface{})
48+
*schema = schemaRaw.(map[string]interface{})
4649

4750
gojsonschema.FormatCheckers.Add("environment", environmentFormatChecker{})
4851
gojsonschema.FormatCheckers.Add("ports", portsFormatChecker{})
4952
gojsonschema.FormatCheckers.Add("expose", portsFormatChecker{})
50-
schemaLoader = gojsonschema.NewGoLoader(schemaRaw)
53+
*schemaLoader = gojsonschema.NewGoLoader(schemaRaw)
5154

52-
definitions := schema["definitions"].(map[string]interface{})
55+
definitions := (*schema)["definitions"].(map[string]interface{})
5356
constraints := definitions["constraints"].(map[string]interface{})
5457
service := constraints["service"].(map[string]interface{})
55-
constraintSchemaLoader = gojsonschema.NewGoLoader(service)
58+
*constraintSchemaLoader = gojsonschema.NewGoLoader(service)
5659

5760
return nil
5861
}

config/testdata/build.v2.yml

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ services:
44
simple1:
55
build: .
66
simple2:
7-
context: ./dir
7+
build:
8+
context: ./dir
89
simple3:
9-
context: ./another
10-
dockerfile: alternate
11-
args:
12-
buildno: 1
13-
user: vincent
10+
build:
11+
context: ./another
12+
dockerfile: alternate
13+
args:
14+
buildno: 1
15+
user: vincent
1416
simple4:
15-
context: ./another
16-
args:
17-
buildno: 2
18-
user: josh
17+
build:
18+
context: ./another
19+
args:
20+
buildno: 2
21+
user: josh

config/validation.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,21 +189,42 @@ func invalidTypeMessage(service, key string, err gojsonschema.ResultError) strin
189189
}
190190

191191
func validate(serviceMap RawServiceMap) error {
192-
if err := setupSchemaLoaders(); err != nil {
192+
if err := setupSchemaLoaders(schemaDataV1, &schemaV1, &schemaLoaderV1, &constraintSchemaLoaderV1); err != nil {
193193
return err
194194
}
195195

196196
serviceMap = convertServiceMapKeysToStrings(serviceMap)
197197

198-
var validationErrors []string
198+
dataLoader := gojsonschema.NewGoLoader(serviceMap)
199+
200+
result, err := gojsonschema.Validate(schemaLoaderV1, dataLoader)
201+
if err != nil {
202+
return err
203+
}
204+
205+
return generateErrorMessages(serviceMap, schemaV1, result)
206+
}
207+
208+
func validateV2(serviceMap RawServiceMap) error {
209+
if err := setupSchemaLoaders(servicesSchemaDataV2, &schemaV2, &schemaLoaderV2, &constraintSchemaLoaderV2); err != nil {
210+
return err
211+
}
212+
213+
serviceMap = convertServiceMapKeysToStrings(serviceMap)
199214

200215
dataLoader := gojsonschema.NewGoLoader(serviceMap)
201216

202-
result, err := gojsonschema.Validate(schemaLoader, dataLoader)
217+
result, err := gojsonschema.Validate(schemaLoaderV2, dataLoader)
203218
if err != nil {
204219
return err
205220
}
206221

222+
return generateErrorMessages(serviceMap, schemaV2, result)
223+
}
224+
225+
func generateErrorMessages(serviceMap RawServiceMap, schema map[string]interface{}, result *gojsonschema.Result) error {
226+
var validationErrors []string
227+
207228
// gojsonschema can create extraneous "additional_property_not_allowed" errors in some cases
208229
// If this is set, and the error is at root level, skip over that error
209230
skipRootAdditionalPropertyError := false
@@ -261,7 +282,7 @@ func validate(serviceMap RawServiceMap) error {
261282
}
262283

263284
func validateServiceConstraints(service RawService, serviceName string) error {
264-
if err := setupSchemaLoaders(); err != nil {
285+
if err := setupSchemaLoaders(schemaDataV1, &schemaV1, &schemaLoaderV1, &constraintSchemaLoaderV1); err != nil {
265286
return err
266287
}
267288

@@ -271,7 +292,7 @@ func validateServiceConstraints(service RawService, serviceName string) error {
271292

272293
dataLoader := gojsonschema.NewGoLoader(service)
273294

274-
result, err := gojsonschema.Validate(constraintSchemaLoader, dataLoader)
295+
result, err := gojsonschema.Validate(constraintSchemaLoaderV1, dataLoader)
275296
if err != nil {
276297
return err
277298
}

0 commit comments

Comments
 (0)