sumomo 0.8.10 → 0.8.14
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/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 +16 -3
- data/lib/sumomo/api.rb +120 -9
- data/lib/sumomo/ec2.rb +2 -1
- data/lib/sumomo/stack.rb +7 -4
- data/lib/sumomo/version.rb +1 -1
- data/lib/sumomo.rb +23 -3
- data/sumomo.gemspec +6 -4
- data/update-spec.rb +381 -0
- metadata +47 -18
data/exe/sumomo
CHANGED
@@ -30,11 +30,21 @@ 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
|
37
|
-
Sumomo.
|
37
|
+
Sumomo.create_stack(name: ARGV[0], region: global_opts[:region]) do
|
38
|
+
proc = proc {}
|
39
|
+
eval File.read(local_opts[:filename]), proc.binding, local_opts[:filename]
|
40
|
+
end
|
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
|
38
48
|
proc = proc {}
|
39
49
|
eval File.read(local_opts[:filename]), proc.binding, local_opts[:filename]
|
40
50
|
end
|
@@ -46,7 +56,10 @@ cmd_opts = case cmd
|
|
46
56
|
when 'login'
|
47
57
|
puts "Login to stack #{ARGV[0]} instance at #{ARGV[1]}"
|
48
58
|
`aws s3 cp s3://#{ARGV[0]}/cloudformation/#{ARGV[0]}_master_key.pem x.txt`
|
49
|
-
key = JSON.parse(File.read('x.txt'))['value']
|
59
|
+
key = JSON.parse(File.read('x.txt'))['value'].
|
60
|
+
gsub('-----BEGIN RSA PRIVATE KEY----- ', "-----BEGIN RSA PRIVATE KEY-----\n").
|
61
|
+
gsub(' -----END RSA PRIVATE KEY-----', "\n-----END RSA PRIVATE KEY-----").
|
62
|
+
gsub(/(.{64}) /, "\\1\n")
|
50
63
|
File.write('key.pem', key)
|
51
64
|
`chmod 0600 key.pem`
|
52
65
|
exec "ssh -i 'key.pem' ec2-user@#{ARGV[1]} #{ARGV[2]}"
|
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
@@ -96,6 +96,7 @@ module Sumomo
|
|
96
96
|
call('Fn::Join', '', [
|
97
97
|
|
98
98
|
"#!/bin/bash -v\n",
|
99
|
+
"yum install -y aws-cfn-bootstrap\n",
|
99
100
|
"yum update -y aws-cfn-bootstrap\n",
|
100
101
|
|
101
102
|
"# Helper function\n",
|
@@ -510,7 +511,7 @@ module Sumomo
|
|
510
511
|
|
511
512
|
if ecs_cluster
|
512
513
|
ecs_config = <<~CONFIG
|
513
|
-
ECS_CLUSTER={{cluster_name}}
|
514
|
+
ECS_CLUSTER={{ cluster_name }}
|
514
515
|
ECS_ENGINE_AUTH_TYPE=docker
|
515
516
|
ECS_ENGINE_AUTH_DATA={"https://index.docker.io/v1/":{"username":"{{docker_username}}","password":"{{docker_password}}","email":"{{docker_email}}"}}
|
516
517
|
CONFIG
|
data/lib/sumomo/stack.rb
CHANGED
@@ -23,9 +23,10 @@ module Sumomo
|
|
23
23
|
description: "Lambda Function in #{@bucket_name}",
|
24
24
|
function_key: "cloudformation/lambda/function_#{name}",
|
25
25
|
handler: 'index.handler',
|
26
|
-
runtime: '
|
26
|
+
runtime: 'nodejs14.x',
|
27
27
|
memory_size: 128,
|
28
28
|
timeout: 30,
|
29
|
+
enable_logging: true,
|
29
30
|
role: nil)
|
30
31
|
|
31
32
|
name ||= make_default_resource_name('Lambda')
|
@@ -59,9 +60,11 @@ module Sumomo
|
|
59
60
|
Role role.Arn
|
60
61
|
end
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
63
|
+
if enable_logging
|
64
|
+
make 'AWS::Logs::LogGroup', name: "#{name}LogGroup" do
|
65
|
+
LogGroupName call('Fn::Join', '', ['/aws/lambda/', fun])
|
66
|
+
RetentionInDays 30
|
67
|
+
end
|
65
68
|
end
|
66
69
|
|
67
70
|
fun
|
data/lib/sumomo/version.rb
CHANGED
data/lib/sumomo.rb
CHANGED
@@ -36,7 +36,7 @@ module Sumomo
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def self.update_stack(name:, region:, sns_arn: nil, &block)
|
39
|
+
def self.update_stack(name:, region:, sns_arn: nil, changeset: false, &block)
|
40
40
|
cf = Aws::CloudFormation::Client.new(region: region)
|
41
41
|
s3 = Aws::S3::Client.new(region: region)
|
42
42
|
ec2 = Aws::EC2::Client.new(region: region)
|
@@ -117,11 +117,20 @@ module Sumomo
|
|
117
117
|
stack_name: name,
|
118
118
|
template_url: store.url('cloudformation/template'),
|
119
119
|
parameters: hidden_values,
|
120
|
+
disable_rollback: false,
|
120
121
|
capabilities: ['CAPABILITY_IAM']
|
121
122
|
}
|
122
123
|
|
123
124
|
begin
|
124
|
-
|
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
|
+
|
125
134
|
rescue StandardError => e
|
126
135
|
if e.message.end_with? 'does not exist'
|
127
136
|
update_options[:timeout_in_minutes] = @timeout if @timeout
|
@@ -134,6 +143,10 @@ module Sumomo
|
|
134
143
|
end
|
135
144
|
end
|
136
145
|
|
146
|
+
def self.curtimestr
|
147
|
+
Time.now.strftime('%Y%m%d%H%M%S')
|
148
|
+
end
|
149
|
+
|
137
150
|
def self.wait_for_stack(name:, region:)
|
138
151
|
cf = Aws::CloudFormation::Client.new(region: region)
|
139
152
|
|
@@ -197,7 +210,14 @@ module Sumomo
|
|
197
210
|
instance_eval(&block)
|
198
211
|
end
|
199
212
|
|
200
|
-
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
|
201
221
|
@apis[name] = block
|
202
222
|
end
|
203
223
|
|
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
|