nomade 0.0.5 → 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 +4 -4
- data/lib/nomade/deployer.rb +88 -37
- data/lib/nomade/exceptions.rb +5 -1
- data/lib/nomade/hooks.rb +7 -0
- data/lib/nomade/http.rb +72 -30
- data/lib/nomade/job.rb +8 -41
- data/lib/nomade/job_builder.rb +46 -0
- data/lib/nomade/logger.rb +4 -2
- data/lib/nomade.rb +6 -5
- metadata +36 -7
- data/lib/nomade/shell.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6c3684724566430b8c0af280a5be1e03be57a5c7bcac2298c22d14d03098565
|
4
|
+
data.tar.gz: ae59d84da529ab3e4041d52a9216f0cf4e68cd7cd39751d895907d05f52b19cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fb1d40654d23c00694ca29e9423050e3e829dd543dd293b5655c7def2885fa0c73593bc06a35a7f3c7f53869b3f4afc470077d9e9613cb8b0d113d1328ee49f
|
7
|
+
data.tar.gz: be3a100801b40b10a38f162095a86f3f36e386b9ff17e46ee7597e7ab37c373e059c8472acbfa6262bd56d37743252d5bb7780925812cfef6227a7f18c63d54f
|
data/lib/nomade/deployer.rb
CHANGED
@@ -1,66 +1,103 @@
|
|
1
1
|
module Nomade
|
2
2
|
class Deployer
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
@deployment_id = nil
|
7
|
-
@timeout = Time.now.utc + 60 * 3 # minutes
|
3
|
+
attr_reader :nomad_job
|
4
|
+
|
5
|
+
def initialize(nomad_endpoint, opts = {})
|
8
6
|
@nomad_endpoint = nomad_endpoint
|
9
7
|
@http = Nomade::Http.new(@nomad_endpoint)
|
8
|
+
@job_builder = Nomade::JobBuilder.new(@http)
|
10
9
|
@logger = opts.fetch(:logger, Nomade.logger)
|
11
10
|
|
12
|
-
@
|
13
|
-
|
14
|
-
@
|
11
|
+
@timeout = 60 * 3 # seconds
|
12
|
+
|
13
|
+
@hooks = {
|
14
|
+
Nomade::Hooks::DEPLOY_RUNNING => [],
|
15
|
+
Nomade::Hooks::DEPLOY_FINISHED => [],
|
16
|
+
Nomade::Hooks::DEPLOY_FAILED => [],
|
17
|
+
}
|
18
|
+
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def init_job(template_file, image_full_name, template_variables = {})
|
23
|
+
@nomad_job = @job_builder.build(template_file, image_full_name, template_variables)
|
24
|
+
@evaluation_id = nil
|
25
|
+
@deployment_id = nil
|
26
|
+
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_hook(hook, hook_method)
|
31
|
+
if Nomade::Hooks::DEPLOY_RUNNING == hook
|
32
|
+
@hooks[Nomade::Hooks::DEPLOY_RUNNING] << hook_method
|
33
|
+
elsif Nomade::Hooks::DEPLOY_FINISHED == hook
|
34
|
+
@hooks[Nomade::Hooks::DEPLOY_FINISHED] << hook_method
|
35
|
+
elsif Nomade::Hooks::DEPLOY_FAILED == hook
|
36
|
+
@hooks[Nomade::Hooks::DEPLOY_FAILED] << hook_method
|
37
|
+
else
|
38
|
+
raise "#{hook} not supported!"
|
39
|
+
end
|
15
40
|
end
|
16
41
|
|
17
42
|
def deploy!
|
18
|
-
|
19
|
-
|
43
|
+
run_hooks(Nomade::Hooks::DEPLOY_RUNNING, @nomad_job, nil)
|
44
|
+
_plan
|
45
|
+
_deploy
|
46
|
+
run_hooks(Nomade::Hooks::DEPLOY_FINISHED, @nomad_job, nil)
|
20
47
|
rescue Nomade::NoModificationsError => e
|
21
|
-
|
48
|
+
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.message, "No modifications to make, exiting!"])
|
22
49
|
exit(0)
|
23
50
|
rescue Nomade::GeneralError => e
|
24
|
-
|
51
|
+
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.message, "GeneralError hit, exiting!"])
|
25
52
|
exit(1)
|
26
|
-
rescue Nomade::PlanningError => e
|
27
|
-
call_failure_handlers ["Couldn't make a plan, maybe a bad connection to Nomad server, exiting!"]
|
28
|
-
exit(2)
|
29
53
|
rescue Nomade::AllocationFailedError => e
|
30
|
-
|
54
|
+
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.message, "Allocation failed with errors, exiting!"])
|
31
55
|
exit(3)
|
32
56
|
rescue Nomade::UnsupportedDeploymentMode => e
|
33
|
-
|
57
|
+
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.message, "Deployment failed with errors, exiting!"])
|
34
58
|
exit(4)
|
35
59
|
rescue Nomade::FailedTaskGroupPlan => e
|
36
|
-
|
60
|
+
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.message, "Couldn't plan correctly, exiting!"])
|
37
61
|
exit(5)
|
62
|
+
rescue Nomade::DeploymentFailedError => e
|
63
|
+
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.message, "Couldn't deploy succesfully, exiting!"])
|
64
|
+
exit(6)
|
38
65
|
end
|
39
66
|
|
40
|
-
|
41
|
-
|
42
|
-
def call_failure_handlers(messages)
|
43
|
-
@on_failure.each do |failure_handler|
|
44
|
-
failure_handler.call(messages)
|
45
|
-
end
|
67
|
+
def stop!(purge = false)
|
68
|
+
@http.stop_job(@nomad_job, purge)
|
46
69
|
end
|
47
70
|
|
48
|
-
|
49
|
-
|
50
|
-
|
71
|
+
private
|
72
|
+
|
73
|
+
def run_hooks(hook, job, messages)
|
74
|
+
@hooks[hook].each do |hook_method|
|
75
|
+
hook_method.call(hook, job, messages)
|
51
76
|
end
|
52
77
|
end
|
53
78
|
|
54
|
-
def
|
79
|
+
def _plan
|
55
80
|
@http.capacity_plan_job(@nomad_job)
|
56
81
|
end
|
57
82
|
|
58
|
-
def
|
83
|
+
def _deploy
|
59
84
|
@logger.info "Deploying #{@nomad_job.job_name} (#{@nomad_job.job_type}) with #{@nomad_job.image_name_and_version}"
|
60
85
|
@logger.info "URL: #{@nomad_endpoint}/ui/jobs/#{@nomad_job.job_name}"
|
61
86
|
|
62
87
|
@logger.info "Checking cluster for connectivity and capacity.."
|
63
|
-
@http.plan_job(@nomad_job)
|
88
|
+
plan_data = @http.plan_job(@nomad_job)
|
89
|
+
|
90
|
+
sum_of_changes = plan_data["Annotations"]["DesiredTGUpdates"].map { |group_name, task_group_updates|
|
91
|
+
task_group_updates["Stop"] +
|
92
|
+
task_group_updates["Place"] +
|
93
|
+
task_group_updates["Migrate"] +
|
94
|
+
task_group_updates["DestructiveUpdate"] +
|
95
|
+
task_group_updates["Canary"]
|
96
|
+
}.sum
|
97
|
+
|
98
|
+
if sum_of_changes == 0
|
99
|
+
raise Nomade::NoModificationsError.new
|
100
|
+
end
|
64
101
|
|
65
102
|
@evaluation_id = if @http.check_if_job_exists?(@nomad_job)
|
66
103
|
@logger.info "Updating existing job"
|
@@ -81,7 +118,14 @@ module Nomade
|
|
81
118
|
sleep(1)
|
82
119
|
end
|
83
120
|
|
84
|
-
@logger.info "Waiting until allocations are
|
121
|
+
@logger.info "Waiting until allocations are no longer pending"
|
122
|
+
allocations = @http.allocations_from_evaluation_request(@evaluation_id)
|
123
|
+
until allocations.all?{|a| a["ClientStatus"] != "pending"}
|
124
|
+
@logger.info "."
|
125
|
+
sleep(2)
|
126
|
+
allocations = @http.allocations_from_evaluation_request(@evaluation_id)
|
127
|
+
end
|
128
|
+
|
85
129
|
case @nomad_job.job_type
|
86
130
|
when "service"
|
87
131
|
service_deploy
|
@@ -106,7 +150,7 @@ module Nomade
|
|
106
150
|
if stdout != ""
|
107
151
|
@logger.info
|
108
152
|
@logger.info "stdout:"
|
109
|
-
stdout.lines do |logline|
|
153
|
+
stdout.lines.each do |logline|
|
110
154
|
@logger.info(logline.strip)
|
111
155
|
end
|
112
156
|
end
|
@@ -115,7 +159,7 @@ module Nomade
|
|
115
159
|
if stderr != ""
|
116
160
|
@logger.info
|
117
161
|
@logger.info "stderr:"
|
118
|
-
stderr.lines do |logline|
|
162
|
+
stderr.lines.each do |logline|
|
119
163
|
@logger.info(logline.strip)
|
120
164
|
end
|
121
165
|
end
|
@@ -140,7 +184,8 @@ module Nomade
|
|
140
184
|
|
141
185
|
def service_deploy
|
142
186
|
@logger.info "Waiting until tasks are placed"
|
143
|
-
|
187
|
+
deploy_timeout = Time.now.utc + @timeout
|
188
|
+
@logger.info ".. deploy timeout is #{deploy_timeout}"
|
144
189
|
|
145
190
|
json = @http.deployment_request(@deployment_id)
|
146
191
|
@logger.info "#{json["JobID"]} version #{json["JobVersion"]}"
|
@@ -192,7 +237,7 @@ module Nomade
|
|
192
237
|
succesful_deployment = false
|
193
238
|
end
|
194
239
|
|
195
|
-
if succesful_deployment == nil && Time.now.utc >
|
240
|
+
if succesful_deployment == nil && Time.now.utc > deploy_timeout
|
196
241
|
@logger.info "Timeout hit, rolling back deploy!"
|
197
242
|
@http.fail_deployment(@deployment_id)
|
198
243
|
succesful_deployment = false
|
@@ -235,9 +280,13 @@ module Nomade
|
|
235
280
|
if succesful_deployment
|
236
281
|
@logger.info ""
|
237
282
|
@logger.info "#{@deployment_id} (version #{json["JobVersion"]}) was succesfully deployed!"
|
283
|
+
|
284
|
+
true
|
238
285
|
else
|
239
286
|
@logger.warn ""
|
240
287
|
@logger.warn "#{@deployment_id} (version #{json["JobVersion"]}) deployment _failed_!"
|
288
|
+
|
289
|
+
raise DeploymentFailedError.new
|
241
290
|
end
|
242
291
|
end
|
243
292
|
|
@@ -286,7 +335,7 @@ module Nomade
|
|
286
335
|
if stdout != ""
|
287
336
|
@logger.info
|
288
337
|
@logger.info "stdout:"
|
289
|
-
stdout.lines do |logline|
|
338
|
+
stdout.lines.each do |logline|
|
290
339
|
@logger.info(logline.strip)
|
291
340
|
end
|
292
341
|
end
|
@@ -295,7 +344,7 @@ module Nomade
|
|
295
344
|
if stderr != ""
|
296
345
|
@logger.info
|
297
346
|
@logger.info "stderr:"
|
298
|
-
stderr.lines do |logline|
|
347
|
+
stderr.lines.each do |logline|
|
299
348
|
@logger.info(logline.strip)
|
300
349
|
end
|
301
350
|
end
|
@@ -307,6 +356,8 @@ module Nomade
|
|
307
356
|
|
308
357
|
sleep(1)
|
309
358
|
end
|
359
|
+
|
360
|
+
true
|
310
361
|
end
|
311
362
|
|
312
363
|
# Task-helpers
|
data/lib/nomade/exceptions.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Nomade
|
2
|
+
class FormattingError < StandardError; end
|
3
|
+
|
2
4
|
class GeneralError < StandardError; end
|
3
5
|
class NoModificationsError < StandardError; end
|
4
|
-
class PlanningError < StandardError; end
|
5
6
|
|
6
7
|
class AllocationFailedError < StandardError
|
7
8
|
def initialize(evaluation_id, allocations)
|
@@ -10,6 +11,9 @@ module Nomade
|
|
10
11
|
end
|
11
12
|
attr_reader :evaluation_id, :allocations
|
12
13
|
end
|
14
|
+
|
15
|
+
class DeploymentFailedError < StandardError;end
|
16
|
+
|
13
17
|
class UnsupportedDeploymentMode < StandardError; end
|
14
18
|
class FailedTaskGroupPlan < StandardError; end
|
15
19
|
end
|
data/lib/nomade/hooks.rb
ADDED
data/lib/nomade/http.rb
CHANGED
@@ -120,9 +120,10 @@ module Nomade
|
|
120
120
|
|
121
121
|
req = Net::HTTP::Post.new(uri)
|
122
122
|
req.add_field "Content-Type", "application/json"
|
123
|
-
req.body = nomad_job.configuration(:
|
123
|
+
req.body = JSON.generate({"Job" => nomad_job.configuration(:hash)})
|
124
124
|
|
125
125
|
res = http.request(req)
|
126
|
+
|
126
127
|
raise if res.code != "200"
|
127
128
|
raise if res.content_type != "application/json"
|
128
129
|
|
@@ -143,7 +144,34 @@ module Nomade
|
|
143
144
|
|
144
145
|
req = Net::HTTP::Post.new(uri)
|
145
146
|
req.add_field "Content-Type", "application/json"
|
146
|
-
req.body = nomad_job.configuration(:
|
147
|
+
req.body = JSON.generate({"Job" => nomad_job.configuration(:hash)})
|
148
|
+
|
149
|
+
res = http.request(req)
|
150
|
+
|
151
|
+
raise if res.code != "200"
|
152
|
+
raise if res.content_type != "application/json"
|
153
|
+
|
154
|
+
return JSON.parse(res.body)["EvalID"]
|
155
|
+
rescue StandardError => e
|
156
|
+
Nomade.logger.fatal "HTTP Request failed (#{e.message})"
|
157
|
+
raise
|
158
|
+
end
|
159
|
+
|
160
|
+
def stop_job(nomad_job, purge = false)
|
161
|
+
uri = if purge
|
162
|
+
URI("#{@nomad_endpoint}/v1/job/#{nomad_job.job_name}?purge=true")
|
163
|
+
else
|
164
|
+
URI("#{@nomad_endpoint}/v1/job/#{nomad_job.job_name}")
|
165
|
+
end
|
166
|
+
|
167
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
168
|
+
if @nomad_endpoint.include?("https://")
|
169
|
+
http.use_ssl = true
|
170
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
171
|
+
end
|
172
|
+
|
173
|
+
req = Net::HTTP::Delete.new(uri)
|
174
|
+
req.add_field "Content-Type", "application/json"
|
147
175
|
|
148
176
|
res = http.request(req)
|
149
177
|
raise if res.code != "200"
|
@@ -223,7 +251,22 @@ module Nomade
|
|
223
251
|
end
|
224
252
|
|
225
253
|
def capacity_plan_job(nomad_job)
|
226
|
-
|
254
|
+
plan_output = plan_job(nomad_job)
|
255
|
+
|
256
|
+
if plan_output["FailedTGAllocs"]
|
257
|
+
raise Nomade::FailedTaskGroupPlan.new("Failed to plan groups: #{plan_output["FailedTGAllocs"].keys.join(",")}")
|
258
|
+
end
|
259
|
+
|
260
|
+
true
|
261
|
+
rescue Nomade::FailedTaskGroupPlan => e
|
262
|
+
raise
|
263
|
+
rescue StandardError => e
|
264
|
+
Nomade.logger.fatal "HTTP Request failed (#{e.message})"
|
265
|
+
raise
|
266
|
+
end
|
267
|
+
|
268
|
+
def convert_hcl_to_json(job_hcl)
|
269
|
+
uri = URI("#{@nomad_endpoint}/v1/jobs/parse")
|
227
270
|
|
228
271
|
http = Net::HTTP.new(uri.host, uri.port)
|
229
272
|
if @nomad_endpoint.include?("https://")
|
@@ -233,46 +276,45 @@ module Nomade
|
|
233
276
|
|
234
277
|
req = Net::HTTP::Post.new(uri)
|
235
278
|
req.add_field "Content-Type", "application/json"
|
236
|
-
|
279
|
+
|
280
|
+
req.body = JSON.generate({
|
281
|
+
"JobHCL": job_hcl,
|
282
|
+
"Canonicalize": false,
|
283
|
+
})
|
237
284
|
|
238
285
|
res = http.request(req)
|
239
286
|
raise if res.code != "200"
|
240
287
|
raise if res.content_type != "application/json"
|
241
288
|
|
242
|
-
|
243
|
-
|
244
|
-
if plan_output["FailedTGAllocs"]
|
245
|
-
raise Nomade::FailedTaskGroupPlan.new("Failed to plan groups: #{plan_output["FailedTGAllocs"].keys.join(",")}")
|
246
|
-
end
|
247
|
-
|
248
|
-
true
|
249
|
-
rescue Nomade::FailedTaskGroupPlan => e
|
250
|
-
raise
|
289
|
+
res.body
|
251
290
|
rescue StandardError => e
|
252
291
|
Nomade.logger.fatal "HTTP Request failed (#{e.message})"
|
253
292
|
raise
|
254
293
|
end
|
255
294
|
|
256
295
|
def plan_job(nomad_job)
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
exit_status, stdout, stderr = Shell.exec("NOMAD_ADDR=#{@nomad_endpoint} nomad job plan -diff -verbose -no-color -", rendered_template, allowed_exit_codes)
|
265
|
-
|
266
|
-
case exit_status
|
267
|
-
when 0
|
268
|
-
raise Nomade::NoModificationsError.new
|
269
|
-
when 1
|
270
|
-
# no-op
|
271
|
-
when 255
|
272
|
-
raise Nomade::PlanningError.new
|
296
|
+
uri = URI("#{@nomad_endpoint}/v1/job/#{nomad_job.job_name}/plan")
|
297
|
+
|
298
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
299
|
+
if @nomad_endpoint.include?("https://")
|
300
|
+
http.use_ssl = true
|
301
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
273
302
|
end
|
274
303
|
|
275
|
-
|
304
|
+
req = Net::HTTP::Post.new(uri)
|
305
|
+
req.add_field "Content-Type", "application/json"
|
306
|
+
req.body = JSON.generate({"Job" => nomad_job.configuration(:hash)})
|
307
|
+
|
308
|
+
res = http.request(req)
|
309
|
+
|
310
|
+
raise if res.code != "200"
|
311
|
+
raise if res.content_type != "application/json"
|
312
|
+
|
313
|
+
JSON.parse(res.body)
|
314
|
+
rescue StandardError => e
|
315
|
+
Nomade.logger.fatal "HTTP Request failed (#{e.message})"
|
316
|
+
raise
|
276
317
|
end
|
318
|
+
|
277
319
|
end
|
278
320
|
end
|
data/lib/nomade/job.rb
CHANGED
@@ -1,25 +1,10 @@
|
|
1
|
-
require "erb"
|
2
|
-
require "json"
|
3
|
-
|
4
1
|
module Nomade
|
5
2
|
class Job
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(template_file, image_full_name, template_variables = {})
|
3
|
+
def initialize(image_full_name, config_hcl, config_json, config_hash)
|
9
4
|
@image_full_name = image_full_name
|
10
|
-
@
|
11
|
-
|
12
|
-
|
13
|
-
# redis:4.0.1
|
14
|
-
# kaspergrubbe/secretimage:latest
|
15
|
-
# billetto/billetto-rails:4.2.24
|
16
|
-
unless @image_full_name.match(/\A[a-zA-Z0-9\/\-\_]+\:[a-zA-Z0-9\.\-\_]+\z/)
|
17
|
-
raise Nomade::Job::FormattingError.new("Image-format wrong: #{@image_full_name}")
|
18
|
-
end
|
19
|
-
|
20
|
-
@config_hcl = render_erb(template_file)
|
21
|
-
@config_json = convert_job_hcl_to_json(@config_hcl)
|
22
|
-
@config_hash = JSON.parse(@config_json)
|
5
|
+
@config_hcl = config_hcl
|
6
|
+
@config_json = config_json
|
7
|
+
@config_hash = config_hash
|
23
8
|
end
|
24
9
|
|
25
10
|
def configuration(format)
|
@@ -28,17 +13,19 @@ module Nomade
|
|
28
13
|
@config_hcl
|
29
14
|
when :json
|
30
15
|
@config_json
|
16
|
+
when :hash
|
17
|
+
@config_hash
|
31
18
|
else
|
32
19
|
@config_hash
|
33
20
|
end
|
34
21
|
end
|
35
22
|
|
36
23
|
def job_name
|
37
|
-
@config_hash["
|
24
|
+
@config_hash["ID"]
|
38
25
|
end
|
39
26
|
|
40
27
|
def job_type
|
41
|
-
@config_hash["
|
28
|
+
@config_hash["Type"]
|
42
29
|
end
|
43
30
|
|
44
31
|
def image_name_and_version
|
@@ -53,25 +40,5 @@ module Nomade
|
|
53
40
|
image_name_and_version.split(":").last
|
54
41
|
end
|
55
42
|
|
56
|
-
def template_variables
|
57
|
-
@template_variables
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
|
62
|
-
def render_erb(erb_template)
|
63
|
-
file = File.open(erb_template).read
|
64
|
-
rendered = ERB.new(file, nil, '-').result(binding)
|
65
|
-
|
66
|
-
rendered
|
67
|
-
end
|
68
|
-
|
69
|
-
def convert_job_hcl_to_json(rendered_template)
|
70
|
-
exit_status, stdout, stderr = Shell.exec("nomad job run -output -no-color -", rendered_template)
|
71
|
-
|
72
|
-
JSON.pretty_generate({
|
73
|
-
"Job": JSON.parse(stdout)["Job"],
|
74
|
-
})
|
75
|
-
end
|
76
43
|
end
|
77
44
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "erb"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module Nomade
|
5
|
+
class JobBuilder
|
6
|
+
def initialize(http)
|
7
|
+
@http = http
|
8
|
+
end
|
9
|
+
|
10
|
+
def build(template_file, image_full_name, template_variables = {})
|
11
|
+
# image_full_name should be in the form of:
|
12
|
+
# redis:4.0.1
|
13
|
+
# kaspergrubbe/secretimage:latest
|
14
|
+
# billetto/billetto-rails:4.2.24
|
15
|
+
unless image_full_name.match(/\A[a-zA-Z0-9\/\-\_]+\:[a-zA-Z0-9\.\-\_]+\z/)
|
16
|
+
raise Nomade::FormattingError.new("Image-format wrong: #{image_full_name}")
|
17
|
+
end
|
18
|
+
|
19
|
+
job_hcl = render_erb(template_file, image_full_name, template_variables)
|
20
|
+
job_json = @http.convert_hcl_to_json(job_hcl)
|
21
|
+
job_hash = JSON.parse(job_json)
|
22
|
+
|
23
|
+
Nomade::Job.new(image_full_name, job_hcl, job_json, job_hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def render_erb(erb_template, image_full_name, template_variables)
|
29
|
+
file = File.open(erb_template).read
|
30
|
+
|
31
|
+
local_binding = binding
|
32
|
+
local_binding.local_variable_set(:image_name_and_version, image_full_name)
|
33
|
+
local_binding.local_variable_set(:image_full_name, image_full_name)
|
34
|
+
local_binding.local_variable_set(:template_variables, template_variables)
|
35
|
+
|
36
|
+
# https://github.com/ruby/ruby/commit/3406c5d
|
37
|
+
rendered = if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
|
38
|
+
ERB.new(file, trim_mode: '-')
|
39
|
+
else
|
40
|
+
ERB.new(file, nil, '-')
|
41
|
+
end
|
42
|
+
|
43
|
+
rendered.result(local_binding)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/nomade/logger.rb
CHANGED
@@ -10,8 +10,10 @@ module Nomade
|
|
10
10
|
end
|
11
11
|
|
12
12
|
Yell.new do |l|
|
13
|
-
|
14
|
-
|
13
|
+
unless ARGV.include?("-q")
|
14
|
+
l.adapter STDOUT, level: stdout
|
15
|
+
l.adapter STDERR, level: [:error, :fatal]
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
data/lib/nomade.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
ENV["TZ"] = "UTC"
|
2
2
|
|
3
|
-
require "nomade/
|
4
|
-
require "nomade/
|
5
|
-
require "nomade/logger"
|
3
|
+
require "nomade/decorators"
|
4
|
+
require "nomade/deployer"
|
6
5
|
require "nomade/exceptions"
|
6
|
+
require "nomade/hooks"
|
7
7
|
require "nomade/http"
|
8
|
-
require "nomade/
|
9
|
-
require "nomade/
|
8
|
+
require "nomade/job"
|
9
|
+
require "nomade/job_builder"
|
10
|
+
require "nomade/logger"
|
10
11
|
|
11
12
|
module Nomade
|
12
13
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nomade
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kasper Grubbe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yell
|
@@ -42,16 +42,44 @@ dependencies:
|
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.9.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.9.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
61
|
+
version: 0.18.5
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- - "
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.18.5
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: irb
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
53
81
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
82
|
+
version: 1.0.0
|
55
83
|
description:
|
56
84
|
email: nomade@kaspergrubbe.com
|
57
85
|
executables: []
|
@@ -62,10 +90,11 @@ files:
|
|
62
90
|
- lib/nomade/decorators.rb
|
63
91
|
- lib/nomade/deployer.rb
|
64
92
|
- lib/nomade/exceptions.rb
|
93
|
+
- lib/nomade/hooks.rb
|
65
94
|
- lib/nomade/http.rb
|
66
95
|
- lib/nomade/job.rb
|
96
|
+
- lib/nomade/job_builder.rb
|
67
97
|
- lib/nomade/logger.rb
|
68
|
-
- lib/nomade/shell.rb
|
69
98
|
homepage: https://billetto.com
|
70
99
|
licenses:
|
71
100
|
- MIT
|
data/lib/nomade/shell.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require "open3"
|
2
|
-
|
3
|
-
module Nomade
|
4
|
-
class Shell
|
5
|
-
def self.exec(command, input = nil, allowed_exit_codes = [0])
|
6
|
-
Nomade.logger.debug("+: #{command}")
|
7
|
-
|
8
|
-
process, status, stdout, stderr = Open3.popen3(command) do |stdin, stdout, stderr, wait_thread|
|
9
|
-
if input
|
10
|
-
stdin.puts(input)
|
11
|
-
end
|
12
|
-
stdin.close
|
13
|
-
|
14
|
-
threads = {}.tap do |it|
|
15
|
-
it[:stdout] = Thread.new do
|
16
|
-
output = []
|
17
|
-
stdout.each do |l|
|
18
|
-
output << l
|
19
|
-
Nomade.logger.debug(l)
|
20
|
-
end
|
21
|
-
Thread.current[:output] = output.join
|
22
|
-
end
|
23
|
-
|
24
|
-
it[:stderr] = Thread.new do
|
25
|
-
output = []
|
26
|
-
stderr.each do |l|
|
27
|
-
output << l
|
28
|
-
Nomade.logger.debug(l)
|
29
|
-
end
|
30
|
-
Thread.current[:output] = output.join
|
31
|
-
end
|
32
|
-
end
|
33
|
-
threads.values.map(&:join)
|
34
|
-
|
35
|
-
[wait_thread.value, wait_thread.value.exitstatus, threads[:stdout][:output], threads[:stderr][:output]]
|
36
|
-
end
|
37
|
-
|
38
|
-
unless allowed_exit_codes.include?(status)
|
39
|
-
raise "`#{command}` failed with status=#{status}"
|
40
|
-
end
|
41
|
-
|
42
|
-
return [status, stdout, stderr]
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|