bako 0.1.2 → 0.1.3
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 +4 -4
- data/.codeclimate.yml +25 -0
- data/.rubocop.yml +1159 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +5 -0
- data/README.md +14 -4
- data/bako.gemspec +1 -0
- data/example/hello/hello.rb +4 -2
- data/lib/bako.rb +5 -0
- data/lib/bako/cli.rb +5 -1
- data/lib/bako/cli/run.rb +9 -5
- data/lib/bako/common_helper.rb +12 -9
- data/lib/bako/dsl.rb +2 -0
- data/lib/bako/dsl/context.rb +24 -17
- data/lib/bako/dsl/context/job.rb +29 -17
- data/lib/bako/dsl/context/job_definition.rb +17 -22
- data/lib/bako/error.rb +3 -1
- data/lib/bako/models/job.rb +41 -27
- data/lib/bako/models/job_definition.rb +27 -19
- data/lib/bako/version.rb +3 -1
- metadata +19 -2
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.4.1
|
data/.travis.yml
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
|
+
cache: bundler
|
3
4
|
rvm:
|
4
5
|
- 2.3.3
|
5
6
|
before_install: gem install bundler -v 1.14.6
|
7
|
+
addons:
|
8
|
+
code_climate:
|
9
|
+
repo_token:
|
10
|
+
secure: "rzEVWgZoxVjhiqC3YwS3h2+aYLlA8FWnEuHfrvFS7kRbiOmA0h8STR7ajMS8K4nglen1UCo5uoH194UeGNeaVKUgADS/5Db4nadA9fQ8bOwpIyq9FpAA9IHqMkmQ7cHPJ6cYf4m0z25mVq4Wy7xJQQgBSSLJPGe9ZAHrE6sHd0LggsGM4St6IYqUXyf3Nshs36Mx70Kxi0YIh743frUAWDEXWv7VPtKjhLEBHN6ZB3F9W3HvwlRrpFKx5nJT6aeEdQxy+Day3cWel6a4j/VH2pm3LDGrkF9/WByu1ULCL5aUY46vKhAfVdWIucUc9ABi09+6xhI/mf8rcMUeK96qa/gCtE1f9Tn7bX8qolvJlOprJanYTiy2eOMjP0PCuWlOazW7oKoODIn74LHIZqz9Nk3zS9GmLsfc87M1BUM4ri9txoN8RlLu6mzR4Tf6D4uceDa8VlTJLCkxRyi/CDJDwIsmyWSeBHtoRn8AfeIhrZsmCCKq3giYUJawbprZB57aQ377f5r1ZasRrdUfpMXMw/6+YVqfnLzIaFfGsS2Jz5uddSIHww9fHYPEAy/0OIPG9AgmxrKFmi4DQe5O4I1wr3yuKRpMQtqJOBNS2vvryvoNmoMLLW2ThC5D1k2ig3/+FMMYNh8hsv6nYCz1o/EDnDxJ4bQAf9ulPAc/6feyqrk="
|
6
11
|
deploy:
|
7
12
|
provider: rubygems
|
8
13
|
api_key:
|
@@ -11,3 +16,5 @@ deploy:
|
|
11
16
|
on:
|
12
17
|
tags: true
|
13
18
|
repo: ayemos/bako
|
19
|
+
after_success:
|
20
|
+
- bundle exec codeclimate-test-reporter
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# Bako
|
2
|
+
[](https://badge.fury.io/rb/bako)
|
3
|
+
[](https://codeclimate.com/github/ayemos/bako)
|
4
|
+
[](https://codeclimate.com/github/ayemos/bako/coverage)
|
5
|
+
[](https://codeclimate.com/github/ayemos/bako)
|
2
6
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
7
|
+
Bako is a CLI tool to manage your [AWS Batch](https://aws.amazon.com/batch/) jobs. It also has its own DSL for AWS Batch.
|
6
8
|
|
7
9
|
## Installation
|
8
10
|
|
@@ -22,7 +24,15 @@ Or install it yourself as:
|
|
22
24
|
|
23
25
|
## Usage
|
24
26
|
|
25
|
-
|
27
|
+
### Prepare environment
|
28
|
+
|
29
|
+
Before start using Bako, you need to prepare basic environment on AWS Batch.
|
30
|
+
We need at least
|
31
|
+
- one Job Queue
|
32
|
+
- one Compute Environment
|
33
|
+
- and one [Amazon EC2 Container Registory](https://aws.amazon.com/jp/ecr/) (only if you use container image for batch implementation)
|
34
|
+
|
35
|
+
## Examples
|
26
36
|
|
27
37
|
## Development
|
28
38
|
|
data/bako.gemspec
CHANGED
data/example/hello/hello.rb
CHANGED
@@ -9,6 +9,7 @@ preproc_jobs = []
|
|
9
9
|
[*1..2].each do |i|
|
10
10
|
preproc_job = job "preproc-inception-#{i}" do
|
11
11
|
job_definition preproc_jd
|
12
|
+
job_queue 'bako-test-queue-001'
|
12
13
|
|
13
14
|
param({
|
14
15
|
foo: 'bar'
|
@@ -22,11 +23,12 @@ train_jd = job_definition 'train-inception' do
|
|
22
23
|
command ['python', '/tensorflow/tensorflow/examples/learn/mnist.py']
|
23
24
|
type 'container'
|
24
25
|
memory 1024
|
25
|
-
vcpus
|
26
|
+
vcpus 4
|
26
27
|
image 'tensorflow/tensorflow:latest-devel'
|
27
28
|
end
|
28
29
|
|
29
30
|
job 'train-inception' do
|
30
31
|
job_definition train_jd
|
31
|
-
|
32
|
+
job_queue 'bako-test-queue-001'
|
33
|
+
depends_on preproc_jobs
|
32
34
|
end
|
data/lib/bako.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bako/version"
|
2
4
|
require 'bako/common_helper'
|
5
|
+
require 'logger'
|
3
6
|
|
4
7
|
module Bako
|
5
8
|
def Bako.logger
|
@@ -7,6 +10,8 @@ module Bako
|
|
7
10
|
end
|
8
11
|
end
|
9
12
|
|
13
|
+
require 'bako/error'
|
14
|
+
|
10
15
|
require 'bako/dsl'
|
11
16
|
require 'bako/dsl/context'
|
12
17
|
require 'bako/dsl/context/job'
|
data/lib/bako/cli.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'thor'
|
2
4
|
|
3
5
|
module Bako
|
@@ -5,7 +7,9 @@ module Bako
|
|
5
7
|
class_option :verbose, aliases: '-v', type: :boolean
|
6
8
|
map '--version' => :print_version
|
7
9
|
|
8
|
-
desc 'run', '
|
10
|
+
desc 'run JOB_FILE', 'Run batch job'
|
11
|
+
method_option :dry_run, aliases: '-n', type: :boolean,
|
12
|
+
desc: 'Run job locally without call any actual APIs'
|
9
13
|
def runjob(path)
|
10
14
|
require 'bako/cli/run'
|
11
15
|
Bako::CLI::Run.new(path, options, self).run
|
data/lib/bako/cli/run.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bako
|
2
4
|
class CLI::Run
|
3
5
|
include Bako::CommonHelper
|
@@ -9,10 +11,12 @@ module Bako
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def run
|
12
|
-
|
13
|
-
|
14
|
+
dry_run = @options['dry_run']
|
15
|
+
|
16
|
+
dsl.result[:job_definitions].each do |_, jd_context|
|
17
|
+
jd = Bako::Models::JobDefinition.from_context(jd_context, dry_run: dry_run)
|
14
18
|
|
15
|
-
if jd.remote_exists?
|
19
|
+
if !dry_run && jd.remote_exists?
|
16
20
|
y_or_n = @thor.ask("JobDefinition #{jd.name} seems to exist on remote. would you like to update it? (y/n)")
|
17
21
|
next unless y_or_n =~ /y/i
|
18
22
|
end
|
@@ -21,14 +25,14 @@ module Bako
|
|
21
25
|
end
|
22
26
|
|
23
27
|
jobs_to_be_run.each do |job|
|
24
|
-
Bako::Models::Job.from_context(job).start
|
28
|
+
Bako::Models::Job.from_context(job, dry_run: dry_run).start
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
28
32
|
private
|
29
33
|
|
30
34
|
def jobs_to_be_run
|
31
|
-
dsl.jobs.values - dsl.jobs.values.map{|j| j.
|
35
|
+
dsl.result[:jobs].values - dsl.result[:jobs].values.map{|j| j.result[:depends_on]}.flatten
|
32
36
|
end
|
33
37
|
|
34
38
|
def dsl
|
data/lib/bako/common_helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'aws-sdk'
|
2
4
|
|
3
5
|
module Bako
|
@@ -5,12 +7,11 @@ module Bako
|
|
5
7
|
DEFAULTS = {
|
6
8
|
vcpus: 1,
|
7
9
|
memory: 128
|
8
|
-
}
|
10
|
+
}.freeze
|
11
|
+
|
9
12
|
def batch_client
|
10
13
|
@batch_client ||= Aws::Batch::Client.new
|
11
14
|
end
|
12
|
-
def remote_resource(arn)
|
13
|
-
end
|
14
15
|
|
15
16
|
def remote_job_definition(name_or_arn, status=nil)
|
16
17
|
remote_job_definitions(status).find{|jd|
|
@@ -24,12 +25,14 @@ module Bako
|
|
24
25
|
}).job_definitions.map do |jd|
|
25
26
|
Bako::Models::JobDefinition.new(
|
26
27
|
jd.job_definition_name,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
{
|
29
|
+
command: jd.container_properties&.command,
|
30
|
+
image: jd.container_properties&.image,
|
31
|
+
role_arn: jd.container_properties&.job_role_arn,
|
32
|
+
type: jd.type,
|
33
|
+
memory: jd.container_properties&.memory,
|
34
|
+
vcpus: jd.container_properties&.vcpus,
|
35
|
+
}
|
33
36
|
)
|
34
37
|
end
|
35
38
|
end
|
data/lib/bako/dsl.rb
CHANGED
data/lib/bako/dsl/context.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
require 'active_support/core_ext/string/inflections'
|
4
|
+
|
1
5
|
class Bako::DSL::Context
|
2
|
-
attr_reader :
|
6
|
+
attr_reader :result
|
3
7
|
|
4
8
|
def self.eval(dsl)
|
5
9
|
new do
|
@@ -8,31 +12,34 @@ class Bako::DSL::Context
|
|
8
12
|
end
|
9
13
|
|
10
14
|
def initialize(&block)
|
11
|
-
|
12
|
-
@
|
15
|
+
|
16
|
+
@result = {
|
17
|
+
jobs: {},
|
18
|
+
job_definitions: {},
|
19
|
+
}
|
13
20
|
|
14
21
|
instance_eval(&block)
|
15
22
|
end
|
16
23
|
|
17
24
|
private
|
18
25
|
|
19
|
-
|
20
|
-
|
26
|
+
%i[
|
27
|
+
job
|
28
|
+
job_definition
|
29
|
+
].each do |context|
|
30
|
+
define_method(context) do |name, &block|
|
31
|
+
name = name.to_s
|
32
|
+
result_key = context.to_s.pluralize.to_sym
|
21
33
|
|
22
|
-
|
23
|
-
|
24
|
-
|
34
|
+
if result[result_key][name]
|
35
|
+
raise "#{context.to_s.capitalize} `#{name}` is already defined"
|
36
|
+
end
|
25
37
|
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
def job_definition(name, &block)
|
30
|
-
name = name.to_s
|
31
|
-
|
32
|
-
if @job_definitions[name]
|
33
|
-
raise "JobDefinition `#{name}` is already defined"
|
38
|
+
@result[result_key][name] = load_context(context).new(name, &block)
|
34
39
|
end
|
40
|
+
end
|
35
41
|
|
36
|
-
|
42
|
+
def load_context(context)
|
43
|
+
Object.const_get("Bako::DSL::Context::#{context.to_s.camelize}")
|
37
44
|
end
|
38
45
|
end
|
data/lib/bako/dsl/context/job.rb
CHANGED
@@ -1,21 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bako
|
2
4
|
class DSL::Context::Job
|
3
|
-
attr_reader :name, :
|
5
|
+
attr_reader :name, :result
|
4
6
|
|
5
7
|
def initialize(name, &block)
|
6
8
|
@name = name
|
9
|
+
@result = {}
|
7
10
|
|
8
11
|
instance_eval(&block)
|
12
|
+
validate!
|
9
13
|
end
|
10
14
|
|
11
15
|
private
|
12
16
|
|
17
|
+
%i[
|
18
|
+
param
|
19
|
+
memory
|
20
|
+
vcpus
|
21
|
+
job_queue
|
22
|
+
].each do |attr|
|
23
|
+
define_method(attr) do |v|
|
24
|
+
result[attr] = v
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate!
|
29
|
+
raise InvalidArgumentError.new('job_queue must be set') unless result[:job_queue]
|
30
|
+
raise InvalidArgumentError.new('job_definition must be set') unless result[:job_definition]
|
31
|
+
end
|
32
|
+
|
13
33
|
def job_definition(jd)
|
14
34
|
if jd.nil?
|
15
35
|
raise InvalidArgumentError.new('JobDefinition must be set')
|
16
36
|
end
|
17
37
|
|
18
|
-
|
38
|
+
result[:job_definition] =
|
19
39
|
if jd.is_a?(Bako::DSL::Context::JobDefinition)
|
20
40
|
jd
|
21
41
|
elsif jd.is_a?(String)
|
@@ -26,7 +46,7 @@ module Bako
|
|
26
46
|
end
|
27
47
|
|
28
48
|
def depends_on(jobs)
|
29
|
-
|
49
|
+
result[:depends_on] = jobs&.map do |job|
|
30
50
|
if job.is_a?(Bako::DSL::Context::Job)
|
31
51
|
job
|
32
52
|
elsif job.is_a?(String)
|
@@ -37,20 +57,12 @@ module Bako
|
|
37
57
|
end
|
38
58
|
end
|
39
59
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
def vcpus(vcpus_b)
|
49
|
-
@vcpus_b = vcpus_b
|
50
|
-
end
|
51
|
-
|
52
|
-
def job_queue(job_queue_b)
|
53
|
-
@job_queue_b = job_queue_b
|
60
|
+
def command(v)
|
61
|
+
result[:command] = if v.is_a?(Array)
|
62
|
+
v.map(&:to_s)
|
63
|
+
else
|
64
|
+
v.split.map(&:to_s)
|
65
|
+
end
|
54
66
|
end
|
55
67
|
end
|
56
68
|
end
|
@@ -1,39 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module Bako
|
3
4
|
class DSL::Context::JobDefinition
|
4
|
-
attr_reader :name, :
|
5
|
+
attr_reader :name, :result
|
5
6
|
|
6
7
|
def initialize(name, &block)
|
7
8
|
@name = name
|
8
|
-
@
|
9
|
+
@result = {}
|
9
10
|
|
10
11
|
instance_eval(&block)
|
12
|
+
validate!
|
11
13
|
end
|
12
14
|
|
13
15
|
private
|
14
16
|
|
15
|
-
def
|
16
|
-
|
17
|
+
def validate!
|
18
|
+
raise InvalidArgumentError.new('type must be set') unless result[:type]
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
def memory(memory_b)
|
32
|
-
@memory_b = memory_b
|
33
|
-
end
|
34
|
-
|
35
|
-
def vcpus(vcpus_b)
|
36
|
-
@vcpus_b = vcpus_b
|
21
|
+
%i[
|
22
|
+
type
|
23
|
+
image
|
24
|
+
command
|
25
|
+
role_arn
|
26
|
+
memory
|
27
|
+
vcpus
|
28
|
+
].each do |attr|
|
29
|
+
define_method(attr) do |v|
|
30
|
+
result[attr] = v
|
31
|
+
end
|
37
32
|
end
|
38
33
|
end
|
39
34
|
end
|
data/lib/bako/error.rb
CHANGED
data/lib/bako/models/job.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
require 'pathname'
|
3
5
|
|
@@ -6,50 +8,62 @@ module Bako
|
|
6
8
|
class Job
|
7
9
|
include Bako::CommonHelper
|
8
10
|
|
9
|
-
attr_reader :name, :job_definition, :depends_on, :param, :id, :memory, :vcpus, :job_queue
|
11
|
+
attr_reader :name, :job_definition, :depends_on, :param, :id, :memory, :vcpus, :job_queue, :command
|
10
12
|
|
11
|
-
def self.from_context(context)
|
13
|
+
def self.from_context(context, dry_run: false)
|
12
14
|
new(
|
13
15
|
context.name,
|
14
|
-
context.
|
15
|
-
|
16
|
-
Bako::Models::Job.from_context(job_context)
|
17
|
-
},
|
18
|
-
context.param_b,
|
19
|
-
context.memory_b,
|
20
|
-
context.vcpus_b,
|
21
|
-
context.job_queue_b
|
16
|
+
context.result,
|
17
|
+
dry_run: dry_run
|
22
18
|
)
|
23
19
|
end
|
24
20
|
|
25
|
-
def initialize(name,
|
21
|
+
def initialize(name, result, dry_run: false)
|
26
22
|
@name = name
|
27
|
-
@job_definition = job_definition
|
28
|
-
@depends_on = depends_on
|
29
|
-
|
30
|
-
|
31
|
-
@
|
32
|
-
@
|
23
|
+
@job_definition = result[:job_definition]
|
24
|
+
@depends_on = result[:depends_on]&.map{|job_context|
|
25
|
+
Bako::Models::Job.from_context(job_context)
|
26
|
+
}
|
27
|
+
@param = result[:param]
|
28
|
+
@memory = result[:memory]
|
29
|
+
@vcpus = result[:vcpus]
|
30
|
+
@job_queue = result[:job_queue]
|
31
|
+
@command = result[:command]
|
32
|
+
@dry_run = dry_run
|
33
33
|
end
|
34
34
|
|
35
35
|
def start
|
36
|
-
|
37
|
-
|
36
|
+
_start(dry_run: @dry_run)
|
37
|
+
end
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
def _start(dry_run: false)
|
40
|
+
# start 'depends_on' jobs first
|
41
|
+
@depends_on&.each{|j| j._start(dry_run: dry_run)}
|
42
42
|
|
43
|
-
|
44
|
-
|
43
|
+
Bako.logger.info("Submitting job #{@name}:")
|
44
|
+
job_arg = {
|
45
45
|
job_definition: @job_definition.name,
|
46
46
|
job_name: @name,
|
47
47
|
job_queue: @job_queue,
|
48
48
|
depends_on: @depends_on&.map{|j| [[:job_id, j.id]].to_h},
|
49
|
-
parameters: @param
|
50
|
-
|
49
|
+
parameters: @param,
|
50
|
+
container_overrides: {
|
51
|
+
command: @command,
|
52
|
+
vcpus: @vcpus,
|
53
|
+
memory: @memory
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
Bako.logger.info("\n#{job_arg.to_yaml}\n")
|
58
|
+
|
59
|
+
# start job
|
60
|
+
if dry_run
|
61
|
+
@id = '(dry_run)'
|
62
|
+
else
|
63
|
+
resp = batch_client.submit_job(job_arg)
|
64
|
+
@id = resp.job_id
|
65
|
+
end
|
51
66
|
|
52
|
-
@id = resp.job_id
|
53
67
|
Bako.logger.info("Submitted job #{@name} (id: #{@id})")
|
54
68
|
|
55
69
|
resp
|