nomadsl 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +12 -0
- data/README.md +123 -0
- data/lib/nomadsl/dsl.rb +4 -0
- data/lib/nomadsl/version.rb +3 -0
- data/lib/nomadsl.rb +524 -0
- data/nomadsl.gemspec +21 -0
- metadata +49 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4f3c9be8c5c4c5293c3faa964df8b2cc49b06f16
|
4
|
+
data.tar.gz: aa028437bee6a60e1e04e35cd1f02fdd2fe0aea3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2d984c2ebd0ceafd1ebc361c68a6d9d0c582f4707bb63f31f7586571728bfd53ec38db2935dee923ed3b9893c7b488da00ffc9552ab222d5c9fd47dbb09fa6ee
|
7
|
+
data.tar.gz: '094f041d9f2b4502920e35e09a3d3d3459bbfc157d1f71d4b422e750d0a0270bd23b0bd8952e32ad6f026e53afd11be7c73702ca80bf5514c058a0af15c3bb0d'
|
data/LICENSE
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
This work is dedicated to the public domain. No rights reserved.
|
2
|
+
|
3
|
+
I, the copyright holder of this work, hereby release it into the public
|
4
|
+
domain. This applies worldwide.
|
5
|
+
|
6
|
+
I grant any entity the right to use this work for any purpose, without
|
7
|
+
any conditions, unless such conditions are required by law.
|
8
|
+
|
9
|
+
If you require a fuller legal statement, please refer to the Creative
|
10
|
+
Commons Zero license:
|
11
|
+
|
12
|
+
http://creativecommons.org/publicdomain/zero/1.0/
|
data/README.md
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
# nomadsl
|
2
|
+
|
3
|
+
Nomadsl is a Ruby DSL for generating Nomad job specification files.
|
4
|
+
|
5
|
+
Methods mapping to keys and attributes described in the Nomad Job Specification
|
6
|
+
(https://www.nomadproject.io/docs/job-specification/index.html) are defined in
|
7
|
+
an includable module.
|
8
|
+
|
9
|
+
The mapping of key and attribute names to method names is generally one-to-one.
|
10
|
+
|
11
|
+
## Example: DSL direct to stdout
|
12
|
+
|
13
|
+
Simply `require 'nomadsl/dsl` and the DSL methods will be injected into the
|
14
|
+
root namespace. For example, this source file:
|
15
|
+
|
16
|
+
#!/usr/bin/env ruby
|
17
|
+
|
18
|
+
require 'nomadsl/dsl'
|
19
|
+
|
20
|
+
job "example" do
|
21
|
+
type "batch"
|
22
|
+
region "iad"
|
23
|
+
datacenters "prod"
|
24
|
+
parameterized(payload: "required")
|
25
|
+
group "work" do
|
26
|
+
task "work" do
|
27
|
+
vault(policies: ["example-job"])
|
28
|
+
meta(aws_region: "ap-southeast-2")
|
29
|
+
dispatch_payload(file: "message.txt")
|
30
|
+
preloaded_vault_aws_creds("iam", "iam/sts/example-iam")
|
31
|
+
artifact(source: "s3.amazonaws.com/example-bucket/example-job/script.sh")
|
32
|
+
config(command: "script.sh")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Will generate this output:
|
38
|
+
|
39
|
+
$ ruby example.nomadsl
|
40
|
+
job "example" {
|
41
|
+
type = "batch"
|
42
|
+
region = "iad"
|
43
|
+
datacenters = ["prod"]
|
44
|
+
|
45
|
+
parameterized {
|
46
|
+
payload = "required"
|
47
|
+
}
|
48
|
+
|
49
|
+
group "work" {
|
50
|
+
task "work" {
|
51
|
+
driver = "exec"
|
52
|
+
|
53
|
+
vault {
|
54
|
+
policies = ["example-job"]
|
55
|
+
}
|
56
|
+
|
57
|
+
meta {
|
58
|
+
aws_region = "ap-southeast-2"
|
59
|
+
}
|
60
|
+
|
61
|
+
dispatch_payload {
|
62
|
+
file = "message.txt"
|
63
|
+
}
|
64
|
+
|
65
|
+
template {
|
66
|
+
destination = "secrets/iam.env"
|
67
|
+
data = <<BLOB
|
68
|
+
{{with secret "iam/sts/example-iam"}}
|
69
|
+
AWS_ACCESS_KEY_ID={{.Data.access_key}}
|
70
|
+
AWS_SECRET_ACCESS_KEY={{.Data.secret_key}}
|
71
|
+
AWS_SESSION_TOKEN={{.Data.security_token}}
|
72
|
+
{{end}}
|
73
|
+
BLOB
|
74
|
+
env = true
|
75
|
+
}
|
76
|
+
|
77
|
+
artifact {
|
78
|
+
source = "s3.amazonaws.com/example-bucket/example-job/script.sh"
|
79
|
+
}
|
80
|
+
|
81
|
+
config {
|
82
|
+
command = "script.sh"
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
## Other uses
|
89
|
+
|
90
|
+
By requiring only `nomadsl`, you can inject these methods into another class:
|
91
|
+
|
92
|
+
#!/usr/bin/env ruby
|
93
|
+
|
94
|
+
require 'nomadsl'
|
95
|
+
|
96
|
+
class Example
|
97
|
+
include Nomadsl
|
98
|
+
|
99
|
+
def generate
|
100
|
+
@result = job "example" do
|
101
|
+
# ...
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
puts Example.new.generate
|
107
|
+
|
108
|
+
## Roadmap
|
109
|
+
|
110
|
+
* Make all attributes explicitly callable
|
111
|
+
* Make subkeys embeddable in arglists if sensible
|
112
|
+
* Allow injecting comments into the rendered file
|
113
|
+
* Finish custom config blocks for each task driver
|
114
|
+
* Make errors report their correct location
|
115
|
+
|
116
|
+
## Contributing
|
117
|
+
|
118
|
+
I'm happy to accept suggestions, bug reports, and pull requests through Github.
|
119
|
+
|
120
|
+
## License
|
121
|
+
|
122
|
+
This software is public domain. No rights are reserved. See LICENSE for more
|
123
|
+
information.
|
data/lib/nomadsl/dsl.rb
ADDED
data/lib/nomadsl.rb
ADDED
@@ -0,0 +1,524 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
ARTIFACTS = {}
|
6
|
+
|
7
|
+
module Nomadsl
|
8
|
+
def die(err)
|
9
|
+
raise err
|
10
|
+
end
|
11
|
+
|
12
|
+
def nomadsl_print(b)
|
13
|
+
@nomadsl_print = b
|
14
|
+
end
|
15
|
+
|
16
|
+
def only(*levels)
|
17
|
+
unless levels.include? @stack.last
|
18
|
+
loc = caller_locations(1,1)[0]
|
19
|
+
die "Bad syntax on line #{loc.lineno}! '#{loc.label}' can only appear in #{levels.collect{|x| "'#{x}'" }.join(', ')}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#################################################################
|
24
|
+
# rendering methods
|
25
|
+
|
26
|
+
def str!(k, v)
|
27
|
+
die "Value for '#{k}' is nil" if v.nil?
|
28
|
+
str(k, v)
|
29
|
+
end
|
30
|
+
|
31
|
+
def str(k, v)
|
32
|
+
render "#{k} = #{v.to_s.to_json}" unless v.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
def list!(k, v)
|
36
|
+
die "Value for '#{k}' is nil" if v.nil?
|
37
|
+
list(k, v)
|
38
|
+
end
|
39
|
+
|
40
|
+
def list(k, v)
|
41
|
+
render "#{k} = #{[v].flatten.to_json}" unless v.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def int!(k, v)
|
45
|
+
die "Value for '#{k}' is nil" if v.nil?
|
46
|
+
int(k, v)
|
47
|
+
end
|
48
|
+
|
49
|
+
def int(k, v)
|
50
|
+
render "#{k} = #{v.to_i}" unless v.nil?
|
51
|
+
end
|
52
|
+
|
53
|
+
def bool!(k, v)
|
54
|
+
die "Value for '#{k}' is nil" if v.nil?
|
55
|
+
bool(k, v)
|
56
|
+
end
|
57
|
+
|
58
|
+
def bool(k, v)
|
59
|
+
render "#{k} = #{v ? true : false}" unless v.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
def blob!(k, v)
|
63
|
+
die "Value for '#{k}' is nil" if v.nil?
|
64
|
+
blob(k, v)
|
65
|
+
end
|
66
|
+
|
67
|
+
def blob(k, v)
|
68
|
+
render "#{k} = <<BLOB"
|
69
|
+
@out << "#{v.chomp}\nBLOB\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
# try really hard
|
73
|
+
def any(k, v)
|
74
|
+
if v.nil?
|
75
|
+
return
|
76
|
+
elsif v.is_a? Array
|
77
|
+
list k, v
|
78
|
+
elsif v.is_a? Integer
|
79
|
+
int k, v
|
80
|
+
elsif v.is_a? TrueClass or v.is_a? FalseClass
|
81
|
+
bool k, v
|
82
|
+
elsif v.is_a? String
|
83
|
+
if v.to_i.to_s == v
|
84
|
+
int k, v
|
85
|
+
else
|
86
|
+
str k, v
|
87
|
+
end
|
88
|
+
elsif v.is_a? Hash
|
89
|
+
v.each do |k, v|
|
90
|
+
any k, v
|
91
|
+
end
|
92
|
+
else
|
93
|
+
die "An unexpected type was encountered."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def render(s)
|
98
|
+
@first = false
|
99
|
+
@out << "#{' '*@indent}#{s}\n"
|
100
|
+
end
|
101
|
+
|
102
|
+
def block(t, n=nil)
|
103
|
+
unless @first
|
104
|
+
@out << "\n"
|
105
|
+
end
|
106
|
+
|
107
|
+
render(n ? "#{t} #{n.to_json} {" : "#{t} {")
|
108
|
+
|
109
|
+
if block_given?
|
110
|
+
@stack.push t
|
111
|
+
@first = true
|
112
|
+
@indent += 1
|
113
|
+
yield
|
114
|
+
@indent -= 1
|
115
|
+
@first = false
|
116
|
+
@stack.pop
|
117
|
+
end
|
118
|
+
render "}"
|
119
|
+
end
|
120
|
+
|
121
|
+
################################################
|
122
|
+
# real stuff
|
123
|
+
# https://www.nomadproject.io/docs/job-specification/
|
124
|
+
|
125
|
+
# https://www.nomadproject.io/docs/job-specification/job.html#all_at_once
|
126
|
+
def all_at_once(v)
|
127
|
+
only :job
|
128
|
+
bool :all_at_once, v
|
129
|
+
end
|
130
|
+
|
131
|
+
# https://www.nomadproject.io/docs/job-specification/artifact.html
|
132
|
+
def artifact(source:, destination: nil, mode: nil, options: nil)
|
133
|
+
only :task
|
134
|
+
block(:artifact) do
|
135
|
+
str! :source, source
|
136
|
+
str :destination, destination
|
137
|
+
str :mode, mode
|
138
|
+
if options
|
139
|
+
block(:options) do
|
140
|
+
options.each do |k,v|
|
141
|
+
str k, v
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# https://www.nomadproject.io/docs/job-specification/service.html#check-parameters
|
149
|
+
def check(address_mode: nil, args: nil, command: nil, grpc_service: nil, grpc_use_tls: nil, initial_status: nil, interval: nil, method: nil, name: nil, path: nil, port: nil, protocol: nil, timeout: nil, type: nil, tls_skip_verify: nil)
|
150
|
+
only :service
|
151
|
+
block(:check) do
|
152
|
+
str :address_mode, address_mode
|
153
|
+
list :args, args
|
154
|
+
str :command, command
|
155
|
+
str :grpc_service, grpc_service
|
156
|
+
bool :grpc_use_tls, grpc_use_tls
|
157
|
+
str :initial_status, initial_status
|
158
|
+
str :interval, interval
|
159
|
+
str :method, method
|
160
|
+
str :name, name
|
161
|
+
str :path, path
|
162
|
+
str :port, port
|
163
|
+
str :protocol, protocol
|
164
|
+
str :timeout, timeout
|
165
|
+
str :type, type
|
166
|
+
bool :tls_skip_verify, tls_skip_verify
|
167
|
+
yield if block_given?
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# https://www.nomadproject.io/docs/job-specification/check_restart.html
|
172
|
+
def check_restart(limit: nil, grace: nil, ignore_warnings: nil)
|
173
|
+
only :service, :check
|
174
|
+
block(:check_restart) do
|
175
|
+
int :limit, limit
|
176
|
+
str :grace, grace
|
177
|
+
bool :ignore_warnings, ignore_warnings
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# https://www.nomadproject.io/docs/job-specification/task.html#config
|
182
|
+
def config(**opts)
|
183
|
+
only :task
|
184
|
+
config_method = "__config_#{@driver}".to_sym
|
185
|
+
if private_methods.include?(config_method)
|
186
|
+
send(config_method, **opts)
|
187
|
+
else
|
188
|
+
# try to wing it
|
189
|
+
block(:config) do
|
190
|
+
opts.each do |k,v|
|
191
|
+
any k, v
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def __config_exec(command:, args: nil)
|
198
|
+
only :task
|
199
|
+
block(:config) do
|
200
|
+
str! :command, command
|
201
|
+
list :args, args
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
# https://www.nomadproject.io/docs/job-specification/constraint.html
|
207
|
+
def constraint(attribute: nil, operator: nil, value: nil)
|
208
|
+
only :job, :group, :task
|
209
|
+
block(:constraint) do
|
210
|
+
str :attribute, attribute
|
211
|
+
str :operator, operator
|
212
|
+
str :value, value
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# https://www.nomadproject.io/docs/job-specification/job.html#datacenters
|
217
|
+
def datacenters(*d)
|
218
|
+
only :job
|
219
|
+
list! :datacenters, d
|
220
|
+
end
|
221
|
+
|
222
|
+
# https://www.nomadproject.io/docs/job-specification/dispatch_payload.html
|
223
|
+
def dispatch_payload(file:)
|
224
|
+
only :task
|
225
|
+
block(:dispatch_payload) do
|
226
|
+
str! :file, file
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# https://www.nomadproject.io/docs/job-specification/env.html
|
231
|
+
def env(**opts)
|
232
|
+
only :task
|
233
|
+
block(:env) do
|
234
|
+
opts.each do |k,v|
|
235
|
+
str k, v
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# https://www.nomadproject.io/docs/job-specification/ephemeral_disk.html
|
241
|
+
def ephemeral_disk(migrate: nil, size: nil, sticky: nil)
|
242
|
+
only :group
|
243
|
+
block(:ephemeral_disk) do
|
244
|
+
bool :migrate, migrate
|
245
|
+
int :size, size
|
246
|
+
bool :sticky, sticky
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# https://www.nomadproject.io/docs/job-specification/group.html
|
251
|
+
def group(name, count: nil)
|
252
|
+
only :job
|
253
|
+
block(:group, name) do
|
254
|
+
int :count, count
|
255
|
+
yield
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# https://www.nomadproject.io/docs/job-specification/service.html#header-stanza
|
260
|
+
def header(name, values)
|
261
|
+
only :check
|
262
|
+
block(:header) do
|
263
|
+
list! name, values
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# https://www.nomadproject.io/docs/job-specification/job.html
|
268
|
+
def job(j)
|
269
|
+
# initialize the variables since this is the actual root
|
270
|
+
@out = ""
|
271
|
+
@indent = 0
|
272
|
+
@first = true
|
273
|
+
@stack = [:root]
|
274
|
+
|
275
|
+
only :root
|
276
|
+
result = block(:job, j) { yield }
|
277
|
+
if @nomadsl_print
|
278
|
+
puts result
|
279
|
+
end
|
280
|
+
result
|
281
|
+
end
|
282
|
+
|
283
|
+
# https://www.nomadproject.io/docs/job-specification/logs.html
|
284
|
+
def logs(max_files: nil, max_file_size: nil)
|
285
|
+
only :task
|
286
|
+
block(:logs) do
|
287
|
+
int :max_files, max_files
|
288
|
+
int :max_file_size, max_file_size
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# https://www.nomadproject.io/docs/job-specification/meta.html
|
293
|
+
def meta(**opts)
|
294
|
+
only :job, :group, :task
|
295
|
+
block(:meta) do
|
296
|
+
opts.each do |k,v|
|
297
|
+
str k, v
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# https://www.nomadproject.io/docs/job-specification/migrate.html
|
303
|
+
def migrate(max_parallel: nil, health_check: nil, min_healthy_time: nil, healthy_deadline: nil)
|
304
|
+
only :job, :group
|
305
|
+
block(:migrate) do
|
306
|
+
int :max_parallel, max_parallel
|
307
|
+
str :health_check, health_check
|
308
|
+
str :min_healthy_time, min_healthy_time
|
309
|
+
str :healthy_deadline, healthy_deadline
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# https://www.nomadproject.io/docs/job-specification/job.html#namespace
|
314
|
+
# Supported by Nomad Enterprise ONLY
|
315
|
+
def namespace(n)
|
316
|
+
only :job
|
317
|
+
str! :namespace, n
|
318
|
+
end
|
319
|
+
|
320
|
+
# https://www.nomadproject.io/docs/job-specification/network.html
|
321
|
+
def network(mbits: nil)
|
322
|
+
only :resources
|
323
|
+
block(:network) do
|
324
|
+
int :mbits, mbits
|
325
|
+
yield if block_given?
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
# https://www.nomadproject.io/docs/job-specification/parameterized.html
|
330
|
+
def parameterized(payload: "optional", meta_optional: nil, meta_required: nil)
|
331
|
+
only :job
|
332
|
+
die "Bad option for parameterized.payload: '#{payload}'" unless %w( optional required forbidden ).include?(payload)
|
333
|
+
block :parameterized do
|
334
|
+
str! :payload, payload
|
335
|
+
list :meta_optional, meta_optional
|
336
|
+
list :meta_required, meta_required
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
# https://www.nomadproject.io/docs/job-specification/periodic.html
|
341
|
+
def periodic(cron: nil, prohibit_overlap: nil, time_zone: nil)
|
342
|
+
only :job
|
343
|
+
block(:periodic) do
|
344
|
+
str :cron, cron
|
345
|
+
bool :prohibit_overlap, prohibit_overlap
|
346
|
+
str :time_zone, time_zone
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
# https://www.nomadproject.io/docs/job-specification/network.html#port
|
351
|
+
def port(n, static: nil)
|
352
|
+
only :network
|
353
|
+
if static
|
354
|
+
block(:port, n) do
|
355
|
+
int :static, static
|
356
|
+
end
|
357
|
+
else
|
358
|
+
render "port #{n.to_json} {}"
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
# https://www.nomadproject.io/docs/job-specification/job.html#priority
|
363
|
+
def priority(p)
|
364
|
+
only :job
|
365
|
+
int! :priority, p
|
366
|
+
end
|
367
|
+
|
368
|
+
# https://www.nomadproject.io/docs/job-specification/job.html#region
|
369
|
+
def region(r)
|
370
|
+
only :job
|
371
|
+
str! :region, r
|
372
|
+
end
|
373
|
+
|
374
|
+
# https://www.nomadproject.io/docs/job-specification/reschedule.html
|
375
|
+
def reschedule(attempts: nil, interval: nil, delay: nil, delay_function: nil, max_delay: nil, unlimited: nil)
|
376
|
+
only :job, :group
|
377
|
+
block(:reschedule) do
|
378
|
+
int :attempts, attempts
|
379
|
+
str :interval, interval
|
380
|
+
str :delay, delay
|
381
|
+
str :delay_function, delay_function
|
382
|
+
str :max_delay, max_delay
|
383
|
+
bool :unlimited, unlimited
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
# https://www.nomadproject.io/docs/job-specification/resources.html
|
388
|
+
def resources(cpu: nil, iops: nil, memory: nil)
|
389
|
+
only :task
|
390
|
+
block(:resources) do
|
391
|
+
int :cpu, cpu
|
392
|
+
int :iops, iops
|
393
|
+
int :memory, memory
|
394
|
+
yield if block_given?
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
# https://www.nomadproject.io/docs/job-specification/restart.html
|
399
|
+
def restart(attempts: nil, delay: nil, interval: nil, mode: nil)
|
400
|
+
only :group
|
401
|
+
block(:restart)do
|
402
|
+
int :attempts, attempts
|
403
|
+
str :delay, delay
|
404
|
+
str :interval, interval
|
405
|
+
str :mode, mode
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
# https://www.nomadproject.io/docs/job-specification/service.html
|
410
|
+
def service(address_mode: nil, canary_tags: nil, name: nil, port: nil, tags: nil)
|
411
|
+
only :task
|
412
|
+
block(:service) do
|
413
|
+
str :address_mode, address_mode
|
414
|
+
list :canary_tags, canary_tags
|
415
|
+
str :name, name
|
416
|
+
str :port, port
|
417
|
+
list :tags, tags
|
418
|
+
yield if block_given?
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
# https://www.nomadproject.io/docs/job-specification/task.html
|
423
|
+
def task(t, driver: "exec", kill_signal: nil, kill_timeout: nil, leader: nil, shutdown_delay: nil, user: nil)
|
424
|
+
only :group
|
425
|
+
@driver = driver
|
426
|
+
block(:task, t) do
|
427
|
+
str :driver, driver
|
428
|
+
str :kill_signal, kill_signal
|
429
|
+
str :kill_timeout, kill_timeout
|
430
|
+
bool :leader, leader
|
431
|
+
str :shutdown_delay, shutdown_delay
|
432
|
+
str :user, user
|
433
|
+
yield
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
# https://www.nomadproject.io/docs/job-specification/template.html
|
438
|
+
def template(change_mode: nil, change_signal: nil, data: nil, destination:, env: nil, left_delimiter: nil, perms: nil, right_delimiter: nil, source: nil, splay: nil, vault_grace: nil)
|
439
|
+
only :task
|
440
|
+
block(:template) do
|
441
|
+
str :change_mode, change_mode
|
442
|
+
str :change_signal, change_signal
|
443
|
+
str! :destination, destination
|
444
|
+
blob :data, data
|
445
|
+
bool :env, env
|
446
|
+
str :left_delimiter, left_delimiter
|
447
|
+
str :perms, perms
|
448
|
+
str :right_delimiter, right_delimiter
|
449
|
+
str :source, source
|
450
|
+
str :splay, splay
|
451
|
+
str :vault_grace, vault_grace
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
# https://www.nomadproject.io/docs/job-specification/job.html#type
|
456
|
+
def type(t)
|
457
|
+
only :job
|
458
|
+
die "Bad job type '#{t}'" unless %w( batch service system ).include?(t)
|
459
|
+
str! :type, t
|
460
|
+
end
|
461
|
+
|
462
|
+
# https://www.nomadproject.io/docs/job-specification/update.html
|
463
|
+
def update(max_parallel: nil, health_check: nil, min_healthy_time: nil, healthy_deadline: nil, progress_deadline: nil, auto_revert: nil, canary: nil, stagger: nil)
|
464
|
+
only :job, :group
|
465
|
+
block(:update) do
|
466
|
+
int :max_parallel, max_parallel
|
467
|
+
str :health_check, health_check
|
468
|
+
str :min_healthy_time, min_healthy_time
|
469
|
+
str :healthy_deadline, healthy_deadline
|
470
|
+
str :progress_deadline, progress_deadline
|
471
|
+
bool :auto_revert, auto_revert
|
472
|
+
int :canary, canary
|
473
|
+
str :stagger, stagger
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
# https://www.nomadproject.io/docs/job-specification/vault.html
|
478
|
+
def vault(change_mode: nil, change_token: nil, env: nil, policies: nil)
|
479
|
+
only :job, :group, :task
|
480
|
+
block(:vault) do
|
481
|
+
str :change_mode, change_mode
|
482
|
+
str :change_token, change_token
|
483
|
+
bool :env, env
|
484
|
+
list :policies, policies
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
# https://www.nomadproject.io/docs/job-specification/job.html#vault_token
|
489
|
+
# NOTE: explicitly unsupported, dangerous
|
490
|
+
|
491
|
+
|
492
|
+
########################################################
|
493
|
+
# shortcuts
|
494
|
+
|
495
|
+
def package(id)
|
496
|
+
if pkg = ARTIFACTS[id.to_sym]
|
497
|
+
artifact(**pkg)
|
498
|
+
else
|
499
|
+
die "Unknown package ID '#{id}'"
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
def preloaded_vault_aws_creds(name, path)
|
504
|
+
data = <<DATA
|
505
|
+
{{with secret "#{path}"}}
|
506
|
+
AWS_ACCESS_KEY_ID={{.Data.access_key}}
|
507
|
+
AWS_SECRET_ACCESS_KEY={{.Data.secret_key}}
|
508
|
+
AWS_SESSION_TOKEN={{.Data.security_token}}
|
509
|
+
{{end}}
|
510
|
+
DATA
|
511
|
+
template(data: data, destination: "secrets/#{name}.env", env: true)
|
512
|
+
end
|
513
|
+
|
514
|
+
def vault_aws_creds(name, path)
|
515
|
+
data = <<DATA
|
516
|
+
{{with secret "#{path}"}}
|
517
|
+
export AWS_ACCESS_KEY_ID={{.Data.access_key}}
|
518
|
+
export AWS_SECRET_ACCESS_KEY={{.Data.secret_key}}
|
519
|
+
export AWS_SESSION_TOKEN={{.Data.security_token}}
|
520
|
+
{{end}}
|
521
|
+
DATA
|
522
|
+
template(data: data, destination: "secrets/#{name}.env")
|
523
|
+
end
|
524
|
+
end
|
data/nomadsl.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'lib/nomadsl/version.rb'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'nomadsl'
|
5
|
+
s.version = Nomadsl::VERSION
|
6
|
+
s.authors = ['David Adams']
|
7
|
+
s.email = 'daveadams@gmail.com'
|
8
|
+
s.date = Time.now.strftime('%Y-%m-%d')
|
9
|
+
s.license = 'CC0'
|
10
|
+
s.homepage = 'https://github.com/daveadams/nomadsl'
|
11
|
+
s.required_ruby_version = '>=2.4.0'
|
12
|
+
|
13
|
+
s.summary = 'Ruby DSL for generating Nomad job specification files'
|
14
|
+
|
15
|
+
s.require_paths = ['lib']
|
16
|
+
s.files = Dir["lib/**/*.rb"] + [
|
17
|
+
'README.md',
|
18
|
+
'LICENSE',
|
19
|
+
'nomadsl.gemspec'
|
20
|
+
]
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nomadsl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Adams
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-12-19 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: daveadams@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- LICENSE
|
20
|
+
- README.md
|
21
|
+
- lib/nomadsl.rb
|
22
|
+
- lib/nomadsl/dsl.rb
|
23
|
+
- lib/nomadsl/version.rb
|
24
|
+
- nomadsl.gemspec
|
25
|
+
homepage: https://github.com/daveadams/nomadsl
|
26
|
+
licenses:
|
27
|
+
- CC0
|
28
|
+
metadata: {}
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options: []
|
31
|
+
require_paths:
|
32
|
+
- lib
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.4.0
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
requirements: []
|
44
|
+
rubyforge_project:
|
45
|
+
rubygems_version: 2.6.13
|
46
|
+
signing_key:
|
47
|
+
specification_version: 4
|
48
|
+
summary: Ruby DSL for generating Nomad job specification files
|
49
|
+
test_files: []
|