ecs-easy-cluster 0.0.1
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 +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: []
|