wrapbox 0.1.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 +7 -0
- data/.dockerignore +12 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Dockerfile +7 -0
- data/Gemfile +3 -0
- data/README.md +117 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/wrapbox/config_repository.rb +29 -0
- data/lib/wrapbox/configuration.rb +50 -0
- data/lib/wrapbox/job.rb +13 -0
- data/lib/wrapbox/runner/docker.rb +95 -0
- data/lib/wrapbox/runner/ecs.rb +202 -0
- data/lib/wrapbox/tasks/run.rake +14 -0
- data/lib/wrapbox/version.rb +3 -0
- data/lib/wrapbox.rb +31 -0
- data/wrapbox.gemspec +33 -0
- metadata +188 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c76da62eee815c3ab4d57a567a8a83810d9b7f20
|
4
|
+
data.tar.gz: 4c3df8f6ce34d0ae48f476d32e57d85170ce0028
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c2b799ee4e165c93dcf829659e513d610ad07f666377b8c3631c63209175bee00f7431b233dec3615cbd6dcba509895b4f4f7fa1e21b6b5174e7eb68d1673b22
|
7
|
+
data.tar.gz: 600bd6d4359e2534bf0c047621d61b2a7df7d5bcbe9143eb84e465b081f6714744027c9cf2ff989615c468cb6893b664b21b3aa6fb61322f558e71cc1048e0f1
|
data/.dockerignore
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Dockerfile
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# Wrapbox
|
2
|
+
|
3
|
+
Wrapbox runs Ruby method or shell command in a container (ECS, docker).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'wrapbox'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install wrapbox
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Write config.yml
|
24
|
+
|
25
|
+
```yaml
|
26
|
+
default:
|
27
|
+
cluster: ecsr-test
|
28
|
+
runner: ecs
|
29
|
+
region: ap-northeast-1
|
30
|
+
container_definition:
|
31
|
+
image: joker1007/wrapbox
|
32
|
+
cpu: 512
|
33
|
+
memory: 1024
|
34
|
+
essential: true
|
35
|
+
|
36
|
+
docker:
|
37
|
+
runner: docker
|
38
|
+
rm: true
|
39
|
+
container_definition:
|
40
|
+
image: joker1007/wrapbox
|
41
|
+
cpu: 512
|
42
|
+
memory: 1024
|
43
|
+
```
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
Wrapbox.configure do |c|
|
47
|
+
c.load_yaml(File.expand_path("../config.yml", __FILE__))
|
48
|
+
end
|
49
|
+
|
50
|
+
# runs TestJob#perform in ECS container
|
51
|
+
Wrapbox.run("TestJob", :perform, ["arg1", ["arg2", "arg3"]], environments: [{name: "RAILS_ENV", value: "development"}]) # use default config
|
52
|
+
# runs TestJob#perform in local docker container (Use docker cli)
|
53
|
+
Wrapbox.run("TestJob", :perform, ["arg1", ["arg2", "arg3"]], config_name: :docker, environments: [{name: "RAILS_ENV", value: "development"}]) # use docker config
|
54
|
+
|
55
|
+
# runs ls . command in ECS container
|
56
|
+
Wrapbox.run_cmd("ls", ".", environments: [{name: "RAILS_ENV", value: "development"}])
|
57
|
+
|
58
|
+
# runs ls . command in local docker container
|
59
|
+
Wrapbox.run_cmd("ls", ".", config_name: :docker, environments: [{name: "RAILS_ENV", value: "development"}])
|
60
|
+
```
|
61
|
+
|
62
|
+
## Config
|
63
|
+
|
64
|
+
### Common
|
65
|
+
|
66
|
+
| name | desc |
|
67
|
+
| ------ | ----------------- |
|
68
|
+
| runner | "ecs" or "docker" |
|
69
|
+
|
70
|
+
### for ECS
|
71
|
+
|
72
|
+
| name | desc |
|
73
|
+
| -------------------- | ------------------------------------------------ |
|
74
|
+
| cluster | target ECS cluster name |
|
75
|
+
| region | region of ECS cluster |
|
76
|
+
| container_definition | see. http://docs.aws.amazon.com/sdkforruby/api/Aws/ECS/Client.html#register_task_definition-instance_method |
|
77
|
+
| additional_container_definitions | Container definitions for sub containers |
|
78
|
+
| task_role_arn | see. http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html |
|
79
|
+
|
80
|
+
### for docker
|
81
|
+
| name | desc |
|
82
|
+
| -------------------- | ----------------------------------------------------------- |
|
83
|
+
| container_definition | only use `image`, `cpu`, `memory`, and `memory_reservation` |
|
84
|
+
| rm | If true, add `--rm` to cmd options |
|
85
|
+
| use_sudo | If true, invoke `sudo docker` command |
|
86
|
+
|
87
|
+
## API
|
88
|
+
|
89
|
+
#### `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)`
|
90
|
+
|
91
|
+
#### `run_cmd(*cmd, container_definition_overrides: {}, environments: [], task_role_arn: nil, cluster: nil, timeout: 3600 * 24, launch_timeout: 60 * 10, launch_retry: 10)`
|
92
|
+
|
93
|
+
following options is only for ECS.
|
94
|
+
|
95
|
+
- task_role_arn
|
96
|
+
- cluster
|
97
|
+
- timeout
|
98
|
+
- launch_timeout
|
99
|
+
- launch_retry
|
100
|
+
|
101
|
+
If Wrapbox cannot launch task in `launch_timeout` seconds, it puts custom metric data to CloudWatch.
|
102
|
+
Custom metric data is `wrapbox/WaitingTaskCount` that has `ClusterName` dimension.
|
103
|
+
And, it retry launching until retry count reach `launch_retry`.
|
104
|
+
|
105
|
+
After task exited, Wrapbox checks main container exit code.
|
106
|
+
If exit code is not 0, Wrapbox raise error.
|
107
|
+
|
108
|
+
## Development
|
109
|
+
|
110
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
111
|
+
|
112
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
113
|
+
|
114
|
+
## Contributing
|
115
|
+
|
116
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/reproio/wrapbox.
|
117
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "wrapbox"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Wrapbox
|
4
|
+
class ConfigRepository
|
5
|
+
def initialize
|
6
|
+
@configs = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def load_yaml(yaml_file)
|
10
|
+
configs = YAML.load(ERB.new(File.read(yaml_file)).result)
|
11
|
+
configs.each do |name, configuration|
|
12
|
+
load_config(name, configuration.merge("name" => name))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_config(name, configuration)
|
17
|
+
@configs[name.to_sym] = Configuration.load_config(configuration)
|
18
|
+
end
|
19
|
+
|
20
|
+
def default
|
21
|
+
@configs[:default]
|
22
|
+
end
|
23
|
+
|
24
|
+
def get(name)
|
25
|
+
name ? @configs[name.to_sym] : default
|
26
|
+
end
|
27
|
+
alias_method(:[], :get)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "active_support/core_ext/hash"
|
2
|
+
require "active_support/core_ext/string"
|
3
|
+
|
4
|
+
module Wrapbox
|
5
|
+
Configuration = Struct.new(
|
6
|
+
:name,
|
7
|
+
:runner,
|
8
|
+
:cluster,
|
9
|
+
:region,
|
10
|
+
:container_definition,
|
11
|
+
:additional_container_definitions,
|
12
|
+
:task_role_arn,
|
13
|
+
:use_sudo,
|
14
|
+
:rm
|
15
|
+
) do
|
16
|
+
def self.load_config(config)
|
17
|
+
new(
|
18
|
+
config["name"],
|
19
|
+
config["runner"] ? config["runner"].to_sym : :docker,
|
20
|
+
config["cluster"],
|
21
|
+
config["region"],
|
22
|
+
config["container_definition"].deep_symbolize_keys,
|
23
|
+
config["additional_container_definitions"] || [],
|
24
|
+
config["task_role_arn"],
|
25
|
+
config["use_sudo"].nil? ? false : config["use_sudo"],
|
26
|
+
config["rm"].nil? ? false : config["rm"]
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
AVAILABLE_RUNNERS = %i(docker ecs)
|
31
|
+
|
32
|
+
def initialize(*args)
|
33
|
+
super
|
34
|
+
raise "#{runner} is unsupported runner" unless AVAILABLE_RUNNERS.include?(runner)
|
35
|
+
require "wrapbox/runner/#{runner}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_runner
|
39
|
+
Wrapbox::Runner.const_get(runner.to_s.camelcase).new(to_h)
|
40
|
+
end
|
41
|
+
|
42
|
+
def run(class_name, method_name, args, **options)
|
43
|
+
build_runner.run(class_name, method_name, args, **options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def run_cmd(*cmd, **options)
|
47
|
+
build_runner.run_cmd(*cmd, **options)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/wrapbox/job.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
|
3
|
+
module Wrapbox
|
4
|
+
module Job
|
5
|
+
def self.perform
|
6
|
+
klass = ENV[CLASS_NAME_ENV].constantize
|
7
|
+
method_name = ENV[METHOD_NAME_ENV].to_sym
|
8
|
+
args = MultiJson.load(ENV[METHOD_ARGS_ENV])
|
9
|
+
|
10
|
+
klass.new.send(method_name, *args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require "open3"
|
2
|
+
require "multi_json"
|
3
|
+
|
4
|
+
module Wrapbox
|
5
|
+
module Runner
|
6
|
+
class Docker
|
7
|
+
class ExecutionError < StandardError; end
|
8
|
+
|
9
|
+
attr_reader \
|
10
|
+
:name,
|
11
|
+
:container_definition,
|
12
|
+
:rm,
|
13
|
+
:use_sudo
|
14
|
+
|
15
|
+
def initialize(options)
|
16
|
+
@name = options[:name]
|
17
|
+
@container_definition = options[:container_definition]
|
18
|
+
@rm = options[:rm]
|
19
|
+
@use_sudo = options[:use_sudo]
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(class_name, method_name, args, container_definition_overrides: {}, environments: [])
|
23
|
+
definition = container_definition
|
24
|
+
.merge(container_definition_overrides)
|
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"])
|
30
|
+
|
31
|
+
exec_docker(*cmdopt)
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_cmd(*cmd, container_definition_overrides: {}, environments: [])
|
35
|
+
definition = container_definition
|
36
|
+
.merge(container_definition_overrides)
|
37
|
+
|
38
|
+
cmdopt = build_cmdopt(definition)
|
39
|
+
cmdopt.concat(extract_environments(environments))
|
40
|
+
cmdopt.concat([definition[:image], *cmd])
|
41
|
+
|
42
|
+
exec_docker(*cmdopt)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
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
|
+
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)}"]
|
58
|
+
end
|
59
|
+
|
60
|
+
def extract_environments(environments)
|
61
|
+
environments.flat_map do |e|
|
62
|
+
["-e", "#{e[:name]}=#{e[:value]}"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
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
|
87
|
+
end
|
88
|
+
wait_thr.value
|
89
|
+
end
|
90
|
+
|
91
|
+
raise ExecutionError, "exit_code=#{result.exitstatus}" unless result.success?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require "aws-sdk"
|
2
|
+
require "multi_json"
|
3
|
+
|
4
|
+
module Wrapbox
|
5
|
+
module Runner
|
6
|
+
class Ecs
|
7
|
+
class ExecutionError < StandardError; end
|
8
|
+
|
9
|
+
attr_reader \
|
10
|
+
:name,
|
11
|
+
:cluster,
|
12
|
+
:region,
|
13
|
+
:container_definition,
|
14
|
+
:additional_container_definitions,
|
15
|
+
:task_role_arn
|
16
|
+
|
17
|
+
def initialize(options)
|
18
|
+
@name = options[:name]
|
19
|
+
@cluster = options[:cluster]
|
20
|
+
@region = options[:region]
|
21
|
+
@container_definition = options[:container_definition]
|
22
|
+
@additional_container_definitions = options[:additional_container_definitions]
|
23
|
+
@task_role_arn = options[:task_role_arn]
|
24
|
+
end
|
25
|
+
|
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)
|
27
|
+
task_definition = register_task_definition(container_definition_overrides)
|
28
|
+
run_task(
|
29
|
+
task_definition.task_definition_arn, class_name, method_name, args,
|
30
|
+
command: ["bundle", "exec", "rake", "wrapbox:run"],
|
31
|
+
environments: environments,
|
32
|
+
task_role_arn: task_role_arn,
|
33
|
+
cluster: cluster,
|
34
|
+
timeout: timeout,
|
35
|
+
launch_timeout: launch_timeout,
|
36
|
+
launch_retry: launch_retry,
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
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)
|
41
|
+
task_definition = register_task_definition(container_definition_overrides)
|
42
|
+
|
43
|
+
run_task(
|
44
|
+
task_definition.task_definition_arn, nil, nil, nil,
|
45
|
+
command: cmd,
|
46
|
+
environments: environments,
|
47
|
+
task_role_arn: task_role_arn,
|
48
|
+
cluster: cluster,
|
49
|
+
timeout: timeout,
|
50
|
+
launch_timeout: launch_timeout,
|
51
|
+
launch_retry: launch_retry,
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
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)
|
56
|
+
cl = cluster || self.cluster
|
57
|
+
args = Array(args)
|
58
|
+
|
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
|
+
launch_try_count = 0
|
64
|
+
begin
|
65
|
+
launched_at = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
|
66
|
+
client.wait_until(:tasks_running, cluster: cl, tasks: [task.task_arn]) do |w|
|
67
|
+
if launch_timeout
|
68
|
+
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
|
+
end
|
73
|
+
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
|
86
|
+
end
|
87
|
+
rescue Aws::Waiters::Errors::WaiterFailed
|
88
|
+
end
|
89
|
+
|
90
|
+
begin
|
91
|
+
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
|
92
|
+
client.wait_until(:tasks_stopped, cluster: cl, tasks: [task.task_arn]) do |w|
|
93
|
+
if timeout
|
94
|
+
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
|
+
end
|
99
|
+
end
|
100
|
+
rescue Aws::Waiters::Errors::TooManyAttemptsError
|
101
|
+
client.stop_task({
|
102
|
+
cluster: cluster || self.cluster,
|
103
|
+
task: task.task_arn,
|
104
|
+
reason: "process timeout",
|
105
|
+
})
|
106
|
+
end
|
107
|
+
|
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}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def task_definition_name
|
118
|
+
"wrapbox_#{name}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def register_task_definition(container_definition_overrides)
|
122
|
+
definition = container_definition
|
123
|
+
.merge(container_definition_overrides)
|
124
|
+
.merge(name: task_definition_name)
|
125
|
+
container_definitions = [definition, *additional_container_definitions]
|
126
|
+
client.register_task_definition({
|
127
|
+
family: task_definition_name,
|
128
|
+
container_definitions: container_definitions,
|
129
|
+
}).task_definition
|
130
|
+
end
|
131
|
+
|
132
|
+
def client
|
133
|
+
return @client if @client
|
134
|
+
|
135
|
+
options = {}
|
136
|
+
options[:region] = region if region
|
137
|
+
@client = Aws::ECS::Client.new(options)
|
138
|
+
end
|
139
|
+
|
140
|
+
def cloud_watch_client
|
141
|
+
return @cloud_watch_client if @cloud_watch_client
|
142
|
+
|
143
|
+
options = {}
|
144
|
+
options[:region] = region if region
|
145
|
+
@cloud_watch_client = Aws::CloudWatch::Client.new
|
146
|
+
end
|
147
|
+
|
148
|
+
def put_waiting_task_count_metric(cluster)
|
149
|
+
cloud_watch_client.put_metric_data(
|
150
|
+
namespace: "wrapbox",
|
151
|
+
metric_data: [
|
152
|
+
metric_name: "WaitingTaskCount",
|
153
|
+
dimensions: [
|
154
|
+
{
|
155
|
+
name: "ClusterName",
|
156
|
+
value: cluster || self.cluster,
|
157
|
+
},
|
158
|
+
],
|
159
|
+
value: 1.0,
|
160
|
+
unit: "Count",
|
161
|
+
]
|
162
|
+
)
|
163
|
+
end
|
164
|
+
|
165
|
+
def build_run_task_options(class_name, method_name, args, command, environments, cluster, task_definition_arn, task_role_arn)
|
166
|
+
env = environments
|
167
|
+
env += [
|
168
|
+
{
|
169
|
+
name: CLASS_NAME_ENV,
|
170
|
+
value: class_name.to_s,
|
171
|
+
},
|
172
|
+
{
|
173
|
+
name: METHOD_NAME_ENV,
|
174
|
+
value: method_name.to_s,
|
175
|
+
},
|
176
|
+
{
|
177
|
+
name: METHOD_ARGS_ENV,
|
178
|
+
value: MultiJson.dump(args),
|
179
|
+
},
|
180
|
+
] if class_name && method_name && args
|
181
|
+
overrides = {
|
182
|
+
container_overrides: [
|
183
|
+
{
|
184
|
+
name: task_definition_name,
|
185
|
+
command: command,
|
186
|
+
environment: env,
|
187
|
+
},
|
188
|
+
],
|
189
|
+
}
|
190
|
+
role_arn = task_role_arn || self.task_role_arn
|
191
|
+
overrides[:task_role_arn] = role_arn if role_arn
|
192
|
+
|
193
|
+
{
|
194
|
+
cluster: cluster || self.cluster,
|
195
|
+
task_definition: task_definition_arn,
|
196
|
+
overrides: overrides,
|
197
|
+
started_by: "wrapbox-#{Wrapbox::VERSION}",
|
198
|
+
}
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "wrapbox"
|
2
|
+
|
3
|
+
namespace :wrapbox do
|
4
|
+
desc "Run Wrapbox"
|
5
|
+
task :run do
|
6
|
+
Rake::Task["environment"].invoke if defined?(Rails)
|
7
|
+
|
8
|
+
if ENV[Wrapbox::CLASS_NAME_ENV] && ENV[Wrapbox::METHOD_NAME_ENV] && ENV[Wrapbox::METHOD_ARGS_ENV]
|
9
|
+
Wrapbox::Job.perform
|
10
|
+
else
|
11
|
+
raise "Wrapbox ENVs are not found"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/wrapbox.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Wrapbox
|
2
|
+
CLASS_NAME_ENV = "WRAPBOX_CLASS_NAME".freeze
|
3
|
+
METHOD_NAME_ENV = "WRAPBOX_METHOD_NAME".freeze
|
4
|
+
METHOD_ARGS_ENV = "WRAPBOX_METHOD_ARGS".freeze
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def configs
|
8
|
+
@configs ||= ConfigRepository.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def configure
|
12
|
+
yield configs
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(*args, config_name: nil, **options)
|
16
|
+
config = @configs.get(config_name)
|
17
|
+
config.run(*args, **options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_cmd(*args, config_name: nil, **options)
|
21
|
+
config = @configs.get(config_name)
|
22
|
+
config.run_cmd(*args, **options)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require "wrapbox/version"
|
28
|
+
|
29
|
+
require "wrapbox/config_repository"
|
30
|
+
require "wrapbox/configuration"
|
31
|
+
require "wrapbox/job"
|
data/wrapbox.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'wrapbox/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "wrapbox"
|
8
|
+
spec.version = Wrapbox::VERSION
|
9
|
+
spec.authors = ["joker1007"]
|
10
|
+
spec.email = ["kakyoin.hierophant@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Ruby method runner on AWS ECS}
|
13
|
+
spec.description = %q{Ruby method runner on AWS ECS}
|
14
|
+
spec.homepage = ""
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_runtime_dependency "aws-sdk", "~> 2.4"
|
24
|
+
spec.add_runtime_dependency "activesupport", ">= 4"
|
25
|
+
spec.add_runtime_dependency "multi_json"
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
30
|
+
spec.add_development_dependency "webmock"
|
31
|
+
spec.add_development_dependency "tapp"
|
32
|
+
spec.add_development_dependency "tapp-awesome_print"
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wrapbox
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- joker1007
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: multi_json
|
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'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.13'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.13'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: tapp
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: tapp-awesome_print
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: Ruby method runner on AWS ECS
|
140
|
+
email:
|
141
|
+
- kakyoin.hierophant@gmail.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ".dockerignore"
|
147
|
+
- ".gitignore"
|
148
|
+
- ".rspec"
|
149
|
+
- ".travis.yml"
|
150
|
+
- Dockerfile
|
151
|
+
- Gemfile
|
152
|
+
- README.md
|
153
|
+
- Rakefile
|
154
|
+
- bin/console
|
155
|
+
- bin/setup
|
156
|
+
- lib/wrapbox.rb
|
157
|
+
- lib/wrapbox/config_repository.rb
|
158
|
+
- lib/wrapbox/configuration.rb
|
159
|
+
- lib/wrapbox/job.rb
|
160
|
+
- lib/wrapbox/runner/docker.rb
|
161
|
+
- lib/wrapbox/runner/ecs.rb
|
162
|
+
- lib/wrapbox/tasks/run.rake
|
163
|
+
- lib/wrapbox/version.rb
|
164
|
+
- wrapbox.gemspec
|
165
|
+
homepage: ''
|
166
|
+
licenses: []
|
167
|
+
metadata: {}
|
168
|
+
post_install_message:
|
169
|
+
rdoc_options: []
|
170
|
+
require_paths:
|
171
|
+
- lib
|
172
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
requirements: []
|
183
|
+
rubyforge_project:
|
184
|
+
rubygems_version: 2.6.4
|
185
|
+
signing_key:
|
186
|
+
specification_version: 4
|
187
|
+
summary: Ruby method runner on AWS ECS
|
188
|
+
test_files: []
|