hako 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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