hako 0.13.3 → 0.14.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: c1240601c96556b2eab4b5dc18657b2d3509d07d
4
- data.tar.gz: 90672d6874a9b57003cf06ccfd107a33293101b0
3
+ metadata.gz: dcee254b9d6c4c81d6d480835e3c48ea7c73285b
4
+ data.tar.gz: 2b8626bbf5480ed279e1872c757f7932f230a842
5
5
  SHA512:
6
- metadata.gz: 6e45448ebe0cabccf05c76cb61b784d3e4178010672ddacd6135f5409027c65df658ec261ec0b17d3b75a8f65f460e3bb51595a723f50e1d9541349d17d29d02
7
- data.tar.gz: 22ffc83a6c2e3adee2d1aa3827b084307b5559457b3aec6897c9950f93d88eed384bd0399aec5ea40e83763c59933f48e7a62b4b3c3fa74c78549763100d05ab
6
+ metadata.gz: 6325c0e207a2e5f89baa61f7a83a19840d5a439097ed6ecaf35e48b5b540b9d8ade04a063ac04a574328b323dd74d9dd2129791d9861757cfbf2ffc696dbaf74
7
+ data.tar.gz: 202c812931f149fd9db14f58facf35b82c6fc40f896ad13b92125aa95c0f87d243dbd248d9596027cda15d0038bb4aacb903e34cf42c90cd2647d3620033df44
@@ -0,0 +1 @@
1
+ --private
data/Rakefile CHANGED
@@ -2,8 +2,10 @@
2
2
  require 'bundler/gem_tasks'
3
3
  require 'rspec/core/rake_task'
4
4
  require 'rubocop/rake_task'
5
+ require 'yard'
5
6
 
6
7
  RSpec::Core::RakeTask.new(:spec)
7
8
  RuboCop::RakeTask.new(:rubocop)
9
+ YARD::Rake::YardocTask.new(:yard)
8
10
 
9
11
  task :default => [:spec, :rubocop]
@@ -24,10 +24,11 @@ app:
24
24
  path: hello.env
25
25
  PORT: 3000
26
26
  MESSAGE: '#{username}-san'
27
- front:
28
- image_tag: hako-nginx
29
- memory: 32
30
- cpu: 32
27
+ additional_containers:
28
+ front:
29
+ image_tag: hako-nginx
30
+ memory: 32
31
+ cpu: 32
31
32
  scripts:
32
33
  - <<: !include front.yml
33
34
  locations:
@@ -16,11 +16,11 @@ app:
16
16
  path: hello.env
17
17
  PORT: 3000
18
18
  MESSAGE: '#{username}-san'
19
- front:
20
- image_tag: hako-nginx
21
- memory: 32
22
- cpu: 32
23
19
  additional_containers:
20
+ front:
21
+ image_tag: hako-nginx
22
+ memory: 32
23
+ cpu: 32
24
24
  redis:
25
25
  image_tag: redis:3.0
26
26
  cpu: 64
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency 'rake'
25
25
  spec.add_development_dependency 'rspec'
26
26
  spec.add_development_dependency 'rubocop', '>= 0.36.0'
27
+ spec.add_development_dependency 'yard'
27
28
  end
@@ -3,10 +3,12 @@ require 'hako/container'
3
3
 
4
4
  module Hako
5
5
  class AppContainer < Container
6
+ # @return [String]
6
7
  def image_tag
7
8
  "#{@definition['image']}:#{@definition['tag']}"
8
9
  end
9
10
 
11
+ # @return [Fixnum]
10
12
  def port
11
13
  @definition['port']
12
14
  end
@@ -3,6 +3,12 @@ require 'hako/yaml_loader'
3
3
 
4
4
  module Hako
5
5
  class Application
6
+ # @!attribute [r] id
7
+ # @return [String]
8
+ # @!attribute [r] root_path
9
+ # @return [Pathname]
10
+ # @!attribute [r] yaml
11
+ # @return [Hash]
6
12
  attr_reader :id, :root_path, :yaml
7
13
 
8
14
  def initialize(yaml_path)
@@ -8,10 +8,15 @@ require 'hako/scripts'
8
8
 
9
9
  module Hako
10
10
  class Commander
11
+ # @param [Application] app
11
12
  def initialize(app)
12
13
  @app = app
13
14
  end
14
15
 
16
+ # @param [Boolean] force
17
+ # @param [String] tag
18
+ # @param [Boolean] dry_run
19
+ # @return [nil]
15
20
  def deploy(force: false, tag: 'latest', dry_run: false)
16
21
  containers = load_containers(tag, dry_run: dry_run)
17
22
  scripts = @app.yaml.fetch('scripts', []).map { |config| load_script(config, dry_run: dry_run) }
@@ -21,8 +26,14 @@ module Hako
21
26
  scripts.each { |script| script.deploy_starting(containers) }
22
27
  scheduler.deploy(containers)
23
28
  scripts.each { |script| script.deploy_finished(containers) }
29
+ nil
24
30
  end
25
31
 
32
+ # @param [Array<String>] commands
33
+ # @param [String] tag
34
+ # @param [Hash<String, String>] env
35
+ # @param [Boolean] dry_run
36
+ # @return [nil]
26
37
  def oneshot(commands, tag:, containers:, env: {}, dry_run: false)
27
38
  containers = load_containers(tag, dry_run: dry_run, with: containers)
28
39
  scripts = @app.yaml.fetch('scripts', []).map { |config| load_script(config, dry_run: dry_run) }
@@ -37,10 +48,12 @@ module Hako
37
48
  exit exit_code
38
49
  end
39
50
 
51
+ # @return [nil]
40
52
  def status
41
53
  load_scheduler(@app.yaml['scheduler'], []).status
42
54
  end
43
55
 
56
+ # @return [nil]
44
57
  def remove
45
58
  scripts = @app.yaml.fetch('scripts', []).map { |config| load_script(config, dry_run: dry_run) }
46
59
  load_scheduler(@app.yaml['scheduler'], scripts).remove
@@ -52,6 +65,8 @@ module Hako
52
65
  TRAP_SIGNALS = %i[INT TERM].freeze
53
66
  class SignalTrapped < StandardError; end
54
67
 
68
+ # @param [Scheduler] scheduler
69
+ # @yieldreturn [Fixnum]
55
70
  def with_oneshot_signal_handlers(scheduler, &block)
56
71
  old_handlers = {}
57
72
  trapped = false
@@ -77,14 +92,26 @@ module Hako
77
92
  exit_code
78
93
  end
79
94
 
95
+ # @param [String] tag
96
+ # @param [Boolean] dry_run
97
+ # @param [Array<String>, nil] with
98
+ # @return [Hash<String, Container>]
80
99
  def load_containers(tag, dry_run:, with: nil)
81
100
  DefinitionLoader.new(@app, dry_run: dry_run).load(tag, with: with)
82
101
  end
83
102
 
103
+ # @param [Hash] yaml
104
+ # @param [Hash] volumes
105
+ # @param [Boolean] force
106
+ # @param [Boolean] dry_run
107
+ # @return [Scheduler]
84
108
  def load_scheduler(yaml, scripts, volumes: [], force: false, dry_run: false)
85
109
  Loader.new(Hako::Schedulers, 'hako/schedulers').load(yaml.fetch('type')).new(@app.id, yaml, volumes: volumes, scripts: scripts, force: force, dry_run: dry_run)
86
110
  end
87
111
 
112
+ # @param [Hash] yaml
113
+ # @param [Boolean] dry_run
114
+ # @return [Script]
88
115
  def load_script(yaml, dry_run:)
89
116
  Loader.new(Hako::Scripts, 'hako/scripts').load(yaml.fetch('type')).new(@app, yaml, dry_run: dry_run)
90
117
  end
@@ -3,8 +3,13 @@ require 'hako/version'
3
3
 
4
4
  module Hako
5
5
  class Container
6
+ # @!attribute [r] definition
7
+ # @return [Hash]
6
8
  attr_reader :definition
7
9
 
10
+ # @param [Application] app
11
+ # @param [Hash] definition
12
+ # @param [Boolean] dry_run
8
13
  def initialize(app, definition, dry_run:)
9
14
  @app = app
10
15
  @definition = default_config.merge(definition)
@@ -29,10 +34,12 @@ module Hako
29
34
  end
30
35
  end
31
36
 
37
+ # @return [Hash<String, String>]
32
38
  def env
33
39
  @expanded_env ||= expand_env(@definition.fetch('env'))
34
40
  end
35
41
 
42
+ # @return [Array<Hash>]
36
43
  def mount_points
37
44
  @definition['mount_points'].map do |mount_point|
38
45
  {
@@ -47,6 +54,8 @@ module Hako
47
54
 
48
55
  PROVIDERS_KEY = '$providers'
49
56
 
57
+ # @param [Hash<String, String>] env
58
+ # @return [Hash<String, String>]
50
59
  def expand_env(env)
51
60
  env = env.dup
52
61
  provider_types = env.delete(PROVIDERS_KEY) || []
@@ -58,12 +67,15 @@ module Hako
58
67
  end
59
68
  end
60
69
 
70
+ # @param [Array<Hash>] provider_configs
71
+ # @return [Array<EnvProvider>]
61
72
  def load_providers(provider_configs)
62
73
  provider_configs.map do |yaml|
63
74
  Loader.new(Hako::EnvProviders, 'hako/env_providers').load(yaml.fetch('type')).new(@app.root_path, yaml)
64
75
  end
65
76
  end
66
77
 
78
+ # @return [Hash]
67
79
  def default_config
68
80
  {
69
81
  'env' => {},
@@ -74,6 +86,7 @@ module Hako
74
86
  }
75
87
  end
76
88
 
89
+ # @return [Hash<String, String>]
77
90
  def default_labels
78
91
  {
79
92
  'cc.wanko.hako.version' => VERSION,
@@ -6,20 +6,22 @@ require 'hako/loader'
6
6
 
7
7
  module Hako
8
8
  class DefinitionLoader
9
+ # @param [Application] app
10
+ # @param [Boolean] dry_run
9
11
  def initialize(app, dry_run:)
10
12
  @app = app
11
13
  @dry_run = dry_run
12
14
  end
13
15
 
16
+ # @param [String] tag
17
+ # @param [Array<String>, nil] with
18
+ # @return [Hash<String, Container>]
14
19
  def load(tag, with: nil)
15
20
  additional_containers = @app.yaml.fetch('additional_containers', {})
16
21
  container_names = ['app']
17
22
  if with
18
23
  container_names.concat(with)
19
24
  else
20
- if @app.yaml.key?('front')
21
- container_names << 'front'
22
- end
23
25
  container_names.concat(additional_containers.keys)
24
26
  end
25
27
 
@@ -28,6 +30,10 @@ module Hako
28
30
 
29
31
  private
30
32
 
33
+ # @param [String] tag
34
+ # @param [Array<String>] container_names
35
+ # @param [Hash<String, Hash>] additional_containers
36
+ # @return [Hash<String, Container>]
31
37
  def load_containers_from_name(tag, container_names, additional_containers)
32
38
  names = Set.new(container_names)
33
39
  containers = {}
@@ -37,8 +43,6 @@ module Hako
37
43
  case name
38
44
  when 'app'
39
45
  AppContainer.new(@app, @app.yaml['app'].merge('tag' => tag), dry_run: @dry_run)
40
- when 'front'
41
- Container.new(@app, @app.yaml.fetch('front'), dry_run: @dry_run)
42
46
  else
43
47
  Container.new(@app, additional_containers.fetch(name), dry_run: @dry_run)
44
48
  end
@@ -12,10 +12,13 @@ module Hako
12
12
  Literal = Struct.new(:literal)
13
13
  Variable = Struct.new(:name)
14
14
 
15
+ # @param [Array<EnvProvider>] providers
15
16
  def initialize(providers)
16
17
  @providers = providers
17
18
  end
18
19
 
20
+ # @param [Hash<String, String>] env
21
+ # @return [Hash<String, String>]
19
22
  def expand(env)
20
23
  parsed_env = {}
21
24
  variables = Set.new
@@ -52,6 +55,8 @@ module Hako
52
55
 
53
56
  private
54
57
 
58
+ # @param [String] value
59
+ # @return [Array]
55
60
  def parse(value)
56
61
  s = StringScanner.new(value)
57
62
  tokens = []
@@ -4,6 +4,8 @@ require 'hako/env_provider'
4
4
  module Hako
5
5
  module EnvProviders
6
6
  class File < EnvProvider
7
+ # @param [Pathname] root_path
8
+ # @param [Hash<String, Object>] options
7
9
  def initialize(root_path, options)
8
10
  unless options['path']
9
11
  validation_error!('path must be set')
@@ -11,6 +13,8 @@ module Hako
11
13
  @path = root_path.join(options['path'])
12
14
  end
13
15
 
16
+ # @param [Array<String>] variables
17
+ # @return [Hash<String, String>]
14
18
  def ask(variables)
15
19
  env = {}
16
20
  read_from_file do |key, val|
@@ -23,6 +27,9 @@ module Hako
23
27
 
24
28
  private
25
29
 
30
+ # @yieldparam [String] key
31
+ # @yieldparam [String] val
32
+ # @return [nil]
26
33
  def read_from_file(&block)
27
34
  ::File.open(@path) do |f|
28
35
  f.each_line do |line|
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
  module Hako
3
3
  class Loader
4
+ # @param [Module] base_module
5
+ # @param [String] base_path
4
6
  def initialize(base_module, base_path)
5
7
  @base_module = base_module
6
8
  @base_path = base_path
7
9
  end
8
10
 
11
+ # @param [String] name
12
+ # @return [Module]
9
13
  def load(name)
10
14
  require "#{@base_path}/#{name}"
11
15
  @base_module.const_get(camelize(name))
@@ -13,6 +17,8 @@ module Hako
13
17
 
14
18
  private
15
19
 
20
+ # @param [String] name
21
+ # @return [String]
16
22
  def camelize(name)
17
23
  name.split('_').map(&:capitalize).join('')
18
24
  end
@@ -6,6 +6,12 @@ module Hako
6
6
  class ValidationError < Error
7
7
  end
8
8
 
9
+ # @param [String] app_id
10
+ # @param [Hash] options
11
+ # @param [Hash] volumes
12
+ # @param [Array<Script>] scripts
13
+ # @param [Boolean] dry_run
14
+ # @param [Boolean] force
9
15
  def initialize(app_id, options, volumes:, scripts:, dry_run:, force:)
10
16
  @app_id = app_id
11
17
  @volumes = volumes
@@ -15,10 +21,12 @@ module Hako
15
21
  configure(options)
16
22
  end
17
23
 
24
+ # @param [Hash] _options
18
25
  def configure(_options)
19
26
  end
20
27
 
21
- def deploy(_containers, _options)
28
+ # @param [Hash<String, Container>] _containers
29
+ def deploy(_containers)
22
30
  raise NotImplementedError
23
31
  end
24
32
 
@@ -32,6 +40,7 @@ module Hako
32
40
 
33
41
  private
34
42
 
43
+ # @param [String] message
35
44
  def validation_error!(message)
36
45
  raise ValidationError.new(message)
37
46
  end
@@ -13,9 +13,10 @@ module Hako
13
13
 
14
14
  attr_reader :task
15
15
 
16
+ # @param [Hash<String, Object>] options
16
17
  def configure(options)
17
18
  @cluster = options.fetch('cluster', DEFAULT_CLUSTER)
18
- @desired_count = options.fetch('desired_count') { validation_error!('desired_count must be set') }
19
+ @desired_count = options.fetch('desired_count', nil)
19
20
  region = options.fetch('region') { validation_error!('region must be set') }
20
21
  @role = options.fetch('role', nil)
21
22
  @ecs = Aws::ECS::Client.new(region: region)
@@ -25,7 +26,12 @@ module Hako
25
26
  @container_instance_arn = nil
26
27
  end
27
28
 
29
+ # @param [Hash<String, Container>] containers
30
+ # @return [nil]
28
31
  def deploy(containers)
32
+ unless @desired_count
33
+ validation_error!('desired_count must be set')
34
+ end
29
35
  front_port = determine_front_port
30
36
  @scripts.each { |script| script.deploy_started(containers, front_port) }
31
37
  definitions = create_definitions(containers)
@@ -53,6 +59,10 @@ module Hako
53
59
  end
54
60
  end
55
61
 
62
+ # @param [Hash<String, Container>] containers
63
+ # @param [Array<String>] commands
64
+ # @param [Hash<String, String>] env
65
+ # @return [nil]
56
66
  def oneshot(containers, commands, env)
57
67
  definitions = create_definitions(containers)
58
68
  definitions.each do |definition|
@@ -83,6 +93,7 @@ module Hako
83
93
  end
84
94
  end
85
95
 
96
+ # @return [nil]
86
97
  def stop_oneshot
87
98
  if @task
88
99
  Hako.logger.warn "Stopping #{@task.task_arn}"
@@ -91,6 +102,7 @@ module Hako
91
102
  end
92
103
  end
93
104
 
105
+ # @return [nil]
94
106
  def status
95
107
  service = describe_service
96
108
  unless service
@@ -149,6 +161,7 @@ module Hako
149
161
  end
150
162
  end
151
163
 
164
+ # @return [nil]
152
165
  def remove
153
166
  service = describe_service
154
167
  if service
@@ -163,6 +176,7 @@ module Hako
163
176
 
164
177
  private
165
178
 
179
+ # @return [Aws::ECS::Types::Service, nil]
166
180
  def describe_service
167
181
  service = @ecs.describe_services(cluster: @cluster, services: [@app_id]).services[0]
168
182
  if service && service.status != 'INACTIVE'
@@ -170,6 +184,7 @@ module Hako
170
184
  end
171
185
  end
172
186
 
187
+ # @return [Fixnum]
173
188
  def determine_front_port
174
189
  if @dry_run
175
190
  return DEFAULT_FRONT_PORT
@@ -182,6 +197,7 @@ module Hako
182
197
  end
183
198
  end
184
199
 
200
+ # @return [Fixnum]
185
201
  def new_front_port
186
202
  max_port = -1
187
203
  @ecs.list_services(cluster: @cluster).each do |page|
@@ -203,6 +219,8 @@ module Hako
203
219
  end
204
220
  end
205
221
 
222
+ # @param [Aws::ECS::Types::Service] service
223
+ # @return [Fixnum, nil]
206
224
  def find_front_port(service)
207
225
  task_definition = @ecs.describe_task_definition(task_definition: service.task_definition).task_definition
208
226
  container_definitions = {}
@@ -214,6 +232,9 @@ module Hako
214
232
  end
215
233
  end
216
234
 
235
+ # @param [String] family
236
+ # @param [Array<Hash>] definitions
237
+ # @return [Boolean]
217
238
  def task_definition_changed?(family, definitions)
218
239
  if @force
219
240
  return true
@@ -236,6 +257,8 @@ module Hako
236
257
  true
237
258
  end
238
259
 
260
+ # @param [Hash<String, Hash<String, String>>] actual_volumes
261
+ # @return [Boolean]
239
262
  def different_volumes?(actual_volumes)
240
263
  if @volumes.size != actual_volumes.size
241
264
  return true
@@ -253,10 +276,15 @@ module Hako
253
276
  false
254
277
  end
255
278
 
279
+ # @param [Hash] expected_container
280
+ # @param [Aws::ECS::Types::ContainerDefinition] actual_container
281
+ # @return [Boolean]
256
282
  def different_definition?(expected_container, actual_container)
257
283
  EcsDefinitionComparator.new(expected_container).different?(actual_container)
258
284
  end
259
285
 
286
+ # @param [Array<Hash>] definitions
287
+ # @return [Aws::ECS::Types::TaskDefinition, Symbol]
260
288
  def register_task_definition(definitions)
261
289
  if task_definition_changed?(@app_id, definitions)
262
290
  @ecs.register_task_definition(
@@ -269,12 +297,16 @@ module Hako
269
297
  end
270
298
  end
271
299
 
300
+ # @param [Hash<String, Container>] containers
301
+ # @return [nil]
272
302
  def create_definitions(containers)
273
303
  containers.map do |name, container|
274
304
  create_definition(name, container)
275
305
  end
276
306
  end
277
307
 
308
+ # @param [Array<Hash>] definitions
309
+ # @return [Aws::ECS::Types::TaskDefinition, Symbol]
278
310
  def register_task_definition_for_oneshot(definitions)
279
311
  family = "#{@app_id}-oneshot"
280
312
  if task_definition_changed?(family, definitions)
@@ -288,6 +320,7 @@ module Hako
288
320
  end
289
321
  end
290
322
 
323
+ # @return [Hash]
291
324
  def volumes_definition
292
325
  @volumes.map do |name, volume|
293
326
  {
@@ -297,6 +330,9 @@ module Hako
297
330
  end
298
331
  end
299
332
 
333
+ # @param [String] name
334
+ # @param [Container] container
335
+ # @return [Hash]
300
336
  def create_definition(name, container)
301
337
  environment = container.env.map { |k, v| { name: k, value: v } }
302
338
  {
@@ -313,6 +349,10 @@ module Hako
313
349
  }
314
350
  end
315
351
 
352
+ # @param [Aws::ECS::Types::TaskDefinition] task_definition
353
+ # @param [Array<String>] commands
354
+ # @param [Hash<String, String>] env
355
+ # @return [Aws::ECS::Types::Task]
316
356
  def run_task(task_definition, commands, env)
317
357
  environment = env.map { |k, v| { name: k, value: v } }
318
358
  @ecs.run_task(
@@ -332,6 +372,7 @@ module Hako
332
372
  ).tasks[0]
333
373
  end
334
374
 
375
+ # @return [Fixnum]
335
376
  def wait_for_oneshot_finish
336
377
  containers = wait_for_task(@task)
337
378
  @task = nil
@@ -350,6 +391,8 @@ module Hako
350
391
  exit_code
351
392
  end
352
393
 
394
+ # @param [Aws::ECS::Types::Task] task
395
+ # @return [nil]
353
396
  def wait_for_task(task)
354
397
  task_arn = task.task_arn
355
398
  loop do
@@ -385,6 +428,8 @@ module Hako
385
428
  end
386
429
  end
387
430
 
431
+ # @param [String] container_instance_arn
432
+ # @return [nil]
388
433
  def report_container_instance(container_instance_arn)
389
434
  container_instance = @ecs.describe_container_instances(cluster: @cluster, container_instances: [container_instance_arn]).container_instances[0]
390
435
  @ec2.describe_tags(filters: [{ name: 'resource-id', values: [container_instance.ec2_instance_id] }]).each do |page|
@@ -397,6 +442,9 @@ module Hako
397
442
  end
398
443
  end
399
444
 
445
+ # @param [String] task_definition_arn
446
+ # @param [Fixnum] front_port
447
+ # @return [Aws::ECS::Types::Service, Symbol]
400
448
  def create_or_update_service(task_definition_arn, front_port)
401
449
  service = describe_service
402
450
  if service.nil?
@@ -435,6 +483,9 @@ module Hako
435
483
 
436
484
  SERVICE_KEYS = %i[desired_count task_definition].freeze
437
485
 
486
+ # @param [Aws::ECS::Types::Service] service
487
+ # @param [Hash] params
488
+ # @return [Boolean]
438
489
  def service_changed?(service, params)
439
490
  SERVICE_KEYS.each do |key|
440
491
  if service.public_send(key) != params[key]
@@ -444,8 +495,11 @@ module Hako
444
495
  false
445
496
  end
446
497
 
498
+ # @param [Aws::ECS::Types::Service] service
499
+ # @return [nil]
447
500
  def wait_for_ready(service)
448
501
  latest_event_id = find_latest_event_id(service.events)
502
+ Hako.logger.debug " latest_event_id=#{latest_event_id}"
449
503
  loop do
450
504
  s = @ecs.describe_services(cluster: service.cluster_arn, services: [service.service_arn]).services[0]
451
505
  s.events.each do |e|
@@ -456,6 +510,7 @@ module Hako
456
510
  end
457
511
  latest_event_id = find_latest_event_id(s.events)
458
512
  finished = s.deployments.all? { |d| d.status != 'ACTIVE' }
513
+ Hako.logger.debug " latest_event_id=#{latest_event_id}, deployment statuses=#{s.deployments.map(&:status)}"
459
514
  if finished
460
515
  return
461
516
  else
@@ -464,6 +519,8 @@ module Hako
464
519
  end
465
520
  end
466
521
 
522
+ # @param [Array<Aws::ECS::Types::ServiceEvent>] events
523
+ # @return [String, nil]
467
524
  def find_latest_event_id(events)
468
525
  if events.empty?
469
526
  nil
@@ -2,6 +2,7 @@
2
2
  module Hako
3
3
  module Schedulers
4
4
  class EcsDefinitionComparator
5
+ # @param [Hash] expected_container
5
6
  def initialize(expected_container)
6
7
  @expected_container = expected_container
7
8
  end
@@ -11,6 +12,8 @@ module Hako
11
12
  ENVIRONMENT_KEYS = %i[name value].freeze
12
13
  MOUNT_POINT_KEYS = %i[source_volume container_path read_only].freeze
13
14
 
15
+ # @param [Aws::ECS::Types::ContainerDefinition] actual_container
16
+ # @return [Boolean]
14
17
  def different?(actual_container)
15
18
  unless actual_container
16
19
  return true
@@ -33,6 +36,10 @@ module Hako
33
36
 
34
37
  private
35
38
 
39
+ # @param [Hash<String, Object>] expected
40
+ # @param [Hash<String, Object>] actual
41
+ # @param [Array<String>] keys
42
+ # @return [Boolean]
36
43
  def different_members?(expected, actual, keys)
37
44
  keys.each do |key|
38
45
  if actual.public_send(key) != expected[key]
@@ -42,6 +49,10 @@ module Hako
42
49
  false
43
50
  end
44
51
 
52
+ # @param [Hash<String, Array<Object>>] expected
53
+ # @param [Hash<String, Array<Object>>] actual
54
+ # @param [Array<String>] keys
55
+ # @return [Boolean]
45
56
  def different_array?(expected, actual, key, keys)
46
57
  if expected[key].size != actual.public_send(key).size
47
58
  return true
@@ -5,16 +5,22 @@ require 'hako'
5
5
  module Hako
6
6
  module Schedulers
7
7
  class EcsElb
8
+ # @param [String] app_id
9
+ # @param [Aws::ElasticLoadBalancing::Client] elb
10
+ # @param [Hash] elb_config
8
11
  def initialize(app_id, elb, elb_config)
9
12
  @app_id = app_id
10
13
  @elb = elb
11
14
  @elb_config = elb_config
12
15
  end
13
16
 
17
+ # @return [Aws::ElasticLoadBalancing::Types::LoadBalancerDescription]
14
18
  def describe_load_balancer
15
19
  @elb.describe_load_balancers(load_balancer_names: [name]).load_balancer_descriptions[0]
16
20
  end
17
21
 
22
+ # @param [Fixnum] front_port
23
+ # @return [nil]
18
24
  def find_or_create_load_balancer(front_port)
19
25
  if @elb_config
20
26
  unless exist?
@@ -40,6 +46,7 @@ module Hako
40
46
  end
41
47
  end
42
48
 
49
+ # @return [nil]
43
50
  def destroy
44
51
  if exist?
45
52
  @elb.delete_load_balancer(load_balancer_name: name)
@@ -49,6 +56,7 @@ module Hako
49
56
  end
50
57
  end
51
58
 
59
+ # @return [Boolean]
52
60
  def exist?
53
61
  describe_load_balancer
54
62
  true
@@ -56,6 +64,7 @@ module Hako
56
64
  false
57
65
  end
58
66
 
67
+ # @return [String]
59
68
  def name
60
69
  "hako-#{@app_id}"
61
70
  end
@@ -3,32 +3,43 @@ require 'hako/scripts'
3
3
 
4
4
  module Hako
5
5
  class Script
6
+ # @param [Application] app
7
+ # @param [Hash] options
8
+ # @param [Boolean] dry_run
6
9
  def initialize(app, options, dry_run:)
7
10
  @app = app
8
11
  @dry_run = dry_run
9
12
  configure(options)
10
13
  end
11
14
 
15
+ # @param [Hash<String, Container>] _containers
12
16
  def deploy_starting(_containers)
13
17
  end
14
18
 
19
+ # @param [Hash<String, Container>] _containers
20
+ # @param [Fixnum] _front_port
15
21
  def deploy_started(_containers, _front_port)
16
22
  end
17
23
 
24
+ # @param [Hash<String, Container>] _containers
18
25
  def deploy_finished(_containers)
19
26
  end
20
27
 
28
+ # @param [Hash<String, Container>] _containers
21
29
  def oneshot_starting(_containers)
22
30
  end
23
31
 
32
+ # @param [Scheduler] _scheduler
24
33
  def oneshot_started(_scheduler)
25
34
  end
26
35
 
36
+ # @param [Hash<String, Container>] _containers
27
37
  def oneshot_finished(_containers)
28
38
  end
29
39
 
30
40
  private
31
41
 
42
+ # @param [Hash] _options
32
43
  def configure(_options)
33
44
  end
34
45
  end
@@ -8,6 +8,7 @@ module Hako
8
8
  module Scripts
9
9
  class NginxFront < Script
10
10
  S3Config = Struct.new(:region, :bucket, :prefix) do
11
+ # @param [Hash] options
11
12
  def initialize(options)
12
13
  self.region = options.fetch('region')
13
14
  self.bucket = options.fetch('bucket')
@@ -23,6 +24,8 @@ module Hako
23
24
  end
24
25
  end
25
26
 
27
+ # @param [Hash<String, Container>] containers
28
+ # @return [nil]
26
29
  def deploy_starting(containers)
27
30
  front = containers.fetch('front')
28
31
  front.definition['env'].merge!(
@@ -33,6 +36,9 @@ module Hako
33
36
  front.links << link_app
34
37
  end
35
38
 
39
+ # @param [Hash<String, Container>] containers
40
+ # @param [Fixnum] front_port
41
+ # @return [nil]
36
42
  def deploy_started(containers, front_port)
37
43
  app = containers.fetch('app')
38
44
  front = containers.fetch('front')
@@ -43,6 +49,8 @@ module Hako
43
49
 
44
50
  private
45
51
 
52
+ # @param [Hash] options
53
+ # @return [nil]
46
54
  def configure(options)
47
55
  super
48
56
  @options = options
@@ -50,18 +58,24 @@ module Hako
50
58
  @s3 = S3Config.new(@options.fetch('s3'))
51
59
  end
52
60
 
61
+ # @return [String]
53
62
  def link_app
54
63
  'app:app'
55
64
  end
56
65
 
66
+ # @param [Fixnum] front_port
67
+ # @return [Hash]
57
68
  def port_mapping(front_port)
58
69
  { container_port: 80, host_port: front_port, protocol: 'tcp' }
59
70
  end
60
71
 
72
+ # @param [Fixnum] app_port
73
+ # @return [String]
61
74
  def generate_config(app_port)
62
75
  Generator.new(@options, app_port).render
63
76
  end
64
77
 
78
+ # @return [Hash]
65
79
  def upload_config(front_conf)
66
80
  if @dry_run
67
81
  Hako.logger.info "Generated configuration:\n#{front_conf}"
@@ -74,38 +88,47 @@ module Hako
74
88
  end
75
89
  end
76
90
 
91
+ # @return [Aws::S3::Client]
77
92
  def s3_client
78
93
  @s3_client ||= Aws::S3::Client.new(region: @s3.region)
79
94
  end
80
95
 
81
96
  class Generator
97
+ # @param [Hash] options
98
+ # @param [Fixnum] app_port
82
99
  def initialize(options, app_port)
83
100
  @options = options
84
101
  @app_port = app_port
85
102
  end
86
103
 
104
+ # @return [String]
87
105
  def render
88
106
  ERB.new(File.read(nginx_conf_erb), nil, '-').result(binding)
89
107
  end
90
108
 
91
109
  private
92
110
 
111
+ # @return [String]
93
112
  def listen_spec
94
113
  "app:#{@app_port}"
95
114
  end
96
115
 
116
+ # @return [String]
97
117
  def templates_directory
98
118
  File.expand_path('../../templates', __FILE__)
99
119
  end
100
120
 
121
+ # @return [String]
101
122
  def nginx_conf_erb
102
123
  File.join(templates_directory, 'nginx.conf.erb')
103
124
  end
104
125
 
126
+ # @return [String]
105
127
  def nginx_location_conf_erb
106
128
  File.join(templates_directory, 'nginx.location.conf.erb')
107
129
  end
108
130
 
131
+ # @return [Hash<String, Location>]
109
132
  def locations
110
133
  locs = @options.fetch('locations').dup
111
134
  locs.keys.each do |k|
@@ -114,10 +137,14 @@ module Hako
114
137
  locs
115
138
  end
116
139
 
140
+ # @return [String, nil]
117
141
  def client_max_body_size
118
142
  @options.fetch('client_max_body_size', nil)
119
143
  end
120
144
 
145
+ # @param [String] listen_spec
146
+ # @param [Location] location
147
+ # @return [String]
121
148
  def render_location(listen_spec, location)
122
149
  ERB.new(File.read(nginx_location_conf_erb), nil, '-').result(binding).each_line.map do |line|
123
150
  " #{line}"
@@ -125,10 +152,12 @@ module Hako
125
152
  end
126
153
 
127
154
  class Location
155
+ # @param [Hash] config
128
156
  def initialize(config)
129
157
  @config = config
130
158
  end
131
159
 
160
+ # @return [Array<String>, nil]
132
161
  def allow_only_from
133
162
  allow = @config.fetch('allow_only_from', nil)
134
163
  if allow
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Hako
3
- VERSION = '0.13.3'
3
+ VERSION = '0.14.0'
4
4
  end
@@ -7,6 +7,8 @@ module Hako
7
7
  @current_path = nil
8
8
  end
9
9
 
10
+ # @param [String] path
11
+ # @return [Hash]
10
12
  def load(path)
11
13
  class_loader = Psych::ClassLoader.new
12
14
  scanner = Psych::ScalarScanner.new(class_loader)
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.13.3
4
+ version: 0.14.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-04-13 00:00:00.000000000 Z
11
+ date: 2016-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.36.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: Deploy Docker container
84
98
  email:
85
99
  - eagletmt@gmail.com
@@ -93,6 +107,7 @@ files:
93
107
  - ".rubocop.yml"
94
108
  - ".rubocop_todo.yml"
95
109
  - ".travis.yml"
110
+ - ".yardopts"
96
111
  - Gemfile
97
112
  - README.md
98
113
  - Rakefile
@@ -119,7 +134,6 @@ files:
119
134
  - lib/hako/loader.rb
120
135
  - lib/hako/scheduler.rb
121
136
  - lib/hako/schedulers.rb
122
- - lib/hako/schedulers/echo.rb
123
137
  - lib/hako/schedulers/ecs.rb
124
138
  - lib/hako/schedulers/ecs_definition_comparator.rb
125
139
  - lib/hako/schedulers/ecs_elb.rb
@@ -154,3 +168,4 @@ signing_key:
154
168
  specification_version: 4
155
169
  summary: Deploy Docker container
156
170
  test_files: []
171
+ has_rdoc:
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'hako/scheduler'
3
-
4
- module Hako
5
- module Schedulers
6
- class Echo < Scheduler
7
- def deploy(containers)
8
- app = containers.fetch('app')
9
- puts "Deploy #{app.image_tag} with app_port=#{app.port}, force=#{@force}, dry_run=#{@dry_run}"
10
- puts 'Environment variables:'
11
- app.env.each do |key, val|
12
- puts " #{key}=#{val.inspect}"
13
- end
14
- end
15
-
16
- def oneshot(containers, commands, env)
17
- app = containers.fetch('app')
18
- puts "Run #{app.image_tag} with oneshot commands=#{commands.inspect}"
19
- puts 'Environment variables:'
20
- env.each do |key, val|
21
- puts " #{key}=#{val.inspect}"
22
- end
23
- 0
24
- end
25
- end
26
- end
27
- end