nomade 0.1.2 → 0.1.7
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 +222 -35
- data/lib/nomade/exceptions.rb +15 -0
- data/lib/nomade/hooks.rb +4 -0
- data/lib/nomade/http.rb +33 -7
- data/lib/nomade/logger.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed05d51537667ac01f3e77adf01ae2b614ae1d40e06fd4461c3def6a21171936
|
4
|
+
data.tar.gz: ca64489b697185037f1921838878963d3f3dbf585228c7f980e616db1a524d14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd50b280e996fea8c141242bd094b78cb4ecb23271402aa8a55a939d9b8ca6a988a9775d12d9d823db8a402f67ec2e789270eee95e7c8bbc5397e11352f2dfa6
|
7
|
+
data.tar.gz: 54117827d93c75f13c6ae2b79ee6c9eb58d3d3514f6ffaa481a6177a4d0b123a013aae063768e942a02067aee4014b47979465d3525902bc18f942b33d7fb709
|
data/lib/nomade/deployer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "base64"
|
2
|
+
|
1
3
|
module Nomade
|
2
4
|
class Deployer
|
3
5
|
attr_reader :nomad_job
|
@@ -8,21 +10,32 @@ module Nomade
|
|
8
10
|
@job_builder = Nomade::JobBuilder.new(@http)
|
9
11
|
@logger = opts.fetch(:logger, Nomade.logger)
|
10
12
|
|
11
|
-
@timeout = 60 * 3
|
13
|
+
@timeout = opts.fetch(:timeout, 60 * 3)
|
14
|
+
|
15
|
+
@linger = opts.fetch(:linger, 8..28)
|
16
|
+
raise GeneralError.new("Linger needs to be a range, supplied with: #{@linger.class}") unless @linger.class == Range
|
12
17
|
|
13
18
|
@hooks = {
|
14
19
|
Nomade::Hooks::DEPLOY_RUNNING => [],
|
15
20
|
Nomade::Hooks::DEPLOY_FINISHED => [],
|
16
21
|
Nomade::Hooks::DEPLOY_FAILED => [],
|
22
|
+
|
23
|
+
Nomade::Hooks::DISPATCH_RUNNING => [],
|
24
|
+
Nomade::Hooks::DISPATCH_FINISHED => [],
|
25
|
+
Nomade::Hooks::DISPATCH_FAILED => [],
|
17
26
|
}
|
18
|
-
add_hook(Nomade::Hooks::DEPLOY_FAILED, lambda {|
|
27
|
+
add_hook(Nomade::Hooks::DEPLOY_FAILED, lambda {|_hook_type, _nomad_job, messages|
|
19
28
|
@logger.error "Failing deploy:"
|
20
29
|
messages.each do |message|
|
21
30
|
@logger.error "- #{message}"
|
22
31
|
end
|
23
32
|
})
|
24
|
-
|
25
|
-
|
33
|
+
add_hook(Nomade::Hooks::DISPATCH_FAILED, lambda {|_hook_type, _nomad_job, messages|
|
34
|
+
@logger.error "Failing dispatch:"
|
35
|
+
messages.each do |message|
|
36
|
+
@logger.error "- #{message}"
|
37
|
+
end
|
38
|
+
})
|
26
39
|
end
|
27
40
|
|
28
41
|
def init_job(template_file, image_full_name, template_variables = {})
|
@@ -31,6 +44,15 @@ module Nomade
|
|
31
44
|
@deployment_id = nil
|
32
45
|
|
33
46
|
self
|
47
|
+
rescue Nomade::HttpConnectionError => e
|
48
|
+
[e.class.to_s, e.message, "Http connection error, exiting!"].compact.uniq.map{|l| @logger.error(l)}
|
49
|
+
exit(7)
|
50
|
+
rescue Nomade::HttpBadResponse => e
|
51
|
+
[e.class.to_s, e.message, "Http bad response, exiting!"].compact.uniq.map{|l| @logger.error(l)}
|
52
|
+
exit(8)
|
53
|
+
rescue Nomade::HttpBadContentType => e
|
54
|
+
[e.class.to_s, e.message, "Http unexpected content type!"].compact.uniq.map{|l| @logger.error(l)}
|
55
|
+
exit(9)
|
34
56
|
end
|
35
57
|
|
36
58
|
def add_hook(hook, hook_method)
|
@@ -40,12 +62,20 @@ module Nomade
|
|
40
62
|
@hooks[Nomade::Hooks::DEPLOY_FINISHED] << hook_method
|
41
63
|
elsif Nomade::Hooks::DEPLOY_FAILED == hook
|
42
64
|
@hooks[Nomade::Hooks::DEPLOY_FAILED] << hook_method
|
65
|
+
elsif Nomade::Hooks::DISPATCH_RUNNING == hook
|
66
|
+
@hooks[Nomade::Hooks::DISPATCH_RUNNING] << hook_method
|
67
|
+
elsif Nomade::Hooks::DISPATCH_FINISHED == hook
|
68
|
+
@hooks[Nomade::Hooks::DISPATCH_FINISHED] << hook_method
|
69
|
+
elsif Nomade::Hooks::DISPATCH_FAILED == hook
|
70
|
+
@hooks[Nomade::Hooks::DISPATCH_FAILED] << hook_method
|
43
71
|
else
|
44
72
|
raise "#{hook} not supported!"
|
45
73
|
end
|
46
74
|
end
|
47
75
|
|
48
76
|
def deploy!
|
77
|
+
check_for_job_init
|
78
|
+
|
49
79
|
run_hooks(Nomade::Hooks::DEPLOY_RUNNING, @nomad_job, nil)
|
50
80
|
_plan
|
51
81
|
_deploy
|
@@ -67,14 +97,78 @@ module Nomade
|
|
67
97
|
rescue Nomade::DeploymentFailedError => e
|
68
98
|
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.class.to_s, e.message, "Couldn't deploy succesfully, exiting!"].compact.uniq)
|
69
99
|
exit(6)
|
100
|
+
rescue Nomade::HttpConnectionError => e
|
101
|
+
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.class.to_s, e.message, "Http connection error, exiting!"].compact.uniq)
|
102
|
+
exit(7)
|
103
|
+
rescue Nomade::HttpBadResponse => e
|
104
|
+
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.class.to_s, e.message, "Http bad response, exiting!"].compact.uniq)
|
105
|
+
exit(8)
|
106
|
+
rescue Nomade::HttpBadContentType => e
|
107
|
+
run_hooks(Nomade::Hooks::DEPLOY_FAILED, @nomad_job, [e.class.to_s, e.message, "Http unexpected content type!"].compact.uniq)
|
108
|
+
exit(9)
|
109
|
+
end
|
110
|
+
|
111
|
+
def dispatch!(payload_data: nil, payload_metadata: {})
|
112
|
+
check_for_job_init
|
113
|
+
|
114
|
+
run_hooks(Nomade::Hooks::DISPATCH_RUNNING, @nomad_job, nil)
|
115
|
+
_dispatch(payload_data, payload_metadata)
|
116
|
+
run_hooks(Nomade::Hooks::DISPATCH_FINISHED, @nomad_job, nil)
|
117
|
+
rescue Nomade::DispatchMetaDataFormattingError => e
|
118
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Metadata wrongly formatted, exiting!"].compact.uniq)
|
119
|
+
exit(10)
|
120
|
+
rescue Nomade::DispatchMissingMetaData => e
|
121
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Required metadata missing, exiting!"].compact.uniq)
|
122
|
+
exit(11)
|
123
|
+
rescue Nomade::DispatchUnknownMetaData => e
|
124
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Unknown metadata sent to server, exiting!"].compact.uniq)
|
125
|
+
exit(12)
|
126
|
+
rescue Nomade::DispatchMissingPayload => e
|
127
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Job requires payload, but payload isn't set!"].compact.uniq)
|
128
|
+
exit(20)
|
129
|
+
rescue Nomade::DispatchPayloadNotAllowed => e
|
130
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Job does not allow payload!"].compact.uniq)
|
131
|
+
exit(21)
|
132
|
+
rescue Nomade::DispatchPayloadUnknown => e
|
133
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "API error!"].compact.uniq)
|
134
|
+
exit(22)
|
135
|
+
rescue Nomade::DispatchWrongJobType => e
|
136
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Job has wrong job-type"].compact.uniq)
|
137
|
+
exit(30)
|
138
|
+
rescue Nomade::DispatchNotParamaterized => e
|
139
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Job is not paramaterized"].compact.uniq)
|
140
|
+
exit(31)
|
141
|
+
rescue Nomade::AllocationFailedError => e
|
142
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Allocation failed with errors, exiting!"].compact.uniq)
|
143
|
+
exit(40)
|
144
|
+
rescue Nomade::GeneralError => e
|
145
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "GeneralError hit, exiting!"].compact.uniq)
|
146
|
+
exit(1)
|
147
|
+
rescue Nomade::HttpConnectionError => e
|
148
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Http connection error, exiting!"].compact.uniq)
|
149
|
+
exit(7)
|
150
|
+
rescue Nomade::HttpBadResponse => e
|
151
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Http bad response, exiting!"].compact.uniq)
|
152
|
+
exit(8)
|
153
|
+
rescue Nomade::HttpBadContentType => e
|
154
|
+
run_hooks(Nomade::Hooks::DISPATCH_FAILED, @nomad_job, [e.class.to_s, e.message, "Http unexpected content type!"].compact.uniq)
|
155
|
+
exit(9)
|
70
156
|
end
|
71
157
|
|
72
158
|
def stop!(purge = false)
|
159
|
+
check_for_job_init
|
160
|
+
|
73
161
|
@http.stop_job(@nomad_job, purge)
|
74
162
|
end
|
75
163
|
|
76
164
|
private
|
77
165
|
|
166
|
+
def check_for_job_init
|
167
|
+
unless @nomad_job
|
168
|
+
raise Nomade::GeneralError.new("Did you forget to run init_job?")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
78
172
|
def run_hooks(hook, job, messages)
|
79
173
|
@hooks[hook].each do |hook_method|
|
80
174
|
hook_method.call(hook, job, messages)
|
@@ -92,7 +186,7 @@ module Nomade
|
|
92
186
|
@logger.info "Checking cluster for connectivity and capacity.."
|
93
187
|
plan_data = @http.plan_job(@nomad_job)
|
94
188
|
|
95
|
-
sum_of_changes = plan_data["Annotations"]["DesiredTGUpdates"].map { |
|
189
|
+
sum_of_changes = plan_data["Annotations"]["DesiredTGUpdates"].map { |_group_name, task_group_updates|
|
96
190
|
task_group_updates["Stop"] +
|
97
191
|
task_group_updates["Place"] +
|
98
192
|
task_group_updates["Migrate"] +
|
@@ -112,32 +206,36 @@ module Nomade
|
|
112
206
|
@http.create_job(@nomad_job)
|
113
207
|
end
|
114
208
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
eval_status
|
122
|
-
|
123
|
-
|
124
|
-
|
209
|
+
if @evaluation_id.empty?
|
210
|
+
@logger.info "Parameterized job without evaluation, no more work needed"
|
211
|
+
else
|
212
|
+
@logger.info "EvaluationID: #{@evaluation_id}"
|
213
|
+
@logger.info "#{@evaluation_id} Waiting until evaluation is complete"
|
214
|
+
eval_status = nil
|
215
|
+
while(eval_status != "complete") do
|
216
|
+
evaluation = @http.evaluation_request(@evaluation_id)
|
217
|
+
@deployment_id ||= evaluation["DeploymentID"]
|
218
|
+
eval_status = evaluation["Status"]
|
219
|
+
@logger.info "."
|
220
|
+
sleep(1)
|
221
|
+
end
|
125
222
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
223
|
+
@logger.info "Waiting until allocations are no longer pending"
|
224
|
+
allocations = []
|
225
|
+
until !allocations.empty? && allocations.all?{|a| a["ClientStatus"] != "pending"}
|
226
|
+
@logger.info "."
|
227
|
+
sleep(2)
|
228
|
+
allocations = @http.allocations_from_evaluation_request(@evaluation_id)
|
229
|
+
end
|
133
230
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
231
|
+
case @nomad_job.job_type
|
232
|
+
when "service"
|
233
|
+
service_deploy
|
234
|
+
when "batch"
|
235
|
+
batch_deploy
|
236
|
+
else
|
237
|
+
raise Nomade::GeneralError.new("Job-type '#{@nomad_job.job_type}' not implemented")
|
238
|
+
end
|
141
239
|
end
|
142
240
|
rescue Nomade::AllocationFailedError => e
|
143
241
|
e.allocations.each do |allocation|
|
@@ -187,6 +285,96 @@ module Nomade
|
|
187
285
|
raise
|
188
286
|
end
|
189
287
|
|
288
|
+
def _dispatch(payload_data, payload_metadata)
|
289
|
+
@logger.info "Dispatching #{@nomad_job.job_name} (#{@nomad_job.job_type}) with #{@nomad_job.image_name_and_version}"
|
290
|
+
@logger.info "URL: #{@nomad_endpoint}/ui/jobs/#{@nomad_job.job_name}"
|
291
|
+
|
292
|
+
@logger.info "Running sanity checks.."
|
293
|
+
|
294
|
+
if @nomad_job.job_type != "batch"
|
295
|
+
raise DispatchWrongJobType.new("Job-type for #{@nomad_job.job_name} is \"#{@nomad_job.job_type}\" but should be \"batch\"")
|
296
|
+
end
|
297
|
+
|
298
|
+
if @nomad_job.configuration(:hash)["ParameterizedJob"] == nil
|
299
|
+
raise DispatchNotParamaterized.new("Job doesn't seem to be a paramaterized job, returned JobHash doesn't contain ParameterizedJob-key")
|
300
|
+
end
|
301
|
+
|
302
|
+
payload_data = if payload_data
|
303
|
+
Base64.encode64(payload_data)
|
304
|
+
else
|
305
|
+
nil
|
306
|
+
end
|
307
|
+
|
308
|
+
payload_metadata = if payload_metadata == nil
|
309
|
+
{}
|
310
|
+
else
|
311
|
+
Hash[payload_metadata.collect{|k,v| [k.to_s, v]}]
|
312
|
+
payload_metadata.each do |key, value|
|
313
|
+
unless [key, value].map(&:class) == [String, String]
|
314
|
+
raise Nomade::DispatchMetaDataFormattingError.new("Dispatch metadata must only be strings: #{key}(#{key.class}) = #{value}(#{value.class})")
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
meta_required = @nomad_job.configuration(:hash)["ParameterizedJob"]["MetaRequired"]
|
320
|
+
meta_optional = @nomad_job.configuration(:hash)["ParameterizedJob"]["MetaOptional"]
|
321
|
+
payload = @nomad_job.configuration(:hash)["ParameterizedJob"]["Payload"]
|
322
|
+
|
323
|
+
if meta_required
|
324
|
+
@logger.info "Dispatch job expects the following metakeys: #{meta_required.join(", ")}"
|
325
|
+
meta_required.each do |required_key|
|
326
|
+
unless payload_metadata.keys.include?(required_key)
|
327
|
+
raise Nomade::DispatchMissingMetaData.new("Dispatch job expects metakey #{required_key} but it was not set")
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
allowed_meta_tags = [meta_required, meta_optional].flatten.uniq
|
333
|
+
@logger.info "Dispatch job allows the following metakeys: #{allowed_meta_tags.join(", ")}"
|
334
|
+
if payload_metadata
|
335
|
+
payload_metadata.keys.each do |metadata_key|
|
336
|
+
unless allowed_meta_tags.include?(metadata_key)
|
337
|
+
raise Nomade::DispatchUnknownMetaData.new("Dispatch job does not allow #{metadata_key} to be set!")
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
case payload
|
343
|
+
when "optional", ""
|
344
|
+
@logger.info "Expectation for Payload is: optional"
|
345
|
+
when "required"
|
346
|
+
@logger.info "Expectation for Payload is: required"
|
347
|
+
|
348
|
+
unless payload_data
|
349
|
+
raise Nomade::DispatchMissingPayload.new("Dispatch job expects payload_data, but we don't supply any!")
|
350
|
+
end
|
351
|
+
when "forbidden"
|
352
|
+
@logger.info "Expectation for Payload is: forbidden"
|
353
|
+
|
354
|
+
if payload_data
|
355
|
+
raise Nomade::DispatchPayloadNotAllowed.new("Dispatch job do not allow payload_data!")
|
356
|
+
end
|
357
|
+
else
|
358
|
+
raise Nomade::DispatchPayloadUnknown.new("Invalid value for [\"ParameterizedJob\"][\"Payload\"] = #{payload}")
|
359
|
+
end
|
360
|
+
|
361
|
+
@logger.info "Checking cluster for connectivity and capacity.."
|
362
|
+
_plan_data = @http.plan_job(@nomad_job)
|
363
|
+
|
364
|
+
dispatch_job = @http.dispatch_job(@nomad_job, payload_data: payload_data, payload_metadata: payload_metadata)
|
365
|
+
@evaluation_id = dispatch_job["EvalID"]
|
366
|
+
|
367
|
+
@logger.info "Waiting until allocations are no longer pending"
|
368
|
+
allocations = []
|
369
|
+
until !allocations.empty? && allocations.all?{|a| a["ClientStatus"] != "pending"}
|
370
|
+
@logger.info "."
|
371
|
+
sleep(2)
|
372
|
+
allocations = @http.allocations_from_evaluation_request(@evaluation_id)
|
373
|
+
end
|
374
|
+
|
375
|
+
batch_deploy
|
376
|
+
end
|
377
|
+
|
190
378
|
def service_deploy
|
191
379
|
@logger.info "Waiting until tasks are placed"
|
192
380
|
deploy_timeout = Time.now.utc + @timeout
|
@@ -213,7 +401,6 @@ module Nomade
|
|
213
401
|
|
214
402
|
announced_completed = []
|
215
403
|
promoted = false
|
216
|
-
failed = false
|
217
404
|
succesful_deployment = nil
|
218
405
|
while(succesful_deployment == nil) do
|
219
406
|
json = @http.deployment_request(@deployment_id)
|
@@ -223,13 +410,13 @@ module Nomade
|
|
223
410
|
|
224
411
|
desired_canaries = task_data["DesiredCanaries"]
|
225
412
|
desired_total = task_data["DesiredTotal"]
|
226
|
-
|
413
|
+
_placed_allocations = task_data["PlacedAllocs"]
|
227
414
|
healthy_allocations = task_data["HealthyAllocs"]
|
228
|
-
|
415
|
+
_unhealthy_allocations = task_data["UnhealthyAllocs"]
|
229
416
|
|
230
417
|
if manual_work_required
|
231
418
|
@logger.info "#{json["ID"]} #{task_name}: #{healthy_allocations}/#{desired_canaries}/#{desired_total} (Healthy/WantedCanaries/Total)"
|
232
|
-
announced_completed << task_name if healthy_allocations == desired_canaries
|
419
|
+
announced_completed << task_name if healthy_allocations == desired_canaries && desired_canaries > 0
|
233
420
|
else
|
234
421
|
@logger.info "#{json["ID"]} #{task_name}: #{healthy_allocations}/#{desired_total} (Healthy/Total)"
|
235
422
|
announced_completed << task_name if healthy_allocations == desired_total
|
@@ -250,7 +437,7 @@ module Nomade
|
|
250
437
|
|
251
438
|
if succesful_deployment == nil && json["TaskGroups"].values.all?{|tg| tg["HealthyAllocs"] >= tg["DesiredCanaries"]}
|
252
439
|
if !promoted
|
253
|
-
random_linger = rand(
|
440
|
+
random_linger = rand(@linger)
|
254
441
|
@logger.info "Lingering around for #{random_linger} seconds before deployment.."
|
255
442
|
sleep(random_linger)
|
256
443
|
|
@@ -319,7 +506,7 @@ module Nomade
|
|
319
506
|
|
320
507
|
tasks = get_tasks(allocations)
|
321
508
|
upcoming_tasks = get_upcoming_tasks(tasks)
|
322
|
-
|
509
|
+
_succesful_tasks = get_succesful_tasks(tasks)
|
323
510
|
failed_tasks = get_failed_tasks(tasks)
|
324
511
|
|
325
512
|
if upcoming_tasks.size == 0
|
data/lib/nomade/exceptions.rb
CHANGED
@@ -16,4 +16,19 @@ module Nomade
|
|
16
16
|
|
17
17
|
class UnsupportedDeploymentMode < StandardError; end
|
18
18
|
class FailedTaskGroupPlan < StandardError; end
|
19
|
+
|
20
|
+
class DispatchWrongJobType < StandardError; end
|
21
|
+
class DispatchNotParamaterized < StandardError; end
|
22
|
+
|
23
|
+
class DispatchMetaDataFormattingError < StandardError; end
|
24
|
+
class DispatchMissingMetaData < StandardError; end
|
25
|
+
class DispatchUnknownMetaData < StandardError; end
|
26
|
+
|
27
|
+
class DispatchMissingPayload < StandardError; end
|
28
|
+
class DispatchPayloadNotAllowed < StandardError; end
|
29
|
+
class DispatchPayloadUnknown < StandardError; end
|
30
|
+
|
31
|
+
class HttpConnectionError < StandardError; end
|
32
|
+
class HttpBadResponse < StandardError; end
|
33
|
+
class HttpBadContentType < StandardError; end
|
19
34
|
end
|
data/lib/nomade/hooks.rb
CHANGED
data/lib/nomade/http.rb
CHANGED
@@ -90,7 +90,7 @@ module Nomade
|
|
90
90
|
"DeploymentID" => deployment_id,
|
91
91
|
"All" => true,
|
92
92
|
}.to_json
|
93
|
-
|
93
|
+
_request(:post, "/v1/deployment/promote/#{deployment_id}", body: req_body)
|
94
94
|
|
95
95
|
return true
|
96
96
|
rescue StandardError => e
|
@@ -99,7 +99,7 @@ module Nomade
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def fail_deployment(deployment_id)
|
102
|
-
|
102
|
+
_request(:post, "/v1/deployment/fail/#{deployment_id}")
|
103
103
|
return true
|
104
104
|
rescue StandardError => e
|
105
105
|
Nomade.logger.fatal "HTTP Request failed (#{e.message})"
|
@@ -125,7 +125,7 @@ module Nomade
|
|
125
125
|
end
|
126
126
|
|
127
127
|
true
|
128
|
-
rescue Nomade::FailedTaskGroupPlan
|
128
|
+
rescue Nomade::FailedTaskGroupPlan
|
129
129
|
raise
|
130
130
|
rescue StandardError => e
|
131
131
|
Nomade.logger.fatal "HTTP Request failed (#{e.message})"
|
@@ -154,12 +154,34 @@ module Nomade
|
|
154
154
|
raise
|
155
155
|
end
|
156
156
|
|
157
|
+
def dispatch_job(nomad_job, payload_data: nil, payload_metadata: nil)
|
158
|
+
if payload_metadata.class != Hash
|
159
|
+
raise DispatchMetaDataFormattingError.new("Expected #{payload_metadata} to be a Hash, but received #{payload_metadata.class}")
|
160
|
+
end
|
161
|
+
|
162
|
+
req_body = JSON.generate({
|
163
|
+
"Payload": payload_data,
|
164
|
+
"Meta": payload_metadata,
|
165
|
+
}.delete_if { |_k, v| v.nil? })
|
166
|
+
|
167
|
+
res_body = _request(:post, "/v1/job/#{nomad_job.job_name}/dispatch", body: req_body)
|
168
|
+
JSON.parse(res_body)
|
169
|
+
rescue StandardError => e
|
170
|
+
Nomade.logger.fatal "HTTP Request failed (#{e.message})"
|
171
|
+
raise
|
172
|
+
end
|
173
|
+
|
157
174
|
private
|
158
175
|
|
159
176
|
def _request(request_type, path, body: nil, total_retries: 0, expected_content_type: "application/json")
|
160
177
|
uri = URI("#{@nomad_endpoint}#{path}")
|
161
178
|
|
162
179
|
http = Net::HTTP.new(uri.host, uri.port)
|
180
|
+
http.open_timeout = 10
|
181
|
+
http.read_timeout = 10
|
182
|
+
http.write_timeout = 10 if Net::HTTP.method_defined?(:write_timeout)
|
183
|
+
http.ssl_timeout = 10
|
184
|
+
|
163
185
|
if @nomad_endpoint.include?("https://")
|
164
186
|
http.use_ssl = true
|
165
187
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
@@ -175,30 +197,34 @@ module Nomade
|
|
175
197
|
else
|
176
198
|
raise "#{request_type} not supported"
|
177
199
|
end
|
200
|
+
|
178
201
|
req.add_field "Content-Type", "application/json"
|
179
202
|
req.body = body if body
|
180
203
|
|
181
204
|
res = begin
|
182
205
|
retries ||= 0
|
183
206
|
http.request(req)
|
184
|
-
rescue Timeout::Error, Errno::ETIMEDOUT, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, SocketError
|
207
|
+
rescue Timeout::Error, Errno::ETIMEDOUT, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, SocketError => e
|
185
208
|
if retries < total_retries
|
186
209
|
retries += 1
|
187
210
|
sleep 1
|
188
211
|
retry
|
189
212
|
else
|
190
|
-
raise
|
213
|
+
raise HttpConnectionError.new("#{e.class} - #{e.message}")
|
191
214
|
end
|
192
215
|
end
|
193
216
|
|
194
|
-
|
217
|
+
if res.code != "200"
|
218
|
+
raise HttpBadResponse.new("Bad response (not 200) but #{res.code}: #{res.body}")
|
219
|
+
end
|
220
|
+
|
195
221
|
if res.content_type != expected_content_type
|
196
222
|
# Sometimes the log endpoint doesn't set content_type on no content
|
197
223
|
# https://github.com/hashicorp/nomad/issues/7264
|
198
224
|
if res.content_type == nil && expected_content_type == "text/plain"
|
199
225
|
# don't raise
|
200
226
|
else
|
201
|
-
raise
|
227
|
+
raise HttpBadContentType.new("Expected #{expected_content_type} but got #{res.content_type}")
|
202
228
|
end
|
203
229
|
end
|
204
230
|
|
data/lib/nomade/logger.rb
CHANGED
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.1.
|
4
|
+
version: 0.1.7
|
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-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yell
|
@@ -114,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
114
|
- !ruby/object:Gem::Version
|
115
115
|
version: '0'
|
116
116
|
requirements: []
|
117
|
-
rubygems_version: 3.
|
117
|
+
rubygems_version: 3.1.2
|
118
118
|
signing_key:
|
119
119
|
specification_version: 4
|
120
120
|
summary: Gem that deploys nomad jobs
|