wrapbox 0.4.1 → 0.5.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
  SHA1:
3
- metadata.gz: ec530a0b68981cc7a90bcd451c4a54d371d275dd
4
- data.tar.gz: 17e6212341e23126993ebde697b9ddccf4ecc397
3
+ metadata.gz: c24c21fbb7bbac8241ec5750714e5ea7d28f4755
4
+ data.tar.gz: 29fe85200b1df44f85528bdda6eae40b67c23fe8
5
5
  SHA512:
6
- metadata.gz: eccc15faf35450e79202e8b134b9fd304ca66bb3a8179e976b6e181f83cc69d2e4a613326ab2fd872eb268c9485dbc2eb7feb0bf2147985d4b913feaabda0523
7
- data.tar.gz: 2f3623dbb0aa16b3b37b22e0e06e0eacf985f21be5c12b8d1bf217234c3c9e36773bf53cc53429f76b9ae4ff3a5401da89548369183750e1a1eedb8b7ab702af
6
+ metadata.gz: a34af96a5e4ffb23f48cb04bb19bd63baeb8ec6a5b17be701da6182becde100b1937680a34f0e890e859e0f9668b95fdfc37618cd482e4c00d147c8d6f2a74f0
7
+ data.tar.gz: df635e95edceff7169e4fa213dc57722698cf873f67e1e204e988ea0557a95454d103b7a6b0a7c0cca4cd10afee28628310be7c93f606994dfb1f2ec93b97719
data/README.md CHANGED
@@ -24,7 +24,7 @@ Write config.yml
24
24
 
25
25
  ```yaml
26
26
  default:
27
- cluster: ecsr-test
27
+ cluster: wrapbox
28
28
  runner: ecs
29
29
  region: ap-northeast-1
30
30
  container_definition:
@@ -40,6 +40,15 @@ docker:
40
40
  image: joker1007/wrapbox
41
41
  cpu: 512
42
42
  memory: 1024
43
+
44
+ ecs2:
45
+ cluster: wrapbox
46
+ runner: ecs
47
+ region: ap-northeast-1
48
+ # Use already existing task definition
49
+ task_definition:
50
+ task_definition_name: foo_task:1
51
+ main_container_name: container_name_where_command_is_executed
43
52
  ```
44
53
 
45
54
  #### run by CLI
@@ -53,12 +62,14 @@ $ wrapbox ecs run_cmd -f config.yml \
53
62
 
54
63
  #### run by ruby
55
64
 
65
+ Run `rake wrapbox:run` with `CLASS_NAME_ENV` and `METHOD_NAME_ENV` and `METHOD_ARGS_ENV`
66
+
56
67
  ```ruby
57
68
  Wrapbox.configure do |c|
58
69
  c.load_yaml(File.expand_path("../config.yml", __FILE__))
59
70
  end
60
71
 
61
- # runs TestJob#perform in ECS container
72
+ # runs TestJob#perform("arg1", ["arg2", "arg3"]) in ECS container via `rake wrapbox:run`
62
73
  Wrapbox.run("TestJob", :perform, ["arg1", ["arg2", "arg3"]], environments: [{name: "RAILS_ENV", value: "development"}]) # use default config
63
74
  # runs TestJob#perform in local docker container (Use docker cli)
64
75
  Wrapbox.run("TestJob", :perform, ["arg1", ["arg2", "arg3"]], config_name: :docker, environments: [{name: "RAILS_ENV", value: "development"}]) # use docker config
@@ -12,9 +12,21 @@ module Wrapbox
12
12
  :retry_interval,
13
13
  :retry_interval_multiplier,
14
14
  :container_definition,
15
+ :container_definitions,
16
+ :volumes,
17
+ :placement_constraints,
18
+ :placement_strategy,
19
+ :launch_type,
20
+ :requires_compatibilities,
21
+ :task_definition,
15
22
  :additional_container_definitions,
23
+ :network_mode,
24
+ :network_configuration,
25
+ :cpu,
26
+ :memory,
16
27
  :task_role_arn,
17
- :keep_container
28
+ :keep_container,
29
+ :log_fetcher
18
30
  ) do
19
31
  def self.load_config(config)
20
32
  new(
@@ -26,10 +38,22 @@ module Wrapbox
26
38
  config["retry"] || 0,
27
39
  config["retry_interval"] || 1,
28
40
  config["retry_interval_multiplier"] || 2,
29
- config["container_definition"].deep_symbolize_keys,
30
- config["additional_container_definitions"] || [],
41
+ config["container_definition"]&.deep_symbolize_keys,
42
+ config["container_definitions"]&.map(&:deep_symbolize_keys) || [],
43
+ config["volumes"]&.map(&:deep_symbolize_keys) || [],
44
+ config["placement_constraints"]&.map(&:deep_symbolize_keys) || [],
45
+ config["placement_strategy"]&.map(&:deep_symbolize_keys) || [],
46
+ config["launch_type"],
47
+ config["requires_compatibilities"] || ["EC2"],
48
+ config["task_definition"]&.deep_symbolize_keys,
49
+ config["additional_container_definitions"]&.map(&:deep_symbolize_keys) || [],
50
+ config["network_mode"],
51
+ config["network_configuration"]&.deep_symbolize_keys,
52
+ config["cpu"]&.to_s,
53
+ config["memory"]&.to_s,
31
54
  config["task_role_arn"],
32
- config["keep_container"]
55
+ config["keep_container"],
56
+ config["log_fetcher"]&.deep_symbolize_keys
33
57
  )
34
58
  end
35
59
 
@@ -39,10 +63,11 @@ module Wrapbox
39
63
  super
40
64
  end
41
65
 
42
- def build_runner
43
- raise "#{runner} is unsupported runner" unless AVAILABLE_RUNNERS.include?(runner.to_sym)
44
- require "wrapbox/runner/#{runner}"
45
- Wrapbox::Runner.const_get(runner.to_s.camelcase).new(to_h)
66
+ def build_runner(overrided_runner = nil)
67
+ r = overrided_runner || runner
68
+ raise "#{r} is unsupported runner" unless AVAILABLE_RUNNERS.include?(r.to_sym)
69
+ require "wrapbox/runner/#{r}"
70
+ Wrapbox::Runner.const_get(r.to_s.camelcase).new(to_h)
46
71
  end
47
72
 
48
73
  def run(class_name, method_name, args, **options)
@@ -0,0 +1,75 @@
1
+ module Wrapbox
2
+ module LogFetcher
3
+ class Papertrail
4
+ STOP_WAIT_TIMELIMIT = 10
5
+
6
+ def initialize(query: nil, delay: 2, **options)
7
+ begin
8
+ require 'papertrail/cli'
9
+ rescue LoadError
10
+ $stderr.puts "Require papertrail gem"
11
+ exit 1
12
+ end
13
+
14
+ # see. https://github.com/papertrail/papertrail-cli/blob/master/lib/papertrail/cli.rb
15
+ @query = query
16
+ @delay = delay
17
+ @options = options.reject { |_, v| v.nil? }
18
+ end
19
+
20
+ def run
21
+ @started_at = Time.now
22
+ @loop_thread = Thread.start(&method(:main_loop))
23
+ end
24
+
25
+ def stop
26
+ @stop = true
27
+ @loop_thread.join(STOP_WAIT_TIMELIMIT)
28
+ end
29
+
30
+ def main_loop
31
+ papertrail = ::Papertrail::Cli.new
32
+ connection_options = papertrail.options.merge(@options).merge(follow: true)
33
+ connection = ::Papertrail::Connection.new(connection_options)
34
+
35
+ query_options = {}
36
+
37
+ if @options[:system]
38
+ query_options[:system_id] = connection.find_id_for_source(@options[:system])
39
+ unless query_options[:system_id]
40
+ $stderr.puts "System \"#{@options[:system]}\" not found"
41
+ end
42
+ end
43
+
44
+ if @options[:group]
45
+ query_options[:group_id] = connection.find_id_for_group(@options[:group])
46
+ unless query_options[:group_id]
47
+ $stderr.puts "Group \"#{@options[:group]}\" not found"
48
+ end
49
+ end
50
+
51
+ if @options[:search]
52
+ search = connection.find_search(@options[:search], @query_options[:group_id])
53
+ unless search
54
+ $stderr.puts "Search \"#{@options[:search]}\" not found"
55
+ end
56
+
57
+ query_options[:group_id] ||= search['group_id']
58
+ @query = search['query']
59
+ end
60
+
61
+ @query ||= ''
62
+
63
+ search_query = ::Papertrail::SearchQuery.new(connection, @query, query_options)
64
+
65
+ until @stop do
66
+ search_query.next_results_page.events.each do |event|
67
+ next if event.received_at < @started_at
68
+ papertrail.display_result(event)
69
+ end
70
+ sleep @delay
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,14 @@
1
+ require "active_support/core_ext/string"
2
+
3
+ # LogFetcher Implementation requires two methods.
4
+ # - run (start log fetching asynchronously)
5
+ # - stop (stop log fetching)
6
+ module Wrapbox
7
+ module LogFetcher
8
+ def self.new(type, **options)
9
+ raise "log_fetcher config needs `type`" unless type
10
+ require "wrapbox/log_fetcher/#{type}"
11
+ self.const_get(type.classify).new(**options)
12
+ end
13
+ end
14
+ end
@@ -2,6 +2,7 @@ require "open3"
2
2
  require "multi_json"
3
3
  require "docker"
4
4
  require "thor"
5
+ require "shellwords"
5
6
 
6
7
  module Wrapbox
7
8
  module Runner
@@ -15,7 +16,14 @@ module Wrapbox
15
16
 
16
17
  def initialize(options)
17
18
  @name = options[:name]
18
- @container_definition = options[:container_definition]
19
+ @container_definitions = options[:container_definition] ? [options[:container_definition]] : options[:container_definitions][0]
20
+
21
+ if @container_definitions.size >= 2
22
+ raise "Docker runner does not support multi container currently"
23
+ end
24
+
25
+ @container_definition = @container_definitions[0]
26
+
19
27
  @keep_container = options[:keep_container]
20
28
  end
21
29
 
@@ -35,10 +43,15 @@ module Wrapbox
35
43
 
36
44
  environments = extract_environments(environments)
37
45
 
46
+ cmds << nil if cmds.empty?
38
47
  ths = cmds.map.with_index do |cmd, idx|
39
48
  Thread.new(cmd, idx) do |c, i|
40
49
  envs = environments + ["WRAPBOX_CMD_INDEX=#{idx}"]
41
- exec_docker(definition: definition, cmd: c.split(/\s+/), environments: envs)
50
+ exec_docker(
51
+ definition: definition,
52
+ cmd: c ? Shellwords.shellsplit(c) : nil,
53
+ environments: envs
54
+ )
42
55
  end
43
56
  end
44
57
  ths.each(&:join)
@@ -60,9 +73,8 @@ module Wrapbox
60
73
  ::Docker::Image.create("fromImage" => definition[:image])
61
74
  options = {
62
75
  "Image" => definition[:image],
63
- "Cmd" => cmd,
64
76
  "Env" => environments,
65
- }
77
+ }.tap { |o| o["Cmd"] = cmd if cmd }
66
78
  options["HostConfig"] = {}
67
79
  options["HostConfig"]["Cpu"] = definition[:cpu] if definition[:cpu]
68
80
  options["HostConfig"]["Memory"] = definition[:memory] * 1024 * 1024 if definition[:memory]
@@ -5,8 +5,10 @@ require "yaml"
5
5
  require "active_support/core_ext/hash"
6
6
  require "logger"
7
7
  require "pp"
8
+ require "shellwords"
8
9
 
9
10
  require "wrapbox/config_repository"
11
+ require "wrapbox/log_fetcher"
10
12
  require "wrapbox/version"
11
13
 
12
14
  module Wrapbox
@@ -27,8 +29,18 @@ module Wrapbox
27
29
  :revision,
28
30
  :cluster,
29
31
  :region,
30
- :container_definition,
31
- :additional_container_definitions,
32
+ :container_definitions,
33
+ :volumes,
34
+ :placement_constraints,
35
+ :placement_strategy,
36
+ :launch_type,
37
+ :requires_compatibilities,
38
+ :task_definition_name,
39
+ :main_container_name,
40
+ :network_mode,
41
+ :network_configuration,
42
+ :cpu,
43
+ :memory,
32
44
  :task_role_arn
33
45
 
34
46
  def initialize(options)
@@ -36,11 +48,52 @@ module Wrapbox
36
48
  @revision = options[:revision]
37
49
  @cluster = options[:cluster]
38
50
  @region = options[:region]
39
- @container_definition = options[:container_definition]
40
- @additional_container_definitions = options[:additional_container_definitions]
51
+ @volumes = options[:volumes]
52
+ @placement_constraints = options[:placement_constraints]
53
+ @placement_strategy = options[:placement_strategy]
54
+ @launch_type = options[:launch_type]
55
+ @requires_compatibilities = options[:requires_compatibilities]
56
+ @network_mode = options[:network_mode]
57
+ @network_configuration = options[:network_configuration]
58
+ @cpu = options[:cpu]
59
+ @memory = options[:memory]
60
+
61
+ if (options[:container_definition] || options[:container_definitions].empty?.!) && options[:task_definition]
62
+ raise "Please set only one of `container_definition` and `task_definition`"
63
+ end
64
+
65
+ if options[:additional_container_definitions].empty?.!
66
+ warn "`additional_container_definitions` is deprecated parameter, Use `container_definitions` instead of it"
67
+ end
68
+
69
+ @container_definitions = options[:container_definition] ? [options[:container_definition]] : options[:container_definitions]
70
+ @container_definitions.concat(options[:additional_container_definitions]) # deprecated
71
+
72
+ @task_definition_info = options[:task_definition]
73
+
74
+ if !@container_definitions.empty?
75
+ @task_definition_name = "wrapbox_#{@name}"
76
+ @main_container_name = @container_definitions[0][:name] || @task_definition_name
77
+ elsif @task_definition_info
78
+ @task_definition_name = @task_definition_info[:task_definition_name]
79
+ @main_container_name = @task_definition_info[:main_container_name]
80
+ unless @main_container_name
81
+ raise "Please set `task_definition[:main_container_name]`"
82
+ end
83
+ end
84
+
85
+ @container_definitions.each do |d|
86
+ d[:docker_labels]&.stringify_keys!
87
+ d.dig(:log_configuration, :options)&.stringify_keys!
88
+ end
89
+
41
90
  @task_role_arn = options[:task_role_arn]
42
91
  $stdout.sync = true
43
92
  @logger = Logger.new($stdout)
93
+ if options[:log_fetcher]
94
+ type = options[:log_fetcher].delete(:type)
95
+ @log_fetcher = LogFetcher.new(type, options[:log_fetcher])
96
+ end
44
97
  end
45
98
 
46
99
  class Parameter
@@ -65,7 +118,7 @@ module Wrapbox
65
118
  end
66
119
 
67
120
  def run(class_name, method_name, args, container_definition_overrides: {}, **parameters)
68
- task_definition = register_task_definition(container_definition_overrides)
121
+ task_definition = prepare_task_definition(container_definition_overrides)
69
122
  parameter = Parameter.new(**parameters)
70
123
 
71
124
  run_task(
@@ -76,15 +129,16 @@ module Wrapbox
76
129
  end
77
130
 
78
131
  def run_cmd(cmds, container_definition_overrides: {}, **parameters)
79
- task_definition = register_task_definition(container_definition_overrides)
132
+ task_definition = prepare_task_definition(container_definition_overrides)
80
133
 
134
+ cmds << nil if cmds.empty?
81
135
  ths = cmds.map.with_index do |cmd, idx|
82
136
  Thread.new(cmd, idx) do |c, i|
83
137
  Thread.current[:cmd_index] = i
84
138
  envs = (parameters[:environments] || []) + [{name: "WRAPBOX_CMD_INDEX", value: i.to_s}]
85
139
  run_task(
86
140
  task_definition.task_definition_arn, nil, nil, nil,
87
- c.split(/\s+/),
141
+ c ? Shellwords.shellsplit(c) : nil,
88
142
  Parameter.new(**parameters.merge(environments: envs))
89
143
  )
90
144
  end
@@ -94,12 +148,17 @@ module Wrapbox
94
148
 
95
149
  private
96
150
 
151
+ def use_existing_task_definition?
152
+ !!@task_definition_info
153
+ end
154
+
97
155
  def run_task(task_definition_arn, class_name, method_name, args, command, parameter)
98
156
  cl = parameter.cluster || self.cluster
99
157
  execution_try_count = 0
100
158
 
101
159
  begin
102
160
  task = create_task(task_definition_arn, class_name, method_name, args, command, parameter)
161
+ @log_fetcher.run if @log_fetcher
103
162
 
104
163
  @logger.debug("Launch Task: #{task.task_arn}")
105
164
 
@@ -129,13 +188,17 @@ module Wrapbox
129
188
  sleep EXECUTION_RETRY_INTERVAL
130
189
  retry
131
190
  end
191
+ ensure
192
+ if @log_fetcher
193
+ begin
194
+ @log_fetcher.stop
195
+ rescue => e
196
+ @logger.warn(e)
197
+ end
198
+ end
132
199
  end
133
200
  end
134
201
 
135
- def task_definition_name
136
- "wrapbox_#{name}"
137
- end
138
-
139
202
  def create_task(task_definition_arn, class_name, method_name, args, command, parameter)
140
203
  cl = parameter.cluster || self.cluster
141
204
  args = Array(args)
@@ -210,19 +273,8 @@ module Wrapbox
210
273
  end
211
274
  end
212
275
 
213
- def wait_task_running(cluster, task_arn, launch_timeout)
214
- client.wait_until(:tasks_running, cluster: cluster, tasks: [task_arn]) do |w|
215
- if launch_timeout
216
- w.delay = WAIT_DELAY
217
- w.max_attempts = launch_timeout / w.delay
218
- else
219
- w.max_attempts = nil
220
- end
221
- end
222
- end
223
-
224
- def wait_task_stopped(cluster, task_arn, timeout)
225
- client.wait_until(:tasks_stopped, cluster: cluster, tasks: [task_arn]) do |w|
276
+ def wait_until_with_timeout(cluster, task_arn, timeout, waiter_name)
277
+ client.wait_until(waiter_name, cluster: cluster, tasks: [task_arn]) do |w|
226
278
  if timeout
227
279
  w.delay = WAIT_DELAY
228
280
  w.max_attempts = timeout / w.delay
@@ -230,18 +282,26 @@ module Wrapbox
230
282
  w.max_attempts = nil
231
283
  end
232
284
  end
285
+ end
286
+
287
+ def wait_task_running(cluster, task_arn, launch_timeout)
288
+ wait_until_with_timeout(cluster, task_arn, launch_timeout, :tasks_running)
289
+ end
290
+
291
+ def wait_task_stopped(cluster, task_arn, execution_timeout)
292
+ wait_until_with_timeout(cluster, task_arn, execution_timeout, :tasks_stopped)
233
293
  rescue Aws::Waiters::Errors::TooManyAttemptsError
234
294
  client.stop_task({
235
- cluster: cl,
295
+ cluster: cluster,
236
296
  task: task_arn,
237
297
  reason: "process timeout",
238
298
  })
239
- raise ExecutionTimeout, "Container #{task_definition_name} is timeout. task=#{task_arn}, timeout=#{timeout}"
299
+ raise ExecutionTimeout, "Task #{task_definition_name} is timeout. task=#{task_arn}, timeout=#{execution_timeout}"
240
300
  end
241
301
 
242
302
  def fetch_task_status(cluster, task_arn)
243
303
  task = client.describe_tasks(cluster: cluster, tasks: [task_arn]).tasks[0]
244
- container = task.containers.find { |c| c.name == task_definition_name }
304
+ container = task.containers.find { |c| c.name == main_container_name }
245
305
  {
246
306
  last_status: task.last_status,
247
307
  exit_code: container.exit_code,
@@ -250,11 +310,21 @@ module Wrapbox
250
310
  }
251
311
  end
252
312
 
313
+ def prepare_task_definition(container_definition_overrides)
314
+ if use_existing_task_definition?
315
+ client.describe_task_definition(task_definition: task_definition_name).task_definition
316
+ else
317
+ register_task_definition(container_definition_overrides)
318
+ end
319
+ end
320
+
253
321
  def register_task_definition(container_definition_overrides)
254
- definition = container_definition
322
+ main_container_definition = container_definitions[0]
323
+ main_container_definition = main_container_definition
255
324
  .merge(container_definition_overrides)
256
- .merge(name: task_definition_name)
257
- container_definitions = [definition, *additional_container_definitions]
325
+ .merge(name: main_container_name)
326
+
327
+ overrided_container_definitions = [main_container_definition, *(container_definitions.drop(1))]
258
328
 
259
329
  if revision
260
330
  begin
@@ -263,12 +333,17 @@ module Wrapbox
263
333
  end
264
334
  end
265
335
 
266
- @logger.debug("Container Definitions: #{container_definitions}")
336
+ @logger.debug("Container Definitions: #{overrided_container_definitions}")
267
337
  register_retry_count = 0
268
338
  begin
269
339
  client.register_task_definition({
270
340
  family: task_definition_name,
271
- container_definitions: container_definitions,
341
+ cpu: cpu,
342
+ memory: memory,
343
+ network_mode: network_mode,
344
+ container_definitions: overrided_container_definitions,
345
+ volumes: volumes,
346
+ requires_compatibilities: requires_compatibilities,
272
347
  }).task_definition
273
348
  rescue Aws::ECS::Errors::ClientException
274
349
  raise if register_retry_count > 2
@@ -331,10 +406,9 @@ module Wrapbox
331
406
  overrides = {
332
407
  container_overrides: [
333
408
  {
334
- name: task_definition_name,
335
- command: command,
409
+ name: main_container_name,
336
410
  environment: env,
337
- },
411
+ }.tap { |o| o[:command] = command if command },
338
412
  ],
339
413
  }
340
414
  role_arn = task_role_arn || self.task_role_arn
@@ -344,12 +418,16 @@ module Wrapbox
344
418
  cluster: cluster || self.cluster,
345
419
  task_definition: task_definition_arn,
346
420
  overrides: overrides,
421
+ placement_strategy: placement_strategy,
422
+ placement_constraints: placement_constraints,
423
+ launch_type: launch_type,
424
+ network_configuration: network_configuration,
347
425
  started_by: "wrapbox-#{Wrapbox::VERSION}",
348
426
  }
349
427
  end
350
428
 
351
429
  def build_error_message(task_definition_name, task_arn, task_status)
352
- error_message = "Container #{task_definition_name} is failed. task=#{task_arn}, "
430
+ error_message = "Task #{task_definition_name} is failed. task=#{task_arn}, "
353
431
  error_message << "cmd_index=#{Thread.current[:cmd_index]}, " if Thread.current[:cmd_index]
354
432
  error_message << "exit_code=#{task_status[:exit_code]}, task_stopped_reason=#{task_status[:stopped_reason]}, container_stopped_reason=#{task_status[:container_stopped_reason]}"
355
433
  error_message
@@ -1,3 +1,3 @@
1
1
  module Wrapbox
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
data/wrapbox.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
- spec.add_runtime_dependency "aws-sdk", "~> 2.4"
23
+ spec.add_runtime_dependency "aws-sdk", "~> 2.10", ">= 2.10.109"
24
24
  spec.add_runtime_dependency "activesupport", ">= 4"
25
25
  spec.add_runtime_dependency "docker-api"
26
26
  spec.add_runtime_dependency "multi_json"
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.4.1
4
+ version: 0.5.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-07-27 00:00:00.000000000 Z
11
+ date: 2017-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.4'
19
+ version: '2.10'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.10.109
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '2.4'
29
+ version: '2.10'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.10.109
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: activesupport
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -188,6 +194,8 @@ files:
188
194
  - lib/wrapbox/config_repository.rb
189
195
  - lib/wrapbox/configuration.rb
190
196
  - lib/wrapbox/job.rb
197
+ - lib/wrapbox/log_fetcher.rb
198
+ - lib/wrapbox/log_fetcher/papertrail.rb
191
199
  - lib/wrapbox/runner/docker.rb
192
200
  - lib/wrapbox/runner/ecs.rb
193
201
  - lib/wrapbox/tasks/run.rake
@@ -212,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
220
  version: '0'
213
221
  requirements: []
214
222
  rubyforge_project:
215
- rubygems_version: 2.6.11
223
+ rubygems_version: 2.6.13
216
224
  signing_key:
217
225
  specification_version: 4
218
226
  summary: Ruby method runner on AWS ECS