sumomo 0.8.9 → 0.8.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -11
- data/data/sumomo/custom_resources/{USEastCertificate.js → ACMCertificate.js} +8 -3
- data/data/sumomo/custom_resources/{USEastCertificateWaiter.js → ACMCertificateWaiter.js} +3 -1
- data/data/sumomo/custom_resources/AMILookup.js +378 -150
- data/data/sumomo/custom_resources/SelectSpot.js +376 -142
- data/exe/sumomo +12 -2
- data/lib/sumomo/api.rb +120 -9
- data/lib/sumomo/ec2.rb +9 -6
- data/lib/sumomo/stack.rb +1 -1
- data/lib/sumomo/version.rb +1 -1
- data/lib/sumomo.rb +33 -5
- data/sumomo.gemspec +6 -4
- data/update-spec.rb +381 -0
- metadata +51 -22
data/exe/sumomo
CHANGED
@@ -30,7 +30,7 @@ cmd_opts = case cmd
|
|
30
30
|
when 'delete'
|
31
31
|
Sumomo.delete_stack(name: ARGV[0], region: global_opts[:region])
|
32
32
|
|
33
|
-
when 'create'
|
33
|
+
when 'create'
|
34
34
|
local_opts = Trollop.options do
|
35
35
|
opt :filename, 'File that describes the stack', type: :string, default: 'Sumomofile'
|
36
36
|
end
|
@@ -39,6 +39,16 @@ cmd_opts = case cmd
|
|
39
39
|
eval File.read(local_opts[:filename]), proc.binding, local_opts[:filename]
|
40
40
|
end
|
41
41
|
|
42
|
+
when 'update'
|
43
|
+
local_opts = Trollop.options do
|
44
|
+
opt :filename, 'File that describes the stack', type: :string, default: 'Sumomofile'
|
45
|
+
opt :changeset, 'Create a changeset instead of directly update', type: :boolean, default: false
|
46
|
+
end
|
47
|
+
Sumomo.update_stack(name: ARGV[0], changeset: !!local_opts[:changeset], region: global_opts[:region]) do
|
48
|
+
proc = proc {}
|
49
|
+
eval File.read(local_opts[:filename]), proc.binding, local_opts[:filename]
|
50
|
+
end
|
51
|
+
|
42
52
|
when 'outputs'
|
43
53
|
puts "Outputs for stack #{ARGV[0]}"
|
44
54
|
puts Sumomo.get_stack_outputs(name: ARGV[0], region: global_opts[:region]).to_yaml
|
@@ -49,7 +59,7 @@ cmd_opts = case cmd
|
|
49
59
|
key = JSON.parse(File.read('x.txt'))['value']
|
50
60
|
File.write('key.pem', key)
|
51
61
|
`chmod 0600 key.pem`
|
52
|
-
exec "ssh -i 'key.pem' ec2-user@#{ARGV[1]}"
|
62
|
+
exec "ssh -i 'key.pem' ec2-user@#{ARGV[1]} #{ARGV[2]}"
|
53
63
|
|
54
64
|
when 'testapi'
|
55
65
|
local_opts = Trollop.options do
|
data/lib/sumomo/api.rb
CHANGED
@@ -159,9 +159,45 @@ module Sumomo
|
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
162
|
-
def make_api(
|
162
|
+
def make_api(
|
163
|
+
domain_name,
|
164
|
+
name:,
|
165
|
+
script: nil,
|
166
|
+
dns: nil,
|
167
|
+
cert: nil,
|
168
|
+
mtls_truststore: nil,
|
169
|
+
logging: true,
|
170
|
+
with_statements: [], &block)
|
171
|
+
|
163
172
|
api = make 'AWS::ApiGateway::RestApi', name: name do
|
164
173
|
Name name
|
174
|
+
DisableExecuteApiEndpoint true
|
175
|
+
end
|
176
|
+
|
177
|
+
if logging
|
178
|
+
cloudwatchRole = make 'AWS::IAM::Role', name: "#{name}LoggingRole" do
|
179
|
+
AssumeRolePolicyDocument do
|
180
|
+
Version "2012-10-17"
|
181
|
+
Statement [
|
182
|
+
{
|
183
|
+
"Effect" => "Allow",
|
184
|
+
"Principal" => {
|
185
|
+
"Service" => [
|
186
|
+
"apigateway.amazonaws.com"
|
187
|
+
]
|
188
|
+
},
|
189
|
+
"Action" => "sts:AssumeRole"
|
190
|
+
}
|
191
|
+
]
|
192
|
+
end
|
193
|
+
Path '/'
|
194
|
+
ManagedPolicyArns [ "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs" ]
|
195
|
+
end
|
196
|
+
|
197
|
+
make 'AWS::ApiGateway::Account' do
|
198
|
+
depends_on api
|
199
|
+
CloudWatchRoleArn cloudwatchRole.Arn
|
200
|
+
end
|
165
201
|
end
|
166
202
|
|
167
203
|
script ||= File.read(File.join(Gem.loaded_specs['sumomo'].full_gem_path, 'data', 'sumomo', 'api_modules', 'real_script.js'))
|
@@ -183,7 +219,10 @@ module Sumomo
|
|
183
219
|
|
184
220
|
files += [{ name: 'index.js', code: script }]
|
185
221
|
|
186
|
-
fun = make_lambda(
|
222
|
+
fun = make_lambda(
|
223
|
+
name: "#{name}Lambda#{@version_number}",
|
224
|
+
files: files,
|
225
|
+
role: custom_resource_exec_role(with_statements: with_statements) )
|
187
226
|
|
188
227
|
resource = make 'AWS::ApiGateway::Resource', name: "#{name}Resource" do
|
189
228
|
ParentId api.RootResourceId
|
@@ -230,18 +269,79 @@ module Sumomo
|
|
230
269
|
stage = make 'AWS::ApiGateway::Stage', name: "#{name}Stage" do
|
231
270
|
RestApiId api
|
232
271
|
DeploymentId deployment
|
233
|
-
|
272
|
+
|
273
|
+
if logging
|
274
|
+
MethodSettings [
|
275
|
+
{
|
276
|
+
"ResourcePath" => "/*",
|
277
|
+
"HttpMethod" => "*",
|
278
|
+
"DataTraceEnabled" => true,
|
279
|
+
"LoggingLevel" => 'INFO'
|
280
|
+
}
|
281
|
+
]
|
282
|
+
end
|
234
283
|
end
|
235
284
|
|
236
285
|
root_name = /(?<root_name>[^.]+\.[^.]+)$/.match(domain_name)[:root_name]
|
237
286
|
|
238
|
-
|
239
|
-
|
287
|
+
certificate_completion = cert
|
288
|
+
|
289
|
+
bucket_name = @bucket_name
|
290
|
+
mtls = nil
|
291
|
+
if mtls_truststore
|
292
|
+
filename = "#{domain_name}.truststore.pem"
|
293
|
+
upload_file(filename, mtls_truststore)
|
294
|
+
truststore_uri = "s3://#{bucket_name}/uploads/#{filename}"
|
295
|
+
mtls = {
|
296
|
+
"TruststoreUri" => truststore_uri
|
297
|
+
}
|
240
298
|
end
|
241
299
|
|
242
|
-
|
300
|
+
if cert.nil?
|
301
|
+
cert = make 'Custom::ACMCertificate', name: "#{name}Certificate" do
|
302
|
+
DomainName domain_name
|
303
|
+
ValidationMethod 'DNS' if dns[:type] == :route53
|
304
|
+
RegionOverride 'us-east-1' if !mtls
|
305
|
+
end
|
306
|
+
|
307
|
+
certificate_completion = cert
|
308
|
+
|
309
|
+
if dns[:type] == :route53
|
310
|
+
make 'AWS::Route53::RecordSet', name: "#{name}CertificateRoute53Entry" do
|
311
|
+
HostedZoneId dns[:hosted_zone]
|
312
|
+
Name cert.RecordName
|
313
|
+
Type cert.RecordType
|
314
|
+
TTL 60
|
315
|
+
ResourceRecords [cert.RecordValue]
|
316
|
+
end
|
317
|
+
|
318
|
+
cert_waiter = make 'Custom::ACMCertificateWaiter', name: "#{name}CertificateWaiter" do
|
319
|
+
Certificate cert
|
320
|
+
RegionOverride 'us-east-1' if !mtls
|
321
|
+
end
|
322
|
+
|
323
|
+
certificate_completion = cert_waiter
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
domain = make 'AWS::ApiGateway::DomainName', name: "#{name}DomainName" do
|
328
|
+
depends_on certificate_completion
|
329
|
+
|
243
330
|
DomainName domain_name
|
244
|
-
|
331
|
+
|
332
|
+
if mtls != nil
|
333
|
+
RegionalCertificateArn cert
|
334
|
+
MutualTlsAuthentication mtls
|
335
|
+
SecurityPolicy 'TLS_1_2'
|
336
|
+
EndpointConfiguration do
|
337
|
+
Types [ 'REGIONAL' ]
|
338
|
+
end
|
339
|
+
else
|
340
|
+
CertificateArn cert
|
341
|
+
EndpointConfiguration do
|
342
|
+
Types [ 'EDGE' ]
|
343
|
+
end
|
344
|
+
end
|
245
345
|
end
|
246
346
|
|
247
347
|
make 'AWS::ApiGateway::BasePathMapping', name: "#{name}BasePathMapping" do
|
@@ -264,8 +364,19 @@ module Sumomo
|
|
264
364
|
make 'AWS::Route53::RecordSet', name: "#{name}Route53Entry" do
|
265
365
|
HostedZoneId dns[:hosted_zone]
|
266
366
|
Name domain_name
|
267
|
-
|
268
|
-
|
367
|
+
|
368
|
+
if mtls != nil
|
369
|
+
Type 'A'
|
370
|
+
AliasTarget do
|
371
|
+
DNSName domain.RegionalDomainName
|
372
|
+
HostedZoneId domain.RegionalHostedZoneId
|
373
|
+
end
|
374
|
+
else
|
375
|
+
Type 'A'
|
376
|
+
AliasTarget do
|
377
|
+
DNSName domain.DistributionDomainName
|
378
|
+
HostedZoneId domain.DistributionHostedZoneId
|
379
|
+
end end
|
269
380
|
end
|
270
381
|
domain_name
|
271
382
|
else
|
data/lib/sumomo/ec2.rb
CHANGED
@@ -254,6 +254,7 @@ module Sumomo
|
|
254
254
|
has_public_ips: true,
|
255
255
|
ingress: nil,
|
256
256
|
egress: nil,
|
257
|
+
security_groups: [],
|
257
258
|
machine_tag: nil,
|
258
259
|
ec2_sns_arn: nil,
|
259
260
|
ami_name: nil,
|
@@ -297,10 +298,12 @@ module Sumomo
|
|
297
298
|
|
298
299
|
bucket_name = @bucket_name
|
299
300
|
|
300
|
-
|
301
|
+
script_arr = [script]
|
302
|
+
|
303
|
+
script_arr << task_script
|
301
304
|
|
302
305
|
if ecs_cluster
|
303
|
-
|
306
|
+
script_arr << <<~ECS_START
|
304
307
|
|
305
308
|
yum update
|
306
309
|
yum groupinstall "Development Tools"
|
@@ -318,12 +321,12 @@ module Sumomo
|
|
318
321
|
end
|
319
322
|
|
320
323
|
if eip
|
321
|
-
|
324
|
+
script_arr << <<~EIP_ALLOCATE
|
322
325
|
aws ec2 associate-address --region `cat /etc/aws_region` --instance-id `curl http://169.254.169.254/latest/meta-data/instance-id` --allocation-id `cat /etc/eip_allocation_id`
|
323
326
|
EIP_ALLOCATE
|
324
327
|
end
|
325
328
|
|
326
|
-
|
329
|
+
script_arr << "service spot-watcher start" if(spot_price && ec2_sns_arn)
|
327
330
|
|
328
331
|
unless ingress.is_a? Array
|
329
332
|
raise 'ec2: ingress option needs to be an array'
|
@@ -339,7 +342,7 @@ module Sumomo
|
|
339
342
|
|
340
343
|
wait_handle = make 'AWS::CloudFormation::WaitConditionHandle'
|
341
344
|
|
342
|
-
user_data = initscript(wait_handle, name,
|
345
|
+
user_data = initscript(wait_handle, name, call('Fn::Join', "\n", script_arr))
|
343
346
|
|
344
347
|
role_policy_doc = {
|
345
348
|
'Version' => '2012-10-17',
|
@@ -407,7 +410,7 @@ module Sumomo
|
|
407
410
|
launch_config = make 'AWS::AutoScaling::LaunchConfiguration' do
|
408
411
|
AssociatePublicIpAddress has_public_ips
|
409
412
|
KeyName keypair
|
410
|
-
SecurityGroups [web_sec_group]
|
413
|
+
SecurityGroups [web_sec_group] + security_groups
|
411
414
|
ImageId ami_name
|
412
415
|
UserData user_data
|
413
416
|
InstanceType type
|
data/lib/sumomo/stack.rb
CHANGED
data/lib/sumomo/version.rb
CHANGED
data/lib/sumomo.rb
CHANGED
@@ -26,7 +26,17 @@ module Sumomo
|
|
26
26
|
"cloudformation/#{make_master_key_name(name: name)}.pem"
|
27
27
|
end
|
28
28
|
|
29
|
-
def self.
|
29
|
+
def self.create_stack(name:, region:, sns_arn: nil, &block)
|
30
|
+
cf = Aws::CloudFormation::Client.new(region: region)
|
31
|
+
begin
|
32
|
+
cf.describe_stacks(stack_name: name)
|
33
|
+
raise "There is already a stack named '#{name}'"
|
34
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
35
|
+
update_stack(name: name, region: region, sns_arn: sns_arn, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.update_stack(name:, region:, sns_arn: nil, changeset: false, &block)
|
30
40
|
cf = Aws::CloudFormation::Client.new(region: region)
|
31
41
|
s3 = Aws::S3::Client.new(region: region)
|
32
42
|
ec2 = Aws::EC2::Client.new(region: region)
|
@@ -107,11 +117,20 @@ module Sumomo
|
|
107
117
|
stack_name: name,
|
108
118
|
template_url: store.url('cloudformation/template'),
|
109
119
|
parameters: hidden_values,
|
120
|
+
disable_rollback: true,
|
110
121
|
capabilities: ['CAPABILITY_IAM']
|
111
122
|
}
|
112
123
|
|
113
124
|
begin
|
114
|
-
|
125
|
+
if changeset
|
126
|
+
cf.create_change_set(
|
127
|
+
**update_options,
|
128
|
+
change_set_name: "Change#{curtimestr}"
|
129
|
+
)
|
130
|
+
else
|
131
|
+
cf.update_stack(update_options)
|
132
|
+
end
|
133
|
+
|
115
134
|
rescue StandardError => e
|
116
135
|
if e.message.end_with? 'does not exist'
|
117
136
|
update_options[:timeout_in_minutes] = @timeout if @timeout
|
@@ -124,6 +143,10 @@ module Sumomo
|
|
124
143
|
end
|
125
144
|
end
|
126
145
|
|
146
|
+
def self.curtimestr
|
147
|
+
Time.now.strftime('%Y%m%d%H%M%S')
|
148
|
+
end
|
149
|
+
|
127
150
|
def self.wait_for_stack(name:, region:)
|
128
151
|
cf = Aws::CloudFormation::Client.new(region: region)
|
129
152
|
|
@@ -187,7 +210,14 @@ module Sumomo
|
|
187
210
|
instance_eval(&block)
|
188
211
|
end
|
189
212
|
|
190
|
-
def make_api(_domain_name,
|
213
|
+
def make_api(_domain_name,
|
214
|
+
name:, script: nil,
|
215
|
+
dns: nil,
|
216
|
+
mtls_truststore: nil,
|
217
|
+
cert: nil,
|
218
|
+
with_statements: [], &block)
|
219
|
+
|
220
|
+
# we ignore mtls_truststore here
|
191
221
|
@apis[name] = block
|
192
222
|
end
|
193
223
|
|
@@ -249,6 +279,4 @@ module Sumomo
|
|
249
279
|
|
250
280
|
map
|
251
281
|
end
|
252
|
-
|
253
|
-
singleton_class.send(:alias_method, :create_stack, :update_stack)
|
254
282
|
end
|
data/sumomo.gemspec
CHANGED
@@ -27,15 +27,17 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ['lib']
|
29
29
|
|
30
|
-
spec.add_development_dependency 'bundler'
|
31
|
-
spec.add_development_dependency 'rake'
|
32
|
-
spec.add_development_dependency 'rspec'
|
30
|
+
spec.add_development_dependency 'bundler'
|
31
|
+
spec.add_development_dependency 'rake'
|
32
|
+
spec.add_development_dependency 'rspec'
|
33
33
|
|
34
34
|
spec.add_dependency 'activesupport'
|
35
|
-
spec.add_dependency 'aws-sdk', '~>
|
35
|
+
spec.add_dependency 'aws-sdk', '~> 3'
|
36
|
+
spec.add_dependency 'ox'
|
36
37
|
spec.add_dependency 'hashie'
|
37
38
|
spec.add_dependency 'momo', '0.4.1'
|
38
39
|
spec.add_dependency 'rubyzip'
|
39
40
|
spec.add_dependency 's3cabinet'
|
40
41
|
spec.add_dependency 'trollop'
|
42
|
+
spec.add_dependency 'webrick'
|
41
43
|
end
|