sumomo 0.4.0 → 0.5.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 +4 -4
- data/data/sumomo/custom_resources/DeployTime.js +1 -2
- data/data/sumomo/custom_resources/OriginAccessIdentity.js +115 -0
- data/exe/sumomo +6 -0
- data/lib/sumomo.rb +2 -0
- data/lib/sumomo/ec2.rb +5 -4
- data/lib/sumomo/ecs.rb +136 -14
- data/lib/sumomo/network.rb +39 -1
- data/lib/sumomo/stack.rb +6 -0
- data/lib/sumomo/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: 1840367c723c373796e9a822b5c5e148a35bd609
|
4
|
+
data.tar.gz: f9a20e064f13018ce49868289243eb95c893dd96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdfdedee63e23f076103f0de8a0e7c2f945830d254c57587668d8a0065d04ff7894205210b0c45f54c941303f6e3e5af75f8b44e0a9b8bfa47a1c8ce2a9ff087
|
7
|
+
data.tar.gz: 56333dd662ec58d5c426d40a8b2d1837aa78c0547f523bd175cc611fbdf79d59f5bd54fecb86ecfd3e7d6634fe675faff12bb09e1490c22f6a89afd7b08067a6
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
if (request.RequestType == "Create")
|
3
2
|
{
|
4
3
|
Cloudformation.send(request, context, Cloudformation.SUCCESS, {}, "Success", String((new Date).getTime()));
|
@@ -12,4 +11,4 @@ if (request.RequestType == "Update")
|
|
12
11
|
if (request.RequestType == "Delete")
|
13
12
|
{
|
14
13
|
Cloudformation.send(request, context, Cloudformation.SUCCESS, {}, "Success", String((new Date).getTime()));
|
15
|
-
}
|
14
|
+
}
|
@@ -0,0 +1,115 @@
|
|
1
|
+
|
2
|
+
var cloudfront = new aws.CloudFront({region: request.ResourceProperties.Region});
|
3
|
+
|
4
|
+
function randomIntInc (low, high)
|
5
|
+
{
|
6
|
+
return Math.floor(Math.random() * (high - low + 1) + low);
|
7
|
+
}
|
8
|
+
|
9
|
+
function randomNumber()
|
10
|
+
{
|
11
|
+
var numbers = new Array(10);
|
12
|
+
for (var i = 0; i < numbers.length; i++)
|
13
|
+
{
|
14
|
+
numbers[i] = randomIntInc(1,10);
|
15
|
+
}
|
16
|
+
return numbers.join("");
|
17
|
+
}
|
18
|
+
|
19
|
+
function request_identity(ref, onSuccess, onError)
|
20
|
+
{
|
21
|
+
var params = {
|
22
|
+
CloudFrontOriginAccessIdentityConfig: {
|
23
|
+
CallerReference: ref,
|
24
|
+
Comment: request.ResourceProperties.Comment || "No Comment Specified"
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
cloudfront.createCloudFrontOriginAccessIdentity(params, function(err, data) {
|
29
|
+
if (err)
|
30
|
+
{
|
31
|
+
onError(err);
|
32
|
+
}
|
33
|
+
else
|
34
|
+
{
|
35
|
+
onSuccess(data);
|
36
|
+
}
|
37
|
+
});
|
38
|
+
}
|
39
|
+
|
40
|
+
if (request.RequestType == "Create")
|
41
|
+
{
|
42
|
+
var ref = randomNumber();
|
43
|
+
store.put("oai_ref", ref, function() {
|
44
|
+
request_identity(ref,
|
45
|
+
function(data)
|
46
|
+
{
|
47
|
+
console.log(data);
|
48
|
+
Cloudformation.send(request, context, Cloudformation.SUCCESS, {
|
49
|
+
Id: data.CloudFrontOriginAccessIdentity.Id,
|
50
|
+
S3CanonicalUserId: data.CloudFrontOriginAccessIdentity.S3CanonicalUserId
|
51
|
+
}, "Success", "origin-access-identity/cloudfront/" + data.CloudFrontOriginAccessIdentity.Id);
|
52
|
+
|
53
|
+
}, function(err)
|
54
|
+
{
|
55
|
+
console.log(err, err.stack);
|
56
|
+
Cloudformation.send(request, context, Cloudformation.FAILED, {}, "Error: " + err);
|
57
|
+
});
|
58
|
+
}, function(err) {
|
59
|
+
Cloudformation.send(request, context, Cloudformation.FAILED, {}, "Cannot Store OAI Reference");
|
60
|
+
});
|
61
|
+
}
|
62
|
+
|
63
|
+
if (request.RequestType == "Update")
|
64
|
+
{
|
65
|
+
store.get("oai_ref", function(ref) {
|
66
|
+
request_identity(ref,
|
67
|
+
function(data)
|
68
|
+
{
|
69
|
+
console.log(data);
|
70
|
+
Cloudformation.send(request, context, Cloudformation.SUCCESS, {
|
71
|
+
Id: data.CloudFrontOriginAccessIdentity.Id,
|
72
|
+
S3CanonicalUserId: data.CloudFrontOriginAccessIdentity.S3CanonicalUserId
|
73
|
+
}, "Success", "origin-access-identity/cloudfront/" + data.CloudFrontOriginAccessIdentity.Id);
|
74
|
+
|
75
|
+
}, function(err)
|
76
|
+
{
|
77
|
+
console.log(err, err.stack);
|
78
|
+
Cloudformation.send(request, context, Cloudformation.FAILED, {}, "Error: " + err);
|
79
|
+
});
|
80
|
+
}, function(err) {
|
81
|
+
Cloudformation.send(request, context, Cloudformation.FAILED, {}, "Cannot Load OAI Reference");
|
82
|
+
});
|
83
|
+
}
|
84
|
+
|
85
|
+
if (request.RequestType == "Delete")
|
86
|
+
{
|
87
|
+
store.get("oai_ref", function(ref) {
|
88
|
+
request_identity(ref,
|
89
|
+
function(data)
|
90
|
+
{
|
91
|
+
var params = {
|
92
|
+
Id: data.CloudFrontOriginAccessIdentity.Id,
|
93
|
+
};
|
94
|
+
cloudfront.deleteCloudFrontOriginAccessIdentity(params, function(err, data) {
|
95
|
+
if (err)
|
96
|
+
{
|
97
|
+
console.log(err, err.stack);
|
98
|
+
Cloudformation.send(request, context, Cloudformation.FAILED, {}, "Error: " + err);
|
99
|
+
}
|
100
|
+
else
|
101
|
+
{
|
102
|
+
Cloudformation.send(request, context, Cloudformation.SUCCESS, {}, "Success", "" );
|
103
|
+
}
|
104
|
+
});
|
105
|
+
|
106
|
+
}, function(err)
|
107
|
+
{
|
108
|
+
console.log(err, err.stack);
|
109
|
+
Cloudformation.send(request, context, Cloudformation.FAILED, {}, "Error: " + err);
|
110
|
+
});
|
111
|
+
|
112
|
+
}, function(err) {
|
113
|
+
Cloudformation.send(request, context, Cloudformation.FAILED, {}, "Cannot Load OAI Reference");
|
114
|
+
});
|
115
|
+
}
|
data/exe/sumomo
CHANGED
@@ -13,10 +13,16 @@ global_opts = Trollop::options do
|
|
13
13
|
USAGE
|
14
14
|
|
15
15
|
opt :region, "AWS region to use", type: :string, default: "ap-northeast-1"
|
16
|
+
opt :profile, "AWS credential profile to use", type: :string, default: "default"
|
16
17
|
|
17
18
|
stop_on SUB_COMMANDS
|
18
19
|
end
|
19
20
|
|
21
|
+
ENV["AWS_PROFILE"] = global_opts[:profile]
|
22
|
+
|
23
|
+
puts "Using profile:"
|
24
|
+
p ENV["AWS_PROFILE"]
|
25
|
+
|
20
26
|
cmd = ARGV.shift # get the subcommand
|
21
27
|
|
22
28
|
cmd_opts = case cmd
|
data/lib/sumomo.rb
CHANGED
data/lib/sumomo/ec2.rb
CHANGED
@@ -10,7 +10,7 @@ module Sumomo
|
|
10
10
|
end)
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
13
|
+
def allow_port(thing)
|
14
14
|
if (thing == :all)
|
15
15
|
{
|
16
16
|
"IpProtocol" => "-1",
|
@@ -270,6 +270,7 @@ sudo aws s3 cp s3://#{@bucket_name}/uploads/#{name} #{local_path}
|
|
270
270
|
docker_email:"",
|
271
271
|
docker_password: "",
|
272
272
|
eip:nil,
|
273
|
+
policies:[],
|
273
274
|
&block)
|
274
275
|
|
275
276
|
if ami_name == nil
|
@@ -290,8 +291,8 @@ sudo aws s3 cp s3://#{@bucket_name}/uploads/#{name} #{local_path}
|
|
290
291
|
|
291
292
|
task_script = tasks.script
|
292
293
|
|
293
|
-
ingress ||= [
|
294
|
-
egress ||= [
|
294
|
+
ingress ||= [ allow_port(:all) ]
|
295
|
+
egress ||= [ allow_port(:all) ]
|
295
296
|
machine_tag ||= ref("AWS::StackName")
|
296
297
|
name ||= make_default_resource_name("AutoScalingGroup")
|
297
298
|
script ||= ""
|
@@ -393,7 +394,7 @@ aws ec2 associate-address --region `cat /etc/aws_region` --instance-id `curl htt
|
|
393
394
|
"logs:PutLogEvents"
|
394
395
|
],
|
395
396
|
"Resource": "*"
|
396
|
-
}]
|
397
|
+
}] + policies
|
397
398
|
}
|
398
399
|
}]
|
399
400
|
end
|
data/lib/sumomo/ecs.rb
CHANGED
@@ -6,21 +6,67 @@ module Sumomo
|
|
6
6
|
str.gsub(/[^0-9a-zA-Z]/, "_")
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
9
|
+
def make_ecs_role
|
10
|
+
make "AWS::IAM::Role", name: "ECSServiceRole" do
|
11
|
+
|
12
|
+
role_policy_doc = {
|
13
|
+
"Version" => "2012-10-17",
|
14
|
+
"Statement" => [{
|
15
|
+
"Effect" => "Allow",
|
16
|
+
"Principal" => {"Service" => ["ecs.amazonaws.com"]},
|
17
|
+
"Action" => ["sts:AssumeRole"]
|
18
|
+
}]
|
19
|
+
}
|
10
20
|
|
11
|
-
|
21
|
+
AssumeRolePolicyDocument role_policy_doc
|
22
|
+
Path "/"
|
23
|
+
Policies [
|
24
|
+
{
|
25
|
+
"PolicyName" => "ecs-service",
|
26
|
+
"PolicyDocument" => {
|
27
|
+
"Version" => "2012-10-17",
|
28
|
+
"Statement" => [{
|
29
|
+
"Effect" => "Allow",
|
30
|
+
"Action" => [
|
31
|
+
"ec2:AuthorizeSecurityGroupIngress",
|
32
|
+
"ec2:Describe*",
|
33
|
+
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
|
34
|
+
"elasticloadbalancing:DeregisterTargets",
|
35
|
+
"elasticloadbalancing:Describe*",
|
36
|
+
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
|
37
|
+
"elasticloadbalancing:RegisterTargets"
|
38
|
+
],
|
39
|
+
"Resource" => "*"
|
40
|
+
}]
|
41
|
+
}
|
42
|
+
}
|
43
|
+
]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def make_ecs_cluster(name:make_default_resource_name("ECSCluster"),services:[],machine_config:{},network:,log_retention:30,dependencies:[])
|
48
|
+
|
49
|
+
ecs = make "AWS::ECS::Cluster", name: "#{name}" do
|
50
|
+
dependencies.each do |x|
|
51
|
+
depends_on x
|
52
|
+
end
|
53
|
+
end
|
12
54
|
|
13
55
|
volumes = []
|
14
56
|
machine_volume_locations = {}
|
15
57
|
|
16
|
-
|
58
|
+
service_number = 0
|
17
59
|
|
18
60
|
services.each do |service|
|
19
61
|
|
20
|
-
|
62
|
+
alb = service[:alb]
|
63
|
+
certificate = service[:certificate]
|
64
|
+
alb_ports = {}
|
65
|
+
|
66
|
+
service_number += 1
|
21
67
|
|
22
68
|
containers = service[:containers]
|
23
|
-
service_name = service[:name] || "Service#{
|
69
|
+
service_name = service[:name] || "Service#{service_number}"
|
24
70
|
service_count = service[:count] || 1
|
25
71
|
|
26
72
|
container_defs = containers.map do |container|
|
@@ -29,7 +75,7 @@ module Sumomo
|
|
29
75
|
definition["Name"] = "#{sluggify(container[:image]).camelize}"
|
30
76
|
definition["Name"] = container[:name] if container[:name]
|
31
77
|
|
32
|
-
definition["Memory"] = 1024
|
78
|
+
definition["Memory"] = container[:memory] || 1024
|
33
79
|
|
34
80
|
loggroup = make "AWS::Logs::LogGroup", name: "#{name}#{definition["Name"]}Logs" do
|
35
81
|
LogGroupName "#{definition["Name"].underscore}_logs"
|
@@ -68,11 +114,68 @@ module Sumomo
|
|
68
114
|
end
|
69
115
|
|
70
116
|
if container[:ports]
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
117
|
+
if !alb
|
118
|
+
definition["PortMappings"] = container[:ports].map do |from_port, to_port|
|
119
|
+
{
|
120
|
+
"ContainerPort" => from_port,
|
121
|
+
"HostPort" => to_port
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
else
|
126
|
+
definition["PortMappings"] = container[:ports].map do |from_port, to_port|
|
127
|
+
{
|
128
|
+
"ContainerPort" => from_port
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
container[:ports].each do |container_port, host_port|
|
133
|
+
|
134
|
+
if alb_ports[host_port.to_i]
|
135
|
+
raise "Container #{alb_ports[host_port][:name]} is already using #{host_port}"
|
136
|
+
end
|
137
|
+
|
138
|
+
alb_target = make "AWS::ElasticLoadBalancingV2::TargetGroup", name: "#{name}#{definition["Name"]}Target" do
|
139
|
+
HealthCheckIntervalSeconds 60
|
140
|
+
UnhealthyThresholdCount 10
|
141
|
+
HealthCheckPath "/"
|
142
|
+
Name "#{name}Port#{host_port}Target"
|
143
|
+
Port container_port
|
144
|
+
Protocol "HTTP"
|
145
|
+
VpcId network[:vpc]
|
146
|
+
end
|
147
|
+
|
148
|
+
alb_action = {
|
149
|
+
"Type" => "forward",
|
150
|
+
"TargetGroupArn" => alb_target
|
151
|
+
}
|
152
|
+
|
153
|
+
if certificate
|
154
|
+
alb_listener = make "AWS::ElasticLoadBalancingV2::Listener", name: "#{name}#{definition["Name"]}Listener" do
|
155
|
+
Certificates [{ CertificateArn: certificate }]
|
156
|
+
DefaultActions [ alb_action ]
|
157
|
+
LoadBalancerArn alb
|
158
|
+
Port host_port
|
159
|
+
Protocol "HTTPS"
|
160
|
+
end
|
161
|
+
else
|
162
|
+
alb_listener = make "AWS::ElasticLoadBalancingV2::Listener", name: "#{name}#{definition["Name"]}Listener" do
|
163
|
+
DefaultActions [ alb_action ]
|
164
|
+
LoadBalancerArn alb
|
165
|
+
Port host_port
|
166
|
+
Protocol "HTTP"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
alb_ports[host_port.to_i] = {
|
171
|
+
listener: alb_listener,
|
172
|
+
target: alb_target,
|
173
|
+
port: container_port,
|
174
|
+
name: definition["Name"]
|
175
|
+
}
|
176
|
+
|
177
|
+
end
|
178
|
+
|
76
179
|
end
|
77
180
|
container.delete(:ports)
|
78
181
|
end
|
@@ -87,13 +190,12 @@ module Sumomo
|
|
87
190
|
container.delete(:envvars)
|
88
191
|
end
|
89
192
|
|
90
|
-
|
91
193
|
container.each do |key, value|
|
92
194
|
definition["#{key}".camelize] = value
|
93
195
|
end
|
94
196
|
|
95
197
|
definition
|
96
|
-
end
|
198
|
+
end
|
97
199
|
|
98
200
|
|
99
201
|
deployment_config = {
|
@@ -106,13 +208,31 @@ module Sumomo
|
|
106
208
|
Volumes volumes
|
107
209
|
end
|
108
210
|
|
211
|
+
stack = self
|
212
|
+
|
109
213
|
ecs_service = make "AWS::ECS::Service", name: "#{name}#{service_name}" do
|
214
|
+
alb_ports.each do |host_port, info|
|
215
|
+
depends_on info[:listener]
|
216
|
+
end
|
217
|
+
|
110
218
|
Cluster ecs
|
111
219
|
DesiredCount service_count
|
112
220
|
TaskDefinition ecs_task
|
113
221
|
DeploymentConfiguration deployment_config
|
222
|
+
|
223
|
+
if alb_ports.keys.count != 0
|
224
|
+
Role stack.make_ecs_role
|
225
|
+
LoadBalancers alb_ports.values.map { |info|
|
226
|
+
{
|
227
|
+
"TargetGroupArn" => info[:target],
|
228
|
+
"ContainerPort" => info[:port],
|
229
|
+
"ContainerName" => info[:name]
|
230
|
+
}
|
231
|
+
}
|
232
|
+
end
|
233
|
+
|
114
234
|
end
|
115
|
-
end
|
235
|
+
end #services
|
116
236
|
|
117
237
|
machine_config[:methods].each do |method_name|
|
118
238
|
parameters = {ecs_cluster: ecs}
|
@@ -121,6 +241,8 @@ module Sumomo
|
|
121
241
|
parameters[param[1]] = machine_config[param[1]] if (param[0] == :keyreq or param[0] == :key) and machine_config[param[1]]
|
122
242
|
end
|
123
243
|
|
244
|
+
parameters[:network] = network if !parameters[:network]
|
245
|
+
|
124
246
|
method(method_name).call(parameters) do
|
125
247
|
machine_volume_locations.each do |s3_loc, machine_loc|
|
126
248
|
mkdir File.dirname(machine_loc)
|
data/lib/sumomo/network.rb
CHANGED
@@ -38,9 +38,47 @@ module Sumomo
|
|
38
38
|
GatewayId gateway
|
39
39
|
end
|
40
40
|
|
41
|
+
last_unused_number = 0
|
42
|
+
|
43
|
+
subnet_numbers = []
|
44
|
+
|
45
|
+
#load current config
|
46
|
+
number_hash = {}
|
47
|
+
subnet_hash = {}
|
48
|
+
|
49
|
+
ec2 = Aws::EC2::Client.new(region: @region)
|
50
|
+
ec2_subnets = ec2.describe_subnets().subnets
|
51
|
+
ec2_subnets.each do |subnet|
|
52
|
+
if subnet.tags.select {|x| x.key == "aws:cloudformation:stack-name" && x.value == @bucket_name}.length == 1
|
53
|
+
layer = /^#{@bucket_name}-(?<layer_name>.+)-[a-z]+$/.match(subnet.tags.select{|x| x.key == "Name"}.first.value)[:layer_name]
|
54
|
+
zone = subnet.availability_zone
|
55
|
+
number = /^10.0.(?<num>[0-9]+).0/.match(subnet.cidr_block)[:num].to_i
|
56
|
+
|
57
|
+
key = "#{layer}/#{zone}"
|
58
|
+
number_hash[number] = key
|
59
|
+
subnet_hash[key] = number
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# assign numbers to unassigned subnets
|
64
|
+
layers.product(zones).each do |e|
|
65
|
+
key = "#{e[0]}/#{e[1]}"
|
66
|
+
if !subnet_hash.has_key?(key)
|
67
|
+
loop do
|
68
|
+
break if !number_hash.has_key?(last_unused_number)
|
69
|
+
last_unused_number += 1
|
70
|
+
end
|
71
|
+
number_hash[last_unused_number] = key
|
72
|
+
subnet_hash[key] = last_unused_number
|
73
|
+
subnet_numbers << [e, last_unused_number]
|
74
|
+
else
|
75
|
+
subnet_numbers << [e, subnet_hash[key]]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
41
79
|
subnets = {}
|
42
80
|
|
43
|
-
|
81
|
+
subnet_numbers.each do |e, subnet_number|
|
44
82
|
layer = e[0]
|
45
83
|
zone = e[1]
|
46
84
|
|
data/lib/sumomo/stack.rb
CHANGED
@@ -17,6 +17,7 @@ module Sumomo
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def upload_file(name,content)
|
20
|
+
puts "Uploaded #{name}"
|
20
21
|
@store.set_raw("uploads/#{name}", content)
|
21
22
|
end
|
22
23
|
|
@@ -139,6 +140,11 @@ module Sumomo
|
|
139
140
|
"Effect" => "Allow",
|
140
141
|
"Action" => ["s3:DeleteObject", "s3:GetObject", "s3:PutObject"],
|
141
142
|
"Resource" => "arn:aws:s3:::#{bucket_name}/*"
|
143
|
+
},
|
144
|
+
{
|
145
|
+
"Effect" => "Allow",
|
146
|
+
"Action" => ["cloudfront:CreateCloudFrontOriginAccessIdentity", "cloudfront:DeleteCloudFrontOriginAccessIdentity"],
|
147
|
+
"Resource" => "*"
|
142
148
|
}]
|
143
149
|
}
|
144
150
|
}
|
data/lib/sumomo/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sumomo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Siaw
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -171,6 +171,7 @@ files:
|
|
171
171
|
- data/sumomo/custom_resources/AvailabilityZones.js
|
172
172
|
- data/sumomo/custom_resources/CloudflareCNAME.js
|
173
173
|
- data/sumomo/custom_resources/DeployTime.js
|
174
|
+
- data/sumomo/custom_resources/OriginAccessIdentity.js
|
174
175
|
- data/sumomo/custom_resources/SelectSpot.js
|
175
176
|
- data/sumomo/sources/spot-watcher-poller.sh
|
176
177
|
- data/sumomo/sources/spot-watcher.sh
|