sumomo 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 19a7b13c51abbddeff61c5b0b23eb1163dd70bd8
4
- data.tar.gz: fbe8f61d32f2d6acd41b6437fa8f8ac84773f4c3
3
+ metadata.gz: 1840367c723c373796e9a822b5c5e148a35bd609
4
+ data.tar.gz: f9a20e064f13018ce49868289243eb95c893dd96
5
5
  SHA512:
6
- metadata.gz: a12275c78d5ee20bcd911f678607003f6c1681570243d1a8772d702dc1950b8180474cfdfbd10440813d05d8d370b260c6c235c476d15de96c16dbf1dc225b2e
7
- data.tar.gz: a13a1e7840147f9e70948256b81ecd8f0baf25b7bc58bc53e938e641663a8040e5ca00d949dae36de3333a0f3fc54b99da0c592bb95f33323a03d78940194265
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
@@ -91,6 +91,8 @@ module Sumomo
91
91
 
92
92
  end.templatize
93
93
 
94
+
95
+
94
96
  #puts JSON.parse(template).to_yaml
95
97
 
96
98
  store.set_raw("cloudformation/template", template)
@@ -10,7 +10,7 @@ module Sumomo
10
10
  end)
11
11
  end
12
12
 
13
- def allow(thing)
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 ||= [ allow(:all) ]
294
- egress ||= [ allow(:all) ]
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
@@ -6,21 +6,67 @@ module Sumomo
6
6
  str.gsub(/[^0-9a-zA-Z]/, "_")
7
7
  end
8
8
 
9
- def make_ecs_cluster(name:"ECSCluster",services:[],machine_config:{},log_retention:30)
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
- ecs = make "AWS::ECS::Cluster", name: "#{name}"
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
- service_count = 0
58
+ service_number = 0
17
59
 
18
60
  services.each do |service|
19
61
 
20
- service_count += 1
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#{service_count}"
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
- definition["PortMappings"] = container[:ports].map do |from_port, to_port|
72
- {
73
- "ContainerPort" => from_port,
74
- "HostPort" => to_port
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)
@@ -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
- layers.product(zones).each_with_index do |e, subnet_number|
81
+ subnet_numbers.each do |e, subnet_number|
44
82
  layer = e[0]
45
83
  zone = e[1]
46
84
 
@@ -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
  }
@@ -1,3 +1,3 @@
1
1
  module Sumomo
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
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.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-01-02 00:00:00.000000000 Z
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