ddsl 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +1 -1
- data/README.md +63 -1
- data/docs/build.schema.json +28 -3
- data/docs/build.schema.md +28 -0
- data/docs/ddsl.schema.json +7 -0
- data/docs/ddsl.schema.md +26 -0
- data/docs/run.schema.json +39 -1
- data/docs/run.schema.md +28 -2
- data/docs/template.schema.json +17 -0
- data/docs/template.schema.md +40 -0
- data/lib/ddsl/parser.rb +2 -2
- data/lib/ddsl/schema.rb +54 -9
- data/lib/ddsl/schema_parser.rb +50 -0
- data/lib/ddsl/template_merger.rb +121 -0
- data/lib/ddsl/version.rb +1 -1
- data/schemas/build.schema.json +23 -3
- data/schemas/ddsl.schema.json +7 -0
- data/schemas/run.schema.json +30 -0
- data/schemas/template.schema.json +17 -0
- metadata +7 -3
- data/lib/ddsl/schema_validator.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0267bb0d50eb2e64aa3023afdfff575e6de01ea8
|
4
|
+
data.tar.gz: 1c38388f8a46c447598bd380e15a972f73c6dcc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42fb11df5ff0143860630a470ed2372efd59b7b5a843f43f937d6c0ba7a226aa09b4d547863e7b9b10c8d93f67edeeec82fc3e9365b1d12727e7863e30dbd115
|
7
|
+
data.tar.gz: c4ad5c06aac5e57421fe877d3a766f605d07ab0e21485668cdba7c11a81502cffdbbd7c7a00f24ffa34b040c82524bb049e58aeedd225d35ac799b88a71e3798
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v0.0.5](https://github.com/bilby91/ddsl/tree/v0.0.5) (2019-01-11)
|
4
|
+
[Full Changelog](https://github.com/bilby91/ddsl/compare/v0.0.4...v0.0.5)
|
5
|
+
|
6
|
+
**Merged pull requests:**
|
7
|
+
|
8
|
+
- Fix permissions for gem credentials file [\#14](https://github.com/bilby91/ddsl/pull/14) ([bilby91](https://github.com/bilby91))
|
9
|
+
- Bump version [\#13](https://github.com/bilby91/ddsl/pull/13) ([bilby91](https://github.com/bilby91))
|
10
|
+
- Add automatic publish via ddsl and GitLab [\#12](https://github.com/bilby91/ddsl/pull/12) ([bilby91](https://github.com/bilby91))
|
11
|
+
- Fix service\_port for docker-compose run [\#11](https://github.com/bilby91/ddsl/pull/11) ([bilby91](https://github.com/bilby91))
|
12
|
+
- Update README.md [\#10](https://github.com/bilby91/ddsl/pull/10) ([bilby91](https://github.com/bilby91))
|
13
|
+
- Add docs builder with ddsl [\#8](https://github.com/bilby91/ddsl/pull/8) ([bilby91](https://github.com/bilby91))
|
14
|
+
|
3
15
|
## [v0.0.4](https://github.com/bilby91/ddsl/tree/v0.0.4) (2018-12-08)
|
4
16
|
[Full Changelog](https://github.com/bilby91/ddsl/compare/v0.0.3...v0.0.4)
|
5
17
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -68,7 +68,69 @@ Now that we have our image built we can run things on it
|
|
68
68
|
|
69
69
|
### Environment Variables
|
70
70
|
|
71
|
-
|
71
|
+
If you want to inject environmental variables in your build or run definition it's really easy with `ddsl`. You just need to interpolate the environmental variable name in your `.ddsl.yml` file like you would do
|
72
|
+
in a bash script in order to get them injected.
|
73
|
+
|
74
|
+
Lets take a look at a section of the previous example:
|
75
|
+
|
76
|
+
```
|
77
|
+
builds:
|
78
|
+
- name: feature-branch
|
79
|
+
type: docker
|
80
|
+
context: .
|
81
|
+
file: docker/Dockerfile
|
82
|
+
tags:
|
83
|
+
- bilby91/ddsl:$CI_SHA1
|
84
|
+
push: true
|
85
|
+
cache_from:
|
86
|
+
- bilby91/ddsl:latest
|
87
|
+
```
|
88
|
+
|
89
|
+
In this case, our feature-branch build depends on the `CI_SHA1` enviromental variable. When invoking `CI_SHA1=XXXX ddsl build feature-branch`, ddsl will replace `CI_SHA1` with the appropiate value (in this case, XXXX) and continue it's normal work.
|
90
|
+
|
91
|
+
### Templates
|
92
|
+
|
93
|
+
Templates let you [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) your `.ddsl.yml` configurations. If you have multiple builds in your project, templates will be very useful for encapsulating common options that all or some of your builds need. Templates can be used in either builds or runs.
|
94
|
+
|
95
|
+
Lets take a look at a possible scenario where using templates would make sense.
|
96
|
+
|
97
|
+
```
|
98
|
+
version: 1
|
99
|
+
|
100
|
+
templates:
|
101
|
+
- name: base-build
|
102
|
+
context: .
|
103
|
+
file: docker/Dockerfile
|
104
|
+
push: true
|
105
|
+
tags:
|
106
|
+
- bilby91/ddsl:$CI_SHA1
|
107
|
+
cache_from:
|
108
|
+
- bilby91/ddsl:latest
|
109
|
+
|
110
|
+
builds:
|
111
|
+
- name: feature-branch
|
112
|
+
type: docker
|
113
|
+
templates:
|
114
|
+
- base-build
|
115
|
+
|
116
|
+
- name: master
|
117
|
+
type: docker
|
118
|
+
templates:
|
119
|
+
- base-build
|
120
|
+
tags:
|
121
|
+
- bilby91/ddsl:latest
|
122
|
+
```
|
123
|
+
|
124
|
+
In the example above we have introduced a new build called master. We have encapsulated all the common options between master and feature-branch in a template called base-build. When ddsl runs either feature-branch or master builds it will merge the options from the template into each build's options.
|
125
|
+
|
126
|
+
Some important things to note in regards to templates implementation:
|
127
|
+
|
128
|
+
If the templateable object (either a build or a run) have the same key defined, ddsl will behave like this:
|
129
|
+
|
130
|
+
1. If the key's value is either a string or a number, the templetable object value will be favored. This allows overriding certain keys when inheriting from a template.
|
131
|
+
2. If the key's value is an array, the template items of the array will be added to the templatable object array.
|
132
|
+
3. If the key's value is a map, the template items of the map will be merged in the templatable object map.
|
133
|
+
1. If we have a collision here, `ddsl` will behave like described in point 1.
|
72
134
|
|
73
135
|
## Documentation
|
74
136
|
|
data/docs/build.schema.json
CHANGED
@@ -25,11 +25,29 @@
|
|
25
25
|
"build_docker_options": {
|
26
26
|
"type": "object",
|
27
27
|
"required": [
|
28
|
-
"type"
|
29
|
-
|
30
|
-
|
28
|
+
"type"
|
29
|
+
],
|
30
|
+
"anyOf": [
|
31
|
+
{
|
32
|
+
"required": [
|
33
|
+
"templates"
|
34
|
+
]
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"required": [
|
38
|
+
"file",
|
39
|
+
"context"
|
40
|
+
]
|
41
|
+
}
|
31
42
|
],
|
32
43
|
"properties": {
|
44
|
+
"templates": {
|
45
|
+
"type": "array",
|
46
|
+
"items": {
|
47
|
+
"type": "string"
|
48
|
+
},
|
49
|
+
"description": "List of templates the build will inherit"
|
50
|
+
},
|
33
51
|
"type": {
|
34
52
|
"type": "string",
|
35
53
|
"enum": [
|
@@ -89,6 +107,13 @@
|
|
89
107
|
"type"
|
90
108
|
],
|
91
109
|
"properties": {
|
110
|
+
"templates": {
|
111
|
+
"type": "array",
|
112
|
+
"items": {
|
113
|
+
"type": "string"
|
114
|
+
},
|
115
|
+
"description": "List of templates the build will inherit"
|
116
|
+
},
|
92
117
|
"type": {
|
93
118
|
"type": "string",
|
94
119
|
"enum": [
|
data/docs/build.schema.md
CHANGED
@@ -57,6 +57,7 @@ Unique name to identify the build task.
|
|
57
57
|
| [push](#push) | `boolean` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/build.schema.json#/definitions/build_docker_options` |
|
58
58
|
| [service](#service) | `string` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/build.schema.json#/definitions/build_docker_compose_options` |
|
59
59
|
| [tags](#tags) | `string[]` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/build.schema.json#/definitions/build_docker_options` |
|
60
|
+
| [templates](#templates) | `string[]` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/build.schema.json#/definitions/build_docker_compose_options` |
|
60
61
|
| [type](#type) | `enum` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/build.schema.json#/definitions/build_docker_compose_options` |
|
61
62
|
|
62
63
|
## build_args
|
@@ -362,6 +363,33 @@ All items must be of the type:
|
|
362
363
|
|
363
364
|
|
364
365
|
|
366
|
+
## templates
|
367
|
+
|
368
|
+
List of templates the build will inherit
|
369
|
+
|
370
|
+
`templates`
|
371
|
+
|
372
|
+
* is optional
|
373
|
+
* type: `string[]`
|
374
|
+
* defined in this schema
|
375
|
+
|
376
|
+
### templates Type
|
377
|
+
|
378
|
+
|
379
|
+
Array type: `string[]`
|
380
|
+
|
381
|
+
All items must be of the type:
|
382
|
+
`string`
|
383
|
+
|
384
|
+
|
385
|
+
|
386
|
+
|
387
|
+
|
388
|
+
|
389
|
+
|
390
|
+
|
391
|
+
|
392
|
+
|
365
393
|
## type
|
366
394
|
|
367
395
|
Type of builder to use
|
data/docs/ddsl.schema.json
CHANGED
@@ -37,6 +37,13 @@
|
|
37
37
|
"$ref": "https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json"
|
38
38
|
},
|
39
39
|
"description": "List of run tasks to run"
|
40
|
+
},
|
41
|
+
"templates": {
|
42
|
+
"type": "array",
|
43
|
+
"items": {
|
44
|
+
"$ref": "https://raw.githubusercontent.com/bilby91/ddsl/master/docs/template.schema.json"
|
45
|
+
},
|
46
|
+
"description": "List of templates to use in builds or runs"
|
40
47
|
}
|
41
48
|
}
|
42
49
|
}
|
data/docs/ddsl.schema.md
CHANGED
@@ -18,6 +18,7 @@ Schema for the DDSL file format.
|
|
18
18
|
| [builds](#builds) | Build | Optional | | DDSL (this schema) |
|
19
19
|
| [registries](#registries) | Registry | Optional | `[]` | DDSL (this schema) |
|
20
20
|
| [runs](#runs) | Run | Optional | | DDSL (this schema) |
|
21
|
+
| [templates](#templates) | Template | Optional | | DDSL (this schema) |
|
21
22
|
| [version](#version) | `enum` | **Required** | | DDSL (this schema) |
|
22
23
|
|
23
24
|
## builds
|
@@ -97,6 +98,31 @@ All items must be of the type:
|
|
97
98
|
|
98
99
|
|
99
100
|
|
101
|
+
## templates
|
102
|
+
|
103
|
+
List of templates to use in builds or runs
|
104
|
+
|
105
|
+
`templates`
|
106
|
+
|
107
|
+
* is optional
|
108
|
+
* type: Template
|
109
|
+
* defined in this schema
|
110
|
+
|
111
|
+
### templates Type
|
112
|
+
|
113
|
+
|
114
|
+
Array type: Template
|
115
|
+
|
116
|
+
All items must be of the type:
|
117
|
+
* [Template](template.schema.md) – `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/template.schema.json`
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
|
100
126
|
## version
|
101
127
|
|
102
128
|
Version of the DDSL schema
|
data/docs/run.schema.json
CHANGED
@@ -28,7 +28,26 @@
|
|
28
28
|
"type",
|
29
29
|
"image"
|
30
30
|
],
|
31
|
+
"anyOf": [
|
32
|
+
{
|
33
|
+
"required": [
|
34
|
+
"templates"
|
35
|
+
]
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"required": [
|
39
|
+
"image"
|
40
|
+
]
|
41
|
+
}
|
42
|
+
],
|
31
43
|
"properties": {
|
44
|
+
"templates": {
|
45
|
+
"type": "array",
|
46
|
+
"items": {
|
47
|
+
"type": "string"
|
48
|
+
},
|
49
|
+
"description": "List of templates the run will inherit"
|
50
|
+
},
|
32
51
|
"type": {
|
33
52
|
"type": "string",
|
34
53
|
"enum": [
|
@@ -78,7 +97,26 @@
|
|
78
97
|
"type",
|
79
98
|
"service"
|
80
99
|
],
|
100
|
+
"anyOf": [
|
101
|
+
{
|
102
|
+
"required": [
|
103
|
+
"templates"
|
104
|
+
]
|
105
|
+
},
|
106
|
+
{
|
107
|
+
"required": [
|
108
|
+
"service"
|
109
|
+
]
|
110
|
+
}
|
111
|
+
],
|
81
112
|
"properties": {
|
113
|
+
"templates": {
|
114
|
+
"type": "array",
|
115
|
+
"items": {
|
116
|
+
"type": "string"
|
117
|
+
},
|
118
|
+
"description": "List of templates the run will inherit"
|
119
|
+
},
|
82
120
|
"type": {
|
83
121
|
"type": "string",
|
84
122
|
"enum": [
|
@@ -111,7 +149,7 @@
|
|
111
149
|
"description": "Working directory inside the container"
|
112
150
|
},
|
113
151
|
"service_ports": {
|
114
|
-
"type": "
|
152
|
+
"type": "boolean",
|
115
153
|
"description": "Run command with the service's ports enabled and mapped to the host"
|
116
154
|
},
|
117
155
|
"detach": {
|
data/docs/run.schema.md
CHANGED
@@ -51,7 +51,8 @@ Unique name to identify the run task.
|
|
51
51
|
| [no_deps](#no_deps) | `boolean` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json#/definitions/run_docker_compose_options` |
|
52
52
|
| [rm](#rm) | `boolean` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json#/definitions/run_docker_compose_options` |
|
53
53
|
| [service](#service) | `string` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json#/definitions/run_docker_compose_options` |
|
54
|
-
| [service_ports](#service_ports) | `
|
54
|
+
| [service_ports](#service_ports) | `boolean` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json#/definitions/run_docker_compose_options` |
|
55
|
+
| [templates](#templates) | `string[]` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json#/definitions/run_docker_compose_options` |
|
55
56
|
| [type](#type) | `enum` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json#/definitions/run_docker_compose_options` |
|
56
57
|
| [user](#user) | `string` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json#/definitions/run_docker_compose_options` |
|
57
58
|
| [volumes](#volumes) | `string[]` | `https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json#/definitions/run_docker_compose_options` |
|
@@ -229,12 +230,34 @@ Run command with the service's ports enabled and mapped to the host
|
|
229
230
|
`service_ports`
|
230
231
|
|
231
232
|
* is optional
|
232
|
-
* type: `
|
233
|
+
* type: `boolean`
|
233
234
|
* defined in this schema
|
234
235
|
|
235
236
|
### service_ports Type
|
236
237
|
|
237
238
|
|
239
|
+
`boolean`
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
## templates
|
246
|
+
|
247
|
+
List of templates the run will inherit
|
248
|
+
|
249
|
+
`templates`
|
250
|
+
|
251
|
+
* is optional
|
252
|
+
* type: `string[]`
|
253
|
+
* defined in this schema
|
254
|
+
|
255
|
+
### templates Type
|
256
|
+
|
257
|
+
|
258
|
+
Array type: `string[]`
|
259
|
+
|
260
|
+
All items must be of the type:
|
238
261
|
`string`
|
239
262
|
|
240
263
|
|
@@ -243,6 +266,9 @@ Run command with the service's ports enabled and mapped to the host
|
|
243
266
|
|
244
267
|
|
245
268
|
|
269
|
+
|
270
|
+
|
271
|
+
|
246
272
|
## type
|
247
273
|
|
248
274
|
Type of runner to use
|
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-06/schema#",
|
3
|
+
"$id": "https://raw.githubusercontent.com/bilby91/ddsl/master/docs/template.schema.json",
|
4
|
+
"title": "Template",
|
5
|
+
"description": "Template for encapsulating common option either docker or docker-compose",
|
6
|
+
"type": "object",
|
7
|
+
"required": [
|
8
|
+
"name"
|
9
|
+
],
|
10
|
+
"properties": {
|
11
|
+
"name": {
|
12
|
+
"type": "string",
|
13
|
+
"description": "Unique name to identify the template."
|
14
|
+
}
|
15
|
+
},
|
16
|
+
"additionalProperties": true
|
17
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
# Template Schema
|
3
|
+
|
4
|
+
```
|
5
|
+
https://raw.githubusercontent.com/bilby91/ddsl/master/docs/template.schema.json
|
6
|
+
```
|
7
|
+
|
8
|
+
Template for encapsulating common option either docker or docker-compose
|
9
|
+
|
10
|
+
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Defined In |
|
11
|
+
|----------|------------|--------|--------------|-------------------|-----------------------|------------|
|
12
|
+
| Can be instantiated | No | Experimental | No | Forbidden | Permitted | [template.schema.json](template.schema.json) |
|
13
|
+
|
14
|
+
# Template Properties
|
15
|
+
|
16
|
+
| Property | Type | Required | Defined by |
|
17
|
+
|----------|------|----------|------------|
|
18
|
+
| [name](#name) | `string` | **Required** | Template (this schema) |
|
19
|
+
| `*` | any | Additional | this schema *allows* additional properties |
|
20
|
+
|
21
|
+
## name
|
22
|
+
|
23
|
+
Unique name to identify the template.
|
24
|
+
|
25
|
+
`name`
|
26
|
+
|
27
|
+
* is **required**
|
28
|
+
* type: `string`
|
29
|
+
* defined in this schema
|
30
|
+
|
31
|
+
### name Type
|
32
|
+
|
33
|
+
|
34
|
+
`string`
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
data/lib/ddsl/parser.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'json'
|
4
4
|
require 'yaml'
|
5
|
-
require_relative './
|
5
|
+
require_relative './schema_parser'
|
6
6
|
|
7
7
|
module DDSL
|
8
8
|
class Parser
|
@@ -26,7 +26,7 @@ module DDSL
|
|
26
26
|
raise UnsupportedFileFormatError, "format #{format} is unsupported"
|
27
27
|
end
|
28
28
|
|
29
|
-
DDSL::
|
29
|
+
DDSL::SchemaParser.new.parse!(parsed_config)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
data/lib/ddsl/schema.rb
CHANGED
@@ -1,13 +1,58 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'json_schemer'
|
4
|
+
|
3
5
|
module DDSL
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
class Schema
|
7
|
+
VERSION = :draft4
|
8
|
+
|
9
|
+
def initialize(data)
|
10
|
+
@data = data
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate
|
14
|
+
schemer_validator.validate(@data).to_a
|
15
|
+
end
|
16
|
+
|
17
|
+
protected def schema_path
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
private def schemer_validator
|
22
|
+
@schemer_validator ||= JSONSchemer.schema(
|
23
|
+
schema_path,
|
24
|
+
format: true,
|
25
|
+
ref_resolver: resolver
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
private def resolver
|
30
|
+
lambda do |uri|
|
31
|
+
file_name = uri.path.split('/').last
|
32
|
+
file_path = File.join(schema_dir, file_name)
|
33
|
+
|
34
|
+
JSON.parse(File.read(file_path))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private def schema_dir
|
39
|
+
File.join(File.dirname(__FILE__), '../../schemas')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class SchemaDDSL < Schema
|
44
|
+
protected def schema_path
|
45
|
+
Pathname.new(File.join(schema_dir, '/ddsl.schema.json'))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
class SchemaBuild < Schema
|
49
|
+
protected def schema_path
|
50
|
+
Pathname.new(File.join(schema_dir, '/build.schema.json'))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
class SchemaRun < Schema
|
54
|
+
protected def schema_path
|
55
|
+
Pathname.new(File.join(schema_dir, '/run.schema.json'))
|
56
|
+
end
|
57
|
+
end
|
13
58
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json_schemer'
|
4
|
+
require_relative './schema'
|
5
|
+
require_relative './template_merger'
|
6
|
+
|
7
|
+
module DDSL
|
8
|
+
class SchemaParser
|
9
|
+
class InvalidError < StandardError; end
|
10
|
+
|
11
|
+
SCHEMA_MAP = {
|
12
|
+
'builds' => SchemaBuild,
|
13
|
+
'runs' => SchemaRun
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
#
|
17
|
+
# Parse given potentially compatible data schema. Parser will merge template values if used.
|
18
|
+
#
|
19
|
+
# @raise [InvalidError] if data is not compliant with the schema
|
20
|
+
#
|
21
|
+
# @param [Hash] data
|
22
|
+
#
|
23
|
+
# @return [Hash] data
|
24
|
+
#
|
25
|
+
def parse!(data)
|
26
|
+
errors = SchemaDDSL.new(data).validate
|
27
|
+
|
28
|
+
# Validate initial schema without potential templates applied
|
29
|
+
raise InvalidError, 'Invalid schema' if errors&.count&.positive?
|
30
|
+
|
31
|
+
# Apply potentially defined templates to the data
|
32
|
+
applied_data = DDSL::TemplateMerger.new(data).apply
|
33
|
+
|
34
|
+
# Re evaluate schema in case template corrupted the data
|
35
|
+
%w[builds runs].each { |x| validate_schema_key!(applied_data, x) }
|
36
|
+
|
37
|
+
applied_data
|
38
|
+
end
|
39
|
+
|
40
|
+
private def validate_schema_key!(data, key)
|
41
|
+
return unless data.key?(key)
|
42
|
+
|
43
|
+
data[key].each do |build|
|
44
|
+
errors = SCHEMA_MAP[key].new(build).validate
|
45
|
+
|
46
|
+
raise InvalidError, 'Invalid schema' if errors&.count&.positive?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DDSL
|
4
|
+
class TemplateMerger
|
5
|
+
class MissingTemplateError < StandardError; end
|
6
|
+
class ValueTypeMismatchError < StandardError; end
|
7
|
+
|
8
|
+
# Set of keys that can't be extracted from a template
|
9
|
+
SKIPPABLE_TEMPLATE_KEYS = %w[name].freeze
|
10
|
+
|
11
|
+
# Set of keys that can't be merged in a templatable hash
|
12
|
+
SKIPPABLE_MERGE_KEYS = %w[templates].freeze
|
13
|
+
|
14
|
+
# Keys that can use the templates feature
|
15
|
+
TEMPLETABLE_KEYS = %w[builds runs].freeze
|
16
|
+
|
17
|
+
attr_reader :data
|
18
|
+
|
19
|
+
def initialize(data)
|
20
|
+
@data = data.dup
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Apply `build` and `run` templates to data
|
25
|
+
#
|
26
|
+
# @note `templates` key will be removed from objects after they are applied
|
27
|
+
#
|
28
|
+
# @return [Hash]
|
29
|
+
#
|
30
|
+
def apply
|
31
|
+
TEMPLETABLE_KEYS.each do |key|
|
32
|
+
data[key] = data[key].map { |b| apply_templates(b) } if data.key?(key)
|
33
|
+
end
|
34
|
+
|
35
|
+
data
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Merge values of all inherited templates for the given templetable object
|
40
|
+
#
|
41
|
+
# @param [Hash] templatable
|
42
|
+
#
|
43
|
+
# @return [Hash]
|
44
|
+
#
|
45
|
+
private def apply_templates(templatable)
|
46
|
+
templates = templatable['templates'] || []
|
47
|
+
|
48
|
+
templates.inject(templatable) do |applied, template_name|
|
49
|
+
template = find_template!(template_name)
|
50
|
+
|
51
|
+
mergable_key_space(template, applied).map do |key|
|
52
|
+
[key, extend_value!(template[key], applied[key])]
|
53
|
+
end.to_h
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Extend the given spec_value in case it's type is Array or Hash, return the spec_value otherwise
|
59
|
+
#
|
60
|
+
# @raise [ValueTypeMismatchError] if template_value and spec_value are not nil and have different types
|
61
|
+
#
|
62
|
+
# @param [Array|Hash|Object] template_value
|
63
|
+
# @param [Array|Hash|Object] spec_value
|
64
|
+
#
|
65
|
+
# @return [Array|Hash|Object]
|
66
|
+
#
|
67
|
+
private def extend_value!(template_value, spec_value)
|
68
|
+
# Short circuit if either template_value or spec_value are nil
|
69
|
+
return spec_value || template_value if template_value.nil? || spec_value.nil?
|
70
|
+
|
71
|
+
# Check for data type mismatches
|
72
|
+
unless template_value.is_a?(spec_value.class)
|
73
|
+
raise ValueTypeMismatchError, "#{template_value} has a different type than #{spec_value}"
|
74
|
+
end
|
75
|
+
|
76
|
+
case template_value
|
77
|
+
when Array
|
78
|
+
# Template values are concatenated at the end
|
79
|
+
spec_value.concat(template_value)
|
80
|
+
when Hash
|
81
|
+
# We merge the spec_value in order to favor "old" values vs template values
|
82
|
+
# in case of a collision
|
83
|
+
template_value.merge(spec_value)
|
84
|
+
else
|
85
|
+
# We favor spec values vs templates values on collisions again
|
86
|
+
spec_value
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Build array of uniq keys that compose the templetable hash.
|
92
|
+
#
|
93
|
+
# @param [Hash] template
|
94
|
+
# @param [Hash] templatable
|
95
|
+
#
|
96
|
+
# @return [Array<String>]
|
97
|
+
#
|
98
|
+
private def mergable_key_space(template, templatable)
|
99
|
+
Set.new(template.keys.concat(templatable.keys))
|
100
|
+
.to_a
|
101
|
+
.delete_if { |x| SKIPPABLE_MERGE_KEYS.include?(x) }
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# Lookup for template by given name in the data object.
|
106
|
+
#
|
107
|
+
# @raise [MissingTemplateError] if template can't be found
|
108
|
+
#
|
109
|
+
# @param [String] name
|
110
|
+
#
|
111
|
+
# @return [Hash]
|
112
|
+
#
|
113
|
+
private def find_template!(name)
|
114
|
+
template = data['templates'].find { |t| t['name'] == name }
|
115
|
+
|
116
|
+
raise MissingTemplateError, "Missing template #{name}" if template.nil?
|
117
|
+
|
118
|
+
template.dup.delete_if { |x| SKIPPABLE_TEMPLATE_KEYS.include?(x) }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/lib/ddsl/version.rb
CHANGED
data/schemas/build.schema.json
CHANGED
@@ -25,11 +25,24 @@
|
|
25
25
|
"build_docker_options": {
|
26
26
|
"type": "object",
|
27
27
|
"required": [
|
28
|
-
"type"
|
29
|
-
|
30
|
-
|
28
|
+
"type"
|
29
|
+
],
|
30
|
+
"anyOf": [
|
31
|
+
{
|
32
|
+
"required" : ["templates"]
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"required" : ["file", "context"]
|
36
|
+
}
|
31
37
|
],
|
32
38
|
"properties": {
|
39
|
+
"templates": {
|
40
|
+
"type": "array",
|
41
|
+
"items": {
|
42
|
+
"type": "string"
|
43
|
+
},
|
44
|
+
"description": "List of templates the build will inherit"
|
45
|
+
},
|
33
46
|
"type": {
|
34
47
|
"type": "string",
|
35
48
|
"enum": [
|
@@ -89,6 +102,13 @@
|
|
89
102
|
"type"
|
90
103
|
],
|
91
104
|
"properties": {
|
105
|
+
"templates": {
|
106
|
+
"type": "array",
|
107
|
+
"items": {
|
108
|
+
"type": "string"
|
109
|
+
},
|
110
|
+
"description": "List of templates the build will inherit"
|
111
|
+
},
|
92
112
|
"type": {
|
93
113
|
"type": "string",
|
94
114
|
"enum": [
|
data/schemas/ddsl.schema.json
CHANGED
@@ -39,6 +39,13 @@
|
|
39
39
|
"$ref": "https://raw.githubusercontent.com/bilby91/ddsl/master/docs/run.schema.json"
|
40
40
|
},
|
41
41
|
"description": "List of run tasks to run"
|
42
|
+
},
|
43
|
+
"templates": {
|
44
|
+
"type": "array",
|
45
|
+
"items": {
|
46
|
+
"$ref": "https://raw.githubusercontent.com/bilby91/ddsl/master/docs/template.schema.json"
|
47
|
+
},
|
48
|
+
"description": "List of templates to use in builds or runs"
|
42
49
|
}
|
43
50
|
}
|
44
51
|
}
|
data/schemas/run.schema.json
CHANGED
@@ -28,7 +28,22 @@
|
|
28
28
|
"type",
|
29
29
|
"image"
|
30
30
|
],
|
31
|
+
"anyOf": [
|
32
|
+
{
|
33
|
+
"required" : ["templates"]
|
34
|
+
},
|
35
|
+
{
|
36
|
+
"required" : ["image"]
|
37
|
+
}
|
38
|
+
],
|
31
39
|
"properties": {
|
40
|
+
"templates": {
|
41
|
+
"type": "array",
|
42
|
+
"items": {
|
43
|
+
"type": "string"
|
44
|
+
},
|
45
|
+
"description": "List of templates the run will inherit"
|
46
|
+
},
|
32
47
|
"type": {
|
33
48
|
"type": "string",
|
34
49
|
"enum": [
|
@@ -78,7 +93,22 @@
|
|
78
93
|
"type",
|
79
94
|
"service"
|
80
95
|
],
|
96
|
+
"anyOf": [
|
97
|
+
{
|
98
|
+
"required" : ["templates"]
|
99
|
+
},
|
100
|
+
{
|
101
|
+
"required" : ["service"]
|
102
|
+
}
|
103
|
+
],
|
81
104
|
"properties": {
|
105
|
+
"templates": {
|
106
|
+
"type": "array",
|
107
|
+
"items": {
|
108
|
+
"type": "string"
|
109
|
+
},
|
110
|
+
"description": "List of templates the run will inherit"
|
111
|
+
},
|
82
112
|
"type": {
|
83
113
|
"type": "string",
|
84
114
|
"enum": [
|
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-06/schema#",
|
3
|
+
"$id": "https://raw.githubusercontent.com/bilby91/ddsl/master/docs/template.schema.json",
|
4
|
+
"title": "Template",
|
5
|
+
"description": "Template for encapsulating common option either docker or docker-compose",
|
6
|
+
"type": "object",
|
7
|
+
"required": [
|
8
|
+
"name"
|
9
|
+
],
|
10
|
+
"properties": {
|
11
|
+
"name": {
|
12
|
+
"type": "string",
|
13
|
+
"description": "Unique name to identify the template."
|
14
|
+
}
|
15
|
+
},
|
16
|
+
"additionalProperties": true
|
17
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddsl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Fernandez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: clamp
|
@@ -143,6 +143,8 @@ files:
|
|
143
143
|
- docs/registry.schema.md
|
144
144
|
- docs/run.schema.json
|
145
145
|
- docs/run.schema.md
|
146
|
+
- docs/template.schema.json
|
147
|
+
- docs/template.schema.md
|
146
148
|
- lib/ddsl.rb
|
147
149
|
- lib/ddsl/cli.rb
|
148
150
|
- lib/ddsl/command.rb
|
@@ -158,14 +160,16 @@ files:
|
|
158
160
|
- lib/ddsl/functions.rb
|
159
161
|
- lib/ddsl/parser.rb
|
160
162
|
- lib/ddsl/schema.rb
|
161
|
-
- lib/ddsl/
|
163
|
+
- lib/ddsl/schema_parser.rb
|
162
164
|
- lib/ddsl/shell.rb
|
165
|
+
- lib/ddsl/template_merger.rb
|
163
166
|
- lib/ddsl/variable_injector.rb
|
164
167
|
- lib/ddsl/version.rb
|
165
168
|
- schemas/build.schema.json
|
166
169
|
- schemas/ddsl.schema.json
|
167
170
|
- schemas/registry.schema.json
|
168
171
|
- schemas/run.schema.json
|
172
|
+
- schemas/template.schema.json
|
169
173
|
- scripts/publish.sh
|
170
174
|
- scripts/version.sh
|
171
175
|
homepage: https://github.com/bilby91/ddsl
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'json_schemer'
|
4
|
-
require_relative './schema'
|
5
|
-
|
6
|
-
module DDSL
|
7
|
-
class SchemaValidator
|
8
|
-
class InvalidError < StandardError; end
|
9
|
-
|
10
|
-
#
|
11
|
-
# Validate given data against DDSL schema. Will add any defaults if nil values are found
|
12
|
-
#
|
13
|
-
# @raise [InvalidError] if data is not compliant with the schema,
|
14
|
-
#
|
15
|
-
# @param [Hash] data
|
16
|
-
#
|
17
|
-
# @return [Hash] data with defaults if appropiate
|
18
|
-
#
|
19
|
-
def validate!(data)
|
20
|
-
errors = json_schema_validator.validate(data).to_a
|
21
|
-
raise InvalidError, 'Invalid schema' if errors&.count&.positive?
|
22
|
-
|
23
|
-
data
|
24
|
-
end
|
25
|
-
|
26
|
-
private def json_schema_validator
|
27
|
-
@json_schema_validator ||= JSONSchemer.schema(
|
28
|
-
DDSL::SCHEMA_PATH,
|
29
|
-
format: true,
|
30
|
-
ref_resolver: DDSL::SCHEMA_RESOLVER
|
31
|
-
)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|