hako 0.18.1 → 0.19.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: e0c20cd9f0e6cd36eec79e0d44be24027970b626
4
- data.tar.gz: 5061cd6b796075c6a0d6b84d771fa2b910613c28
3
+ metadata.gz: 45f04940c4d0ff4ff960ea9619a525085aba342d
4
+ data.tar.gz: 67610aa17c6877ed84599ecd1be143c4c39d6a03
5
5
  SHA512:
6
- metadata.gz: d3b1e35d43f959e0ab45392f5839932c8a41fc38c40f8da30a966e3c72ff7c6dc7755fd8ebb6b6375205038298f0cf926a666f84e53a40568db85cc41cfea08d
7
- data.tar.gz: 6f14e53cadfdf897764527ec016454cfc0ac444f9d06c77fa70af4cf374f1920ce2c4a7455c31c732a963894b093e114d1872ac1a7bac58afb83ce42d3a20b8c
6
+ metadata.gz: 92407332bca376bcba4e54248842d685568410cf92c4cb19aa7be30d1353a266e549db55da77b3f12c1cc7b5161a78de6edc0e0fc33a2f322822bb937870dbd2
7
+ data.tar.gz: 2599f5133827e410fb4cc2d068fe7fc09e52b654022f140549ab34abc620cade3bc111dae8c8bb861ec60c89768dc9e6e57eb13b89b8dc929dc50e8a0746d7e9
data/.rubocop.yml CHANGED
@@ -37,5 +37,8 @@ Style/TrailingCommaInArguments:
37
37
  Style/TrailingCommaInLiteral:
38
38
  Enabled: false
39
39
 
40
+ Style/PredicateName:
41
+ Enabled: false
42
+
40
43
  Performance/RedundantBlockCall:
41
44
  Enabled: false
@@ -0,0 +1,14 @@
1
+ scheduler:
2
+ type: ecs
3
+ region: ap-northeast-1
4
+ cluster: eagletmt
5
+ role: ecsServiceRole
6
+ autoscaling_group_for_oneshot: hako-batch-cluster
7
+ app:
8
+ image: ryotarai/hello-sinatra
9
+ memory: 128
10
+ cpu: 256
11
+ env:
12
+ PORT: 3000
13
+ MESSAGE: 'hello'
14
+ command: ['echo', 'heavy offline job']
@@ -43,7 +43,7 @@ module Hako
43
43
  end
44
44
  end
45
45
  unless variables.empty?
46
- raise ExpansionError.new("Unresolvable variables: #{variables.to_a}")
46
+ raise ExpansionError.new("Could not resolve embedded variables from $providers=#{@providers}: #{variables.to_a}")
47
47
  end
48
48
 
49
49
  expanded_env = {}
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'aws-sdk'
3
3
  require 'hako'
4
+ require 'hako/error'
4
5
  require 'hako/scheduler'
5
6
  require 'hako/schedulers/ecs_definition_comparator'
6
7
  require 'hako/schedulers/ecs_elb'
@@ -9,6 +10,9 @@ require 'hako/schedulers/ecs_autoscaling'
9
10
  module Hako
10
11
  module Schedulers
11
12
  class Ecs < Scheduler
13
+ class NoTasksStarted < Error
14
+ end
15
+
12
16
  DEFAULT_CLUSTER = 'default'
13
17
  DEFAULT_FRONT_PORT = 10000
14
18
 
@@ -27,6 +31,7 @@ module Hako
27
31
  end
28
32
  @started_at = nil
29
33
  @container_instance_arn = nil
34
+ @autoscaling_group_for_oneshot = options.fetch('autoscaling_group_for_oneshot', nil)
30
35
  end
31
36
 
32
37
  # @param [Hash<String, Container>] containers
@@ -450,9 +455,21 @@ module Hako
450
455
  Hako.logger.error("#{failure.arn} #{failure.reason}")
451
456
  end
452
457
  if result.tasks.empty?
453
- raise 'No tasks started'
458
+ raise NoTasksStarted.new('No tasks started')
454
459
  end
455
460
  result.tasks[0]
461
+ rescue Aws::ECS::Errors::InvalidParameterException => e
462
+ if e.message == 'No Container Instances were found in your cluster.' && on_no_tasks_started(task_definition)
463
+ retry
464
+ else
465
+ raise e
466
+ end
467
+ rescue NoTasksStarted => e
468
+ if on_no_tasks_started(task_definition)
469
+ retry
470
+ else
471
+ raise e
472
+ end
456
473
  end
457
474
 
458
475
  # @return [Fixnum]
@@ -643,6 +660,64 @@ module Hako
643
660
 
644
661
  raise "Unable to find rollback target. #{task_definition.task_definition_arn} is INACTIVE?"
645
662
  end
663
+
664
+ # @param [Aws::ECS::Types::TaskDefinition] task_definition
665
+ # @return [Boolean] true if the capacity is reserved
666
+ def on_no_tasks_started(task_definition)
667
+ unless @autoscaling_group_for_oneshot
668
+ return false
669
+ end
670
+
671
+ autoscaling = Aws::AutoScaling::Client.new
672
+ loop do
673
+ asg = autoscaling.describe_auto_scaling_groups(auto_scaling_group_names: [@autoscaling_group_for_oneshot]).auto_scaling_groups[0]
674
+ unless asg
675
+ raise Error.new("AutoScaling Group '#{@autoscaling_group_for_oneshot}' does not exist")
676
+ end
677
+
678
+ container_instances = ecs_client.list_container_instances(cluster: @cluster).flat_map { |c| ecs_client.describe_container_instances(cluster: @cluster, container_instances: c.container_instance_arns).container_instances }
679
+ if has_capacity?(task_definition, container_instances)
680
+ Hako.logger.info("There's remaining capacity. Start retrying...")
681
+ return true
682
+ end
683
+
684
+ # Check autoscaling group health
685
+ current = asg.instances.count { |i| i.lifecycle_state == 'InService' }
686
+ if asg.desired_capacity != current
687
+ Hako.logger.debug("#{asg.auto_scaling_group_name} isn't in desired state. desired_capacity=#{asg.desired_capacity} in-service instances=#{current}")
688
+ sleep 1
689
+ next
690
+ end
691
+
692
+ # Check out-of-service instances
693
+ out_instances = asg.instances.map(&:instance_id)
694
+ container_instances.each do |ci|
695
+ out_instances.delete(ci.ec2_instance_id)
696
+ end
697
+ unless out_instances.empty?
698
+ Hako.logger.debug("There's instances that is running but not registered as container instances: #{out_instances}")
699
+ sleep 1
700
+ next
701
+ end
702
+
703
+ # Scale out
704
+ desired = current + 1
705
+ Hako.logger.info("Increment desired_capacity of #{asg.auto_scaling_group_name} from #{current} to #{desired}")
706
+ autoscaling.set_desired_capacity(auto_scaling_group_name: asg.auto_scaling_group_name, desired_capacity: desired)
707
+ end
708
+ end
709
+
710
+ # @param [Aws::ECS::Types::TaskDefinition] task_definition
711
+ # @param [Array<Aws::ECS::Types::ContainerInstance>] container_instances
712
+ # @return [Boolean]
713
+ def has_capacity?(task_definition, container_instances)
714
+ required_cpu, required_memory = task_definition.container_definitions.inject([0, 0]) { |(cpu, memory), d| [cpu + d.cpu, memory + d.memory] }
715
+ container_instances.any? do |ci|
716
+ cpu = ci.remaining_resources.find { |r| r.name == 'CPU' }.integer_value
717
+ memory = ci.remaining_resources.find { |r| r.name == 'MEMORY' }.integer_value
718
+ required_cpu < cpu && required_memory < memory
719
+ end
720
+ end
646
721
  end
647
722
  end
648
723
  end
data/lib/hako/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Hako
3
- VERSION = '0.18.1'
3
+ VERSION = '0.19.0'
4
4
  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.18.1
4
+ version: 0.19.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-08-02 00:00:00.000000000 Z
11
+ date: 2016-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -114,6 +114,7 @@ files:
114
114
  - bin/console
115
115
  - bin/setup
116
116
  - examples/front.yml
117
+ - examples/hello-autoscaling-group.yml
117
118
  - examples/hello-autoscaling.yml
118
119
  - examples/hello-lb.yml
119
120
  - examples/hello.env