hako 0.18.1 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/examples/hello-autoscaling-group.yml +14 -0
- data/lib/hako/env_expander.rb +1 -1
- data/lib/hako/schedulers/ecs.rb +76 -1
- data/lib/hako/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45f04940c4d0ff4ff960ea9619a525085aba342d
|
4
|
+
data.tar.gz: 67610aa17c6877ed84599ecd1be143c4c39d6a03
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92407332bca376bcba4e54248842d685568410cf92c4cb19aa7be30d1353a266e549db55da77b3f12c1cc7b5161a78de6edc0e0fc33a2f322822bb937870dbd2
|
7
|
+
data.tar.gz: 2599f5133827e410fb4cc2d068fe7fc09e52b654022f140549ab34abc620cade3bc111dae8c8bb861ec60c89768dc9e6e57eb13b89b8dc929dc50e8a0746d7e9
|
data/.rubocop.yml
CHANGED
@@ -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']
|
data/lib/hako/env_expander.rb
CHANGED
@@ -43,7 +43,7 @@ module Hako
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
unless variables.empty?
|
46
|
-
raise ExpansionError.new("
|
46
|
+
raise ExpansionError.new("Could not resolve embedded variables from $providers=#{@providers}: #{variables.to_a}")
|
47
47
|
end
|
48
48
|
|
49
49
|
expanded_env = {}
|
data/lib/hako/schedulers/ecs.rb
CHANGED
@@ -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
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
|
+
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-
|
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
|