wrapbox 0.1.0 → 0.2.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: c76da62eee815c3ab4d57a567a8a83810d9b7f20
4
- data.tar.gz: 4c3df8f6ce34d0ae48f476d32e57d85170ce0028
3
+ metadata.gz: edc9210efdc2d7248e0b6eab05f04c89f7223b90
4
+ data.tar.gz: afe62fcbfbf5f5383b12e476709fd7d79a36af27
5
5
  SHA512:
6
- metadata.gz: c2b799ee4e165c93dcf829659e513d610ad07f666377b8c3631c63209175bee00f7431b233dec3615cbd6dcba509895b4f4f7fa1e21b6b5174e7eb68d1673b22
7
- data.tar.gz: 600bd6d4359e2534bf0c047621d61b2a7df7d5bcbe9143eb84e465b081f6714744027c9cf2ff989615c468cb6893b664b21b3aa6fb61322f558e71cc1048e0f1
6
+ metadata.gz: 8f856b7dc58a1776c662f4bd43d1165c043c4ec8a2e5ad0a12eac1b4c60a1162d9ef57541c1d54373471f59879f6257cd8ae1105c1b26e142ffc790839694f75
7
+ data.tar.gz: 0cc10bf941d6b73d320581ae722383c888f5cac1fe700bfccfd5b5ab117abd3b1347abb5f67229d8048d1ff784768224122dd8c767f7188888489b1877a0e559
data/Dockerfile CHANGED
@@ -1,7 +1,7 @@
1
1
  FROM ruby:alpine
2
2
 
3
- RUN apk add --no-cache git
3
+ RUN apk add --no-cache git gcc make g++ zlib-dev
4
4
  WORKDIR /app
5
5
  COPY . /app/
6
6
 
7
- RUN bundle install
7
+ RUN bundle install -j3
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "wrapbox/cli"
4
+
5
+ Wrapbox::Cli.start
@@ -0,0 +1,10 @@
1
+ require "thor/group"
2
+ require "wrapbox/runner/docker"
3
+ require "wrapbox/runner/ecs"
4
+
5
+ module Wrapbox
6
+ class Cli < Thor
7
+ register(Wrapbox::Runner::Ecs::Cli, "ecs", "ecs [COMMAND]", "Commands for ECS")
8
+ register(Wrapbox::Runner::Docker::Cli, "docker", "docker [COMMAND]", "Commands for Docker")
9
+ end
10
+ end
@@ -1,4 +1,5 @@
1
1
  require 'yaml'
2
+ require 'wrapbox/configuration'
2
3
 
3
4
  module Wrapbox
4
5
  class ConfigRepository
@@ -4,26 +4,32 @@ require "active_support/core_ext/string"
4
4
  module Wrapbox
5
5
  Configuration = Struct.new(
6
6
  :name,
7
+ :revision,
7
8
  :runner,
8
9
  :cluster,
9
10
  :region,
11
+ :retry,
12
+ :retry_interval,
13
+ :retry_interval_multiplier,
10
14
  :container_definition,
11
15
  :additional_container_definitions,
12
16
  :task_role_arn,
13
- :use_sudo,
14
- :rm
17
+ :keep_container
15
18
  ) do
16
19
  def self.load_config(config)
17
20
  new(
18
21
  config["name"],
22
+ config["revision"],
19
23
  config["runner"] ? config["runner"].to_sym : :docker,
20
24
  config["cluster"],
21
25
  config["region"],
26
+ config["retry"] || 0,
27
+ config["retry_interval"] || 1,
28
+ config["retry_interval_multiplier"] || 2,
22
29
  config["container_definition"].deep_symbolize_keys,
23
30
  config["additional_container_definitions"] || [],
24
31
  config["task_role_arn"],
25
- config["use_sudo"].nil? ? false : config["use_sudo"],
26
- config["rm"].nil? ? false : config["rm"]
32
+ config["keep_container"]
27
33
  )
28
34
  end
29
35
 
@@ -31,11 +37,11 @@ module Wrapbox
31
37
 
32
38
  def initialize(*args)
33
39
  super
34
- raise "#{runner} is unsupported runner" unless AVAILABLE_RUNNERS.include?(runner)
35
- require "wrapbox/runner/#{runner}"
36
40
  end
37
41
 
38
42
  def build_runner
43
+ raise "#{runner} is unsupported runner" unless AVAILABLE_RUNNERS.include?(runner.to_sym)
44
+ require "wrapbox/runner/#{runner}"
39
45
  Wrapbox::Runner.const_get(runner.to_s.camelcase).new(to_h)
40
46
  end
41
47
 
@@ -1,5 +1,7 @@
1
1
  require "open3"
2
2
  require "multi_json"
3
+ require "docker"
4
+ require "thor"
3
5
 
4
6
  module Wrapbox
5
7
  module Runner
@@ -9,86 +11,105 @@ module Wrapbox
9
11
  attr_reader \
10
12
  :name,
11
13
  :container_definition,
12
- :rm,
13
- :use_sudo
14
+ :keep_container
14
15
 
15
16
  def initialize(options)
16
17
  @name = options[:name]
17
18
  @container_definition = options[:container_definition]
18
- @rm = options[:rm]
19
- @use_sudo = options[:use_sudo]
19
+ @keep_container = options[:keep_container]
20
20
  end
21
21
 
22
22
  def run(class_name, method_name, args, container_definition_overrides: {}, environments: [])
23
23
  definition = container_definition
24
24
  .merge(container_definition_overrides)
25
25
 
26
- cmdopt = build_cmdopt(definition)
27
- cmdopt.concat(base_environments(class_name, method_name, args))
28
- cmdopt.concat(extract_environments(environments))
29
- cmdopt.concat([definition[:image], "bundle", "exec", "rake", "wrapbox:run"])
26
+ envs = base_environments(class_name, method_name, args)
27
+ envs.concat(extract_environments(environments))
30
28
 
31
- exec_docker(*cmdopt)
29
+ exec_docker(definition: definition, cmd: ["bundle", "exec", "rake", "wrapbox:run"], environments: envs)
32
30
  end
33
31
 
34
32
  def run_cmd(*cmd, container_definition_overrides: {}, environments: [])
35
33
  definition = container_definition
36
34
  .merge(container_definition_overrides)
37
35
 
38
- cmdopt = build_cmdopt(definition)
39
- cmdopt.concat(extract_environments(environments))
40
- cmdopt.concat([definition[:image], *cmd])
36
+ environments = extract_environments(environments)
41
37
 
42
- exec_docker(*cmdopt)
38
+ exec_docker(definition: definition, cmd: cmd, environments: environments)
43
39
  end
44
40
 
45
41
  private
46
42
 
47
- def build_cmdopt(definition)
48
- cmdopt = ["run"]
49
- cmdopt.concat(["--rm"]) if rm
50
- cmdopt.concat(["--cpu-shares", definition[:cpu].to_s]) if definition[:cpu]
51
- cmdopt.concat(["--memory", "#{definition[:memory]}m"]) if definition[:memory]
52
- cmdopt.concat(["--memory-reservation", "#{definition[:memory_reservation]}m"]) if definition[:memory_reservation]
53
- cmdopt
54
- end
55
-
56
43
  def base_environments(class_name, method_name, args)
57
- ["-e", "#{CLASS_NAME_ENV}=#{class_name}", "-e", "#{METHOD_NAME_ENV}=#{method_name}", "-e", "#{METHOD_ARGS_ENV}=#{MultiJson.dump(args)}"]
44
+ ["#{CLASS_NAME_ENV}=#{class_name}", "#{METHOD_NAME_ENV}=#{method_name}", "#{METHOD_ARGS_ENV}=#{MultiJson.dump(args)}"]
58
45
  end
59
46
 
60
47
  def extract_environments(environments)
61
- environments.flat_map do |e|
62
- ["-e", "#{e[:name]}=#{e[:value]}"]
48
+ environments.map do |e|
49
+ "#{e[:name]}=#{e[:value]}"
50
+ end
51
+ end
52
+
53
+ def exec_docker(definition:, cmd:, environments: [])
54
+ ::Docker::Image.create("fromImage" => definition[:image])
55
+ options = {
56
+ "Image" => definition[:image],
57
+ "Cmd" => cmd,
58
+ "Env" => environments,
59
+ }
60
+ options["HostConfig"] = {}
61
+ options["HostConfig"]["Cpu"] = definition[:cpu] if definition[:cpu]
62
+ options["HostConfig"]["Memory"] = definition[:memory] * 1024 * 1024 if definition[:memory]
63
+ options["HostConfig"]["MemoryReservation"] = definition[:memory_reservation] * 1024 * 1024 if definition[:memory_reservation]
64
+ options["HostConfig"]["Links"] = definition[:links]
65
+ options["Entrypoint"] = definition[:entry_point] if definition[:entry_point]
66
+ options["WorkingDir"] = definition[:working_directory] if definition[:working_directory]
67
+
68
+ container = ::Docker::Container.create(options)
69
+
70
+ container.start!
71
+ output_container_logs(container)
72
+ resp = container.wait
73
+ output_container_logs(container)
74
+
75
+ unless resp["StatusCode"].zero?
76
+ raise ExecutionError, "exit_code=#{resp["StatusCode"]}"
63
77
  end
78
+ ensure
79
+ container.remove(force: true) if container && !keep_container
64
80
  end
65
81
 
66
- def exec_docker(*args)
67
- cmd = use_sudo ? "sudo docker" : "docker"
68
-
69
- result = Open3.popen3(cmd, *args) do |stdin, stdout, stderr, wait_thr|
70
- stdin.close_write
71
- begin
72
- loop do
73
- rs, _ = IO.select([stdout, stderr])
74
- rs.each do |io|
75
- io.each do |line|
76
- next if line.nil? || line.empty?
77
- if io == stdout
78
- $stdout.puts(line)
79
- else
80
- $stderr.puts(line)
81
- end
82
- end
83
- end
84
- break if stdout.eof? && stderr.eof?
85
- end
86
- rescue EOFError
82
+ def output_container_logs(container)
83
+ container.streaming_logs(stdout: true, stderr: true) do |stream, chunk|
84
+ if stream == "stdout"
85
+ $stdout.puts(chunk)
86
+ else
87
+ $stderr.puts(chunk)
87
88
  end
88
- wait_thr.value
89
89
  end
90
+ end
90
91
 
91
- raise ExecutionError, "exit_code=#{result.exitstatus}" unless result.success?
92
+ class Cli < Thor
93
+ namespace :docker
94
+
95
+ desc "run_cmd [shell command]", "Run shell on docker"
96
+ method_option :config, aliases: "-f", required: true, banner: "YAML_FILE", desc: "yaml file path"
97
+ method_option :config_name, aliases: "-n", required: true, default: "default"
98
+ method_option :environments, aliases: "-e"
99
+ def run_cmd(*args)
100
+ if args.size == 1
101
+ args = args[0].split(" ")
102
+ end
103
+
104
+ repo = Wrapbox::ConfigRepository.new.tap { |r| r.load_yaml(options[:config]) }
105
+ config = repo.get(options[:config_name])
106
+ config.runner = :docker
107
+ runner = config.build_runner
108
+ environments = options[:environments].to_s.split(/,\s*/).map { |kv| kv.split("=") }.map do |k, v|
109
+ {name: k, value: v}
110
+ end
111
+ runner.run_cmd(*args, environments: environments)
112
+ end
92
113
  end
93
114
  end
94
115
  end
@@ -1,13 +1,22 @@
1
1
  require "aws-sdk"
2
2
  require "multi_json"
3
+ require "thor"
4
+ require "yaml"
5
+ require "active_support/core_ext/hash"
6
+ require "logger"
7
+
8
+ require "wrapbox/config_repository"
9
+ require "wrapbox/version"
3
10
 
4
11
  module Wrapbox
5
12
  module Runner
6
13
  class Ecs
7
14
  class ExecutionError < StandardError; end
15
+ class LaunchFailure < StandardError; end
8
16
 
9
17
  attr_reader \
10
18
  :name,
19
+ :revision,
11
20
  :cluster,
12
21
  :region,
13
22
  :container_definition,
@@ -16,28 +25,33 @@ module Wrapbox
16
25
 
17
26
  def initialize(options)
18
27
  @name = options[:name]
28
+ @revision = options[:revision]
19
29
  @cluster = options[:cluster]
20
30
  @region = options[:region]
21
31
  @container_definition = options[:container_definition]
22
32
  @additional_container_definitions = options[:additional_container_definitions]
23
33
  @task_role_arn = options[:task_role_arn]
34
+ @logger = Logger.new($stdout)
24
35
  end
25
36
 
26
- def run(class_name, method_name, args, container_definition_overrides: {}, environments: [], task_role_arn: nil, cluster: nil, timeout: 3600 * 24, launch_timeout: 60 * 10, launch_retry: 10)
37
+ def run(class_name, method_name, args, container_definition_overrides: {}, environments: [], task_role_arn: nil, cluster: nil, timeout: 3600 * 24, launch_timeout: 60 * 10, launch_retry: 10, retry_interval: 1, retry_interval_multiplier: 2, max_retry_interval: 120)
27
38
  task_definition = register_task_definition(container_definition_overrides)
28
39
  run_task(
29
40
  task_definition.task_definition_arn, class_name, method_name, args,
30
41
  command: ["bundle", "exec", "rake", "wrapbox:run"],
31
42
  environments: environments,
32
- task_role_arn: task_role_arn,
43
+ task_role_arn: task_role_arn || @task_role_arn,
33
44
  cluster: cluster,
34
45
  timeout: timeout,
35
46
  launch_timeout: launch_timeout,
36
47
  launch_retry: launch_retry,
48
+ retry_interval: retry_interval,
49
+ retry_interval_multiplier: retry_interval_multiplier,
50
+ max_retry_interval: max_retry_interval,
37
51
  )
38
52
  end
39
53
 
40
- def run_cmd(*cmd, container_definition_overrides: {}, environments: [], task_role_arn: nil, cluster: nil, timeout: 3600 * 24, launch_timeout: 60 * 10, launch_retry: 10)
54
+ def run_cmd(*cmd, container_definition_overrides: {}, environments: [], task_role_arn: nil, cluster: nil, timeout: 3600 * 24, launch_timeout: 60 * 10, launch_retry: 10, retry_interval: 1, retry_interval_multiplier: 2, max_retry_interval: 120)
41
55
  task_definition = register_task_definition(container_definition_overrides)
42
56
 
43
57
  run_task(
@@ -49,52 +63,64 @@ module Wrapbox
49
63
  timeout: timeout,
50
64
  launch_timeout: launch_timeout,
51
65
  launch_retry: launch_retry,
66
+ retry_interval: retry_interval,
67
+ retry_interval_multiplier: retry_interval_multiplier,
68
+ max_retry_interval: max_retry_interval,
52
69
  )
53
70
  end
54
71
 
55
- def run_task(task_definition_arn, class_name, method_name, args, command:, environments: [], task_role_arn: nil, cluster: nil, timeout: 3600 * 24, launch_timeout: 60 * 10, launch_retry: 10)
72
+ def run_task(task_definition_arn, class_name, method_name, args, command:, environments: [], task_role_arn: nil, cluster: nil, timeout: 3600 * 24, launch_timeout: 60 * 10, launch_retry: 10, retry_interval: 1, retry_interval_multiplier: 2, max_retry_interval: 120)
56
73
  cl = cluster || self.cluster
57
74
  args = Array(args)
58
75
 
59
- task = client
60
- .run_task(build_run_task_options(class_name, method_name, args, command, environments, cluster, task_definition_arn, task_role_arn))
61
- .tasks[0]
62
-
63
76
  launch_try_count = 0
77
+ current_retry_interval = retry_interval
78
+ task = nil
79
+ exit_code = nil
64
80
  begin
65
- launched_at = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
81
+ task = client
82
+ .run_task(build_run_task_options(class_name, method_name, args, command, environments, cluster, task_definition_arn, task_role_arn))
83
+ .tasks[0]
84
+ raise LaunchFailure unless task
85
+ @logger.debug("Create Task: #{task.task_arn}")
66
86
  client.wait_until(:tasks_running, cluster: cl, tasks: [task.task_arn]) do |w|
67
87
  if launch_timeout
88
+ w.delay = 5
89
+ w.max_attempts = launch_timeout / w.delay
90
+ else
68
91
  w.max_attempts = nil
69
- w.before_wait do
70
- throw :failure if Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) - launched_at > launch_timeout
71
- end
72
92
  end
73
93
  end
74
- rescue Aws::Waiters::Errors::TooManyAttemptsError
75
- if launch_try_count >= launch_retry
76
- client.stop_task(
77
- cluster: cl,
78
- task: task.task_arn,
79
- reason: "launch timeout"
80
- )
81
- raise
82
- else
83
- put_waiting_task_count_metric(cl)
84
- launch_try_count += 1
85
- retry
94
+ rescue Aws::Waiters::Errors::WaiterFailed, LaunchFailure
95
+ exit_code = task && fetch_exit_code(cl, task.task_arn)
96
+ unless exit_code
97
+ if launch_try_count >= launch_retry
98
+ client.stop_task(
99
+ cluster: cl,
100
+ task: task.task_arn,
101
+ reason: "launch timeout"
102
+ ) if task
103
+ raise
104
+ else
105
+ put_waiting_task_count_metric(cl)
106
+ launch_try_count += 1
107
+ @logger.debug("Retry Create Task after #{current_retry_interval} sec")
108
+ sleep current_retry_interval
109
+ current_retry_interval = [current_retry_interval * retry_interval_multiplier, max_retry_interval].min
110
+ retry
111
+ end
86
112
  end
87
- rescue Aws::Waiters::Errors::WaiterFailed
88
113
  end
89
114
 
115
+ @logger.debug("Launch Task: #{task.task_arn}")
116
+
90
117
  begin
91
- started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
92
118
  client.wait_until(:tasks_stopped, cluster: cl, tasks: [task.task_arn]) do |w|
93
119
  if timeout
120
+ w.delay = 5
121
+ w.max_attempts = timeout / w.delay
122
+ else
94
123
  w.max_attempts = nil
95
- w.before_wait do
96
- throw :failure if Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) - started_at > timeout
97
- end
98
124
  end
99
125
  end
100
126
  rescue Aws::Waiters::Errors::TooManyAttemptsError
@@ -103,12 +129,14 @@ module Wrapbox
103
129
  task: task.task_arn,
104
130
  reason: "process timeout",
105
131
  })
132
+ raise ExecutionError, "process timeout"
106
133
  end
107
134
 
108
- task = client.describe_tasks(cluster: cl, tasks: [task.task_arn]).tasks[0]
109
- container = task.containers.find { |c| c.name = task_definition_name }
110
- unless container.exit_code == 0
111
- raise ExecutionError, "Container #{task_definition_name} is failed. exit_code=#{container.exit_code}"
135
+ @logger.debug("Stop Task: #{task.task_arn}")
136
+
137
+ exit_code ||= fetch_exit_code(cl, task.task_arn)
138
+ unless exit_code == 0
139
+ raise ExecutionError, "Container #{task_definition_name} is failed. exit_code=#{exit_code}"
112
140
  end
113
141
  end
114
142
 
@@ -118,11 +146,25 @@ module Wrapbox
118
146
  "wrapbox_#{name}"
119
147
  end
120
148
 
149
+ def fetch_exit_code(cluster, task_arn)
150
+ task = client.describe_tasks(cluster: cluster, tasks: [task_arn]).tasks[0]
151
+ container = task.containers.find { |c| c.name = task_definition_name }
152
+ container.exit_code
153
+ end
154
+
121
155
  def register_task_definition(container_definition_overrides)
122
156
  definition = container_definition
123
157
  .merge(container_definition_overrides)
124
158
  .merge(name: task_definition_name)
125
159
  container_definitions = [definition, *additional_container_definitions]
160
+
161
+ if revision
162
+ begin
163
+ return client.describe_task_definition(task_definition: "#{task_definition_name}:#{revision}").task_definition
164
+ rescue
165
+ end
166
+ end
167
+
126
168
  client.register_task_definition({
127
169
  family: task_definition_name,
128
170
  container_definitions: container_definitions,
@@ -142,7 +184,7 @@ module Wrapbox
142
184
 
143
185
  options = {}
144
186
  options[:region] = region if region
145
- @cloud_watch_client = Aws::CloudWatch::Client.new
187
+ @cloud_watch_client = Aws::CloudWatch::Client.new(options)
146
188
  end
147
189
 
148
190
  def put_waiting_task_count_metric(cluster)
@@ -197,6 +239,42 @@ module Wrapbox
197
239
  started_by: "wrapbox-#{Wrapbox::VERSION}",
198
240
  }
199
241
  end
242
+
243
+ class Cli < Thor
244
+ namespace :ecs
245
+
246
+ desc "run_cmd [shell command]", "Run shell on ECS"
247
+ method_option :config, aliases: "-f", required: true, banner: "YAML_FILE", desc: "yaml file path"
248
+ method_option :config_name, aliases: "-n", required: true, default: "default"
249
+ method_option :cluster, aliases: "-c"
250
+ method_option :environments, aliases: "-e"
251
+ method_option :task_role_arn
252
+ method_option :timeout, type: :numeric
253
+ method_option :launch_timeout, type: :numeric
254
+ method_option :launch_retry, type: :numeric
255
+ method_option :max_retry_interval, type: :numeric
256
+ def run_cmd(*args)
257
+ if args.size == 1
258
+ args = args[0].split(" ")
259
+ end
260
+
261
+ repo = Wrapbox::ConfigRepository.new.tap { |r| r.load_yaml(options[:config]) }
262
+ config = repo.get(options[:config_name])
263
+ config.runner = :ecs
264
+ runner = config.build_runner
265
+ environments = options[:environments].to_s.split(/,\s*/).map { |kv| kv.split("=") }.map do |k, v|
266
+ {name: k, value: v}
267
+ end
268
+ run_options = {
269
+ task_role_arn: options[:task_role_arn],
270
+ timeout: options[:timeout],
271
+ launch_timeout: options[:launch_timeout],
272
+ launch_retry: options[:launch_retry],
273
+ max_retry_interval: options[:max_retry_interval]
274
+ }.reject { |_, v| v.nil? }
275
+ runner.run_cmd(*args, environments: environments, **run_options)
276
+ end
277
+ end
200
278
  end
201
279
  end
202
280
  end
@@ -1,3 +1,3 @@
1
1
  module Wrapbox
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -22,7 +22,9 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_runtime_dependency "aws-sdk", "~> 2.4"
24
24
  spec.add_runtime_dependency "activesupport", ">= 4"
25
+ spec.add_runtime_dependency "docker-api"
25
26
  spec.add_runtime_dependency "multi_json"
27
+ spec.add_runtime_dependency "thor"
26
28
 
27
29
  spec.add_development_dependency "bundler", "~> 1.13"
28
30
  spec.add_development_dependency "rake", "~> 10.0"
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.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - joker1007
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-10-31 00:00:00.000000000 Z
11
+ date: 2017-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: docker-api
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: multi_json
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: bundler
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -139,7 +167,8 @@ dependencies:
139
167
  description: Ruby method runner on AWS ECS
140
168
  email:
141
169
  - kakyoin.hierophant@gmail.com
142
- executables: []
170
+ executables:
171
+ - wrapbox
143
172
  extensions: []
144
173
  extra_rdoc_files: []
145
174
  files:
@@ -153,7 +182,9 @@ files:
153
182
  - Rakefile
154
183
  - bin/console
155
184
  - bin/setup
185
+ - exe/wrapbox
156
186
  - lib/wrapbox.rb
187
+ - lib/wrapbox/cli.rb
157
188
  - lib/wrapbox/config_repository.rb
158
189
  - lib/wrapbox/configuration.rb
159
190
  - lib/wrapbox/job.rb
@@ -181,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
212
  version: '0'
182
213
  requirements: []
183
214
  rubyforge_project:
184
- rubygems_version: 2.6.4
215
+ rubygems_version: 2.6.8
185
216
  signing_key:
186
217
  specification_version: 4
187
218
  summary: Ruby method runner on AWS ECS