cloud-mu 3.2.0 → 3.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/Dockerfile +1 -1
- data/ansible/roles/mu-nat/tasks/main.yml +3 -0
- data/bin/mu-adopt +12 -1
- data/bin/mu-aws-setup +41 -7
- data/bin/mu-azure-setup +34 -0
- data/bin/mu-configure +214 -119
- data/bin/mu-gcp-setup +37 -2
- data/bin/mu-load-config.rb +2 -1
- data/bin/mu-node-manage +3 -0
- data/bin/mu-refresh-ssl +67 -0
- data/bin/mu-run-tests +28 -6
- data/bin/mu-self-update +30 -10
- data/bin/mu-upload-chef-artifacts +30 -26
- data/cloud-mu.gemspec +10 -8
- data/cookbooks/mu-master/attributes/default.rb +5 -1
- data/cookbooks/mu-master/metadata.rb +2 -2
- data/cookbooks/mu-master/recipes/default.rb +81 -26
- data/cookbooks/mu-master/recipes/init.rb +197 -62
- data/cookbooks/mu-master/recipes/update_nagios_only.rb +1 -1
- data/cookbooks/mu-master/recipes/vault.rb +78 -77
- data/cookbooks/mu-master/templates/default/mods/rewrite.conf.erb +1 -0
- data/cookbooks/mu-master/templates/default/nagios.conf.erb +103 -0
- data/cookbooks/mu-master/templates/default/web_app.conf.erb +14 -30
- data/cookbooks/mu-tools/attributes/default.rb +12 -0
- data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
- data/cookbooks/mu-tools/libraries/helper.rb +98 -4
- data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
- data/cookbooks/mu-tools/recipes/apply_security.rb +31 -9
- data/cookbooks/mu-tools/recipes/aws_api.rb +8 -2
- data/cookbooks/mu-tools/recipes/base_repositories.rb +1 -1
- data/cookbooks/mu-tools/recipes/gcloud.rb +2 -9
- data/cookbooks/mu-tools/recipes/google_api.rb +7 -0
- data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
- data/cookbooks/mu-tools/resources/disk.rb +113 -42
- data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
- data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
- data/extras/Gemfile.lock.bootstrap +394 -0
- data/extras/bucketstubs/error.html +0 -0
- data/extras/bucketstubs/index.html +0 -0
- data/extras/clean-stock-amis +11 -3
- data/extras/generate-stock-images +6 -3
- data/extras/git_rpm/build.sh +20 -0
- data/extras/git_rpm/mugit.spec +53 -0
- data/extras/image-generators/AWS/centos7.yaml +19 -16
- data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
- data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -0
- data/extras/image-generators/VMWare/centos8.yaml +15 -0
- data/extras/openssl_rpm/build.sh +19 -0
- data/extras/openssl_rpm/mussl.spec +46 -0
- data/extras/python_rpm/muthon.spec +14 -4
- data/extras/ruby_rpm/muby.spec +9 -5
- data/extras/sqlite_rpm/build.sh +19 -0
- data/extras/sqlite_rpm/muqlite.spec +47 -0
- data/install/installer +7 -5
- data/modules/mommacat.ru +2 -2
- data/modules/mu.rb +14 -7
- data/modules/mu/adoption.rb +5 -5
- data/modules/mu/cleanup.rb +47 -25
- data/modules/mu/cloud.rb +29 -1
- data/modules/mu/cloud/dnszone.rb +0 -2
- data/modules/mu/cloud/machine_images.rb +1 -1
- data/modules/mu/cloud/providers.rb +6 -1
- data/modules/mu/cloud/resource_base.rb +16 -7
- data/modules/mu/cloud/ssh_sessions.rb +5 -1
- data/modules/mu/cloud/wrappers.rb +20 -7
- data/modules/mu/config.rb +28 -12
- data/modules/mu/config/bucket.rb +31 -2
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/container_cluster.rb +1 -1
- data/modules/mu/config/database.rb +3 -3
- data/modules/mu/config/dnszone.rb +4 -3
- data/modules/mu/config/endpoint.rb +1 -0
- data/modules/mu/config/firewall_rule.rb +1 -1
- data/modules/mu/config/function.rb +16 -7
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/notifier.rb +7 -18
- data/modules/mu/config/ref.rb +55 -9
- data/modules/mu/config/schema_helpers.rb +12 -3
- data/modules/mu/config/server.rb +11 -5
- data/modules/mu/config/server_pool.rb +2 -2
- data/modules/mu/config/vpc.rb +11 -10
- data/modules/mu/defaults/AWS.yaml +106 -106
- data/modules/mu/deploy.rb +40 -14
- data/modules/mu/groomers/chef.rb +2 -2
- data/modules/mu/master.rb +70 -3
- data/modules/mu/mommacat.rb +28 -9
- data/modules/mu/mommacat/daemon.rb +13 -7
- data/modules/mu/mommacat/naming.rb +2 -2
- data/modules/mu/mommacat/search.rb +16 -5
- data/modules/mu/mommacat/storage.rb +67 -32
- data/modules/mu/providers/aws.rb +298 -85
- data/modules/mu/providers/aws/alarm.rb +5 -5
- data/modules/mu/providers/aws/bucket.rb +284 -50
- data/modules/mu/providers/aws/cache_cluster.rb +26 -26
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/providers/aws/collection.rb +16 -16
- data/modules/mu/providers/aws/container_cluster.rb +84 -64
- data/modules/mu/providers/aws/database.rb +59 -55
- data/modules/mu/providers/aws/dnszone.rb +29 -12
- data/modules/mu/providers/aws/endpoint.rb +535 -50
- data/modules/mu/providers/aws/firewall_rule.rb +32 -26
- data/modules/mu/providers/aws/folder.rb +1 -1
- data/modules/mu/providers/aws/function.rb +300 -134
- data/modules/mu/providers/aws/group.rb +16 -14
- data/modules/mu/providers/aws/habitat.rb +4 -4
- data/modules/mu/providers/aws/job.rb +469 -0
- data/modules/mu/providers/aws/loadbalancer.rb +67 -45
- data/modules/mu/providers/aws/log.rb +17 -17
- data/modules/mu/providers/aws/msg_queue.rb +22 -13
- data/modules/mu/providers/aws/nosqldb.rb +99 -8
- data/modules/mu/providers/aws/notifier.rb +137 -65
- data/modules/mu/providers/aws/role.rb +119 -83
- data/modules/mu/providers/aws/search_domain.rb +166 -30
- data/modules/mu/providers/aws/server.rb +209 -118
- data/modules/mu/providers/aws/server_pool.rb +95 -130
- data/modules/mu/providers/aws/storage_pool.rb +19 -11
- data/modules/mu/providers/aws/user.rb +5 -5
- data/modules/mu/providers/aws/userdata/linux.erb +5 -4
- data/modules/mu/providers/aws/vpc.rb +109 -54
- data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
- data/modules/mu/providers/azure.rb +78 -12
- data/modules/mu/providers/azure/server.rb +20 -4
- data/modules/mu/providers/cloudformation/server.rb +1 -1
- data/modules/mu/providers/google.rb +21 -5
- data/modules/mu/providers/google/bucket.rb +1 -1
- data/modules/mu/providers/google/container_cluster.rb +1 -1
- data/modules/mu/providers/google/database.rb +1 -1
- data/modules/mu/providers/google/firewall_rule.rb +1 -1
- data/modules/mu/providers/google/folder.rb +7 -3
- data/modules/mu/providers/google/function.rb +66 -31
- data/modules/mu/providers/google/group.rb +1 -1
- data/modules/mu/providers/google/habitat.rb +1 -1
- data/modules/mu/providers/google/loadbalancer.rb +1 -1
- data/modules/mu/providers/google/role.rb +6 -3
- data/modules/mu/providers/google/server.rb +1 -1
- data/modules/mu/providers/google/server_pool.rb +1 -1
- data/modules/mu/providers/google/user.rb +1 -1
- data/modules/mu/providers/google/vpc.rb +28 -3
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/aws-servers-with-handrolled-iam.yaml +37 -0
- data/modules/tests/centos6.yaml +4 -0
- data/modules/tests/centos7.yaml +4 -0
- data/modules/tests/ecs.yaml +2 -2
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/k8s.yaml +1 -1
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +5 -5
- data/modules/tests/regrooms/rds.yaml +5 -5
- data/modules/tests/server-with-scrub-muisms.yaml +1 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +2 -2
- metadata +42 -17
data/modules/mu/providers/aws.rb
CHANGED
|
@@ -16,7 +16,6 @@ require "net/http"
|
|
|
16
16
|
require 'open-uri'
|
|
17
17
|
require 'timeout'
|
|
18
18
|
require 'inifile'
|
|
19
|
-
gem 'aws-sdk-core'
|
|
20
19
|
autoload :Aws, "aws-sdk-core"
|
|
21
20
|
|
|
22
21
|
|
|
@@ -54,14 +53,19 @@ module MU
|
|
|
54
53
|
def self.resourceInitHook(cloudobj, _deploy)
|
|
55
54
|
class << self
|
|
56
55
|
attr_reader :cloudformation_data
|
|
56
|
+
attr_reader :region
|
|
57
57
|
end
|
|
58
|
+
return if !cloudobj
|
|
58
59
|
cloudobj.instance_variable_set(:@cloudformation_data, {})
|
|
60
|
+
|
|
61
|
+
cloudobj.instance_variable_set(:@region, cloudobj.config['region'])
|
|
59
62
|
end
|
|
60
63
|
|
|
61
64
|
# Load some credentials for using the AWS API
|
|
62
65
|
# @param name [String]: The name of the mu.yaml AWS credential set to use. If not specified, will use the default credentials, and set the global Aws.config credentials to those.
|
|
63
66
|
# @return [Aws::Credentials]
|
|
64
67
|
def self.loadCredentials(name = nil)
|
|
68
|
+
gem 'aws-sdk-core'
|
|
65
69
|
@@creds_loaded ||= {}
|
|
66
70
|
|
|
67
71
|
if name.nil?
|
|
@@ -124,10 +128,14 @@ module MU
|
|
|
124
128
|
# pull access key and secret from a vault
|
|
125
129
|
begin
|
|
126
130
|
vault, item = cred_cfg["credentials"].split(/:/)
|
|
127
|
-
data =
|
|
128
|
-
|
|
131
|
+
data = if !vault or !item
|
|
132
|
+
raise MuError.new "AWS #{name} credentials field value '#{cred_cfg["credentials"]}' malformed, should be vaultname:itemname", details: cred_cfg
|
|
133
|
+
else
|
|
134
|
+
MU::Groomer::Chef.getSecret(vault: vault, item: item).to_h
|
|
135
|
+
end
|
|
136
|
+
if data and data["access_key"] and data["access_secret"]
|
|
129
137
|
cred_obj = Aws::Credentials.new(
|
|
130
|
-
|
|
138
|
+
data['access_key'], data['access_secret']
|
|
131
139
|
)
|
|
132
140
|
if name.nil?
|
|
133
141
|
# Aws.config = {
|
|
@@ -137,10 +145,10 @@ module MU
|
|
|
137
145
|
# }
|
|
138
146
|
end
|
|
139
147
|
else
|
|
140
|
-
|
|
148
|
+
raise MuError.new "AWS #{name} credentials vault:item #{cred_cfg["credentials"]} specified, but is missing access_key or access_secret elements", details: cred_cfg
|
|
141
149
|
end
|
|
142
150
|
rescue MU::Groomer::MuNoSuchSecret
|
|
143
|
-
|
|
151
|
+
raise MuError.new "AWS #{name} credentials vault:item #{cred_cfg["credentials"]} specified, but does not exist", details: cred_cfg
|
|
144
152
|
end
|
|
145
153
|
end
|
|
146
154
|
|
|
@@ -186,6 +194,7 @@ end
|
|
|
186
194
|
# @param r [String]
|
|
187
195
|
# @return [String]
|
|
188
196
|
def self.validate_region(r, credentials: nil)
|
|
197
|
+
require "aws-sdk-ec2"
|
|
189
198
|
begin
|
|
190
199
|
MU::Cloud::AWS.ec2(region: r, credentials: credentials).describe_availability_zones.availability_zones.first.region_name
|
|
191
200
|
rescue ::Aws::EC2::Errors::UnauthorizedOperation => e
|
|
@@ -204,6 +213,7 @@ end
|
|
|
204
213
|
# @param othertags [Array<Hash>]: Miscellaneous custom tags, in Basket of Kittens style
|
|
205
214
|
# @return [void]
|
|
206
215
|
def self.createStandardTags(resource = nil, region: MU.curRegion, credentials: nil, optional: true, nametag: nil, othertags: nil)
|
|
216
|
+
require "aws-sdk-ec2"
|
|
207
217
|
tags = []
|
|
208
218
|
MU::MommaCat.listStandardTags.each_pair { |name, value|
|
|
209
219
|
tags << {key: name, value: value} if !value.nil?
|
|
@@ -261,20 +271,33 @@ end
|
|
|
261
271
|
@@myVPCObj
|
|
262
272
|
end
|
|
263
273
|
|
|
264
|
-
# If we've configured AWS as a provider, or are simply hosted in AWS,
|
|
274
|
+
# If we've configured AWS as a provider, or are simply hosted in AWS,
|
|
265
275
|
# decide what our default region is.
|
|
266
|
-
def self.myRegion(credentials = nil)
|
|
267
|
-
|
|
276
|
+
def self.myRegion(credentials = nil, debug: false)
|
|
277
|
+
loglevel = debug ? MU::NOTICE : MU::DEBUG
|
|
278
|
+
if @@myRegion_var
|
|
279
|
+
MU.log "AWS.myRegion: returning #{@@myRegion_var} from cache", loglevel
|
|
280
|
+
return @@myRegion_var
|
|
281
|
+
end
|
|
268
282
|
|
|
283
|
+
MU.log "AWS.myRegion: credConfig", loglevel, details: credConfig
|
|
284
|
+
MU.log "AWS.myRegion: hosted?", loglevel, details: hosted?.to_s
|
|
285
|
+
MU.log "AWS.myRegion: ENV['EC2_REGION']", loglevel, details: ENV['EC2_REGION']
|
|
286
|
+
MU.log "AWS.myRegion: $MU_CFG['aws']", loglevel, details: $MU_CFG['aws']
|
|
269
287
|
if credConfig.nil? and !hosted? and !ENV['EC2_REGION']
|
|
288
|
+
MU.log "AWS.myRegion: nothing of use set, returning", loglevel
|
|
270
289
|
return nil
|
|
271
290
|
end
|
|
272
291
|
|
|
273
292
|
if $MU_CFG and $MU_CFG['aws']
|
|
274
293
|
$MU_CFG['aws'].each_pair { |credset, cfg|
|
|
294
|
+
MU.log "AWS.myRegion: #{credset} != #{credentials} ?", loglevel, details: cfg
|
|
275
295
|
next if credentials and credset != credentials
|
|
296
|
+
MU.log "AWS.myRegion: validating credset #{credset}", loglevel, details: cfg
|
|
276
297
|
next if !cfg['region']
|
|
277
|
-
|
|
298
|
+
MU.log "AWS.myRegion: validation response", loglevel, details: validate_region(cfg['region'], credentials: credset)
|
|
299
|
+
if (cfg['default'] or !@@myRegion_var or $MU_CFG['aws'].size == 1) and validate_region(cfg['region'], credentials: credset)
|
|
300
|
+
MU.log "AWS.myRegion: liking this set", loglevel, details: cfg
|
|
278
301
|
@@myRegion_var = cfg['region']
|
|
279
302
|
break if cfg['default'] or credentials
|
|
280
303
|
end
|
|
@@ -286,15 +309,21 @@ end
|
|
|
286
309
|
(Aws.config['access_key'] and Aws.config['access_secret'])
|
|
287
310
|
)
|
|
288
311
|
# Make sure this string is valid by way of the API
|
|
312
|
+
MU.log "AWS.myRegion: using ENV", loglevel, details: ENV
|
|
289
313
|
@@myRegion_var = ENV['EC2_REGION']
|
|
290
314
|
end
|
|
291
315
|
|
|
292
316
|
if hosted? and !@@myRegion_var
|
|
293
317
|
# hacky, but useful in a pinch (and if we're hosted in AWS)
|
|
294
318
|
az_str = MU::Cloud::AWS.getAWSMetaData("placement/availability-zone")
|
|
319
|
+
MU.log "AWS.myRegion: using hosted", loglevel, details: az_str
|
|
295
320
|
@@myRegion_var = az_str.sub(/[a-z]$/i, "") if az_str
|
|
296
321
|
end
|
|
297
322
|
|
|
323
|
+
if credConfig and credConfig["region"]
|
|
324
|
+
@@myRegion_var ||= credConfig["region"]
|
|
325
|
+
end
|
|
326
|
+
|
|
298
327
|
@@myRegion_var
|
|
299
328
|
end
|
|
300
329
|
|
|
@@ -382,8 +411,9 @@ end
|
|
|
382
411
|
# Plant a Mu deploy secret into a storage bucket somewhere for so our kittens can consume it
|
|
383
412
|
# @param deploy_id [String]: The deploy for which we're writing the secret
|
|
384
413
|
# @param value [String]: The contents of the secret
|
|
385
|
-
def self.writeDeploySecret(
|
|
386
|
-
|
|
414
|
+
def self.writeDeploySecret(deploy, value, name = nil, credentials: nil)
|
|
415
|
+
require "aws-sdk-s3"
|
|
416
|
+
name ||= deploy.deploy_id+"-secret"
|
|
387
417
|
begin
|
|
388
418
|
MU.log "Writing #{name} to S3 bucket #{adminBucketName(credentials)}"
|
|
389
419
|
MU::Cloud::AWS.s3(region: myRegion, credentials: credentials).put_object(
|
|
@@ -401,35 +431,35 @@ end
|
|
|
401
431
|
def self.cloudtrailBucketPolicy(credentials = nil)
|
|
402
432
|
cfg = credConfig(credentials)
|
|
403
433
|
policy_json = '{
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
434
|
+
"Version": "2012-10-17",
|
|
435
|
+
"Statement": [
|
|
436
|
+
{
|
|
437
|
+
"Sid": "AWSCloudTrailAclCheck20131101",
|
|
438
|
+
"Effect": "Allow",
|
|
409
439
|
"Principal": {
|
|
410
440
|
"AWS": "arn:'+(MU::Cloud::AWS.isGovCloud?(cfg['region']) ? "aws-us-gov" : "aws")+':iam::<%= MU.account_number %>:root",
|
|
411
441
|
"Service": "cloudtrail.amazonaws.com"
|
|
412
442
|
},
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
443
|
+
"Action": "s3:GetBucketAcl",
|
|
444
|
+
"Resource": "arn:'+(MU::Cloud::AWS.isGovCloud?(cfg['region']) ? "aws-us-gov" : "aws")+':s3:::'+MU::Cloud::AWS.adminBucketName(credentials)+'"
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"Sid": "AWSCloudTrailWrite20131101",
|
|
448
|
+
"Effect": "Allow",
|
|
419
449
|
"Principal": {
|
|
420
450
|
"AWS": "arn:'+(MU::Cloud::AWS.isGovCloud?(cfg['region']) ? "aws-us-gov" : "aws")+':iam::'+credToAcct(credentials)+':root",
|
|
421
451
|
"Service": "cloudtrail.amazonaws.com"
|
|
422
452
|
},
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
453
|
+
"Action": "s3:PutObject",
|
|
454
|
+
"Resource": "arn:'+(MU::Cloud::AWS.isGovCloud?(cfg['region']) ? "aws-us-gov" : "aws")+':s3:::'+MU::Cloud::AWS.adminBucketName(credentials)+'/AWSLogs/'+credToAcct(credentials)+'/*",
|
|
455
|
+
"Condition": {
|
|
456
|
+
"StringEquals": {
|
|
457
|
+
"s3:x-amz-acl": "bucket-owner-full-control"
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
]
|
|
462
|
+
}'
|
|
433
463
|
ERB.new(policy_json).result
|
|
434
464
|
end
|
|
435
465
|
|
|
@@ -440,6 +470,53 @@ end
|
|
|
440
470
|
MU::Cloud::AWS.hosted?
|
|
441
471
|
end
|
|
442
472
|
|
|
473
|
+
# If we're in AWS and NVME-aware, return a mapping of AWS-side device
|
|
474
|
+
# names to actual NVME devices.
|
|
475
|
+
# @return [Hash]
|
|
476
|
+
def self.attachedNVMeDisks
|
|
477
|
+
if !hosted? or !File.executable?("/bin/lsblk") or !File.executable?("/sbin/nvme")
|
|
478
|
+
return {}
|
|
479
|
+
end
|
|
480
|
+
map = {}
|
|
481
|
+
devices = MU::Master.listBlockDevices
|
|
482
|
+
return {} if !devices
|
|
483
|
+
devices.each { |d|
|
|
484
|
+
if d =~ /^\/dev\/nvme/
|
|
485
|
+
%x{/sbin/nvme id-ctrl -v #{d}}.each_line { |desc|
|
|
486
|
+
if desc.match(/^0000: (?:[0-9a-f]{2} ){16}"(.+?)\./)
|
|
487
|
+
virt_dev = Regexp.last_match[1]
|
|
488
|
+
map[virt_dev] = d
|
|
489
|
+
break
|
|
490
|
+
end
|
|
491
|
+
}
|
|
492
|
+
end
|
|
493
|
+
}
|
|
494
|
+
map
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
# Map our own idea of what a block device is called back to whatever AWS
|
|
498
|
+
# and the operating system decided on amongst themselves. This currently
|
|
499
|
+
# exists to map generic "xvd[a-z]" style names back to real NVMe devices.
|
|
500
|
+
# @param dev [String]
|
|
501
|
+
def self.realDevicePath(dev)
|
|
502
|
+
return dev if !hosted?
|
|
503
|
+
value = nil
|
|
504
|
+
should_retry = Proc.new {
|
|
505
|
+
!value and MU::Master.nvme?
|
|
506
|
+
}
|
|
507
|
+
MU.retrier(loop_if: should_retry, wait: 5, max: 6) {
|
|
508
|
+
map = attachedNVMeDisks
|
|
509
|
+
value = if map[dev]
|
|
510
|
+
map[dev]
|
|
511
|
+
elsif map[dev.gsub(/.*?\//, '')]
|
|
512
|
+
map[dev.gsub(/.*?\//, '')]
|
|
513
|
+
else
|
|
514
|
+
dev # be nice to actually handle this too
|
|
515
|
+
end
|
|
516
|
+
}
|
|
517
|
+
value
|
|
518
|
+
end
|
|
519
|
+
|
|
443
520
|
# Determine whether we (the Mu master, presumably) are hosted in this
|
|
444
521
|
# cloud.
|
|
445
522
|
# @return [Boolean]
|
|
@@ -457,7 +534,7 @@ end
|
|
|
457
534
|
|
|
458
535
|
begin
|
|
459
536
|
Timeout.timeout(4) do
|
|
460
|
-
instance_id = open("http://169.254.169.254/latest/meta-data/instance-id").read
|
|
537
|
+
instance_id = URI.open("http://169.254.169.254/latest/meta-data/instance-id").read
|
|
461
538
|
if !instance_id.nil? and instance_id.size > 0
|
|
462
539
|
@@is_in_aws = true
|
|
463
540
|
region = getAWSMetaData("placement/availability-zone").sub(/[a-z]$/i, "")
|
|
@@ -550,7 +627,9 @@ end
|
|
|
550
627
|
def self.credToAcct(name = nil)
|
|
551
628
|
creds = credConfig(name)
|
|
552
629
|
|
|
553
|
-
|
|
630
|
+
if creds['account_number'] and !creds['account_number'].empty?
|
|
631
|
+
return creds['account_number']
|
|
632
|
+
end
|
|
554
633
|
|
|
555
634
|
acct_num = MU::Cloud::AWS.iam(credentials: name).list_users.users.first.arn.split(/:/)[4]
|
|
556
635
|
acct_num.to_s
|
|
@@ -564,17 +643,18 @@ end
|
|
|
564
643
|
end
|
|
565
644
|
|
|
566
645
|
$MU_CFG['aws'].keys
|
|
567
|
-
end
|
|
646
|
+
end
|
|
568
647
|
|
|
569
648
|
# Resolve the administrative S3 bucket for a given credential set, or
|
|
570
649
|
# return a default.
|
|
571
650
|
# @param credentials [String]
|
|
572
651
|
# @return [String]
|
|
573
652
|
def self.adminBucketName(credentials = nil)
|
|
653
|
+
require "aws-sdk-s3"
|
|
574
654
|
cfg = credConfig(credentials)
|
|
575
655
|
return nil if !cfg
|
|
576
656
|
if !cfg['log_bucket_name']
|
|
577
|
-
cfg['log_bucket_name'] = $MU_CFG['hostname']
|
|
657
|
+
cfg['log_bucket_name'] = $MU_CFG['hostname']
|
|
578
658
|
MU.log "No AWS log bucket defined for credentials #{credentials}, attempting to use default of #{cfg['log_bucket_name']}", MU::WARN
|
|
579
659
|
end
|
|
580
660
|
resp = MU::Cloud::AWS.s3(credentials: credentials).list_buckets
|
|
@@ -608,7 +688,7 @@ end
|
|
|
608
688
|
|
|
609
689
|
# Return the $MU_CFG data associated with a particular profile/name/set of
|
|
610
690
|
# credentials. If no account name is specified, will return one flagged as
|
|
611
|
-
# default. Returns nil if AWS is not configured. Throws an exception if
|
|
691
|
+
# default. Returns nil if AWS is not configured. Throws an exception if
|
|
612
692
|
# an account name is specified which does not exist.
|
|
613
693
|
# @param name [String]: The name of the key under 'aws' in mu.yaml to return
|
|
614
694
|
# @return [Hash,nil]
|
|
@@ -623,10 +703,13 @@ end
|
|
|
623
703
|
|
|
624
704
|
if hosted?
|
|
625
705
|
begin
|
|
626
|
-
|
|
627
|
-
if
|
|
628
|
-
|
|
629
|
-
|
|
706
|
+
iam_blob = getAWSMetaData("iam/info")
|
|
707
|
+
if iam_blob
|
|
708
|
+
iam_data = JSON.parse(iam_blob)
|
|
709
|
+
if iam_data["InstanceProfileArn"] and !iam_data["InstanceProfileArn"].empty?
|
|
710
|
+
@@my_hosted_cfg = hosted_config
|
|
711
|
+
return name_only ? "#default" : @@my_hosted_cfg
|
|
712
|
+
end
|
|
630
713
|
end
|
|
631
714
|
rescue JSON::ParserError => e
|
|
632
715
|
end
|
|
@@ -672,8 +755,8 @@ end
|
|
|
672
755
|
next
|
|
673
756
|
end
|
|
674
757
|
acct_num = MU::Cloud::AWS.iam(credentials: acctname).list_users.users.first.arn.split(/:/)[4]
|
|
675
|
-
|
|
676
|
-
|
|
758
|
+
cfg['account_number'] ||= acct_num.to_s
|
|
759
|
+
if acct_num.to_s == name.to_s
|
|
677
760
|
@@acct_to_profile_map[name.to_s] = cfg
|
|
678
761
|
return name_only ? name.to_s : cfg
|
|
679
762
|
end
|
|
@@ -690,6 +773,7 @@ end
|
|
|
690
773
|
# XXX this needs to be "myAccountNumber" or somesuch
|
|
691
774
|
# XXX and maybe do the IAM thing for arbitrary, non-resident accounts
|
|
692
775
|
def self.account_number
|
|
776
|
+
require "aws-sdk-ec2"
|
|
693
777
|
return nil if credConfig.nil?
|
|
694
778
|
return @@my_acct_num if @@my_acct_num
|
|
695
779
|
loadCredentials
|
|
@@ -747,7 +831,7 @@ end
|
|
|
747
831
|
@@regions.keys.uniq
|
|
748
832
|
end
|
|
749
833
|
|
|
750
|
-
# XXX GovCloud doesn't show up if you query a commercial endpoint... that's
|
|
834
|
+
# XXX GovCloud doesn't show up if you query a commercial endpoint... that's
|
|
751
835
|
# *probably* ok for most purposes? We can't call listAZs on it from out here
|
|
752
836
|
# apparently, so getting around it is nontrivial
|
|
753
837
|
# if !@@regions.has_key?("us-gov-west-1")
|
|
@@ -772,6 +856,7 @@ end
|
|
|
772
856
|
# @param public_key [String]: The public key
|
|
773
857
|
# @return [Array<String>]: keypairname, ssh_private_key, ssh_public_key
|
|
774
858
|
def self.createEc2SSHKey(keyname, public_key, credentials: nil)
|
|
859
|
+
require "aws-sdk-ec2"
|
|
775
860
|
# We replicate this key in all regions
|
|
776
861
|
if !MU::Cloud::CloudFormation.emitCloudFormation
|
|
777
862
|
MU::Cloud::AWS.listRegions.each { |region|
|
|
@@ -800,8 +885,16 @@ end
|
|
|
800
885
|
def self.listInstanceTypes(region = myRegion)
|
|
801
886
|
return @@instance_types if @@instance_types and @@instance_types[region]
|
|
802
887
|
return {} if credConfig.nil?
|
|
888
|
+
if region.nil?
|
|
889
|
+
region = myRegion(debug: true)
|
|
890
|
+
end
|
|
891
|
+
return {} if region.nil?
|
|
803
892
|
|
|
804
893
|
human_region = @@regionLookup[region]
|
|
894
|
+
if human_region.nil?
|
|
895
|
+
MU.log "Failed to map a Pricing API region name from #{region}", MU::ERR
|
|
896
|
+
return {}
|
|
897
|
+
end
|
|
805
898
|
|
|
806
899
|
@@instance_types ||= {}
|
|
807
900
|
@@instance_types[region] ||= {}
|
|
@@ -844,6 +937,8 @@ end
|
|
|
844
937
|
@@instance_types
|
|
845
938
|
end
|
|
846
939
|
|
|
940
|
+
@@certificates = {}
|
|
941
|
+
|
|
847
942
|
# AWS can stash API-available certificates in Amazon Certificate Manager
|
|
848
943
|
# or in IAM. Rather than make people crazy trying to get the syntax
|
|
849
944
|
# correct in our Baskets of Kittens, let's have a helper that tries to do
|
|
@@ -852,21 +947,25 @@ end
|
|
|
852
947
|
# @param name [String]: The name of the cert. For IAM certs this can be any IAM name; for ACM, it's usually the domain name. If multiple matches are found, or no matches, an exception is raised.
|
|
853
948
|
# @param id [String]: The ARN of a known certificate. We just validate that it exists. This is ignored if a name parameter is supplied.
|
|
854
949
|
# @return [String]: The ARN of a matching certificate that is known to exist. If it is an ACM certificate, we also know that it is not expired.
|
|
855
|
-
def self.findSSLCertificate(name: nil, id: nil, region: myRegion)
|
|
856
|
-
|
|
950
|
+
def self.findSSLCertificate(name: nil, id: nil, region: myRegion, credentials: nil, raise_on_missing: true)
|
|
951
|
+
require "aws-sdk-iam"
|
|
952
|
+
if (name.nil? or name.empty?) and (id.nil? or id.empty?)
|
|
857
953
|
raise MuError, "Can't call findSSLCertificate without specifying either a name or an id"
|
|
858
954
|
end
|
|
955
|
+
if id and @@certificates[id]
|
|
956
|
+
return [id, @@certificates[id]]
|
|
957
|
+
end
|
|
859
958
|
|
|
860
959
|
if !name.nil? and !name.empty?
|
|
861
960
|
matches = []
|
|
862
|
-
acmcerts = MU::Cloud::AWS.acm(region: region).list_certificates(
|
|
961
|
+
acmcerts = MU::Cloud::AWS.acm(region: region, credentials: credentials).list_certificates(
|
|
863
962
|
certificate_statuses: ["ISSUED"]
|
|
864
963
|
)
|
|
865
964
|
acmcerts.certificate_summary_list.each { |cert|
|
|
866
965
|
matches << cert.certificate_arn if cert.domain_name == name
|
|
867
966
|
}
|
|
868
967
|
begin
|
|
869
|
-
iamcert = MU::Cloud::AWS.iam.get_server_certificate(
|
|
968
|
+
iamcert = MU::Cloud::AWS.iam(credentials: credentials).get_server_certificate(
|
|
870
969
|
server_certificate_name: name
|
|
871
970
|
)
|
|
872
971
|
rescue Aws::IAM::Errors::ValidationError, Aws::IAM::Errors::NoSuchEntity
|
|
@@ -876,32 +975,45 @@ end
|
|
|
876
975
|
matches << iamcert.server_certificate.server_certificate_metadata.arn
|
|
877
976
|
end
|
|
878
977
|
if matches.size == 1
|
|
879
|
-
|
|
978
|
+
id = matches.first
|
|
880
979
|
elsif matches.size == 0
|
|
881
|
-
|
|
980
|
+
if raise_on_missing
|
|
981
|
+
raise MuError, "No IAM or ACM certificate named #{name} was found in #{region}"
|
|
982
|
+
else
|
|
983
|
+
return nil
|
|
984
|
+
end
|
|
882
985
|
elsif matches.size > 1
|
|
883
|
-
raise MuError, "Multiple certificates named #{name} were found in #{region}. Remove extras or use ssl_certificate_id to supply the exact ARN of the one you want to use."
|
|
986
|
+
raise MuError, "Multiple certificates named #{name} were found in #{region}. Remove extras or use ssl_certificate_id to supply the exact ARN of the one you want to use."
|
|
884
987
|
end
|
|
885
988
|
end
|
|
886
989
|
|
|
990
|
+
domains = []
|
|
991
|
+
|
|
887
992
|
if id.match(/^arn:aws(?:-us-gov)?:acm/)
|
|
888
|
-
resp = MU::Cloud::AWS.acm(region: region).
|
|
993
|
+
resp = MU::Cloud::AWS.acm(region: region).describe_certificate(
|
|
889
994
|
certificate_arn: id
|
|
890
995
|
)
|
|
891
|
-
|
|
996
|
+
|
|
997
|
+
if resp.nil? or resp.certificate.nil?
|
|
892
998
|
raise MuError, "No such ACM certificate '#{id}'"
|
|
893
999
|
end
|
|
1000
|
+
domains << resp.certificate.domain_name
|
|
1001
|
+
if resp.certificate.subject_alternative_names
|
|
1002
|
+
domains.concat(resp.certificate.subject_alternative_names)
|
|
1003
|
+
end
|
|
894
1004
|
elsif id.match(/^arn:aws(?:-us-gov)?:iam/)
|
|
895
1005
|
resp = MU::Cloud::AWS.iam.list_server_certificates
|
|
896
1006
|
if resp.nil?
|
|
897
1007
|
raise MuError, "No such IAM certificate '#{id}'"
|
|
898
1008
|
end
|
|
899
1009
|
resp.server_certificate_metadata_list.each { |cert|
|
|
1010
|
+
|
|
900
1011
|
if cert.arn == id
|
|
901
1012
|
if cert.expiration < Time.now
|
|
902
1013
|
MU.log "IAM SSL certificate #{cert.server_certificate_name} (#{id}) is EXPIRED", MU::WARN
|
|
903
1014
|
end
|
|
904
|
-
|
|
1015
|
+
@@certificates[id] = [cert.server_certificate_name]
|
|
1016
|
+
return [id, [cert.server_certificate_name]]
|
|
905
1017
|
end
|
|
906
1018
|
}
|
|
907
1019
|
raise MuError, "No such IAM certificate '#{id}'"
|
|
@@ -909,7 +1021,56 @@ end
|
|
|
909
1021
|
raise MuError, "The format of '#{id}' doesn't look like an ARN for either Amazon Certificate Manager or IAM"
|
|
910
1022
|
end
|
|
911
1023
|
|
|
912
|
-
id
|
|
1024
|
+
@@certificates[id] = domains.uniq
|
|
1025
|
+
[id, domains.uniq]
|
|
1026
|
+
end
|
|
1027
|
+
|
|
1028
|
+
# Given a domain name and an ACM or IAM certificate identifier, sort out
|
|
1029
|
+
# whether the domain name is "covered" by the certificate
|
|
1030
|
+
# @param name [String]
|
|
1031
|
+
# @param cert_id [String]
|
|
1032
|
+
# @return [Boolean]
|
|
1033
|
+
def self.nameMatchesCertificate(name, cert_id)
|
|
1034
|
+
_id, domains = findSSLCertificate(id: cert_id)
|
|
1035
|
+
return false if !domains
|
|
1036
|
+
domains.each { |dom|
|
|
1037
|
+
if dom == name or
|
|
1038
|
+
(dom =~ /^\*/ and name =~ /.*#{Regexp.quote(dom[1..-1])}/)
|
|
1039
|
+
return true
|
|
1040
|
+
end
|
|
1041
|
+
}
|
|
1042
|
+
false
|
|
1043
|
+
end
|
|
1044
|
+
|
|
1045
|
+
# Given a {MU::Config::Ref} block for an IAM or ACM SSL certificate,
|
|
1046
|
+
# look up and validate the specified certificate. This is intended to be
|
|
1047
|
+
# invoked from resource implementations' +validateConfig+ methods.
|
|
1048
|
+
# @param certblock [Hash,MU::Config::Ref]:
|
|
1049
|
+
# @param region [String]: Default region to use when looking up the certificate, if its configuration block does not specify any
|
|
1050
|
+
# @param credentials [String]: Default credentials to use when looking up the certificate, if its configuration block does not specify any
|
|
1051
|
+
# @return [Boolean]
|
|
1052
|
+
def self.resolveSSLCertificate(certblock, region: nil, credentials: nil)
|
|
1053
|
+
return false if !certblock
|
|
1054
|
+
ok = true
|
|
1055
|
+
|
|
1056
|
+
certblock['region'] ||= region if !certblock['id']
|
|
1057
|
+
certblock['credentials'] ||= credentials
|
|
1058
|
+
cert_arn, cert_domains = MU::Cloud::AWS.findSSLCertificate(
|
|
1059
|
+
name: certblock["name"],
|
|
1060
|
+
id: certblock["id"],
|
|
1061
|
+
region: certblock['region'],
|
|
1062
|
+
credentials: certblock['credentials']
|
|
1063
|
+
)
|
|
1064
|
+
|
|
1065
|
+
if cert_arn
|
|
1066
|
+
certblock['id'] ||= cert_arn
|
|
1067
|
+
end
|
|
1068
|
+
|
|
1069
|
+
['region', 'credentials'].each { |field|
|
|
1070
|
+
certblock.delete(field) if certblock[field].nil?
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
[cert_arn, cert_domains]
|
|
913
1074
|
end
|
|
914
1075
|
|
|
915
1076
|
# Amazon Certificate Manager API
|
|
@@ -1029,6 +1190,14 @@ end
|
|
|
1029
1190
|
@@cloudwatchlogs_api[credentials][region]
|
|
1030
1191
|
end
|
|
1031
1192
|
|
|
1193
|
+
# Amazon's CloudWatchEvents API
|
|
1194
|
+
def self.cloudwatchevents(region: MU.curRegion, credentials: nil)
|
|
1195
|
+
region ||= myRegion
|
|
1196
|
+
@@cloudwatchevents_api[credentials] ||= {}
|
|
1197
|
+
@@cloudwatchevents_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "CloudWatchEvents", region: region, credentials: credentials)
|
|
1198
|
+
@@cloudwatchevents_api[credentials][region]
|
|
1199
|
+
end
|
|
1200
|
+
|
|
1032
1201
|
# Amazon's CloudFront API
|
|
1033
1202
|
def self.cloudfront(region: MU.curRegion, credentials: nil)
|
|
1034
1203
|
region ||= myRegion
|
|
@@ -1044,7 +1213,7 @@ end
|
|
|
1044
1213
|
@@elasticache_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "ElastiCache", region: region, credentials: credentials)
|
|
1045
1214
|
@@elasticache_api[credentials][region]
|
|
1046
1215
|
end
|
|
1047
|
-
|
|
1216
|
+
|
|
1048
1217
|
# Amazon's SNS API
|
|
1049
1218
|
def self.sns(region: MU.curRegion, credentials: nil)
|
|
1050
1219
|
region ||= myRegion
|
|
@@ -1052,7 +1221,7 @@ end
|
|
|
1052
1221
|
@@sns_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "SNS", region: region, credentials: credentials)
|
|
1053
1222
|
@@sns_api[credentials][region]
|
|
1054
1223
|
end
|
|
1055
|
-
|
|
1224
|
+
|
|
1056
1225
|
# Amazon's SQS API
|
|
1057
1226
|
def self.sqs(region: MU.curRegion, credentials: nil)
|
|
1058
1227
|
region ||= myRegion
|
|
@@ -1084,7 +1253,7 @@ end
|
|
|
1084
1253
|
@@apig_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "APIGateway", region: region, credentials: credentials)
|
|
1085
1254
|
@@apig_api[credentials][region]
|
|
1086
1255
|
end
|
|
1087
|
-
|
|
1256
|
+
|
|
1088
1257
|
# Amazon's Cloudwatch Events API
|
|
1089
1258
|
def self.cloudwatch_events(region = MU.cureRegion)
|
|
1090
1259
|
region ||= myRegion
|
|
@@ -1117,6 +1286,14 @@ end
|
|
|
1117
1286
|
@@dynamo_api[credentials][region]
|
|
1118
1287
|
end
|
|
1119
1288
|
|
|
1289
|
+
# Amazon's DynamoStream API
|
|
1290
|
+
def self.dynamostream(region: MU.curRegion, credentials: nil)
|
|
1291
|
+
region ||= myRegion
|
|
1292
|
+
@@dynamostream_api[credentials] ||= {}
|
|
1293
|
+
@@dynamostream_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "DynamoDBStreams", region: region, credentials: credentials)
|
|
1294
|
+
@@dynamostream_api[credentials][region]
|
|
1295
|
+
end
|
|
1296
|
+
|
|
1120
1297
|
# Amazon's Pricing API
|
|
1121
1298
|
def self.pricing(region: MU.curRegion, credentials: nil)
|
|
1122
1299
|
region ||= myRegion
|
|
@@ -1165,6 +1342,14 @@ end
|
|
|
1165
1342
|
@@kms_api[credentials][region]
|
|
1166
1343
|
end
|
|
1167
1344
|
|
|
1345
|
+
# Amazon's CloudFront API
|
|
1346
|
+
def self.cloudfront(region: MU.curRegion, credentials: nil)
|
|
1347
|
+
region ||= myRegion
|
|
1348
|
+
@@cloudfront_api[credentials] ||= {}
|
|
1349
|
+
@@cloudfront_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "CloudFront", region: region, credentials: credentials)
|
|
1350
|
+
@@cloudfront_api[credentials][region]
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1168
1353
|
# Amazon's Organizations API
|
|
1169
1354
|
def self.orgs(credentials: nil)
|
|
1170
1355
|
@@organizations_api ||= {}
|
|
@@ -1181,7 +1366,7 @@ end
|
|
|
1181
1366
|
begin
|
|
1182
1367
|
response = nil
|
|
1183
1368
|
Timeout.timeout(1) do
|
|
1184
|
-
response = open("#{base_url}/#{param}").read
|
|
1369
|
+
response = URI.open("#{base_url}/#{param}").read
|
|
1185
1370
|
end
|
|
1186
1371
|
|
|
1187
1372
|
response
|
|
@@ -1206,6 +1391,7 @@ end
|
|
|
1206
1391
|
tag_value=MU.deploy_id,
|
|
1207
1392
|
region: MU.curRegion,
|
|
1208
1393
|
credentials: nil)
|
|
1394
|
+
require "aws-sdk-ec2"
|
|
1209
1395
|
attempts = 0
|
|
1210
1396
|
|
|
1211
1397
|
return nil if resource.nil?
|
|
@@ -1246,6 +1432,7 @@ end
|
|
|
1246
1432
|
# Mu Master, if we're in AWS.
|
|
1247
1433
|
# @return [void]
|
|
1248
1434
|
def self.openFirewallForClients
|
|
1435
|
+
require "aws-sdk-ec2"
|
|
1249
1436
|
MU::Cloud.resourceClass("AWS", :FirewallRule)
|
|
1250
1437
|
begin
|
|
1251
1438
|
if File.exist?(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
|
|
@@ -1425,6 +1612,7 @@ end
|
|
|
1425
1612
|
def initialize(region: nil, api: "EC2", credentials: nil)
|
|
1426
1613
|
@cred_obj = MU::Cloud::AWS.loadCredentials(credentials)
|
|
1427
1614
|
@credentials = MU::Cloud::AWS.credConfig(credentials, name_only: true)
|
|
1615
|
+
@api_name = api
|
|
1428
1616
|
|
|
1429
1617
|
if !@cred_obj
|
|
1430
1618
|
raise MuError, "Unable to locate valid AWS credentials for #{api} API. #{credentials ? "Credentials requested were '#{credentials}'": ""}"
|
|
@@ -1442,6 +1630,8 @@ end
|
|
|
1442
1630
|
params[:credentials] = @cred_obj
|
|
1443
1631
|
|
|
1444
1632
|
MU.log "Initializing #{api} object with credentials #{credentials}", MU::DEBUG, details: params
|
|
1633
|
+
require "aws-sdk-#{api.downcase}"
|
|
1634
|
+
|
|
1445
1635
|
@api = Object.const_get("Aws::#{api}::Client").new(params)
|
|
1446
1636
|
end
|
|
1447
1637
|
|
|
@@ -1450,26 +1640,31 @@ end
|
|
|
1450
1640
|
# rescues for known silly endpoint behavior.
|
|
1451
1641
|
def method_missing(method_sym, *arguments)
|
|
1452
1642
|
# make sure error symbols are loaded for our exception handling later
|
|
1453
|
-
require "aws-sdk-
|
|
1454
|
-
require "aws-sdk-
|
|
1455
|
-
require "aws-sdk-
|
|
1456
|
-
require "aws-sdk-
|
|
1457
|
-
require "aws-sdk-
|
|
1458
|
-
require "aws-sdk-
|
|
1459
|
-
require "aws-sdk-
|
|
1460
|
-
require "aws-sdk-
|
|
1461
|
-
require "aws-sdk-
|
|
1462
|
-
require "aws-sdk-
|
|
1463
|
-
require "aws-sdk-
|
|
1464
|
-
require "aws-sdk-
|
|
1465
|
-
require "aws-sdk-
|
|
1466
|
-
require "aws-sdk-
|
|
1467
|
-
require "aws-sdk-
|
|
1468
|
-
|
|
1643
|
+
require "aws-sdk-lambda"
|
|
1644
|
+
require "aws-sdk-rds"
|
|
1645
|
+
require "aws-sdk-ec2"
|
|
1646
|
+
require "aws-sdk-route53"
|
|
1647
|
+
require "aws-sdk-iam"
|
|
1648
|
+
require "aws-sdk-efs"
|
|
1649
|
+
require "aws-sdk-pricing"
|
|
1650
|
+
require "aws-sdk-apigateway"
|
|
1651
|
+
require "aws-sdk-ecs"
|
|
1652
|
+
require "aws-sdk-eks"
|
|
1653
|
+
require "aws-sdk-cloudwatchlogs"
|
|
1654
|
+
require "aws-sdk-cloudwatchevents"
|
|
1655
|
+
require "aws-sdk-elasticloadbalancing"
|
|
1656
|
+
require "aws-sdk-elasticloadbalancingv2"
|
|
1657
|
+
require "aws-sdk-autoscaling"
|
|
1658
|
+
|
|
1659
|
+
known_concats = {
|
|
1660
|
+
"Pricing" => {
|
|
1661
|
+
:get_products => :price_list
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1469
1664
|
|
|
1470
1665
|
retries = 0
|
|
1471
1666
|
begin
|
|
1472
|
-
MU.log "Calling #{method_sym} in #{@region}", MU::DEBUG, details: arguments
|
|
1667
|
+
MU.log "Calling #{@api_name}.#{method_sym} in #{@region}", MU::DEBUG, details: arguments
|
|
1473
1668
|
|
|
1474
1669
|
retval = if !arguments.nil? and arguments.size == 1
|
|
1475
1670
|
@api.method(method_sym).call(arguments[0])
|
|
@@ -1481,24 +1676,39 @@ end
|
|
|
1481
1676
|
|
|
1482
1677
|
if !retval.nil?
|
|
1483
1678
|
begin
|
|
1484
|
-
page_markers =
|
|
1679
|
+
page_markers = {
|
|
1680
|
+
:marker => :marker,
|
|
1681
|
+
:next_token => :next_token,
|
|
1682
|
+
:next_marker => :marker
|
|
1683
|
+
}
|
|
1485
1684
|
paginator = nil
|
|
1486
1685
|
new_page = nil
|
|
1487
|
-
|
|
1686
|
+
page_markers.each_key { |m|
|
|
1488
1687
|
if !retval.nil? and retval.respond_to?(m)
|
|
1489
1688
|
paginator = m
|
|
1490
|
-
new_page = retval.send(
|
|
1689
|
+
new_page = retval.send(m)
|
|
1491
1690
|
break
|
|
1492
1691
|
end
|
|
1493
1692
|
}
|
|
1494
1693
|
|
|
1495
1694
|
if paginator and new_page and !new_page.empty?
|
|
1496
1695
|
resp = retval.respond_to?(:__getobj__) ? retval.__getobj__ : retval
|
|
1497
|
-
concat_to =
|
|
1696
|
+
concat_to = MU.structToHash(resp).keys.reject { |m|
|
|
1498
1697
|
m.to_s.match(/=$/) or m == paginator or resp.send(m).nil? or !resp.send(m).is_a?(Array)
|
|
1499
1698
|
}
|
|
1699
|
+
|
|
1700
|
+
if concat_to.empty? and known_concats[@api_name] and
|
|
1701
|
+
known_concats[@api_name][method_sym]
|
|
1702
|
+
concat_to << known_concats[@api_name][method_sym]
|
|
1703
|
+
end
|
|
1704
|
+
|
|
1705
|
+
if concat_to.empty? and method_sym.to_s.match(/^(?:describe|list)_(.*)/)
|
|
1706
|
+
my_attr = Regexp.last_match[1].to_sym
|
|
1707
|
+
concat_to << my_attr if resp.respond_to?(my_attr)
|
|
1708
|
+
end
|
|
1709
|
+
|
|
1500
1710
|
if concat_to.size != 1
|
|
1501
|
-
|
|
1711
|
+
raise MuError.new "Tried to figure out where I might append paginated results for a #{@api_name}.#{method_sym}, but failed", details: MU.structToHash(resp).keys
|
|
1502
1712
|
else
|
|
1503
1713
|
concat_to = concat_to.first
|
|
1504
1714
|
new_args = arguments ? arguments.dup : [{}]
|
|
@@ -1506,12 +1716,12 @@ end
|
|
|
1506
1716
|
if new_args.is_a?(Array)
|
|
1507
1717
|
new_args << {} if new_args.empty?
|
|
1508
1718
|
if new_args.size == 1 and new_args.first.is_a?(Hash)
|
|
1509
|
-
new_args[0][paginator] = new_page
|
|
1719
|
+
new_args[0][page_markers[paginator]] = new_page
|
|
1510
1720
|
else
|
|
1511
1721
|
MU.log "I don't know how to insert a #{paginator} into these arguments for #{method_sym}", MU::WARN, details: new_args
|
|
1512
1722
|
end
|
|
1513
1723
|
elsif new_args.is_a?(Hash)
|
|
1514
|
-
new_args[paginator] = new_page
|
|
1724
|
+
new_args[page_markers[paginator]] = new_page
|
|
1515
1725
|
end
|
|
1516
1726
|
|
|
1517
1727
|
MU.log "Attempting magic pagination for #{method_sym}", MU::DEBUG, details: new_args
|
|
@@ -1535,7 +1745,7 @@ end
|
|
|
1535
1745
|
end
|
|
1536
1746
|
|
|
1537
1747
|
return retval
|
|
1538
|
-
rescue Aws::RDS::Errors::Throttling, Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException, Net::ReadTimeout, Faraday::TimeoutError, Aws::CloudWatchLogs::Errors::ThrottlingException => e
|
|
1748
|
+
rescue Aws::Lambda::Errors::TooManyRequestsException, Aws::RDS::Errors::Throttling, Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException, Net::ReadTimeout, Faraday::TimeoutError, Aws::CloudWatchLogs::Errors::ThrottlingException => e
|
|
1539
1749
|
if e.class.name == "Seahorse::Client::NetworkingError" and e.message.match(/Name or service not known/)
|
|
1540
1750
|
MU.log e.inspect, MU::ERR
|
|
1541
1751
|
raise e
|
|
@@ -1577,6 +1787,7 @@ end
|
|
|
1577
1787
|
@@wafglobal = {}
|
|
1578
1788
|
@@waf = {}
|
|
1579
1789
|
@@cloudwatchlogs_api = {}
|
|
1790
|
+
@@cloudwatchevents_api = {}
|
|
1580
1791
|
@@cloudfront_api = {}
|
|
1581
1792
|
@@elasticache_api = {}
|
|
1582
1793
|
@@sns_api = {}
|
|
@@ -1595,6 +1806,8 @@ end
|
|
|
1595
1806
|
@@kms_api ={}
|
|
1596
1807
|
@@organization_api ={}
|
|
1597
1808
|
@@dynamo_api ={}
|
|
1809
|
+
@@dynamostream_api ={}
|
|
1810
|
+
@@cloudfront_api ={}
|
|
1598
1811
|
end
|
|
1599
1812
|
end
|
|
1600
1813
|
end
|