wrapbox 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a28f3af84133c270e231a949bd36a0fdde4cc202f8f8f67de03e52075cacf44
4
- data.tar.gz: 4bdb1546a8241d60bff8023d0b0201763ac40bfd55897521ead82ae94086b930
3
+ metadata.gz: 499da8de956c6c61f2ca34b4bb049c9eb157c6f45ca47d6a26e945359e981b80
4
+ data.tar.gz: 4ccd2cca92341d42f4fc301cbe51cf0c42d2901a4f6e7c4002eb7db80deeabbe
5
5
  SHA512:
6
- metadata.gz: ba3d465e670b3608b190b0859ab1bf5af1113a005a5a1f573b39828d835c4987a06506ae563ad293450b007ea6ac288961ef070359578c8d1549532e4d53af76
7
- data.tar.gz: 9dcf2cd150611c6c140320d0b457cc4ba16f9ffd531dc70b15b4577997ff40cfebb72cdafdf7d3b9dbaf4f27d613e41ce5e9c8e87bee816266bf12badc4b9dab
6
+ metadata.gz: aa498ca42d1b1fa4beb7e0f8be8760ff074ca0c6d090a9b1a51944e198821f3985434747d6e0c3f21acf0c6941f18cd0474488624fa28e87e5f7cec4533d8eef
7
+ data.tar.gz: 67963b588f10bb0046a2ced0eb8d42935e7562d281b473b801ba289fb7c2c9d4abbc39e014212ecf7e4e12f3e8adb4595c8ba9e1aafc4c850b8eedd99f0f6aa8
@@ -24,7 +24,7 @@ module Wrapbox
24
24
 
25
25
  def stop
26
26
  @stop = true
27
- @loop_thread.join(STOP_WAIT_TIMELIMIT)
27
+ @loop_thread&.join(STOP_WAIT_TIMELIMIT)
28
28
  end
29
29
 
30
30
  def main_loop
@@ -17,6 +17,7 @@ module Wrapbox
17
17
  def initialize(options)
18
18
  @name = options[:name]
19
19
  @container_definitions = options[:container_definition] ? [options[:container_definition]] : options[:container_definitions]
20
+ @logger = Logger.new($stdout)
20
21
 
21
22
  if @container_definitions.size >= 2
22
23
  raise "Docker runner does not support multi container currently"
@@ -37,15 +38,16 @@ module Wrapbox
37
38
  exec_docker(definition: definition, cmd: ["bundle", "exec", "rake", "wrapbox:run"], environments: envs)
38
39
  end
39
40
 
40
- def run_cmd(cmds, container_definition_overrides: {}, environments: [])
41
+ def run_cmd(cmds, container_definition_overrides: {}, environments: [], ignore_signal: false)
42
+ ths = []
41
43
  definition = container_definition
42
44
  .merge(container_definition_overrides)
43
45
 
44
46
  environments = extract_environments(environments)
45
47
 
46
48
  cmds << nil if cmds.empty?
47
- ths = cmds.map.with_index do |cmd, idx|
48
- Thread.new(cmd, idx) do |c, i|
49
+ cmds.each_with_index do |cmd, idx|
50
+ ths << Thread.new(cmd, idx) do |c, i|
49
51
  envs = environments + ["WRAPBOX_CMD_INDEX=#{idx}"]
50
52
  exec_docker(
51
53
  definition: definition,
@@ -54,7 +56,23 @@ module Wrapbox
54
56
  )
55
57
  end
56
58
  end
57
- ths.each(&:join)
59
+ ths.each { |th| th&.join }
60
+
61
+ true
62
+ rescue SignalException => e
63
+ sig = "SIG#{Signal.signame(e.signo)}"
64
+ if ignore_signal
65
+ @logger.info("Receive #{sig} signal. But Docker container continue running")
66
+ else
67
+ @logger.info("Receive #{sig} signal. Stop All tasks")
68
+ ths.each do |th|
69
+ th.report_on_exception = false
70
+ th.raise(e)
71
+ end
72
+ thread_timeout = 15
73
+ ths.each { |th| th.join(thread_timeout) }
74
+ end
75
+ nil
58
76
  end
59
77
 
60
78
  private
@@ -93,6 +111,9 @@ module Wrapbox
93
111
  unless resp["StatusCode"].zero?
94
112
  raise ExecutionError, "exit_code=#{resp["StatusCode"]}"
95
113
  end
114
+ rescue SignalException => e
115
+ sig = Signal.signame(e.signo)
116
+ container&.kill(signal: sig)
96
117
  ensure
97
118
  container.remove(force: true) if container && !keep_container
98
119
  end
@@ -116,6 +137,7 @@ module Wrapbox
116
137
  method_option :cpu, type: :numeric
117
138
  method_option :memory, type: :numeric
118
139
  method_option :environments, aliases: "-e"
140
+ method_option :ignore_signal, type: :boolean, default: false, desc: "Even if receive a signal (like TERM, INT, QUIT), Docker container continue running"
119
141
  def run_cmd(*args)
120
142
  repo = Wrapbox::ConfigRepository.new.tap { |r| r.load_yaml(options[:config]) }
121
143
  config = repo.get(options[:config_name])
@@ -129,7 +151,9 @@ module Wrapbox
129
151
  else
130
152
  container_definition_overrides = {}
131
153
  end
132
- runner.run_cmd(args, environments: environments, container_definition_overrides: container_definition_overrides)
154
+ unless runner.run_cmd(args, environments: environments, container_definition_overrides: container_definition_overrides, ignore_signal: options[:ignore_signal])
155
+ exit 1
156
+ end
133
157
  end
134
158
  end
135
159
  end
@@ -22,6 +22,7 @@ module Wrapbox
22
22
 
23
23
  EXECUTION_RETRY_INTERVAL = 3
24
24
  WAIT_DELAY = 5
25
+ TERM_TIMEOUT = 120
25
26
  HOST_TERMINATED_REASON_REGEXP = /Host EC2.*terminated/
26
27
 
27
28
  attr_reader \
@@ -128,12 +129,14 @@ module Wrapbox
128
129
  )
129
130
  end
130
131
 
131
- def run_cmd(cmds, container_definition_overrides: {}, **parameters)
132
+ def run_cmd(cmds, container_definition_overrides: {}, ignore_signal: false, **parameters)
133
+ ths = []
134
+
132
135
  task_definition = prepare_task_definition(container_definition_overrides)
133
136
 
134
137
  cmds << nil if cmds.empty?
135
- ths = cmds.map.with_index do |cmd, idx|
136
- Thread.new(cmd, idx) do |c, i|
138
+ cmds.each_with_index do |cmd, idx|
139
+ ths << Thread.new(cmd, idx) do |c, i|
137
140
  Thread.current[:cmd_index] = i
138
141
  envs = (parameters[:environments] || []) + [{name: "WRAPBOX_CMD_INDEX", value: i.to_s}]
139
142
  run_task(
@@ -144,6 +147,25 @@ module Wrapbox
144
147
  end
145
148
  end
146
149
  ths.each(&:join)
150
+
151
+ true
152
+ rescue SignalException => e
153
+ sig = "SIG#{Signal.signame(e.signo)}"
154
+ if ignore_signal
155
+ @logger.info("Receive #{sig} signal. But ECS Tasks continue running")
156
+ else
157
+ @logger.info("Receive #{sig} signal. Stop All tasks")
158
+ ths.each do |th|
159
+ th.report_on_exception = false
160
+ th.raise(e)
161
+ end
162
+ wait_until = Time.now + TERM_TIMEOUT + 15 # thread_timeout_buffer
163
+ ths.each do |th|
164
+ wait = wait_until - Time.now
165
+ th.join(wait) if wait.positive?
166
+ end
167
+ end
168
+ nil
147
169
  end
148
170
 
149
171
  private
@@ -158,6 +180,8 @@ module Wrapbox
158
180
 
159
181
  begin
160
182
  task = create_task(task_definition_arn, class_name, method_name, args, command, parameter)
183
+ return unless task # only Task creation aborted by SignalException
184
+
161
185
  @log_fetcher.run if @log_fetcher
162
186
 
163
187
  @logger.debug("Launch Task: #{task.task_arn}")
@@ -188,6 +212,14 @@ module Wrapbox
188
212
  sleep EXECUTION_RETRY_INTERVAL
189
213
  retry
190
214
  end
215
+ rescue SignalException
216
+ client.stop_task(
217
+ cluster: cl,
218
+ task: task.task_arn,
219
+ reason: "signal interrupted"
220
+ )
221
+ wait_task_stopped(cl, task.task_arn, TERM_TIMEOUT)
222
+ @logger.debug("Stop Task: #{task.task_arn}")
191
223
  ensure
192
224
  if @log_fetcher
193
225
  begin
@@ -209,10 +241,12 @@ module Wrapbox
209
241
  begin
210
242
  run_task_options = build_run_task_options(task_definition_arn, class_name, method_name, args, command, cl, parameter.environments, parameter.task_role_arn)
211
243
  @logger.debug("Task Options: #{run_task_options}")
212
- task = client
213
- .run_task(run_task_options)
214
- .tasks[0]
244
+ resp = client.run_task(run_task_options)
245
+ task = resp.tasks[0]
215
246
 
247
+ resp.failures.each do |failure|
248
+ @logger.debug("Failure: Arn=#{failure.arn}, Reason=#{failure.reason}")
249
+ end
216
250
  raise LackResource unless task # this case is almost lack of container resource.
217
251
 
218
252
  @logger.debug("Create Task: #{task.task_arn}")
@@ -270,6 +304,17 @@ module Wrapbox
270
304
  current_retry_interval = [current_retry_interval * parameter.retry_interval_multiplier, parameter.max_retry_interval].min
271
305
  retry
272
306
  end
307
+ rescue SignalException
308
+ if task
309
+ client.stop_task(
310
+ cluster: cl,
311
+ task: task.task_arn,
312
+ reason: "signal interrupted"
313
+ )
314
+ wait_task_stopped(cl, task.task_arn, TERM_TIMEOUT)
315
+ @logger.debug("Stop Task: #{task.task_arn}")
316
+ nil
317
+ end
273
318
  end
274
319
  end
275
320
 
@@ -409,6 +454,12 @@ module Wrapbox
409
454
  name: main_container_name,
410
455
  environment: env,
411
456
  }.tap { |o| o[:command] = command if command },
457
+ *container_definitions.drop(1).map do |c|
458
+ {
459
+ name: c[:name],
460
+ environment: env,
461
+ }
462
+ end
412
463
  ],
413
464
  }
414
465
  role_arn = task_role_arn || self.task_role_arn
@@ -449,6 +500,7 @@ module Wrapbox
449
500
  method_option :launch_retry, type: :numeric
450
501
  method_option :execution_retry, type: :numeric
451
502
  method_option :max_retry_interval, type: :numeric
503
+ method_option :ignore_signal, type: :boolean, default: false, desc: "Even if receive a signal (like TERM, INT, QUIT), ECS Tasks continue running"
452
504
  def run_cmd(*args)
453
505
  repo = Wrapbox::ConfigRepository.new.tap { |r| r.load_yaml(options[:config]) }
454
506
  config = repo.get(options[:config_name])
@@ -464,14 +516,17 @@ module Wrapbox
464
516
  launch_timeout: options[:launch_timeout],
465
517
  launch_retry: options[:launch_retry],
466
518
  execution_retry: options[:execution_retry],
467
- max_retry_interval: options[:max_retry_interval]
519
+ max_retry_interval: options[:max_retry_interval],
520
+ ignore_signal: options[:ignore_signal],
468
521
  }.reject { |_, v| v.nil? }
469
522
  if options[:cpu] || options[:memory]
470
523
  container_definition_overrides = {cpu: options[:cpu], memory: options[:memory]}.reject { |_, v| v.nil? }
471
524
  else
472
525
  container_definition_overrides = {}
473
526
  end
474
- runner.run_cmd(args, environments: environments, container_definition_overrides: container_definition_overrides, **run_options)
527
+ unless runner.run_cmd(args, environments: environments, container_definition_overrides: container_definition_overrides, **run_options)
528
+ exit 1
529
+ end
475
530
  end
476
531
  end
477
532
  end
@@ -1,3 +1,3 @@
1
1
  module Wrapbox
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wrapbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - joker1007
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-29 00:00:00.000000000 Z
11
+ date: 2018-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk