ecs-easy-cluster 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +72 -0
- data/Rakefile +2 -0
- data/ecs-easy-cluster.gemspec +25 -0
- data/lib/ecs/easy/cluster.rb +38 -0
- data/lib/ecs/easy/cluster/base.rb +168 -0
- data/lib/ecs/easy/cluster/config/cloudformation_template.json +517 -0
- data/lib/ecs/easy/cluster/config/ec2_profile.json +37 -0
- data/lib/ecs/easy/cluster/mem_scale.rb +61 -0
- data/lib/ecs/easy/cluster/version.rb +7 -0
- data/lib/ecs/easy/configure.rb +33 -0
- data/lib/ecs/easy/instance.rb +63 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6deb5e083c0a0a6c90456bb28a6538ecb009b87a
|
4
|
+
data.tar.gz: d14a41c0c460cef5c5cb1c466b36ff4352d27a34
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 332a2068fbfe7169e026d490182b22dbef5fc70c45211660054585f33abe92254dbe10cca8493761da0733b5fb3aa8cd90613317441acf8234592c0f82cb58ca
|
7
|
+
data.tar.gz: 4fbdfe7f61a815c8339b695a58fa19edb20f802160dd581695441587fd2e9a3c1d99258f28debe10a80b757ad1abf79be6e42687026cd7ada9e62691b65e4fae
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 metheglin
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Ecs::Easy::Cluster
|
2
|
+
|
3
|
+
ecs-easy-cluster is a easy clustering tool for AWS ECS.
|
4
|
+
This tool focuses on executing tiny scripts, jobs or batches without considering the running environment.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'ecs-easy-cluster'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install ecs-easy-cluster
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
```
|
23
|
+
require "ecs-easy-cluster"
|
24
|
+
|
25
|
+
#
|
26
|
+
# Set basic info: credentials and region
|
27
|
+
#
|
28
|
+
configure = Ecs::Easy::Configure.new do |c|
|
29
|
+
c.profile = "your-aws-profile"
|
30
|
+
c.region = "your-aws-region"
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Define ec2 instance profile
|
35
|
+
#
|
36
|
+
instance = Ecs::Easy::Instance.new do |i|
|
37
|
+
i.type = "t2.nano"
|
38
|
+
i.keypair = "your-keypair"
|
39
|
+
i.azs = "ap-northeast-1a,ap-northeast-1c"
|
40
|
+
i.subnets = "subnet-00000000,subnet-11111111"
|
41
|
+
i.vpc = "vpc-00000000"
|
42
|
+
i.image_id = "ami-00000000"
|
43
|
+
i.security_group = "sg-00000000"
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Define the scale setting of your cluster
|
48
|
+
#
|
49
|
+
cluster = Ecs::Easy::Cluster::MemScale.new("cluster-name", configure) do |c|
|
50
|
+
c.max_instances = 2
|
51
|
+
c.min_instances = 1
|
52
|
+
c.instance = instance
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Make your task running
|
57
|
+
#
|
58
|
+
cluster.make_task_running!("your-task-definition-name")
|
59
|
+
|
60
|
+
#
|
61
|
+
# Shrink your scaled instances
|
62
|
+
# ------------
|
63
|
+
# !! CAUTION !!
|
64
|
+
# This command terminates redundant instances even if some tasks are running on them.
|
65
|
+
#
|
66
|
+
cluster.shrink!
|
67
|
+
```
|
68
|
+
|
69
|
+
## Memo
|
70
|
+
|
71
|
+
ecs/easy/cluster/cloudformation_template.json.erb is refered from the link below.
|
72
|
+
https://github.com/aws/amazon-ecs-cli/blob/master/ecs-cli/modules/aws/clients/cloudformation/template.go
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ecs/easy/cluster/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ecs-easy-cluster"
|
8
|
+
spec.version = Ecs::Easy::Cluster::VERSION
|
9
|
+
spec.authors = ["metheglin"]
|
10
|
+
spec.email = ["pigmybank@gmail.com"]
|
11
|
+
spec.summary = %q{easy-to-use AWS ECS Cluster.}
|
12
|
+
spec.description = %q{easy-to-use AWS ECS Cluster.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "aws-sdk", "~> 2.4"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "ecs/easy/cluster/version"
|
2
|
+
|
3
|
+
require "ostruct"
|
4
|
+
require "aws-sdk"
|
5
|
+
|
6
|
+
require "ecs/easy/configure"
|
7
|
+
require "ecs/easy/instance"
|
8
|
+
|
9
|
+
# configure = Ecs::Easy::Configure.new do |c|
|
10
|
+
# c.profile = ""
|
11
|
+
# c.region = ""
|
12
|
+
# end
|
13
|
+
# instance = Ecs::Easy::Instance.new do |i|
|
14
|
+
# i.instance_type = "t2.nano"
|
15
|
+
# i.keypair = "your-keypair"
|
16
|
+
# i.azs = "ap-northeast-1a,ap-northeast-1c"
|
17
|
+
# i.subnets = "subnet-00000000,subnet-11111111"
|
18
|
+
# i.vpc = "vpc-00000000"
|
19
|
+
# i.image_id = "ami-00000000"
|
20
|
+
# i.security_group = "sg-00000000"
|
21
|
+
# end
|
22
|
+
# cluster = Ecs::Easy::Cluster::MemScale.new("cluster-name", configure) do |c|
|
23
|
+
# c.max_instances = 2
|
24
|
+
# c.min_instances = 1
|
25
|
+
# c.instance = instance
|
26
|
+
# end
|
27
|
+
# cluster.make_task_running!("your-task-definition-name")
|
28
|
+
|
29
|
+
module Ecs
|
30
|
+
module Easy
|
31
|
+
module Cluster
|
32
|
+
|
33
|
+
autoload :Base, File.expand_path("../cluster/base.rb", __FILE__)
|
34
|
+
autoload :MemScale, File.expand_path("../cluster/mem_scale.rb", __FILE__)
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
module Ecs::Easy::Cluster
|
2
|
+
class Base
|
3
|
+
|
4
|
+
TEMPLATE_PATH = File.expand_path("../config/cloudFormation_template.json", __FILE__)
|
5
|
+
TEMPLATE_BODY = File.read( TEMPLATE_PATH )
|
6
|
+
|
7
|
+
attr_reader :name, :configure, :ecs_client, :stack_name, :cfn_client
|
8
|
+
attr_accessor :instance, :min_instances, :max_instances
|
9
|
+
|
10
|
+
def initialize( name, configure )
|
11
|
+
@name = name
|
12
|
+
@configure = configure
|
13
|
+
@ecs_client = Aws::ECS::Client.new(
|
14
|
+
region: configure.region,
|
15
|
+
credentials: configure.credentials
|
16
|
+
)
|
17
|
+
@stack_name = configure.cfn_stack_name_prefix + name
|
18
|
+
@cfn_client = Aws::CloudFormation::Client.new(
|
19
|
+
region: configure.region,
|
20
|
+
credentials: configure.credentials
|
21
|
+
)
|
22
|
+
|
23
|
+
# default
|
24
|
+
@min_instances = 1
|
25
|
+
@max_instances = 1
|
26
|
+
|
27
|
+
yield( self ) if block_given?
|
28
|
+
end
|
29
|
+
|
30
|
+
# Check if the cluster exists
|
31
|
+
# A cluster existence should be decided as cloudformation stack existence
|
32
|
+
def exists?
|
33
|
+
res = cfn_client.describe_stacks( stack_name: stack_name )
|
34
|
+
return res.stacks.length > 0
|
35
|
+
rescue => e
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
|
39
|
+
# Check if all the container instances on the cluster are ready
|
40
|
+
def ready?
|
41
|
+
return false unless exists?
|
42
|
+
instance_arns = ecs_client.list_container_instances(cluster: name).container_instance_arns
|
43
|
+
return false if instance_arns.nil? or instance_arns.empty?
|
44
|
+
res = ecs_client.describe_container_instances(
|
45
|
+
cluster: name,
|
46
|
+
container_instances: instance_arns
|
47
|
+
)
|
48
|
+
# unless res.respond_to?("container_instances") or
|
49
|
+
# res.container_instances.nil?
|
50
|
+
# return false
|
51
|
+
# end
|
52
|
+
res.container_instances.all? {|i| i.status == "ACTIVE" }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Check if the task exists on the cluster
|
56
|
+
def task_exists?( task )
|
57
|
+
task_arns = ecs_client.list_tasks(cluster: name).task_arns
|
58
|
+
task_arns.include?( task )
|
59
|
+
end
|
60
|
+
|
61
|
+
def num_instances
|
62
|
+
ecs_client.list_container_instances(cluster: name).container_instance_arns.length
|
63
|
+
end
|
64
|
+
|
65
|
+
# Wait until all the container instances ready
|
66
|
+
def wait_until_ready( retry_count=30, sleep_sec=2 )
|
67
|
+
retry_count.times do
|
68
|
+
break if ready?
|
69
|
+
sleep sleep_sec
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def wait_until_task_running( arn )
|
74
|
+
raise "Task Not Found. Possibly the task is already stopped." unless task_exists?( arn )
|
75
|
+
ecs_client.wait_until(:tasks_running, tasks: [arn])
|
76
|
+
end
|
77
|
+
|
78
|
+
def run_task!( task_definition, overrides={} )
|
79
|
+
res = ecs_client.run_task(
|
80
|
+
cluster: name,
|
81
|
+
task_definition: task_definition,
|
82
|
+
overrides: overrides
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
def up!
|
87
|
+
unless exists?
|
88
|
+
ecs_client.create_cluster( cluster_name: name )
|
89
|
+
|
90
|
+
params = instance.cfn_parameters( name, "AsgMaxSize" => min_instances.to_s)
|
91
|
+
cfn_client.create_stack(
|
92
|
+
stack_name: stack_name,
|
93
|
+
template_body: TEMPLATE_BODY,
|
94
|
+
parameters: params,
|
95
|
+
capabilities: ["CAPABILITY_IAM"],
|
96
|
+
on_failure: "DELETE",
|
97
|
+
)
|
98
|
+
cfn_client.wait_until(
|
99
|
+
:stack_create_complete,
|
100
|
+
stack_name: stack_name
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
return exists?
|
105
|
+
end
|
106
|
+
|
107
|
+
def destroy!
|
108
|
+
cfn_client.delete_stack(stack_name: stack_name)
|
109
|
+
cfn_client.wait_until(
|
110
|
+
:stack_delete_complete,
|
111
|
+
stack_name: stack_name
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
def scale!
|
116
|
+
size = (num_instances+1 <= max_instances) ? num_instances+1 : max_instances
|
117
|
+
|
118
|
+
params = instance.cfn_parameters( name, "AsgMaxSize" => size.to_s)
|
119
|
+
cfn_client.update_stack(
|
120
|
+
stack_name: stack_name,
|
121
|
+
template_body: TEMPLATE_BODY,
|
122
|
+
parameters: params,
|
123
|
+
capabilities: ["CAPABILITY_IAM"],
|
124
|
+
)
|
125
|
+
cfn_client.wait_until(
|
126
|
+
:stack_update_complete,
|
127
|
+
stack_name: stack_name
|
128
|
+
)
|
129
|
+
|
130
|
+
# Check the scale completion every 2 seconds until max 30 times
|
131
|
+
30.times do
|
132
|
+
return true if num_instances == size
|
133
|
+
sleep 2
|
134
|
+
end
|
135
|
+
|
136
|
+
return false
|
137
|
+
rescue Aws::Waiters::Errors::WaiterFailed => e
|
138
|
+
puts e
|
139
|
+
end
|
140
|
+
|
141
|
+
# Deregister some container instances if they are idling
|
142
|
+
# TODO: Support idling check of container instances
|
143
|
+
def shrink!
|
144
|
+
params = instance.cfn_parameters( name, "AsgMaxSize" => min_instances.to_s)
|
145
|
+
cfn_client.update_stack(
|
146
|
+
stack_name: stack_name,
|
147
|
+
template_body: TEMPLATE_BODY,
|
148
|
+
parameters: params,
|
149
|
+
capabilities: ["CAPABILITY_IAM"],
|
150
|
+
)
|
151
|
+
cfn_client.wait_until(
|
152
|
+
:stack_update_complete,
|
153
|
+
stack_name: stack_name
|
154
|
+
)
|
155
|
+
rescue Aws::Waiters::Errors::WaiterFailed => e
|
156
|
+
puts e
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
def fail_reason( failures )
|
161
|
+
reasons = failures.map {|f| f.reason }
|
162
|
+
if reasons.include?( "RESOURCE:MEMORY" )
|
163
|
+
return "RESOURCE:MEMORY"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,517 @@
|
|
1
|
+
{
|
2
|
+
"AWSTemplateFormatVersion": "2010-09-09",
|
3
|
+
"Description": "AWS CloudFormation template to create resources required to run tasks on an ECS cluster.",
|
4
|
+
"Mappings": {
|
5
|
+
"VpcCidrs": {
|
6
|
+
"vpc": {"cidr" : "10.0.0.0/16"},
|
7
|
+
"pubsubnet1": {"cidr" : "10.0.0.0/24"},
|
8
|
+
"pubsubnet2": {"cidr" :"10.0.1.0/24"}
|
9
|
+
}
|
10
|
+
},
|
11
|
+
"Parameters": {
|
12
|
+
"EcsAmiId": {
|
13
|
+
"Type": "String",
|
14
|
+
"Description": "ECS EC2 AMI id",
|
15
|
+
"Default": ""
|
16
|
+
},
|
17
|
+
"EcsInstanceType": {
|
18
|
+
"Type": "String",
|
19
|
+
"Description": "ECS EC2 instance type",
|
20
|
+
"Default": "t2.micro",
|
21
|
+
"AllowedValues": [
|
22
|
+
"t2.nano",
|
23
|
+
"t2.micro",
|
24
|
+
"t2.small",
|
25
|
+
"t2.medium",
|
26
|
+
"t2.large",
|
27
|
+
"m3.medium",
|
28
|
+
"m3.large",
|
29
|
+
"m3.xlarge",
|
30
|
+
"m3.2xlarge",
|
31
|
+
"m4.large",
|
32
|
+
"m4.xlarge",
|
33
|
+
"m4.2xlarge",
|
34
|
+
"m4.4xlarge",
|
35
|
+
"m4.10xlarge",
|
36
|
+
"c4.large",
|
37
|
+
"c4.xlarge",
|
38
|
+
"c4.2xlarge",
|
39
|
+
"c4.4xlarge",
|
40
|
+
"c4.8xlarge",
|
41
|
+
"c3.large",
|
42
|
+
"c3.xlarge",
|
43
|
+
"c3.2xlarge",
|
44
|
+
"c3.4xlarge",
|
45
|
+
"c3.8xlarge",
|
46
|
+
"r3.large",
|
47
|
+
"r3.xlarge",
|
48
|
+
"r3.2xlarge",
|
49
|
+
"r3.4xlarge",
|
50
|
+
"r3.8xlarge",
|
51
|
+
"i2.xlarge",
|
52
|
+
"i2.2xlarge",
|
53
|
+
"i2.4xlarge",
|
54
|
+
"i2.8xlarge",
|
55
|
+
"g2.2xlarge",
|
56
|
+
"g2.8xlarge",
|
57
|
+
"d2.xlarge",
|
58
|
+
"d2.2xlarge",
|
59
|
+
"d2.4xlarge",
|
60
|
+
"d2.8xlarge"
|
61
|
+
],
|
62
|
+
"ConstraintDescription": "must be a valid EC2 instance type."
|
63
|
+
},
|
64
|
+
"KeyName": {
|
65
|
+
"Type": "AWS::EC2::KeyPair::KeyName",
|
66
|
+
"Description": "Optional - Name of an existing EC2 KeyPair to enable SSH access to the ECS instances",
|
67
|
+
"Default": ""
|
68
|
+
},
|
69
|
+
"VpcId": {
|
70
|
+
"Type": "String",
|
71
|
+
"Description": "Optional - VPC Id of existing VPC. Leave blank to have a new VPC created",
|
72
|
+
"Default": "",
|
73
|
+
"AllowedPattern": "^(?:vpc-[0-9a-f]{8}|)$",
|
74
|
+
"ConstraintDescription": "VPC Id must begin with 'vpc-' or leave blank to have a new VPC created"
|
75
|
+
},
|
76
|
+
"SubnetIds": {
|
77
|
+
"Type": "CommaDelimitedList",
|
78
|
+
"Description": "Optional - Comma separated list of two (2) existing VPC Subnet Ids where ECS instances will run. Required if setting VpcId.",
|
79
|
+
"Default": ""
|
80
|
+
},
|
81
|
+
"AsgMaxSize": {
|
82
|
+
"Type": "Number",
|
83
|
+
"Description": "Maximum size and initial Desired Capacity of ECS Auto Scaling Group",
|
84
|
+
"Default": "1"
|
85
|
+
},
|
86
|
+
"SecurityGroup": {
|
87
|
+
"Type": "String",
|
88
|
+
"Description": "Optional - Existing security group to associate the container instances. Creates one by default.",
|
89
|
+
"Default": ""
|
90
|
+
},
|
91
|
+
"SourceCidr": {
|
92
|
+
"Type": "String",
|
93
|
+
"Description": "Optional - CIDR/IP range for EcsPort - defaults to 0.0.0.0/0",
|
94
|
+
"Default": "0.0.0.0/0"
|
95
|
+
},
|
96
|
+
"EcsPort" : {
|
97
|
+
"Type" : "String",
|
98
|
+
"Description" : "Optional - Security Group port to open on ECS instances - defaults to port 80",
|
99
|
+
"Default" : "80"
|
100
|
+
},
|
101
|
+
"VpcAvailabilityZones": {
|
102
|
+
"Type": "CommaDelimitedList",
|
103
|
+
"Description": "Optional - Comma-delimited list of VPC availability zones in which to create subnets. Required if setting VpcId.",
|
104
|
+
"Default": ""
|
105
|
+
},
|
106
|
+
"EcsCluster" : {
|
107
|
+
"Type" : "String",
|
108
|
+
"Description" : "ECS Cluster Name",
|
109
|
+
"Default" : "default"
|
110
|
+
}
|
111
|
+
},
|
112
|
+
"Conditions": {
|
113
|
+
"CreateVpcResources": {
|
114
|
+
"Fn::Equals": [
|
115
|
+
{
|
116
|
+
"Ref": "VpcId"
|
117
|
+
},
|
118
|
+
""
|
119
|
+
]
|
120
|
+
},
|
121
|
+
"CreateSecurityGroup": {
|
122
|
+
"Fn::Equals": [
|
123
|
+
{
|
124
|
+
"Ref": "SecurityGroup"
|
125
|
+
},
|
126
|
+
""
|
127
|
+
]
|
128
|
+
},
|
129
|
+
"CreateEC2LCWithKeyPair": {
|
130
|
+
"Fn::Not": [
|
131
|
+
{
|
132
|
+
"Fn::Equals": [
|
133
|
+
{
|
134
|
+
"Ref": "KeyName"
|
135
|
+
},
|
136
|
+
""
|
137
|
+
]
|
138
|
+
}
|
139
|
+
]
|
140
|
+
},
|
141
|
+
"CreateEC2LCWithoutKeyPair": {
|
142
|
+
"Fn::Equals": [
|
143
|
+
{
|
144
|
+
"Ref": "KeyName"
|
145
|
+
},
|
146
|
+
""
|
147
|
+
]
|
148
|
+
},
|
149
|
+
"UseSpecifiedVpcAvailabilityZones": {
|
150
|
+
"Fn::Not": [
|
151
|
+
{
|
152
|
+
"Fn::Equals": [
|
153
|
+
{
|
154
|
+
"Fn::Join": [
|
155
|
+
"",
|
156
|
+
{
|
157
|
+
"Ref": "VpcAvailabilityZones"
|
158
|
+
}
|
159
|
+
]
|
160
|
+
},
|
161
|
+
""
|
162
|
+
]
|
163
|
+
}
|
164
|
+
]
|
165
|
+
}
|
166
|
+
},
|
167
|
+
"Resources": {
|
168
|
+
"Vpc": {
|
169
|
+
"Condition": "CreateVpcResources",
|
170
|
+
"Type": "AWS::EC2::VPC",
|
171
|
+
"Properties": {
|
172
|
+
"CidrBlock": {
|
173
|
+
"Fn::FindInMap": ["VpcCidrs", "vpc", "cidr"]
|
174
|
+
}
|
175
|
+
}
|
176
|
+
},
|
177
|
+
"PubSubnetAz1": {
|
178
|
+
"Condition": "CreateVpcResources",
|
179
|
+
"Type": "AWS::EC2::Subnet",
|
180
|
+
"Properties": {
|
181
|
+
"VpcId": {
|
182
|
+
"Ref": "Vpc"
|
183
|
+
},
|
184
|
+
"CidrBlock": {
|
185
|
+
"Fn::FindInMap": ["VpcCidrs", "pubsubnet1", "cidr"]
|
186
|
+
},
|
187
|
+
"AvailabilityZone": {
|
188
|
+
"Fn::If": [
|
189
|
+
"UseSpecifiedVpcAvailabilityZones",
|
190
|
+
{
|
191
|
+
"Fn::Select": [
|
192
|
+
"0",
|
193
|
+
{
|
194
|
+
"Ref": "VpcAvailabilityZones"
|
195
|
+
}
|
196
|
+
]
|
197
|
+
},
|
198
|
+
{
|
199
|
+
"Fn::Select": [
|
200
|
+
"0",
|
201
|
+
{
|
202
|
+
"Fn::GetAZs": {
|
203
|
+
"Ref": "AWS::Region"
|
204
|
+
}
|
205
|
+
}
|
206
|
+
]
|
207
|
+
}
|
208
|
+
]
|
209
|
+
}
|
210
|
+
}
|
211
|
+
},
|
212
|
+
"PubSubnetAz2": {
|
213
|
+
"Condition": "CreateVpcResources",
|
214
|
+
"Type": "AWS::EC2::Subnet",
|
215
|
+
"Properties": {
|
216
|
+
"VpcId": {
|
217
|
+
"Ref": "Vpc"
|
218
|
+
},
|
219
|
+
"CidrBlock": {
|
220
|
+
"Fn::FindInMap": ["VpcCidrs", "pubsubnet2", "cidr"]
|
221
|
+
},
|
222
|
+
"AvailabilityZone": {
|
223
|
+
"Fn::If": [
|
224
|
+
"UseSpecifiedVpcAvailabilityZones",
|
225
|
+
{
|
226
|
+
"Fn::Select": [
|
227
|
+
"1",
|
228
|
+
{
|
229
|
+
"Ref": "VpcAvailabilityZones"
|
230
|
+
}
|
231
|
+
]
|
232
|
+
},
|
233
|
+
{
|
234
|
+
"Fn::Select": [
|
235
|
+
"1",
|
236
|
+
{
|
237
|
+
"Fn::GetAZs": {
|
238
|
+
"Ref": "AWS::Region"
|
239
|
+
}
|
240
|
+
}
|
241
|
+
]
|
242
|
+
}
|
243
|
+
]
|
244
|
+
}
|
245
|
+
}
|
246
|
+
},
|
247
|
+
"InternetGateway": {
|
248
|
+
"Condition": "CreateVpcResources",
|
249
|
+
"Type": "AWS::EC2::InternetGateway"
|
250
|
+
},
|
251
|
+
"AttachGateway": {
|
252
|
+
"Condition": "CreateVpcResources",
|
253
|
+
"Type": "AWS::EC2::VPCGatewayAttachment",
|
254
|
+
"Properties": {
|
255
|
+
"VpcId": {
|
256
|
+
"Ref": "Vpc"
|
257
|
+
},
|
258
|
+
"InternetGatewayId": {
|
259
|
+
"Ref": "InternetGateway"
|
260
|
+
}
|
261
|
+
}
|
262
|
+
},
|
263
|
+
"RouteViaIgw": {
|
264
|
+
"Condition": "CreateVpcResources",
|
265
|
+
"Type": "AWS::EC2::RouteTable",
|
266
|
+
"Properties": {
|
267
|
+
"VpcId": {
|
268
|
+
"Ref": "Vpc"
|
269
|
+
}
|
270
|
+
}
|
271
|
+
},
|
272
|
+
"PublicRouteViaIgw": {
|
273
|
+
"Condition": "CreateVpcResources",
|
274
|
+
"DependsOn": "AttachGateway",
|
275
|
+
"Type": "AWS::EC2::Route",
|
276
|
+
"Properties": {
|
277
|
+
"RouteTableId": {
|
278
|
+
"Ref": "RouteViaIgw"
|
279
|
+
},
|
280
|
+
"DestinationCidrBlock": "0.0.0.0/0",
|
281
|
+
"GatewayId": {
|
282
|
+
"Ref": "InternetGateway"
|
283
|
+
}
|
284
|
+
}
|
285
|
+
},
|
286
|
+
"PubSubnet1RouteTableAssociation": {
|
287
|
+
"Condition": "CreateVpcResources",
|
288
|
+
"Type": "AWS::EC2::SubnetRouteTableAssociation",
|
289
|
+
"Properties": {
|
290
|
+
"SubnetId": {
|
291
|
+
"Ref": "PubSubnetAz1"
|
292
|
+
},
|
293
|
+
"RouteTableId": {
|
294
|
+
"Ref": "RouteViaIgw"
|
295
|
+
}
|
296
|
+
}
|
297
|
+
},
|
298
|
+
"PubSubnet2RouteTableAssociation": {
|
299
|
+
"Condition": "CreateVpcResources",
|
300
|
+
"Type": "AWS::EC2::SubnetRouteTableAssociation",
|
301
|
+
"Properties": {
|
302
|
+
"SubnetId": {
|
303
|
+
"Ref": "PubSubnetAz2"
|
304
|
+
},
|
305
|
+
"RouteTableId": {
|
306
|
+
"Ref": "RouteViaIgw"
|
307
|
+
}
|
308
|
+
}
|
309
|
+
},
|
310
|
+
"EcsSecurityGroup": {
|
311
|
+
"Condition": "CreateSecurityGroup",
|
312
|
+
"Type": "AWS::EC2::SecurityGroup",
|
313
|
+
"Properties": {
|
314
|
+
"GroupDescription": "ECS Allowed Ports",
|
315
|
+
"VpcId": {
|
316
|
+
"Fn::If": [
|
317
|
+
"CreateVpcResources",
|
318
|
+
{
|
319
|
+
"Ref": "Vpc"
|
320
|
+
},
|
321
|
+
{
|
322
|
+
"Ref": "VpcId"
|
323
|
+
}
|
324
|
+
]
|
325
|
+
},
|
326
|
+
"SecurityGroupIngress" : [ {
|
327
|
+
"IpProtocol" : "tcp",
|
328
|
+
"FromPort" : { "Ref" : "EcsPort" },
|
329
|
+
"ToPort" : { "Ref" : "EcsPort" },
|
330
|
+
"CidrIp" : { "Ref" : "SourceCidr" }
|
331
|
+
} ]
|
332
|
+
}
|
333
|
+
},
|
334
|
+
"EcsInstancePolicy": {
|
335
|
+
"Type": "AWS::IAM::Role",
|
336
|
+
"Properties": {
|
337
|
+
"AssumeRolePolicyDocument": {
|
338
|
+
"Version": "2012-10-17",
|
339
|
+
"Statement": [
|
340
|
+
{
|
341
|
+
"Effect": "Allow",
|
342
|
+
"Principal": {
|
343
|
+
"Service": [
|
344
|
+
"ec2.amazonaws.com"
|
345
|
+
]
|
346
|
+
},
|
347
|
+
"Action": [
|
348
|
+
"sts:AssumeRole"
|
349
|
+
]
|
350
|
+
}
|
351
|
+
]
|
352
|
+
},
|
353
|
+
"Path": "/",
|
354
|
+
"ManagedPolicyArns": [
|
355
|
+
"arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
|
356
|
+
]
|
357
|
+
}
|
358
|
+
},
|
359
|
+
"EcsInstanceProfile": {
|
360
|
+
"Type": "AWS::IAM::InstanceProfile",
|
361
|
+
"Properties": {
|
362
|
+
"Path": "/",
|
363
|
+
"Roles": [
|
364
|
+
{
|
365
|
+
"Ref": "EcsInstancePolicy"
|
366
|
+
}
|
367
|
+
]
|
368
|
+
}
|
369
|
+
},
|
370
|
+
"EcsInstanceLc": {
|
371
|
+
"Condition": "CreateEC2LCWithKeyPair",
|
372
|
+
"Type": "AWS::AutoScaling::LaunchConfiguration",
|
373
|
+
"Properties": {
|
374
|
+
"ImageId": { "Ref" : "EcsAmiId" },
|
375
|
+
"InstanceType": {
|
376
|
+
"Ref": "EcsInstanceType"
|
377
|
+
},
|
378
|
+
"AssociatePublicIpAddress": true,
|
379
|
+
"IamInstanceProfile": {
|
380
|
+
"Ref": "EcsInstanceProfile"
|
381
|
+
},
|
382
|
+
"KeyName": {
|
383
|
+
"Ref": "KeyName"
|
384
|
+
},
|
385
|
+
"SecurityGroups": {
|
386
|
+
"Fn::If": [
|
387
|
+
"CreateSecurityGroup",
|
388
|
+
[ {
|
389
|
+
"Ref": "EcsSecurityGroup"
|
390
|
+
} ],
|
391
|
+
[ {
|
392
|
+
"Ref": "SecurityGroup"
|
393
|
+
} ]
|
394
|
+
]
|
395
|
+
},
|
396
|
+
"UserData": {
|
397
|
+
"Fn::Base64": {
|
398
|
+
"Fn::Join": [
|
399
|
+
"",
|
400
|
+
[
|
401
|
+
"#!/bin/bash\n",
|
402
|
+
"echo ECS_CLUSTER=",
|
403
|
+
{
|
404
|
+
"Ref": "EcsCluster"
|
405
|
+
},
|
406
|
+
" >> /etc/ecs/ecs.config\n"
|
407
|
+
]
|
408
|
+
]
|
409
|
+
}
|
410
|
+
}
|
411
|
+
}
|
412
|
+
},
|
413
|
+
"EcsInstanceLcWithoutKeyPair": {
|
414
|
+
"Condition": "CreateEC2LCWithoutKeyPair",
|
415
|
+
"Type": "AWS::AutoScaling::LaunchConfiguration",
|
416
|
+
"Properties": {
|
417
|
+
"ImageId": { "Ref" : "EcsAmiId" },
|
418
|
+
"InstanceType": {
|
419
|
+
"Ref": "EcsInstanceType"
|
420
|
+
},
|
421
|
+
"AssociatePublicIpAddress": true,
|
422
|
+
"IamInstanceProfile": {
|
423
|
+
"Ref": "EcsInstanceProfile"
|
424
|
+
},
|
425
|
+
"SecurityGroups": {
|
426
|
+
"Fn::If": [
|
427
|
+
"CreateSecurityGroup",
|
428
|
+
[ {
|
429
|
+
"Ref": "EcsSecurityGroup"
|
430
|
+
} ],
|
431
|
+
[ {
|
432
|
+
"Ref": "SecurityGroup"
|
433
|
+
} ]
|
434
|
+
]
|
435
|
+
},
|
436
|
+
"UserData": {
|
437
|
+
"Fn::Base64": {
|
438
|
+
"Fn::Join": [
|
439
|
+
"",
|
440
|
+
[
|
441
|
+
"#!/bin/bash\n",
|
442
|
+
"echo ECS_CLUSTER=",
|
443
|
+
{
|
444
|
+
"Ref": "EcsCluster"
|
445
|
+
},
|
446
|
+
" >> /etc/ecs/ecs.config\n"
|
447
|
+
]
|
448
|
+
]
|
449
|
+
}
|
450
|
+
}
|
451
|
+
}
|
452
|
+
},
|
453
|
+
"EcsInstanceAsg": {
|
454
|
+
"Type": "AWS::AutoScaling::AutoScalingGroup",
|
455
|
+
"Properties": {
|
456
|
+
"VPCZoneIdentifier": {
|
457
|
+
"Fn::If": [
|
458
|
+
"CreateVpcResources",
|
459
|
+
[
|
460
|
+
{
|
461
|
+
"Fn::Join": [
|
462
|
+
",",
|
463
|
+
[
|
464
|
+
{
|
465
|
+
"Ref": "PubSubnetAz1"
|
466
|
+
},
|
467
|
+
{
|
468
|
+
"Ref": "PubSubnetAz2"
|
469
|
+
}
|
470
|
+
]
|
471
|
+
]
|
472
|
+
}
|
473
|
+
],
|
474
|
+
{
|
475
|
+
"Ref": "SubnetIds"
|
476
|
+
}
|
477
|
+
]
|
478
|
+
},
|
479
|
+
"LaunchConfigurationName": {
|
480
|
+
"Fn::If": [
|
481
|
+
"CreateEC2LCWithKeyPair",
|
482
|
+
{
|
483
|
+
"Ref": "EcsInstanceLc"
|
484
|
+
},
|
485
|
+
{
|
486
|
+
"Ref": "EcsInstanceLcWithoutKeyPair"
|
487
|
+
}
|
488
|
+
]
|
489
|
+
},
|
490
|
+
"MinSize": "1",
|
491
|
+
"MaxSize": {
|
492
|
+
"Ref": "AsgMaxSize"
|
493
|
+
},
|
494
|
+
"DesiredCapacity": {
|
495
|
+
"Ref": "AsgMaxSize"
|
496
|
+
},
|
497
|
+
"Tags": [
|
498
|
+
{
|
499
|
+
"Key": "Name",
|
500
|
+
"Value": {
|
501
|
+
"Fn::Join": [
|
502
|
+
"",
|
503
|
+
[
|
504
|
+
"ECS Instance - ",
|
505
|
+
{
|
506
|
+
"Ref": "AWS::StackName"
|
507
|
+
}
|
508
|
+
]
|
509
|
+
]
|
510
|
+
},
|
511
|
+
"PropagateAtLaunch": "true"
|
512
|
+
}
|
513
|
+
]
|
514
|
+
}
|
515
|
+
}
|
516
|
+
}
|
517
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
{
|
2
|
+
"t2.nano": { "mem": 0.5 },
|
3
|
+
"t2.micro": { "mem": 1 },
|
4
|
+
"t2.small": { "mem": 2 },
|
5
|
+
"t2.medium": { "mem": 4 },
|
6
|
+
"t2.large": { "mem": 8 },
|
7
|
+
|
8
|
+
"m4.large": { "mem": 8 },
|
9
|
+
"m4.xlarge": { "mem": 16 },
|
10
|
+
"m4.2xlarge": { "mem": 32 },
|
11
|
+
"m4.4xlarge": { "mem": 64 },
|
12
|
+
"m4.10xlarge": { "mem": 160 },
|
13
|
+
|
14
|
+
"m3.medium": { "mem": 3.75 },
|
15
|
+
"m3.large": { "mem": 7.5 },
|
16
|
+
"m3.xlarge": { "mem": 15 },
|
17
|
+
"m3.2xlarge": { "mem": 30 },
|
18
|
+
|
19
|
+
"c4.large": { "mem": 3.75 },
|
20
|
+
"c4.xlarge": { "mem": 7.5 },
|
21
|
+
"c4.2xlarge": { "mem": 15 },
|
22
|
+
"c4.4xlarge": { "mem": 30 },
|
23
|
+
"c4.8xlarge": { "mem": 60 },
|
24
|
+
|
25
|
+
"c3.large": { "mem": 3.75 },
|
26
|
+
"c3.xlarge": { "mem": 7.5 },
|
27
|
+
"c3.2xlarge": { "mem": 15 },
|
28
|
+
"c3.4xlarge": { "mem": 30 },
|
29
|
+
"c3.8xlarge": { "mem": 60 },
|
30
|
+
|
31
|
+
"r3.large": { "mem": 15.25 },
|
32
|
+
"r3.xlarge": { "mem": 30.5 },
|
33
|
+
"r3.2xlarge": { "mem": 61 },
|
34
|
+
"r3.4xlarge": { "mem": 122 },
|
35
|
+
"r3.8xlarge": { "mem": 244 }
|
36
|
+
|
37
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Ecs::Easy::Cluster
|
2
|
+
class MemScale < Base
|
3
|
+
|
4
|
+
EC2_PROFILE_PATH = File.expand_path("../config/ec2_profile.json", __FILE__)
|
5
|
+
INSTANCE_TYPES = JSON.parse(File.read( EC2_PROFILE_PATH ))
|
6
|
+
|
7
|
+
def make_task_running!( task_definition, overrides={} )
|
8
|
+
unless exists?
|
9
|
+
unless up!
|
10
|
+
raise "Failed to create the new cluster. You should check the CloudFormation events."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
res = nil
|
15
|
+
3.times do
|
16
|
+
wait_until_ready
|
17
|
+
res = run_task!( task_definition, overrides )
|
18
|
+
|
19
|
+
if res.failures.empty?
|
20
|
+
break
|
21
|
+
else # Failure because some reasons
|
22
|
+
puts res.failures
|
23
|
+
case fail_reason(res.failures)
|
24
|
+
when "RESOURCE:MEMORY"
|
25
|
+
puts "No enough memory on current container instances to execute this task. Add another container instance automatically."
|
26
|
+
|
27
|
+
if num_instances >= max_instances
|
28
|
+
raise "Could\'t scale more instances because it reaches maximum instances. You should upgrade the maximum number of instance to execute multiple tasks at the same time."
|
29
|
+
end
|
30
|
+
unless acceptable_task?( task_definition )
|
31
|
+
raise "Could\'t accept this task because of the lack of memory. You should upgrade ec2 instance type."
|
32
|
+
end
|
33
|
+
|
34
|
+
scale!
|
35
|
+
else
|
36
|
+
raise "Unknown reason: #{res.failures}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
res
|
42
|
+
end
|
43
|
+
|
44
|
+
def acceptable_task?( task_definition )
|
45
|
+
# It preserves 128MB for ecs-agent
|
46
|
+
required_memory( task_definition ) <= current_instance_memory - (128*1024*1024)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def required_memory( task_definition )
|
51
|
+
res = ecs_client.describe_task_definition( task_definition: task_definition )
|
52
|
+
container_mems = res.task_definition.container_definitions.map(&:memory)
|
53
|
+
total_mem_mb = container_mems.inject(0){|sum,n| sum + n}
|
54
|
+
total_mem_mb * 1024 * 1024 # byte
|
55
|
+
end
|
56
|
+
|
57
|
+
def current_instance_memory
|
58
|
+
INSTANCE_TYPES[instance.type]["mem"] * 1024 * 1024 * 1024 # byte
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Ecs
|
2
|
+
module Easy
|
3
|
+
class Configure
|
4
|
+
|
5
|
+
attr_accessor :profile,
|
6
|
+
:access_key,
|
7
|
+
:secret_key,
|
8
|
+
:region,
|
9
|
+
:compose_project_name_prefix,
|
10
|
+
:compose_service_name_prefix,
|
11
|
+
:cfn_stack_name_prefix
|
12
|
+
|
13
|
+
def initialize **params
|
14
|
+
@compose_project_name_prefix = ""
|
15
|
+
@compose_service_name_prefix = "ecscompose-service-"
|
16
|
+
@cfn_stack_name_prefix = "amazon-ecs-cli-setup-"
|
17
|
+
|
18
|
+
params.each do |k,v|
|
19
|
+
self.send("#{k}=", v) if self.methods.include?(k)
|
20
|
+
end
|
21
|
+
yield( self ) if block_given?
|
22
|
+
end
|
23
|
+
|
24
|
+
def credentials
|
25
|
+
@credentials ||= profile ?
|
26
|
+
Aws::SharedCredentials.new( profile_name: profile ) :
|
27
|
+
Aws::Credentials.new( access_key, secret_key )
|
28
|
+
@credentials
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Ecs
|
2
|
+
module Easy
|
3
|
+
class Instance
|
4
|
+
|
5
|
+
attr_accessor :type,
|
6
|
+
:keypair,
|
7
|
+
:azs, # availability zones
|
8
|
+
:subnets,
|
9
|
+
:vpc,
|
10
|
+
:image_id,
|
11
|
+
:security_group
|
12
|
+
|
13
|
+
def initialize **params
|
14
|
+
params.each do |k,v|
|
15
|
+
self.send("#{k}=", v) if self.methods.include?(k)
|
16
|
+
end
|
17
|
+
yield( self ) if block_given?
|
18
|
+
end
|
19
|
+
|
20
|
+
# Generate the parameters for cloudformation
|
21
|
+
def cfn_parameters( cluster_name, params={} )
|
22
|
+
base_params = [
|
23
|
+
{
|
24
|
+
parameter_key: "EcsAmiId",
|
25
|
+
parameter_value: image_id,
|
26
|
+
},
|
27
|
+
{
|
28
|
+
parameter_key: "EcsInstanceType",
|
29
|
+
parameter_value: type,
|
30
|
+
},
|
31
|
+
{
|
32
|
+
parameter_key: "KeyName",
|
33
|
+
parameter_value: keypair,
|
34
|
+
},
|
35
|
+
{
|
36
|
+
parameter_key: "VpcId",
|
37
|
+
parameter_value: vpc,
|
38
|
+
},
|
39
|
+
{
|
40
|
+
parameter_key: "SubnetIds",
|
41
|
+
parameter_value: subnets,
|
42
|
+
},
|
43
|
+
{
|
44
|
+
parameter_key: "SecurityGroup",
|
45
|
+
parameter_value: security_group,
|
46
|
+
},
|
47
|
+
{
|
48
|
+
parameter_key: "EcsCluster",
|
49
|
+
parameter_value: cluster_name,
|
50
|
+
},
|
51
|
+
]
|
52
|
+
params.each do |k,v|
|
53
|
+
base_params << ({
|
54
|
+
"parameter_key" => k,
|
55
|
+
"parameter_value" => v,
|
56
|
+
})
|
57
|
+
end
|
58
|
+
base_params
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ecs-easy-cluster
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- metheglin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: easy-to-use AWS ECS Cluster.
|
56
|
+
email:
|
57
|
+
- pigmybank@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- ecs-easy-cluster.gemspec
|
68
|
+
- lib/ecs/easy/cluster.rb
|
69
|
+
- lib/ecs/easy/cluster/base.rb
|
70
|
+
- lib/ecs/easy/cluster/config/cloudformation_template.json
|
71
|
+
- lib/ecs/easy/cluster/config/ec2_profile.json
|
72
|
+
- lib/ecs/easy/cluster/mem_scale.rb
|
73
|
+
- lib/ecs/easy/cluster/version.rb
|
74
|
+
- lib/ecs/easy/configure.rb
|
75
|
+
- lib/ecs/easy/instance.rb
|
76
|
+
homepage: ''
|
77
|
+
licenses:
|
78
|
+
- MIT
|
79
|
+
metadata: {}
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.5.1
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: easy-to-use AWS ECS Cluster.
|
100
|
+
test_files: []
|