wrapbox 0.5.2 → 0.6.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: 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