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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85557a8305dae1d56eaf0f9d8497948f928f270b8f43d28860836a1ad1fb0b3e
4
- data.tar.gz: 92e9afd8c92efb363edf7daf7c3f04f40dd71ca243c58dddfd9d4cd71925bd65
3
+ metadata.gz: c6c3684724566430b8c0af280a5be1e03be57a5c7bcac2298c22d14d03098565
4
+ data.tar.gz: ae59d84da529ab3e4041d52a9216f0cf4e68cd7cd39751d895907d05f52b19cf
5
5
  SHA512:
6
- metadata.gz: 0f33f910a59f67c4dcf63ba394a4d4a6d3e48ea555a562d73f5ee2d0dc59e98489270b9502a5e3dc8a2f56398a4d605e0ee11a135d26332a74a5186e3b162d44
7
- data.tar.gz: 172af74987917d6a0b2cea45d2e461991a5bc7af46de64a738edd220ecd0e829a25293013fcc45e864c1e7e4eeb74cbcc4da813b86188403a57016bb3f813266
6
+ metadata.gz: 1fb1d40654d23c00694ca29e9423050e3e829dd543dd293b5655c7def2885fa0c73593bc06a35a7f3c7f53869b3f4afc470077d9e9613cb8b0d113d1328ee49f
7
+ data.tar.gz: be3a100801b40b10a38f162095a86f3f36e386b9ff17e46ee7597e7ab37c373e059c8472acbfa6262bd56d37743252d5bb7780925812cfef6227a7f18c63d54f
@@ -1,66 +1,103 @@
1
1
  module Nomade
2
2
  class Deployer
3
- def initialize(nomad_endpoint, nomad_job, opts = {})
4
- @nomad_job = nomad_job
5
- @evaluation_id = nil
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
- @on_success = opts.fetch(:on_success, [])
13
- @on_failure = opts.fetch(:on_failure, [])
14
- @on_failure << method(:print_errors)
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
- plan
19
- deploy
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
- call_failure_handlers ["No modifications to make, exiting!"]
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
- call_failure_handlers [e.message, "GeneralError hit, exiting!"]
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
- call_failure_handlers ["Allocation failed with errors, exiting!"]
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
- call_failure_handlers [e.message, "Deployment failed with errors, exiting!"]
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
- call_failure_handlers [e.message, "Couldn't plan correctly, exiting!"]
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
- private
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
- def print_errors(errors)
49
- errors.each do |error|
50
- @logger.warn(error)
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 plan
79
+ def _plan
55
80
  @http.capacity_plan_job(@nomad_job)
56
81
  end
57
82
 
58
- def deploy
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 complete"
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
- @logger.info ".. deploy timeout is #{@timeout}"
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 > @timeout
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
@@ -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
@@ -0,0 +1,7 @@
1
+ module Nomade
2
+ module Hooks
3
+ DEPLOY_RUNNING = Class.new
4
+ DEPLOY_FINISHED = Class.new
5
+ DEPLOY_FAILED = Class.new
6
+ end
7
+ end
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(:json)
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(:json)
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
- uri = URI("#{@nomad_endpoint}/v1/job/#{nomad_job.job_name}/plan")
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
- req.body = nomad_job.configuration(:json)
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
- plan_output = JSON.parse(res.body)
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
- rendered_template = nomad_job.configuration(:hcl)
258
-
259
- # 0: No allocations created or destroyed. Nothing to do.
260
- # 1: Allocations created or destroyed.
261
- # 255: Error determining plan results. Nothing to do.
262
- allowed_exit_codes = [0, 1, 255]
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
- true
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
- class FormattingError < StandardError; end
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
- @template_variables = template_variables
11
-
12
- # image_full_name should be in the form of:
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["Job"]["ID"]
24
+ @config_hash["ID"]
38
25
  end
39
26
 
40
27
  def job_type
41
- @config_hash["Job"]["Type"]
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
- l.adapter STDOUT, level: stdout
14
- l.adapter STDERR, level: [:error, :fatal]
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/shell"
4
- require "nomade/job"
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/deployer"
9
- require "nomade/decorators"
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.5
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-02-26 00:00:00.000000000 Z
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: '0'
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: '0'
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