wrapbox 0.4.1 → 0.5.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
  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