hako 0.4.0 → 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: 7051366d540062e8a8d89a5e4a29d4fd439e53f9
4
- data.tar.gz: de094d094bcc3773b789b3f4fbe12a24a9f64752
3
+ metadata.gz: 6faa5dea73adc01c789baffd7ecf6823bb86a77f
4
+ data.tar.gz: 38c6d1baa569e5b4872762b5e6a6fd2e28e11a00
5
5
  SHA512:
6
- metadata.gz: 41d1331497077ed082ef86164f37b255a9a644444242ef208fb12e4a0301e3934ba63f2d7ec4e90587d286e2c600c46fc13c76b5665260aed3fc77cf367b6b2c
7
- data.tar.gz: 812835ac65a95d396687eb2a8314d736e5351099669374f5765ecd9b1688451b9325cf4dc99f0308d4a8062271bbaa9749dc3080e39c27b2641667918d16c5f5
6
+ metadata.gz: d090b3321ef8fb21bdc24ff19079e30915b067e3555025c9f83ce3dd0377e002c48318bfa525896e92b1c0a16b2bbf404eb3fd3e99b0d62d233afc770943327d
7
+ data.tar.gz: 4bc41461ca3a40958699833cd99d9b5c0d5108c6e01255a9769919f55520ef4baef4aee2a5a6d86a9b78d4e140356f3df61fa0d480c62562d787697d9d745732
@@ -1,16 +1,6 @@
1
- image: ryotarai/hello-sinatra
2
- env:
3
- $providers:
4
- - type: file
5
- path: examples/hello.env
6
- PORT: 3000
7
- MESSAGE: '#{username}-san'
8
- port: 3000
9
1
  scheduler:
10
2
  type: ecs
11
3
  region: ap-northeast-1
12
- memory: 100
13
- cpu: 100
14
4
  cluster: eagletmt
15
5
  desired_count: 2
16
6
  role: ecsServiceRole
@@ -23,9 +13,22 @@ scheduler:
23
13
  - subnet-YYYYYYYY
24
14
  security_groups:
25
15
  - sg-ZZZZZZZZ
16
+ app:
17
+ image: ryotarai/hello-sinatra
18
+ memory: 100
19
+ cpu: 100
20
+ port: 3000
21
+ env:
22
+ $providers:
23
+ - type: file
24
+ path: examples/hello.env
25
+ PORT: 3000
26
+ MESSAGE: '#{username}-san'
26
27
  front:
27
28
  type: nginx
28
29
  image_tag: hako-nginx
30
+ memory: 100
31
+ cpu: 100
29
32
  s3:
30
33
  region: ap-northeast-1
31
34
  bucket: nanika
@@ -1,21 +1,24 @@
1
- image: ryotarai/hello-sinatra
2
- env:
3
- $providers:
4
- - type: file
5
- path: hello.env
6
- PORT: 3000
7
- MESSAGE: '#{username}-san'
8
- port: 3000
9
1
  scheduler:
10
2
  type: ecs
11
3
  region: ap-northeast-1
12
- memory: 100
13
- cpu: 100
14
4
  cluster: eagletmt
15
5
  desired_count: 2
6
+ app:
7
+ image: ryotarai/hello-sinatra
8
+ memory: 100
9
+ cpu: 100
10
+ port: 3000
11
+ env:
12
+ $providers:
13
+ - type: file
14
+ path: hello.env
15
+ PORT: 3000
16
+ MESSAGE: '#{username}-san'
16
17
  front:
17
18
  type: nginx
18
19
  image_tag: hako-nginx
20
+ memory: 100
21
+ cpu: 100
19
22
  s3:
20
23
  region: ap-northeast-1
21
24
  bucket: nanika
@@ -0,0 +1,13 @@
1
+ require 'hako/container'
2
+
3
+ module Hako
4
+ class AppContainer < Container
5
+ def image_tag
6
+ "#{@definition['image']}:#{@definition['tag']}"
7
+ end
8
+
9
+ def port
10
+ @definition['port']
11
+ end
12
+ end
13
+ end
@@ -1,43 +1,33 @@
1
- require 'hako/container'
1
+ require 'hako/app_container'
2
2
  require 'hako/env_expander'
3
3
  require 'hako/error'
4
- require 'hako/front_config'
5
4
  require 'hako/fronts'
5
+ require 'hako/loader'
6
6
  require 'hako/schedulers'
7
7
  require 'hako/scripts'
8
8
 
9
9
  module Hako
10
10
  class Commander
11
- PROVIDERS_KEY = '$providers'.freeze
12
-
13
11
  def initialize(app)
14
12
  @app = app
15
13
  end
16
14
 
17
15
  def deploy(force: false, tag: 'latest')
18
- env = load_environment(@app.yaml['env'])
16
+ app = AppContainer.new(@app.yaml['app'].merge('tag' => tag))
19
17
  front = load_front(@app.yaml['front'])
20
18
  scheduler = load_scheduler(@app.yaml['scheduler'])
21
- app_port = @app.yaml.fetch('port', nil)
22
- image = @app.yaml.fetch('image') { raise Error.new('image must be set') }
23
- app = Container.new(
24
- 'image_tag' => "#{image}:#{tag}",
25
- 'docker_labels' => @app.yaml.fetch('docker_labels', {}),
26
- )
27
19
  scripts = @app.yaml.fetch('scripts', []).map { |config| load_script(config) }
28
20
 
29
21
  containers = { 'app' => app, 'front' => front }
30
22
  scripts.each { |script| script.before_deploy(containers) }
31
- scheduler.deploy(containers, env, app_port, force: force)
23
+ scheduler.deploy(containers, force: force)
32
24
  scripts.each { |script| script.after_deploy(containers) }
33
25
  end
34
26
 
35
27
  def oneshot(commands, tag: 'latest')
36
- env = load_environment(@app.yaml['env'])
28
+ app = AppContainer.new(@app.yaml['app'].merge('tag' => tag))
37
29
  scheduler = load_scheduler(@app.yaml['scheduler'])
38
- image = @app.yaml.fetch('image') { raise Error.new('image must be set') }
39
- image_tag = "#{image}:#{tag}"
40
- exit scheduler.oneshot(Container.new('image_tag' => image_tag), env, commands)
30
+ exit scheduler.oneshot(app, commands)
41
31
  end
42
32
 
43
33
  def status
@@ -58,40 +48,16 @@ module Hako
58
48
  EnvExpander.new(providers).expand(env)
59
49
  end
60
50
 
61
- def load_providers(provider_configs)
62
- provider_configs.map do |config|
63
- type = config['type']
64
- unless type
65
- raise Error.new("type must be set in each #{PROVIDERS_KEY} element")
66
- end
67
- require "hako/env_providers/#{type}"
68
- Hako::EnvProviders.const_get(camelize(type)).new(@app.root_path, config)
69
- end
70
- end
71
-
72
- def load_scheduler(scheduler_config)
73
- type = scheduler_config['type']
74
- unless type
75
- raise Error.new('type must be set in scheduler')
76
- end
77
- require "hako/schedulers/#{type}"
78
- Hako::Schedulers.const_get(camelize(type)).new(@app.id, scheduler_config)
51
+ def load_scheduler(yaml)
52
+ Loader.new(Hako::Schedulers, 'hako/schedulers').load(yaml.fetch('type')).new(@app.id, yaml)
79
53
  end
80
54
 
81
55
  def load_front(yaml)
82
- front_config = FrontConfig.new(yaml)
83
- require "hako/fronts/#{front_config.type}"
84
- Hako::Fronts.const_get(camelize(front_config.type)).new(front_config)
85
- end
86
-
87
- def load_script(config)
88
- type = config.fetch('type')
89
- require "hako/scripts/#{type}"
90
- Hako::Scripts.const_get(camelize(type)).new(@app, config)
56
+ Loader.new(Hako::Fronts, 'hako/fronts').load(yaml.fetch('type')).new(@app.id, yaml)
91
57
  end
92
58
 
93
- def camelize(name)
94
- name.split('_').map(&:capitalize).join('')
59
+ def load_script(yaml)
60
+ Loader.new(Hako::Scripts, 'hako/scripts').load(yaml.fetch('type')).new(@app, yaml)
95
61
  end
96
62
  end
97
63
  end
@@ -11,6 +11,8 @@ module Hako
11
11
  %w[
12
12
  image_tag
13
13
  docker_labels
14
+ cpu
15
+ memory
14
16
  ].each do |name|
15
17
  define_method(name) do
16
18
  @definition[name]
@@ -20,5 +22,25 @@ module Hako
20
22
  @definition[name] = val
21
23
  end
22
24
  end
25
+
26
+ def env
27
+ @expanded_env ||= expand_env(@definition.fetch('env', {}))
28
+ end
29
+
30
+ private
31
+
32
+ PROVIDERS_KEY = '$providers'.freeze
33
+
34
+ def expand_env(env)
35
+ env = env.dup
36
+ providers = load_providers(env.delete(PROVIDERS_KEY) || [])
37
+ EnvExpander.new(providers).expand(env)
38
+ end
39
+
40
+ def load_providers(provider_configs)
41
+ provider_configs.map do |yaml|
42
+ Loader.new(Hako::EnvProviders, 'hako/env_providers').load(yaml.fetch('type')).new(@app.root_path, yaml)
43
+ end
44
+ end
23
45
  end
24
46
  end
@@ -1,9 +1,41 @@
1
+ require 'hako/container'
2
+
1
3
  module Hako
2
- class Front
3
- attr_reader :config
4
+ class Front < Container
5
+ S3Config = Struct.new(:region, :bucket, :prefix) do
6
+ def initialize(options)
7
+ self.region = options.fetch('region')
8
+ self.bucket = options.fetch('bucket')
9
+ self.prefix = options.fetch('prefix', nil)
10
+ end
11
+
12
+ def key(app_id)
13
+ if prefix
14
+ "#{prefix}/#{app_id}.conf"
15
+ else
16
+ "#{app_id}.conf"
17
+ end
18
+ end
19
+ end
20
+
21
+ attr_reader :s3
22
+
23
+ def initialize(app_id, config)
24
+ super(config)
25
+ @app_id = app_id
26
+ @s3 = S3Config.new(@definition.fetch('s3'))
27
+ end
28
+
29
+ def env
30
+ super.merge(
31
+ 'AWS_DEFAULT_REGION' => @s3.region,
32
+ 'S3_CONFIG_BUCKET' => @s3.bucket,
33
+ 'S3_CONFIG_KEY' => @s3.key(@app_id),
34
+ )
35
+ end
4
36
 
5
- def initialize(front_config)
6
- @config = front_config
37
+ def extra
38
+ @definition.fetch('extra', {})
7
39
  end
8
40
 
9
41
  def generate_config(_app_port)
@@ -24,7 +24,7 @@ module Hako
24
24
  end
25
25
 
26
26
  def locations
27
- locs = @config.extra.fetch('locations', {}).dup
27
+ locs = extra.fetch('locations', {}).dup
28
28
  locs['/'] ||= {}
29
29
  locs.keys.each do |k|
30
30
  locs[k] = Location.new(locs[k])
@@ -33,7 +33,7 @@ module Hako
33
33
  end
34
34
 
35
35
  def client_max_body_size
36
- @config.extra.fetch('client_max_body_size', nil)
36
+ extra.fetch('client_max_body_size', nil)
37
37
  end
38
38
 
39
39
  def render_location(listen_spec, location)
@@ -0,0 +1,19 @@
1
+ module Hako
2
+ class Loader
3
+ def initialize(base_module, base_path)
4
+ @base_module = base_module
5
+ @base_path = base_path
6
+ end
7
+
8
+ def load(name)
9
+ require "#{@base_path}/#{name}"
10
+ @base_module.const_get(camelize(name))
11
+ end
12
+
13
+ private
14
+
15
+ def camelize(name)
16
+ name.split('_').map(&:capitalize).join('')
17
+ end
18
+ end
19
+ end
@@ -8,7 +8,7 @@ module Hako
8
8
  def initialize(_app_id, _options)
9
9
  end
10
10
 
11
- def deploy(_containers, _env, _app_port, _options)
11
+ def deploy(_containers, _options)
12
12
  raise NotImplementedError
13
13
  end
14
14
 
@@ -22,7 +22,7 @@ module Hako
22
22
 
23
23
  def upload_front_config(app_id, front, app_port)
24
24
  front_conf = front.generate_config(app_port)
25
- s3_config = front.config.s3
25
+ s3_config = front.s3
26
26
  s3 = Aws::S3::Client.new(region: s3_config.region)
27
27
  s3.put_object(
28
28
  body: front_conf,
@@ -14,8 +14,6 @@ module Hako
14
14
  @app_id = app_id
15
15
  @cluster = options.fetch('cluster', DEFAULT_CLUSTER)
16
16
  @desired_count = options.fetch('desired_count') { validation_error!('desired_count must be set') }
17
- @cpu = options.fetch('cpu') { validation_error!('cpu must be set') }
18
- @memory = options.fetch('memory') { validation_error!('memory must be set') }
19
17
  region = options.fetch('region') { validation_error!('region must be set') }
20
18
  @role = options.fetch('role', nil)
21
19
  @ecs = Aws::ECS::Client.new(region: region)
@@ -23,24 +21,19 @@ module Hako
23
21
  @ec2 = Aws::EC2::Client.new(region: region)
24
22
  end
25
23
 
26
- def deploy(containers, env, app_port, force: false)
24
+ def deploy(containers, force: false)
27
25
  @force_mode = force
28
26
  app = containers.fetch('app')
29
27
  front = containers.fetch('front')
30
- front_env = {
31
- 'AWS_DEFAULT_REGION' => front.config.s3.region,
32
- 'S3_CONFIG_BUCKET' => front.config.s3.bucket,
33
- 'S3_CONFIG_KEY' => front.config.s3.key(@app_id),
34
- }
35
28
  front_port = determine_front_port
36
- task_definition = register_task_definition(app, env, front.config, front_env, front_port)
29
+ task_definition = register_task_definition(containers, front_port)
37
30
  if task_definition == :noop
38
31
  Hako.logger.info "Task definition isn't changed"
39
32
  task_definition = @ecs.describe_task_definition(task_definition: @app_id).task_definition
40
33
  else
41
34
  Hako.logger.info "Registered task definition: #{task_definition.task_definition_arn}"
42
- upload_front_config(@app_id, front, app_port)
43
- Hako.logger.info "Uploaded front configuration to s3://#{front.config.s3.bucket}/#{front.config.s3.key(@app_id)}"
35
+ upload_front_config(@app_id, front, app.port)
36
+ Hako.logger.info "Uploaded front configuration to s3://#{front.s3.bucket}/#{front.s3.key(@app_id)}"
44
37
  end
45
38
  service = create_or_update_service(task_definition.task_definition_arn, front_port)
46
39
  if service == :noop
@@ -52,10 +45,10 @@ module Hako
52
45
  Hako.logger.info 'Deployment completed'
53
46
  end
54
47
 
55
- def oneshot(app, env, commands)
48
+ def oneshot(app, commands)
56
49
  task_definition = register_task_definition_for_oneshot(app)
57
50
  Hako.logger.info "Registered task definition: #{task_definition.task_definition_arn}"
58
- task = run_task(task_definition, env, commands)
51
+ task = run_task(task_definition, app.env, commands)
59
52
  Hako.logger.info "Started task: #{task.task_arn}"
60
53
  exit_code = wait_for_task(task)
61
54
  Hako.logger.info 'Oneshot task finished'
@@ -197,9 +190,9 @@ module Hako
197
190
  EcsDefinitionComparator.new(expected_container).different?(actual_container)
198
191
  end
199
192
 
200
- def register_task_definition(app, env, front_config, front_env, front_port)
201
- front_def = front_container(front_config, front_env, front_port)
202
- app_def = app_container(app, env)
193
+ def register_task_definition(containers, front_port)
194
+ front_def = front_container(containers.fetch('front'), front_port)
195
+ app_def = app_container(containers.fetch('app'))
203
196
  if task_definition_changed?(front_def, app_def)
204
197
  @ecs.register_task_definition(
205
198
  family: @app_id,
@@ -217,8 +210,8 @@ module Hako
217
210
  {
218
211
  name: 'oneshot',
219
212
  image: app.image_tag,
220
- cpu: @cpu,
221
- memory: @memory,
213
+ cpu: app.cpu,
214
+ memory: app.memory,
222
215
  links: [],
223
216
  port_mappings: [],
224
217
  environment: [],
@@ -227,28 +220,28 @@ module Hako
227
220
  ).task_definition
228
221
  end
229
222
 
230
- def front_container(front_config, env, front_port)
231
- environment = env.map { |k, v| { name: k, value: v } }
223
+ def front_container(front, front_port)
224
+ environment = front.env.map { |k, v| { name: k, value: v } }
232
225
  {
233
226
  name: 'front',
234
- image: front_config.container.image_tag,
235
- cpu: 100,
236
- memory: 100,
227
+ image: front.image_tag,
228
+ cpu: front.cpu,
229
+ memory: front.memory,
237
230
  links: ['app:app'],
238
231
  port_mappings: [{ container_port: 80, host_port: front_port, protocol: 'tcp' }],
239
232
  essential: true,
240
233
  environment: environment,
241
- docker_labels: front_config.container.docker_labels,
234
+ docker_labels: front.docker_labels,
242
235
  }
243
236
  end
244
237
 
245
- def app_container(app, env)
246
- environment = env.map { |k, v| { name: k, value: v } }
238
+ def app_container(app)
239
+ environment = app.env.map { |k, v| { name: k, value: v } }
247
240
  {
248
241
  name: 'app',
249
242
  image: app.image_tag,
250
- cpu: @cpu,
251
- memory: @memory,
243
+ cpu: app.cpu,
244
+ memory: app.memory,
252
245
  links: [],
253
246
  port_mappings: [],
254
247
  essential: true,
@@ -1,3 +1,3 @@
1
1
  module Hako
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '0.5.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hako
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kohei Suzuki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-02-17 00:00:00.000000000 Z
11
+ date: 2016-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -118,6 +118,7 @@ files:
118
118
  - exe/hako
119
119
  - hako.gemspec
120
120
  - lib/hako.rb
121
+ - lib/hako/app_container.rb
121
122
  - lib/hako/application.rb
122
123
  - lib/hako/cli.rb
123
124
  - lib/hako/commander.rb
@@ -128,9 +129,9 @@ files:
128
129
  - lib/hako/env_providers/file.rb
129
130
  - lib/hako/error.rb
130
131
  - lib/hako/front.rb
131
- - lib/hako/front_config.rb
132
132
  - lib/hako/fronts.rb
133
133
  - lib/hako/fronts/nginx.rb
134
+ - lib/hako/loader.rb
134
135
  - lib/hako/scheduler.rb
135
136
  - lib/hako/schedulers.rb
136
137
  - lib/hako/schedulers/echo.rb
@@ -1,32 +0,0 @@
1
- require 'erb'
2
- require 'hako/container'
3
-
4
- module Hako
5
- FrontConfig = Struct.new(:type, :container, :s3, :extra)
6
- class FrontConfig
7
- S3Config = Struct.new(:region, :bucket, :prefix) do
8
- def initialize(options)
9
- self.region = options.fetch('region')
10
- self.bucket = options.fetch('bucket')
11
- self.prefix = options.fetch('prefix', nil)
12
- end
13
-
14
- def key(app_id)
15
- if prefix
16
- "#{prefix}/#{app_id}.conf"
17
- else
18
- "#{app_id}.conf"
19
- end
20
- end
21
- end
22
-
23
- def initialize(options)
24
- self.type = options.fetch('type')
25
- self.container = Container.new(
26
- 'image_tag' => options.fetch('image_tag'),
27
- )
28
- self.s3 = S3Config.new(options.fetch('s3'))
29
- self.extra = options.fetch('extra', {})
30
- end
31
- end
32
- end