cloud-mu 1.9.0.pre.beta → 2.0.0.pre.alpha
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/Berksfile +16 -54
- data/Berksfile.lock +14 -62
- data/bin/mu-aws-setup +131 -108
- data/bin/mu-configure +311 -74
- data/bin/mu-gcp-setup +84 -62
- data/bin/mu-load-config.rb +46 -2
- data/bin/mu-self-update +11 -9
- data/bin/mu-upload-chef-artifacts +4 -4
- data/{mu.gemspec → cloud-mu.gemspec} +2 -2
- data/cookbooks/awscli/Berksfile +8 -0
- data/cookbooks/mu-activedirectory/Berksfile +11 -0
- data/cookbooks/mu-firewall/Berksfile +9 -0
- data/cookbooks/mu-firewall/metadata.rb +1 -1
- data/cookbooks/mu-glusterfs/Berksfile +10 -0
- data/cookbooks/mu-jenkins/Berksfile +14 -0
- data/cookbooks/mu-master/Berksfile +23 -0
- data/cookbooks/mu-master/attributes/default.rb +1 -1
- data/cookbooks/mu-master/metadata.rb +2 -2
- data/cookbooks/mu-master/recipes/default.rb +1 -1
- data/cookbooks/mu-master/recipes/init.rb +7 -3
- data/cookbooks/mu-master/recipes/ssl-certs.rb +1 -0
- data/cookbooks/mu-mongo/Berksfile +10 -0
- data/cookbooks/mu-openvpn/Berksfile +11 -0
- data/cookbooks/mu-php54/Berksfile +13 -0
- data/cookbooks/mu-splunk/Berksfile +10 -0
- data/cookbooks/mu-tools/Berksfile +21 -0
- data/cookbooks/mu-tools/files/default/Mu_CA.pem +15 -15
- data/cookbooks/mu-utility/Berksfile +9 -0
- data/cookbooks/mu-utility/metadata.rb +2 -1
- data/cookbooks/nagios/Berksfile +7 -4
- data/cookbooks/s3fs/Berksfile +9 -0
- data/environments/dev.json +6 -6
- data/environments/prod.json +6 -6
- data/modules/mu.rb +20 -42
- data/modules/mu/cleanup.rb +102 -100
- data/modules/mu/cloud.rb +90 -28
- data/modules/mu/clouds/aws.rb +449 -218
- data/modules/mu/clouds/aws/alarm.rb +29 -17
- data/modules/mu/clouds/aws/cache_cluster.rb +78 -64
- data/modules/mu/clouds/aws/collection.rb +25 -18
- data/modules/mu/clouds/aws/container_cluster.rb +73 -66
- data/modules/mu/clouds/aws/database.rb +124 -116
- data/modules/mu/clouds/aws/dnszone.rb +27 -20
- data/modules/mu/clouds/aws/firewall_rule.rb +30 -22
- data/modules/mu/clouds/aws/folder.rb +18 -3
- data/modules/mu/clouds/aws/function.rb +77 -23
- data/modules/mu/clouds/aws/group.rb +19 -12
- data/modules/mu/clouds/aws/habitat.rb +153 -0
- data/modules/mu/clouds/aws/loadbalancer.rb +59 -52
- data/modules/mu/clouds/aws/log.rb +30 -23
- data/modules/mu/clouds/aws/msg_queue.rb +29 -20
- data/modules/mu/clouds/aws/notifier.rb +222 -0
- data/modules/mu/clouds/aws/role.rb +178 -90
- data/modules/mu/clouds/aws/search_domain.rb +40 -24
- data/modules/mu/clouds/aws/server.rb +169 -137
- data/modules/mu/clouds/aws/server_pool.rb +60 -83
- data/modules/mu/clouds/aws/storage_pool.rb +59 -31
- data/modules/mu/clouds/aws/user.rb +36 -27
- data/modules/mu/clouds/aws/userdata/linux.erb +101 -93
- data/modules/mu/clouds/aws/vpc.rb +250 -189
- data/modules/mu/clouds/azure.rb +132 -0
- data/modules/mu/clouds/cloudformation.rb +65 -1
- data/modules/mu/clouds/cloudformation/alarm.rb +8 -0
- data/modules/mu/clouds/cloudformation/cache_cluster.rb +7 -0
- data/modules/mu/clouds/cloudformation/collection.rb +7 -0
- data/modules/mu/clouds/cloudformation/database.rb +7 -0
- data/modules/mu/clouds/cloudformation/dnszone.rb +7 -0
- data/modules/mu/clouds/cloudformation/firewall_rule.rb +9 -2
- data/modules/mu/clouds/cloudformation/loadbalancer.rb +7 -0
- data/modules/mu/clouds/cloudformation/log.rb +7 -0
- data/modules/mu/clouds/cloudformation/server.rb +7 -0
- data/modules/mu/clouds/cloudformation/server_pool.rb +7 -0
- data/modules/mu/clouds/cloudformation/vpc.rb +7 -0
- data/modules/mu/clouds/google.rb +214 -110
- data/modules/mu/clouds/google/container_cluster.rb +42 -24
- data/modules/mu/clouds/google/database.rb +15 -6
- data/modules/mu/clouds/google/firewall_rule.rb +17 -25
- data/modules/mu/clouds/google/group.rb +13 -5
- data/modules/mu/clouds/google/habitat.rb +105 -0
- data/modules/mu/clouds/google/loadbalancer.rb +28 -20
- data/modules/mu/clouds/google/server.rb +93 -354
- data/modules/mu/clouds/google/server_pool.rb +18 -10
- data/modules/mu/clouds/google/user.rb +22 -14
- data/modules/mu/clouds/google/vpc.rb +97 -69
- data/modules/mu/config.rb +133 -38
- data/modules/mu/config/alarm.rb +25 -0
- data/modules/mu/config/cache_cluster.rb +5 -3
- data/modules/mu/config/cache_cluster.yml +23 -0
- data/modules/mu/config/database.rb +25 -16
- data/modules/mu/config/database.yml +3 -3
- data/modules/mu/config/function.rb +1 -2
- data/modules/mu/config/{project.rb → habitat.rb} +10 -10
- data/modules/mu/config/notifier.rb +85 -0
- data/modules/mu/config/notifier.yml +9 -0
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/search_domain.yml +2 -2
- data/modules/mu/config/server.rb +13 -1
- data/modules/mu/config/server.yml +3 -3
- data/modules/mu/config/server_pool.rb +3 -1
- data/modules/mu/config/storage_pool.rb +3 -1
- data/modules/mu/config/storage_pool.yml +19 -0
- data/modules/mu/config/vpc.rb +70 -8
- data/modules/mu/groomers/chef.rb +2 -3
- data/modules/mu/kittens.rb +500 -122
- data/modules/mu/master.rb +5 -5
- data/modules/mu/mommacat.rb +151 -91
- data/modules/tests/super_complex_bok.yml +12 -0
- data/modules/tests/super_simple_bok.yml +12 -0
- data/spec/mu/clouds/azure_spec.rb +82 -0
- data/spec/spec_helper.rb +105 -0
- metadata +26 -5
- data/modules/mu/clouds/aws/notification.rb +0 -139
- data/modules/mu/config/notification.rb +0 -44
data/modules/mu/cloud.rb
CHANGED
@@ -39,8 +39,12 @@ module MU
|
|
39
39
|
class MuCloudFlagNotImplemented < StandardError;
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
# Methods which a cloud resource implementation, e.g. Server, must implement
|
43
|
+
generic_class_methods = [:find, :cleanup, :validateConfig, :schema, :isGlobal?]
|
44
|
+
generic_instance_methods = [:create, :notify, :mu_name, :cloud_id, :config]
|
45
|
+
|
46
|
+
# Class methods which the base of a cloud implementation must implement
|
47
|
+
generic_class_methods_toplevel = [:required_instance_methods, :myRegion, :listRegions, :listAZs, :hosted?, :hosted_config, :config_example, :writeDeploySecret, :listCredentials, :credConfig, :listInstanceTypes, :adminBucketName, :adminBucketUrl]
|
44
48
|
|
45
49
|
# Initialize empty classes for each of these. We'll fill them with code
|
46
50
|
# later; we're doing this here because otherwise the parser yells about
|
@@ -80,7 +84,7 @@ module MU
|
|
80
84
|
class Alarm;
|
81
85
|
end
|
82
86
|
# Stub base class; real implementations generated at runtime
|
83
|
-
class
|
87
|
+
class Notifier;
|
84
88
|
end
|
85
89
|
# Stub base class; real implementations generated at runtime
|
86
90
|
class Log;
|
@@ -98,7 +102,7 @@ module MU
|
|
98
102
|
class MsgQueue;
|
99
103
|
end
|
100
104
|
# Stub base class; real implementations generated at runtime
|
101
|
-
class
|
105
|
+
class Habitat;
|
102
106
|
end
|
103
107
|
# Stub base class; real implementations generated at runtime
|
104
108
|
class Folder;
|
@@ -227,12 +231,12 @@ module MU
|
|
227
231
|
:class => generic_class_methods,
|
228
232
|
:instance => generic_instance_methods + [:groom]
|
229
233
|
},
|
230
|
-
:
|
234
|
+
:Notifier => {
|
231
235
|
:has_multiples => false,
|
232
236
|
:can_live_in_vpc => false,
|
233
|
-
:cfg_name => "
|
234
|
-
:cfg_plural => "
|
235
|
-
:interface => self.const_get("
|
237
|
+
:cfg_name => "notifier",
|
238
|
+
:cfg_plural => "notifiers",
|
239
|
+
:interface => self.const_get("Notifier"),
|
236
240
|
:deps_wait_on_my_creation => false,
|
237
241
|
:waits_on_parent_completion => false,
|
238
242
|
:class => generic_class_methods,
|
@@ -304,12 +308,12 @@ module MU
|
|
304
308
|
:class => generic_class_methods,
|
305
309
|
:instance => generic_instance_methods + [:groom]
|
306
310
|
},
|
307
|
-
:
|
311
|
+
:Habitat => {
|
308
312
|
:has_multiples => false,
|
309
313
|
:can_live_in_vpc => false,
|
310
|
-
:cfg_name => "
|
311
|
-
:cfg_plural => "
|
312
|
-
:interface => self.const_get("
|
314
|
+
:cfg_name => "habitat",
|
315
|
+
:cfg_plural => "habitats",
|
316
|
+
:interface => self.const_get("Habitat"),
|
313
317
|
:deps_wait_on_my_creation => true,
|
314
318
|
:waits_on_parent_completion => true,
|
315
319
|
:class => generic_class_methods,
|
@@ -399,16 +403,30 @@ module MU
|
|
399
403
|
}
|
400
404
|
end
|
401
405
|
|
406
|
+
# List of known/supported Cloud providers. This may be modified at runtime
|
407
|
+
# if an implemention is defective or missing required methods.
|
408
|
+
@@supportedCloudList = ['AWS', 'CloudFormation', 'Google', 'Azure']
|
409
|
+
|
402
410
|
# List of known/supported Cloud providers
|
403
411
|
def self.supportedClouds
|
404
|
-
|
412
|
+
@@supportedCloudList
|
405
413
|
end
|
406
414
|
|
407
415
|
# Load the container class for each cloud we know about, and inject autoload
|
408
416
|
# code for each of its supported resource type classes.
|
417
|
+
failed = []
|
409
418
|
MU::Cloud.supportedClouds.each { |cloud|
|
410
419
|
require "mu/clouds/#{cloud.downcase}"
|
420
|
+
cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
|
421
|
+
generic_class_methods_toplevel.each { |method|
|
422
|
+
if !cloudclass.respond_to?(method)
|
423
|
+
MU.log "MU::Cloud::#{cloud} has not implemented required class method #{method}, disabling", MU::ERR
|
424
|
+
failed << cloud
|
425
|
+
end
|
426
|
+
}
|
411
427
|
}
|
428
|
+
failed.uniq!
|
429
|
+
@@supportedCloudList = @@supportedCloudList - failed
|
412
430
|
|
413
431
|
# @return [Mutex]
|
414
432
|
def self.userdata_mutex
|
@@ -559,6 +577,7 @@ module MU
|
|
559
577
|
attr_reader :deploy_id
|
560
578
|
attr_reader :mu_name
|
561
579
|
attr_reader :cloud_id
|
580
|
+
attr_reader :credentials
|
562
581
|
attr_reader :url
|
563
582
|
attr_reader :config
|
564
583
|
attr_reader :deploydata
|
@@ -623,6 +642,7 @@ module MU
|
|
623
642
|
def initialize(mommacat: nil,
|
624
643
|
mu_name: nil,
|
625
644
|
cloud_id: nil,
|
645
|
+
credentials: nil,
|
626
646
|
kitten_cfg: nil,
|
627
647
|
delayed_save: false)
|
628
648
|
raise MuError, "Cannot invoke Cloud objects without a configuration" if kitten_cfg.nil?
|
@@ -631,7 +651,9 @@ module MU
|
|
631
651
|
@config = kitten_cfg
|
632
652
|
@delayed_save = delayed_save
|
633
653
|
@cloud_id = cloud_id
|
634
|
-
|
654
|
+
@credentials = credentials
|
655
|
+
@credentials ||= kitten_cfg['credentials']
|
656
|
+
|
635
657
|
if !@deploy.nil?
|
636
658
|
@deploy_id = @deploy.deploy_id
|
637
659
|
MU.log "Initializing an instance of #{self.class.name} in #{@deploy_id} #{mu_name}", MU::DEBUG, details: kitten_cfg
|
@@ -720,21 +742,23 @@ module MU
|
|
720
742
|
end
|
721
743
|
end
|
722
744
|
end
|
723
|
-
|
724
|
-
def cloud_desc
|
745
|
+
|
746
|
+
def cloud_desc()
|
725
747
|
describe
|
726
748
|
if !@cloudobj.nil?
|
727
|
-
@
|
749
|
+
@cloud_desc_cache ||= @cloudobj.cloud_desc
|
728
750
|
@url = @cloudobj.url if @cloudobj.respond_to?(:url)
|
729
|
-
|
751
|
+
end
|
752
|
+
if !@config.nil? and !@cloud_id.nil? and @cloud_desc_cache.nil?
|
730
753
|
# The find() method should be returning a Hash with the cloud_id
|
731
754
|
# as a key and a cloud platform descriptor as the value.
|
732
755
|
begin
|
733
|
-
|
756
|
+
|
757
|
+
matches = self.class.find(region: @config['region'], cloud_id: @cloud_id, flags: @config, credentials: @credentials)
|
734
758
|
if !matches.nil? and matches.is_a?(Hash) and matches.has_key?(@cloud_id)
|
735
|
-
@
|
759
|
+
@cloud_desc_cache = matches[@cloud_id]
|
736
760
|
else
|
737
|
-
MU.log "Failed to find a live #{self.class.shortname} with identifier #{@cloud_id} in #{@config['region']}, which has a record in deploy #{@deploy.deploy_id}", MU::WARN, details: caller
|
761
|
+
MU.log "Failed to find a live #{self.class.shortname} with identifier #{@cloud_id} in #{@credentials}/#{@config['region']}, which has a record in deploy #{@deploy.deploy_id}", MU::WARN, details: caller
|
738
762
|
end
|
739
763
|
rescue Exception => e
|
740
764
|
MU.log "Got #{e.inspect} trying to find cloud handle for #{self.class.shortname} #{@mu_name} (#{@cloud_id})", MU::WARN
|
@@ -742,7 +766,7 @@ module MU
|
|
742
766
|
end
|
743
767
|
end
|
744
768
|
|
745
|
-
return @
|
769
|
+
return @cloud_desc_cache
|
746
770
|
end
|
747
771
|
|
748
772
|
# Retrieve all of the known metadata for this resource.
|
@@ -755,6 +779,7 @@ module MU
|
|
755
779
|
end
|
756
780
|
res_type = self.class.cfg_plural
|
757
781
|
res_name = @config['name'] if !@config.nil?
|
782
|
+
@credentials ||= @config['credentials'] if !@config.nil?
|
758
783
|
deploydata = nil
|
759
784
|
if !@deploy.nil? and @deploy.is_a?(MU::MommaCat) and
|
760
785
|
!@deploy.deployment.nil? and
|
@@ -836,11 +861,42 @@ module MU
|
|
836
861
|
# Special dependencies: my containing VPC
|
837
862
|
if self.class.can_live_in_vpc and !@config['vpc'].nil?
|
838
863
|
MU.log "Loading VPC for #{self}", MU::DEBUG, details: @config['vpc']
|
839
|
-
if !@config['vpc']["vpc_name"].nil? and
|
864
|
+
if !@config['vpc']["vpc_name"].nil? and @deploy
|
865
|
+
sib_by_name = @deploy.findLitterMate(name: @config['vpc']['vpc_name'], type: "vpcs", return_all: true)
|
866
|
+
if sib_by_name.is_a?(Array)
|
867
|
+
if sib_by_name.size == 1
|
868
|
+
@vpc = matches.first
|
869
|
+
else
|
870
|
+
# XXX ok but this is the wrong place for this really the config parser needs to sort this out somehow
|
871
|
+
# we got multiple matches, try to pick one by preferred subnet
|
872
|
+
# behavior
|
873
|
+
sib_by_name.each { |sibling|
|
874
|
+
all_private = sibling.subnets.map { |s| s.private? }.all?(true)
|
875
|
+
all_public = sibling.subnets.map { |s| s.private? }.all?(false)
|
876
|
+
if all_private and ["private", "all_private"].include?(@config['vpc']['subnet_pref'])
|
877
|
+
@vpc = sibling
|
878
|
+
break
|
879
|
+
elsif all_public and ["public", "all_public"].include?(@config['vpc']['subnet_pref'])
|
880
|
+
@vpc = sibling
|
881
|
+
break
|
882
|
+
else
|
883
|
+
MU.log "Got multiple matching VPCs for #{@mu_name}, so I'm arbitrarily choosing #{sibling.mu_name}"
|
884
|
+
@vpc = sibling
|
885
|
+
break
|
886
|
+
end
|
887
|
+
}
|
888
|
+
end
|
889
|
+
else
|
890
|
+
MU.log "in dependencies() and findLitterMate gave me "+sib_by_name.to_s+" on behalf of "+self.to_s, MU::NOTICE, details: @config['vpc']
|
891
|
+
@vpc = sib_by_name
|
892
|
+
end
|
893
|
+
end
|
894
|
+
|
895
|
+
if !@vpc and !@config['vpc']["vpc_name"].nil? and
|
840
896
|
@dependencies.has_key?("vpc") and
|
841
897
|
@dependencies["vpc"].has_key?(@config['vpc']["vpc_name"])
|
842
898
|
@vpc = @dependencies["vpc"][@config['vpc']["vpc_name"]]
|
843
|
-
|
899
|
+
elsif !@vpc
|
844
900
|
tag_key, tag_value = @config['vpc']['tag'].split(/=/, 2) if !@config['vpc']['tag'].nil?
|
845
901
|
if !@config['vpc'].has_key?("vpc_id") and
|
846
902
|
!@config['vpc'].has_key?("deploy_id") and !@deploy.nil?
|
@@ -883,12 +939,14 @@ module MU
|
|
883
939
|
nat_cloud_id: @config['vpc']['nat_host_id'],
|
884
940
|
nat_filter_key: "vpc-id",
|
885
941
|
region: @config['vpc']["region"],
|
886
|
-
nat_filter_value: @vpc.cloud_id
|
942
|
+
nat_filter_value: @vpc.cloud_id,
|
943
|
+
credentials: @config['credentials']
|
887
944
|
)
|
888
945
|
else
|
889
946
|
@nat = @vpc.findNat(
|
890
947
|
nat_cloud_id: @config['vpc']['nat_host_id'],
|
891
|
-
region: @config['vpc']["region"]
|
948
|
+
region: @config['vpc']["region"],
|
949
|
+
credentials: @config['credentials']
|
892
950
|
)
|
893
951
|
end
|
894
952
|
end
|
@@ -939,9 +997,13 @@ module MU
|
|
939
997
|
# sense there
|
940
998
|
cloudbase = Object.const_get("MU").const_get("Cloud").const_get(cloud)
|
941
999
|
if args[:region] and cloudbase.respond_to?(:listRegions)
|
942
|
-
next if !cloudbase.listRegions.include?(args[:region])
|
1000
|
+
next if !cloudbase.listRegions(credentials: args[:credentials]).include?(args[:region])
|
1001
|
+
end
|
1002
|
+
begin
|
1003
|
+
cloudclass = MU::Cloud.loadCloudType(cloud, shortname)
|
1004
|
+
rescue MU::MuError => e
|
1005
|
+
next
|
943
1006
|
end
|
944
|
-
cloudclass = MU::Cloud.loadCloudType(cloud, shortname)
|
945
1007
|
|
946
1008
|
found = cloudclass.find(args)
|
947
1009
|
if !found.nil?
|
data/modules/mu/clouds/aws.rb
CHANGED
@@ -26,81 +26,112 @@ module MU
|
|
26
26
|
class AWS
|
27
27
|
@@myRegion_var = nil
|
28
28
|
|
29
|
-
@@creds_loaded =
|
29
|
+
@@creds_loaded = {}
|
30
30
|
|
31
31
|
# Load some credentials for using the AWS API
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
if $MU_CFG['aws']['access_key'] and $MU_CFG['aws']['access_secret'] and
|
37
|
-
# access key and secret just sitting in mu.yaml
|
38
|
-
!$MU_CFG['aws']['access_key'].empty? and
|
39
|
-
!$MU_CFG['aws']['access_secret'].empty?
|
40
|
-
Aws.config = {
|
41
|
-
access_key_id: $MU_CFG['aws']['access_key'],
|
42
|
-
secret_access_key: $MU_CFG['aws']['access_secret'],
|
43
|
-
region: $MU_CFG['aws']['region']
|
44
|
-
}
|
45
|
-
loaded = true
|
46
|
-
elsif $MU_CFG['aws']['credentials_file'] and
|
47
|
-
!$MU_CFG['aws']['credentials_file'].empty?
|
48
|
-
# pull access key and secret from an awscli-style credentials file
|
49
|
-
begin
|
50
|
-
File.read($MU_CFG["aws"]["credentials_file"]) # make sure it's there
|
51
|
-
credfile = IniFile.load($MU_CFG["aws"]["credentials_file"])
|
32
|
+
# @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.
|
33
|
+
# @return [Aws::Credentials]
|
34
|
+
def self.loadCredentials(name = nil)
|
35
|
+
@@creds_loaded ||= {}
|
52
36
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
37
|
+
if name.nil?
|
38
|
+
return @@creds_loaded["#default"] if @@creds_loaded["#default"]
|
39
|
+
else
|
40
|
+
return @@creds_loaded[name] if @@creds_loaded[name]
|
41
|
+
end
|
42
|
+
|
43
|
+
cred_cfg = credConfig(name)
|
44
|
+
if cred_cfg.nil?
|
45
|
+
return nil
|
46
|
+
end
|
47
|
+
|
48
|
+
loaded = false
|
49
|
+
cred_obj = nil
|
50
|
+
if cred_cfg['access_key'] and cred_cfg['access_secret'] and
|
51
|
+
# access key and secret just sitting in mu.yaml
|
52
|
+
!cred_cfg['access_key'].empty? and
|
53
|
+
!cred_cfg['access_secret'].empty?
|
54
|
+
cred_obj = Aws::Credentials.new(
|
55
|
+
cred_cfg['access_key'], cred_cfg['access_secret']
|
56
|
+
)
|
57
|
+
if name.nil?
|
58
|
+
# Aws.config = {
|
59
|
+
# access_key_id: cred_cfg['access_key'],
|
60
|
+
# secret_access_key: cred_cfg['access_secret'],
|
61
|
+
# region: cred_cfg['region']
|
62
|
+
# }
|
63
|
+
end
|
64
|
+
elsif cred_cfg['credentials_file'] and
|
65
|
+
!cred_cfg['credentials_file'].empty?
|
66
|
+
|
67
|
+
# pull access key and secret from an awscli-style credentials file
|
68
|
+
begin
|
69
|
+
File.read(cred_cfg["credentials_file"]) # make sure it's there
|
70
|
+
credfile = IniFile.load(cred_cfg["credentials_file"])
|
71
|
+
|
72
|
+
if !credfile.sections or credfile.sections.size == 0
|
73
|
+
raise ::IniFile::Error, "No AWS profiles found in #{cred_cfg["credentials_file"]}"
|
74
|
+
end
|
75
|
+
data = credfile.has_section?("default") ? credfile["default"] : credfile[credfile.sections.first]
|
76
|
+
if data["aws_access_key_id"] and data["aws_secret_access_key"]
|
77
|
+
cred_obj = Aws::Credentials.new(
|
78
|
+
data['aws_access_key_id'], data['aws_secret_access_key']
|
79
|
+
)
|
80
|
+
if name.nil?
|
81
|
+
# Aws.config = {
|
82
|
+
# access_key_id: data['aws_access_key_id'],
|
83
|
+
# secret_access_key: data['aws_secret_access_key'],
|
84
|
+
# region: cred_cfg['region']
|
85
|
+
# }
|
66
86
|
end
|
67
|
-
|
68
|
-
MU.log "AWS credentials
|
87
|
+
else
|
88
|
+
MU.log "AWS credentials in #{cred_cfg["credentials_file"]} specified, but is missing aws_access_key_id or aws_secret_access_key elements", MU::WARN
|
69
89
|
end
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
90
|
+
rescue IniFile::Error, Errno::ENOENT, Errno::EACCES => e
|
91
|
+
MU.log "AWS credentials file #{cred_cfg["credentials_file"]} is missing or invalid", MU::WARN, details: e.message
|
92
|
+
end
|
93
|
+
elsif cred_cfg['credentials'] and
|
94
|
+
!cred_cfg['credentials'].empty?
|
95
|
+
# pull access key and secret from a vault
|
96
|
+
begin
|
97
|
+
vault, item = cred_cfg["credentials"].split(/:/)
|
98
|
+
data = MU::Groomer::Chef.getSecret(vault: vault, item: item).to_h
|
99
|
+
if data["access_key"] and data["access_secret"]
|
100
|
+
cred_obj = Aws::Credentials.new(
|
101
|
+
cred_cfg['access_key'], cred_cfg['access_secret']
|
102
|
+
)
|
103
|
+
if name.nil?
|
104
|
+
# Aws.config = {
|
105
|
+
# access_key_id: data['access_key'],
|
106
|
+
# secret_access_key: data['access_secret'],
|
107
|
+
# region: cred_cfg['region']
|
108
|
+
# }
|
85
109
|
end
|
86
|
-
|
87
|
-
MU.log "AWS credentials vault:item #{
|
110
|
+
else
|
111
|
+
MU.log "AWS credentials vault:item #{cred_cfg["credentials"]} specified, but is missing access_key or access_secret elements", MU::WARN
|
88
112
|
end
|
113
|
+
rescue MU::Groomer::Chef::MuNoSuchSecret
|
114
|
+
MU.log "AWS credentials vault:item #{cred_cfg["credentials"]} specified, but does not exist", MU::WARN
|
89
115
|
end
|
116
|
+
end
|
90
117
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
118
|
+
if !cred_obj and hosted?
|
119
|
+
# assume we've got an IAM profile and hope for the best
|
120
|
+
ENV.delete('AWS_ACCESS_KEY_ID')
|
121
|
+
ENV.delete('AWS_SECRET_ACCESS_KEY')
|
122
|
+
cred_obj = Aws::InstanceProfileCredentials.new
|
123
|
+
# if name.nil?
|
124
|
+
# Aws.config = {region: ENV['EC2_REGION']}
|
125
|
+
# end
|
126
|
+
end
|
98
127
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
128
|
+
if name.nil?
|
129
|
+
@@creds_loaded["#default"] = cred_obj
|
130
|
+
else
|
131
|
+
@@creds_loaded[name] = cred_obj
|
103
132
|
end
|
133
|
+
|
134
|
+
cred_obj
|
104
135
|
end
|
105
136
|
|
106
137
|
# Any cloud-specific instance methods we require our resource
|
@@ -114,13 +145,17 @@ module MU
|
|
114
145
|
# If we've configured AWS as a provider, or are simply hosted in AWS,
|
115
146
|
# decide what our default region is.
|
116
147
|
def self.myRegion
|
148
|
+
return @@myRegion_var if @@myRegion_var
|
149
|
+
return nil if credConfig.nil? and !hosted?
|
150
|
+
|
117
151
|
if $MU_CFG and (!$MU_CFG['aws'] or !account_number) and !hosted?
|
118
152
|
return nil
|
119
153
|
end
|
154
|
+
|
120
155
|
if $MU_CFG and $MU_CFG['aws'] and $MU_CFG['aws']['region']
|
121
|
-
@@myRegion_var ||= MU::Cloud::AWS.ec2($MU_CFG['aws']['region']).describe_availability_zones.availability_zones.first.region_name
|
156
|
+
@@myRegion_var ||= MU::Cloud::AWS.ec2(region: $MU_CFG['aws']['region']).describe_availability_zones.availability_zones.first.region_name
|
122
157
|
elsif ENV.has_key?("EC2_REGION") and !ENV['EC2_REGION'].empty?
|
123
|
-
@@myRegion_var ||= MU::Cloud::AWS.ec2(ENV['EC2_REGION']).describe_availability_zones.availability_zones.first.region_name
|
158
|
+
@@myRegion_var ||= MU::Cloud::AWS.ec2(region: ENV['EC2_REGION']).describe_availability_zones.availability_zones.first.region_name
|
124
159
|
else
|
125
160
|
# hacky, but useful in a pinch
|
126
161
|
az_str = MU::Cloud::AWS.getAWSMetaData("placement/availability-zone")
|
@@ -140,7 +175,7 @@ module MU
|
|
140
175
|
# @param value [String]: The value of the tag to remove
|
141
176
|
# @param region [String]: The cloud provider region
|
142
177
|
def self.removeTag(key, value, resources = [], region: myRegion)
|
143
|
-
MU::Cloud::AWS.ec2(region).delete_tags(
|
178
|
+
MU::Cloud::AWS.ec2(region: region).delete_tags(
|
144
179
|
resources: resources,
|
145
180
|
tags: [
|
146
181
|
{
|
@@ -158,11 +193,11 @@ module MU
|
|
158
193
|
# @param value [String]: The value of the tag
|
159
194
|
# @param region [String]: The cloud provider region
|
160
195
|
# @return [void,<Hash>]
|
161
|
-
def self.createTag(key, value, resources = [], region: myRegion)
|
196
|
+
def self.createTag(key, value, resources = [], region: myRegion, credentials: nil)
|
162
197
|
|
163
198
|
if !MU::Cloud::CloudFormation.emitCloudFormation
|
164
199
|
begin
|
165
|
-
MU::Cloud::AWS.ec2(region).create_tags(
|
200
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).create_tags(
|
166
201
|
resources: resources,
|
167
202
|
tags: [
|
168
203
|
{
|
@@ -196,7 +231,7 @@ module MU
|
|
196
231
|
# server resides.
|
197
232
|
# @param region [String]: The region to search.
|
198
233
|
# @return [Array<String>]: The Availability Zones in this region.
|
199
|
-
def self.listAZs(region
|
234
|
+
def self.listAZs(region: MU.curRegion, account: nil, credentials: nil)
|
200
235
|
if $MU_CFG and (!$MU_CFG['aws'] or !account_number)
|
201
236
|
return []
|
202
237
|
end
|
@@ -204,7 +239,7 @@ module MU
|
|
204
239
|
return @@azs[region]
|
205
240
|
end
|
206
241
|
if region
|
207
|
-
azs = MU::Cloud::AWS.ec2(region).describe_availability_zones(
|
242
|
+
azs = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_availability_zones(
|
208
243
|
filters: [name: "region-name", values: [region]]
|
209
244
|
)
|
210
245
|
end
|
@@ -218,21 +253,57 @@ module MU
|
|
218
253
|
# Plant a Mu deploy secret into a storage bucket somewhere for so our kittens can consume it
|
219
254
|
# @param deploy_id [String]: The deploy for which we're writing the secret
|
220
255
|
# @param value [String]: The contents of the secret
|
221
|
-
def self.writeDeploySecret(deploy_id, value, name = nil)
|
256
|
+
def self.writeDeploySecret(deploy_id, value, name = nil, credentials: nil)
|
222
257
|
name ||= deploy_id+"-secret"
|
223
258
|
begin
|
224
|
-
MU.log "Writing #{name} to S3 bucket #{
|
225
|
-
MU::Cloud::AWS.s3(myRegion).put_object(
|
259
|
+
MU.log "Writing #{name} to S3 bucket #{adminBucketName(credentials)}"
|
260
|
+
MU::Cloud::AWS.s3(region: myRegion, credentials: credentials).put_object(
|
226
261
|
acl: "private",
|
227
|
-
bucket:
|
262
|
+
bucket: adminBucketName(credentials),
|
228
263
|
key: name,
|
229
264
|
body: value
|
230
265
|
)
|
231
266
|
rescue Aws::S3::Errors => e
|
232
|
-
raise MU::MommaCat::DeployInitializeError, "Got #{e.inspect} trying to write #{name} to #{
|
267
|
+
raise MU::MommaCat::DeployInitializeError, "Got #{e.inspect} trying to write #{name} to #{adminBucketName(credentials)}"
|
233
268
|
end
|
234
269
|
end
|
235
270
|
|
271
|
+
# Log bucket policy for enabling CloudTrail logging to our log bucket in S3.
|
272
|
+
def self.cloudtrailBucketPolicy(credentials = nil)
|
273
|
+
cfg = credConfig(credentials)
|
274
|
+
policy_json = '{
|
275
|
+
"Version": "2012-10-17",
|
276
|
+
"Statement": [
|
277
|
+
{
|
278
|
+
"Sid": "AWSCloudTrailAclCheck20131101",
|
279
|
+
"Effect": "Allow",
|
280
|
+
"Principal": {
|
281
|
+
"AWS": "arn:'+(MU::Cloud::AWS.isGovCloud?(cfg['region']) ? "aws-us-gov" : "aws")+':iam::<%= MU.account_number %>:root",
|
282
|
+
"Service": "cloudtrail.amazonaws.com"
|
283
|
+
},
|
284
|
+
"Action": "s3:GetBucketAcl",
|
285
|
+
"Resource": "arn:'+(MU::Cloud::AWS.isGovCloud?(cfg['region']) ? "aws-us-gov" : "aws")+':s3:::'+MU::Cloud::AWS.adminBucketName(credentials)+'"
|
286
|
+
},
|
287
|
+
{
|
288
|
+
"Sid": "AWSCloudTrailWrite20131101",
|
289
|
+
"Effect": "Allow",
|
290
|
+
"Principal": {
|
291
|
+
"AWS": "arn:'+(MU::Cloud::AWS.isGovCloud?(cfg['region']) ? "aws-us-gov" : "aws")+':iam::'+credToAcct(credentials)+':root",
|
292
|
+
"Service": "cloudtrail.amazonaws.com"
|
293
|
+
},
|
294
|
+
"Action": "s3:PutObject",
|
295
|
+
"Resource": "arn:'+(MU::Cloud::AWS.isGovCloud?(cfg['region']) ? "aws-us-gov" : "aws")+':s3:::'+MU::Cloud::AWS.adminBucketName(credentials)+'/AWSLogs/'+credToAcct(credentials)+'/*",
|
296
|
+
"Condition": {
|
297
|
+
"StringEquals": {
|
298
|
+
"s3:x-amz-acl": "bucket-owner-full-control"
|
299
|
+
}
|
300
|
+
}
|
301
|
+
}
|
302
|
+
]
|
303
|
+
}'
|
304
|
+
ERB.new(policy_json).result
|
305
|
+
end
|
306
|
+
|
236
307
|
@@is_in_aws = nil
|
237
308
|
|
238
309
|
# Alias for #{MU::Cloud::AWS.hosted?}
|
@@ -293,32 +364,137 @@ module MU
|
|
293
364
|
sample
|
294
365
|
end
|
295
366
|
|
296
|
-
|
367
|
+
@@my_acct_num = nil
|
368
|
+
@@my_hosted_cfg = nil
|
369
|
+
@@acct_to_profile_map = {}
|
370
|
+
|
371
|
+
# Map the name of a credential set back to an AWS account number
|
372
|
+
# @param name [String]
|
373
|
+
def self.credToAcct(name = nil)
|
374
|
+
creds = credConfig(name)
|
375
|
+
|
376
|
+
return creds['account_number'] if creds['account_number']
|
377
|
+
|
378
|
+
user_list = MU::Cloud::AWS.iam(credentials: name).list_users.users
|
379
|
+
acct_num = MU::Cloud::AWS.iam(credentials: name).list_users.users.first.arn.split(/:/)[4]
|
380
|
+
acct_num.to_s
|
381
|
+
end
|
382
|
+
|
383
|
+
# Return the name strings of all known sets of credentials for this cloud
|
384
|
+
# @return [Array<String>]
|
385
|
+
def self.listCredentials
|
386
|
+
if !$MU_CFG['aws']
|
387
|
+
return hosted? ? ["#default"] : nil
|
388
|
+
end
|
389
|
+
|
390
|
+
$MU_CFG['aws'].keys
|
391
|
+
end
|
392
|
+
|
393
|
+
def self.adminBucketName(credentials = nil)
|
394
|
+
#XXX find a default if this particular account doesn't have a log_bucket_name configured
|
395
|
+
cfg = credConfig(credentials)
|
396
|
+
cfg['log_bucket_name']
|
397
|
+
end
|
398
|
+
|
399
|
+
def self.adminBucketUrl(credentials = nil)
|
400
|
+
"s3://"+adminBucketName+"/"
|
401
|
+
end
|
402
|
+
|
403
|
+
# Return the $MU_CFG data associated with a particular profile/name/set of
|
404
|
+
# credentials. If no account name is specified, will return one flagged as
|
405
|
+
# default. Returns nil if AWS is not configured. Throws an exception if
|
406
|
+
# an account name is specified which does not exist.
|
407
|
+
# @param name [String]: The name of the key under 'aws' in mu.yaml to return
|
408
|
+
# @return [Hash,nil]
|
409
|
+
def self.credConfig(name = nil, name_only: false)
|
410
|
+
# If there's nothing in mu.yaml (which is wrong), but we're running
|
411
|
+
# on a machine hosted in AWS, *and* that machine has an IAM profile,
|
412
|
+
# fake it with those credentials and hope for the best.
|
413
|
+
if !$MU_CFG['aws'] or !$MU_CFG['aws'].is_a?(Hash) or $MU_CFG['aws'].size == 0
|
414
|
+
return @@my_hosted_cfg if @@my_hosted_cfg
|
415
|
+
|
416
|
+
if hosted?
|
417
|
+
begin
|
418
|
+
iam_data = JSON.parse(getAWSMetaData("iam/info"))
|
419
|
+
if iam_data["InstanceProfileArn"] and !iam_data["InstanceProfileArn"].empty?
|
420
|
+
@@my_hosted_cfg = hosted_config
|
421
|
+
return name_only ? "#default" : @@my_hosted_cfg
|
422
|
+
end
|
423
|
+
rescue JSON::ParserError => e
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
return nil
|
428
|
+
end
|
429
|
+
|
430
|
+
if name.nil?
|
431
|
+
$MU_CFG['aws'].each_pair { |name, cfg|
|
432
|
+
if cfg['default']
|
433
|
+
return name_only ? name : cfg
|
434
|
+
end
|
435
|
+
}
|
436
|
+
else
|
437
|
+
if $MU_CFG['aws'][name]
|
438
|
+
return name_only ? name : $MU_CFG['aws'][name]
|
439
|
+
elsif @@acct_to_profile_map[name.to_s]
|
440
|
+
return name_only ? name : @@acct_to_profile_map[name.to_s]
|
441
|
+
elsif name.is_a?(Integer) or name.match(/^\d+$/)
|
442
|
+
# Try to map backwards from an account id, if that's what we go
|
443
|
+
$MU_CFG['aws'].each_pair { |acctname, cfg|
|
444
|
+
if cfg['account_number'] and name.to_s == cfg['account_number'].to_s
|
445
|
+
return name_only ? acctname : $MU_CFG['aws'][acctname]
|
446
|
+
end
|
447
|
+
}
|
448
|
+
|
449
|
+
# Check each credential sets' resident account, then
|
450
|
+
$MU_CFG['aws'].each_pair { |acctname, cfg|
|
451
|
+
begin
|
452
|
+
user_list = MU::Cloud::AWS.iam(credentials: acctname).list_users.users
|
453
|
+
# rescue ::Aws::IAM::Errors => e # XXX why does this NameError here?
|
454
|
+
rescue Exception => e
|
455
|
+
MU.log e.inspect, MU::WARN, details: cfg
|
456
|
+
next
|
457
|
+
end
|
458
|
+
acct_num = MU::Cloud::AWS.iam(credentials: acctname).list_users.users.first.arn.split(/:/)[4]
|
459
|
+
if acct_num.to_s == name.to_s
|
460
|
+
cfg['account_number'] = acct_num.to_s
|
461
|
+
@@acct_to_profile_map[name.to_s] = cfg
|
462
|
+
return name_only ? name.to_s : cfg
|
463
|
+
return cfg
|
464
|
+
end
|
465
|
+
}
|
466
|
+
end
|
467
|
+
|
468
|
+
raise MuError, "AWS credential set #{name} was requested, but I see no such working credentials in mu.yaml"
|
469
|
+
end
|
470
|
+
end
|
297
471
|
|
298
|
-
# Fetch the AWS account number where this Mu master resides. If it's not
|
299
|
-
# AWS at all, or otherwise cannot be determined, return nil.
|
300
|
-
# here.
|
472
|
+
# Fetch the AWS account number where this Mu master resides. If it's not
|
473
|
+
# in AWS at all, or otherwise cannot be determined, return nil. here.
|
301
474
|
# XXX account for Google and non-cloud situations
|
302
|
-
# XXX
|
475
|
+
# XXX this needs to be "myAccountNumber" or somesuch
|
476
|
+
# XXX and maybe do the IAM thing for arbitrary, non-resident accounts
|
303
477
|
def self.account_number
|
304
|
-
return nil if
|
305
|
-
return
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
#
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
478
|
+
return nil if credConfig.nil?
|
479
|
+
return @@my_acct_num if @@my_acct_num
|
480
|
+
loadCredentials
|
481
|
+
# XXX take optional credential set argument
|
482
|
+
|
483
|
+
# begin
|
484
|
+
# user_list = MU::Cloud::AWS.iam(region: credConfig['region']).list_users.users
|
485
|
+
## rescue ::Aws::IAM::Errors => e # XXX why does this NameError here?
|
486
|
+
# rescue Exception => e
|
487
|
+
# MU.log "Got #{e.inspect} while trying to figure out our account number", MU::WARN, details: caller
|
488
|
+
# end
|
489
|
+
# if user_list.nil? or user_list.size == 0
|
314
490
|
mac = MU::Cloud::AWS.getAWSMetaData("network/interfaces/macs/").split(/\n/)[0]
|
315
491
|
acct_num = MU::Cloud::AWS.getAWSMetaData("network/interfaces/macs/#{mac}owner-id")
|
316
492
|
acct_num.chomp!
|
317
|
-
else
|
318
|
-
acct_num = MU::Cloud::AWS.iam(
|
319
|
-
end
|
493
|
+
# else
|
494
|
+
# acct_num = MU::Cloud::AWS.iam(region: credConfig['region']).list_users.users.first.arn.split(/:/)[4]
|
495
|
+
# end
|
320
496
|
MU.setVar("acct_num", acct_num)
|
321
|
-
|
497
|
+
@@my_acct_num ||= acct_num
|
322
498
|
acct_num
|
323
499
|
end
|
324
500
|
|
@@ -327,17 +503,19 @@ module MU
|
|
327
503
|
# region that is local to this Mu server will be listed first.
|
328
504
|
# @param us_only [Boolean]: Restrict results to United States only
|
329
505
|
# @return [Array<String>]
|
330
|
-
def self.listRegions(us_only = false)
|
331
|
-
|
332
|
-
return []
|
333
|
-
end
|
506
|
+
def self.listRegions(us_only = false, credentials: nil)
|
507
|
+
|
334
508
|
if @@regions.size == 0
|
335
|
-
|
509
|
+
return [] if credConfig.nil?
|
510
|
+
result = MU::Cloud::AWS.ec2(region: myRegion, credentials: credentials).describe_regions.regions
|
336
511
|
regions = []
|
337
512
|
result.each { |r|
|
338
|
-
@@regions[r.region_name] = Proc.new {
|
513
|
+
@@regions[r.region_name] = Proc.new {
|
514
|
+
listAZs(region: r.region_name, credentials: credentials)
|
515
|
+
}
|
339
516
|
}
|
340
517
|
end
|
518
|
+
|
341
519
|
regions = if us_only
|
342
520
|
@@regions.keys.delete_if { |r| !r.match(/^us\-/) }.uniq
|
343
521
|
else
|
@@ -368,14 +546,14 @@ module MU
|
|
368
546
|
# @param keyname [String]: The name of the key to create.
|
369
547
|
# @param public_key [String]: The public key
|
370
548
|
# @return [Array<String>]: keypairname, ssh_private_key, ssh_public_key
|
371
|
-
def self.createEc2SSHKey(keyname, public_key)
|
549
|
+
def self.createEc2SSHKey(keyname, public_key, credentials: nil)
|
372
550
|
# We replicate this key in all regions
|
373
551
|
if !MU::Cloud::CloudFormation.emitCloudFormation
|
374
552
|
MU::Cloud::AWS.listRegions.each { |region|
|
375
553
|
MU.log "Replicating #{keyname} to EC2 in #{region}", MU::DEBUG, details: @ssh_public_key
|
376
|
-
MU::Cloud::AWS.ec2(region).import_key_pair(
|
377
|
-
|
378
|
-
|
554
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).import_key_pair(
|
555
|
+
key_name: keyname,
|
556
|
+
public_key_material: public_key
|
379
557
|
)
|
380
558
|
}
|
381
559
|
end
|
@@ -389,9 +567,7 @@ module MU
|
|
389
567
|
# @return [Hash]
|
390
568
|
def self.listInstanceTypes(region = myRegion)
|
391
569
|
return @@instance_types if @@instance_types and @@instance_types[region]
|
392
|
-
|
393
|
-
return {}
|
394
|
-
end
|
570
|
+
return {} if credConfig.nil?
|
395
571
|
|
396
572
|
human_region = @@regionLookup[region]
|
397
573
|
|
@@ -402,7 +578,7 @@ module MU
|
|
402
578
|
begin
|
403
579
|
# Pricing API isn't widely available, so ask a region we know supports
|
404
580
|
# it
|
405
|
-
resp = MU::Cloud::AWS.pricing("us-east-1").get_products(
|
581
|
+
resp = MU::Cloud::AWS.pricing(region: "us-east-1").get_products(
|
406
582
|
service_code: "AmazonEC2",
|
407
583
|
filters: [
|
408
584
|
{
|
@@ -456,7 +632,7 @@ module MU
|
|
456
632
|
|
457
633
|
if !name.nil? and !name.empty?
|
458
634
|
matches = []
|
459
|
-
acmcerts = MU::Cloud::AWS.acm(region).list_certificates(
|
635
|
+
acmcerts = MU::Cloud::AWS.acm(region: region).list_certificates(
|
460
636
|
certificate_statuses: ["ISSUED"]
|
461
637
|
)
|
462
638
|
acmcerts.certificate_summary_list.each { |cert|
|
@@ -475,14 +651,14 @@ module MU
|
|
475
651
|
if matches.size == 1
|
476
652
|
return matches.first
|
477
653
|
elsif matches.size == 0
|
478
|
-
raise MuError, "No IAM or ACM certificate named #{name} was found"
|
654
|
+
raise MuError, "No IAM or ACM certificate named #{name} was found in #{region}"
|
479
655
|
elsif matches.size > 1
|
480
|
-
raise MuError, "Multiple certificates named #{name} were found. Remove extras or use ssl_certificate_id to supply the exact ARN of the one you want to use."
|
656
|
+
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."
|
481
657
|
end
|
482
658
|
end
|
483
659
|
|
484
660
|
if id.match(/^arn:aws(?:-us-gov)?:acm/)
|
485
|
-
resp = MU::Cloud::AWS.acm(region).get_certificate(
|
661
|
+
resp = MU::Cloud::AWS.acm(region: region).get_certificate(
|
486
662
|
certificate_arn: id
|
487
663
|
)
|
488
664
|
if resp.nil?
|
@@ -510,221 +686,255 @@ module MU
|
|
510
686
|
end
|
511
687
|
|
512
688
|
# Amazon Certificate Manager API
|
513
|
-
def self.acm(region
|
689
|
+
def self.acm(region: MU.curRegion, credentials: nil)
|
514
690
|
region ||= myRegion
|
515
|
-
@@acm_api[
|
516
|
-
@@acm_api[region]
|
691
|
+
@@acm_api[credentials] ||= {}
|
692
|
+
@@acm_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "ACM", region: region, credentials: credentials)
|
693
|
+
@@acm_api[credentials][region]
|
517
694
|
end
|
518
695
|
|
519
696
|
# Amazon's IAM API
|
520
|
-
def self.iam(
|
521
|
-
|
522
|
-
@@iam_api[
|
523
|
-
@@iam_api[region]
|
697
|
+
def self.iam(credentials: nil)
|
698
|
+
@@iam_api[credentials] ||= MU::Cloud::AWS::Endpoint.new(api: "IAM", credentials: credentials)
|
699
|
+
@@iam_api[credentials]
|
524
700
|
end
|
525
701
|
|
526
702
|
# Amazon's EC2 API
|
527
|
-
def self.ec2(region
|
703
|
+
def self.ec2(region: MU.curRegion, credentials: nil)
|
528
704
|
region ||= myRegion
|
529
|
-
@@ec2_api[
|
530
|
-
@@ec2_api[region]
|
705
|
+
@@ec2_api[credentials] ||= {}
|
706
|
+
@@ec2_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "EC2", region: region, credentials: credentials)
|
707
|
+
@@ec2_api[credentials][region]
|
531
708
|
end
|
532
709
|
|
533
710
|
# Amazon's Autoscaling API
|
534
|
-
def self.autoscale(region
|
711
|
+
def self.autoscale(region: MU.curRegion, credentials: nil)
|
535
712
|
region ||= myRegion
|
536
|
-
@@autoscale_api[
|
537
|
-
@@autoscale_api[region]
|
713
|
+
@@autoscale_api[credentials] ||= {}
|
714
|
+
@@autoscale_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "AutoScaling", region: region, credentials: credentials)
|
715
|
+
@@autoscale_api[credentials][region]
|
538
716
|
end
|
539
717
|
|
540
718
|
# Amazon's ElasticLoadBalancing API
|
541
|
-
def self.elb(region
|
719
|
+
def self.elb(region: MU.curRegion, credentials: nil)
|
542
720
|
region ||= myRegion
|
543
|
-
@@elb_api[
|
544
|
-
@@elb_api[region]
|
721
|
+
@@elb_api[credentials] ||= {}
|
722
|
+
@@elb_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "ElasticLoadBalancing", region: region, credentials: credentials)
|
723
|
+
@@elb_api[credentials][region]
|
545
724
|
end
|
546
725
|
|
547
726
|
# Amazon's ElasticLoadBalancingV2 (ALB) API
|
548
|
-
def self.elb2(region
|
727
|
+
def self.elb2(region: MU.curRegion, credentials: nil)
|
549
728
|
region ||= myRegion
|
550
|
-
@@elb2_api[
|
551
|
-
@@elb2_api[region]
|
729
|
+
@@elb2_api[credentials] ||= {}
|
730
|
+
@@elb2_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "ElasticLoadBalancingV2", region: region, credentials: credentials)
|
731
|
+
@@elb2_api[credentials][region]
|
552
732
|
end
|
553
733
|
|
554
734
|
# Amazon's Route53 API
|
555
|
-
def self.route53(
|
556
|
-
|
557
|
-
@@route53_api[
|
558
|
-
@@route53_api[region]
|
735
|
+
def self.route53(credentials: nil)
|
736
|
+
@@route53_api[credentials] ||= MU::Cloud::AWS::Endpoint.new(api: "Route53", credentials: credentials)
|
737
|
+
@@route53_api[credentials]
|
559
738
|
end
|
560
739
|
|
561
740
|
# Amazon's RDS API
|
562
|
-
def self.rds(region
|
741
|
+
def self.rds(region: MU.curRegion, credentials: nil)
|
563
742
|
region ||= myRegion
|
564
|
-
@@rds_api[
|
565
|
-
@@rds_api[region]
|
743
|
+
@@rds_api[credentials] ||= {}
|
744
|
+
@@rds_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "RDS", region: region, credentials: credentials)
|
745
|
+
@@rds_api[credentials][region]
|
566
746
|
end
|
567
747
|
|
568
748
|
# Amazon's CloudFormation API
|
569
|
-
def self.cloudformation(region
|
749
|
+
def self.cloudformation(region: MU.curRegion, credentials: nil)
|
570
750
|
region ||= myRegion
|
571
|
-
@@cloudformation_api[
|
572
|
-
@@cloudformation_api[region]
|
751
|
+
@@cloudformation_api[credentials] ||= {}
|
752
|
+
@@cloudformation_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "CloudFormation", region: region, credentials: credentials)
|
753
|
+
@@cloudformation_api[credentials][region]
|
573
754
|
end
|
574
755
|
|
575
756
|
# Amazon's S3 API
|
576
|
-
def self.s3(region
|
757
|
+
def self.s3(region: MU.curRegion, credentials: nil)
|
577
758
|
region ||= myRegion
|
578
|
-
@@s3_api[
|
579
|
-
@@s3_api[region]
|
759
|
+
@@s3_api[credentials] ||= {}
|
760
|
+
@@s3_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "S3", region: region, credentials: credentials)
|
761
|
+
@@s3_api[credentials][region]
|
580
762
|
end
|
581
763
|
|
582
764
|
# Amazon's CloudTrail API
|
583
|
-
def self.cloudtrail(region
|
765
|
+
def self.cloudtrail(region: MU.curRegion, credentials: nil)
|
584
766
|
region ||= myRegion
|
585
|
-
@@cloudtrail_api[
|
586
|
-
@@cloudtrail_api[region]
|
767
|
+
@@cloudtrail_api[credentials] ||= {}
|
768
|
+
@@cloudtrail_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "CloudTrail", region: region, credentials: credentials)
|
769
|
+
@@cloudtrail_api[credentials][region]
|
587
770
|
end
|
588
771
|
|
589
772
|
# Amazon's CloudWatch API
|
590
|
-
def self.cloudwatch(region
|
773
|
+
def self.cloudwatch(region: MU.curRegion, credentials: nil)
|
591
774
|
region ||= myRegion
|
592
|
-
@@cloudwatch_api[
|
593
|
-
@@cloudwatch_api[region]
|
775
|
+
@@cloudwatch_api[credentials] ||= {}
|
776
|
+
@@cloudwatch_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "CloudWatch", region: region, credentials: credentials)
|
777
|
+
@@cloudwatch_api[credentials][region]
|
594
778
|
end
|
595
779
|
|
596
780
|
# Amazon's Web Application Firewall API (Global, for CloudFront et al)
|
597
|
-
def self.wafglobal(region
|
781
|
+
def self.wafglobal(region: MU.curRegion, credentials: nil)
|
598
782
|
region ||= myRegion
|
599
|
-
@@
|
600
|
-
@@wafglobal[region]
|
783
|
+
@@wafglobal_api[credentials] ||= {}
|
784
|
+
@@wafglobal[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "WAF", region: region, credentials: credentials)
|
785
|
+
@@wafglobal[credentials][region]
|
601
786
|
end
|
602
787
|
|
603
788
|
|
604
789
|
# Amazon's Web Application Firewall API (Regional, for ALBs et al)
|
605
|
-
def self.waf(region
|
790
|
+
def self.waf(region: MU.curRegion, credentials: nil)
|
606
791
|
region ||= myRegion
|
607
|
-
@@waf[
|
608
|
-
@@waf[region]
|
792
|
+
@@waf[credentials] ||= {}
|
793
|
+
@@waf[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "WAFRegional", region: region, credentials: credentials)
|
794
|
+
@@waf[credentials][region]
|
609
795
|
end
|
610
796
|
|
611
797
|
# Amazon's CloudWatchLogs API
|
612
|
-
def self.cloudwatchlogs(region
|
798
|
+
def self.cloudwatchlogs(region: MU.curRegion, credentials: nil)
|
613
799
|
region ||= myRegion
|
614
|
-
@@cloudwatchlogs_api[
|
615
|
-
@@cloudwatchlogs_api[region]
|
800
|
+
@@cloudwatchlogs_api[credentials] ||= {}
|
801
|
+
@@cloudwatchlogs_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "CloudWatchLogs", region: region, credentials: credentials)
|
802
|
+
@@cloudwatchlogs_api[credentials][region]
|
616
803
|
end
|
617
804
|
|
618
805
|
# Amazon's CloudFront API
|
619
|
-
def self.cloudfront(region
|
806
|
+
def self.cloudfront(region: MU.curRegion, credentials: nil)
|
620
807
|
region ||= myRegion
|
621
|
-
@@cloudfront_api[
|
622
|
-
@@cloudfront_api[region]
|
808
|
+
@@cloudfront_api[credentials] ||= {}
|
809
|
+
@@cloudfront_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "CloudFront", region: region, credentials: credentials)
|
810
|
+
@@cloudfront_api[credentials][region]
|
623
811
|
end
|
624
812
|
|
625
813
|
# Amazon's ElastiCache API
|
626
|
-
def self.elasticache(region
|
814
|
+
def self.elasticache(region: MU.curRegion, credentials: nil)
|
627
815
|
region ||= myRegion
|
628
|
-
@@elasticache_api[
|
629
|
-
@@elasticache_api[region]
|
816
|
+
@@elasticache_api[credentials] ||= {}
|
817
|
+
@@elasticache_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "ElastiCache", region: region, credentials: credentials)
|
818
|
+
@@elasticache_api[credentials][region]
|
630
819
|
end
|
631
820
|
|
632
821
|
# Amazon's SNS API
|
633
|
-
def self.sns(region
|
822
|
+
def self.sns(region: MU.curRegion, credentials: nil)
|
634
823
|
region ||= myRegion
|
635
|
-
@@sns_api[
|
636
|
-
@@sns_api[region]
|
824
|
+
@@sns_api[credentials] ||= {}
|
825
|
+
@@sns_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "SNS", region: region, credentials: credentials)
|
826
|
+
@@sns_api[credentials][region]
|
637
827
|
end
|
638
828
|
|
639
829
|
# Amazon's SQS API
|
640
|
-
def self.sqs(region
|
830
|
+
def self.sqs(region: MU.curRegion, credentials: nil)
|
641
831
|
region ||= myRegion
|
642
|
-
@@sqs_api[
|
643
|
-
@@sqs_api[region]
|
832
|
+
@@sqs_api[credentials] ||= {}
|
833
|
+
@@sqs_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "SQS", region: region, credentials: credentials)
|
834
|
+
@@sqs_api[credentials][region]
|
644
835
|
end
|
645
836
|
|
646
837
|
# Amazon's EFS API
|
647
|
-
def self.efs(region
|
838
|
+
def self.efs(region: MU.curRegion, credentials: nil)
|
648
839
|
region ||= myRegion
|
649
|
-
@@efs_api[
|
650
|
-
@@efs_api[region]
|
840
|
+
@@efs_api[credentials] ||= {}
|
841
|
+
@@efs_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "EFS", region: region, credentials: credentials)
|
842
|
+
@@efs_api[credentials][region]
|
651
843
|
end
|
652
844
|
|
653
845
|
# Amazon's Lambda API
|
654
|
-
def self.lambda(region
|
846
|
+
def self.lambda(region: MU.curRegion, credentials: nil)
|
655
847
|
region ||= myRegion
|
656
|
-
@@lambda_api[
|
657
|
-
@@lambda_api[region]
|
848
|
+
@@lambda_api[credentials] ||= {}
|
849
|
+
@@lambda_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "Lambda", region: region, credentials: credentials)
|
850
|
+
@@lambda_api[credentials][region]
|
658
851
|
end
|
659
852
|
|
660
853
|
# Amazon's API Gateway API
|
661
|
-
def self.apig(region
|
854
|
+
def self.apig(region: MU.curRegion, credentials: nil)
|
662
855
|
region ||= myRegion
|
663
|
-
@@apig_api[
|
664
|
-
@@apig_api[region]
|
856
|
+
@@apig_api[credentials] ||= {}
|
857
|
+
@@apig_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "APIGateway", region: region, credentials: credentials)
|
858
|
+
@@apig_api[credentials][region]
|
665
859
|
end
|
666
860
|
|
667
861
|
# Amazon's Cloudwatch Events API
|
668
862
|
def self.cloudwatch_events(region = MU.cureRegion)
|
669
863
|
region ||= myRegion
|
670
|
-
@@cloudwatch_events_api[
|
864
|
+
@@cloudwatch_events_api[credentials] ||= {}
|
865
|
+
@@cloudwatch_events_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "CloudWatchEvents", region: region, credentials: credentials)
|
671
866
|
@@cloudwatch_events_api
|
672
867
|
end
|
673
868
|
|
674
869
|
# Amazon's ECS API
|
675
|
-
def self.ecs(region
|
870
|
+
def self.ecs(region: MU.curRegion, credentials: nil)
|
676
871
|
region ||= myRegion
|
677
|
-
@@ecs_api[
|
678
|
-
@@ecs_api[region]
|
872
|
+
@@ecs_api[credentials] ||= {}
|
873
|
+
@@ecs_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "ECS", region: region, credentials: credentials)
|
874
|
+
@@ecs_api[credentials][region]
|
679
875
|
end
|
680
876
|
|
681
877
|
# Amazon's EKS API
|
682
|
-
def self.eks(region
|
878
|
+
def self.eks(region: MU.curRegion, credentials: nil)
|
683
879
|
region ||= myRegion
|
684
|
-
@@eks_api[
|
685
|
-
@@eks_api[region]
|
880
|
+
@@eks_api[credentials] ||= {}
|
881
|
+
@@eks_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "EKS", region: region, credentials: credentials)
|
882
|
+
@@eks_api[credentials][region]
|
686
883
|
end
|
687
884
|
|
688
885
|
# Amazon's Pricing API
|
689
|
-
def self.pricing(region
|
886
|
+
def self.pricing(region: MU.curRegion, credentials: nil)
|
690
887
|
region ||= myRegion
|
691
|
-
@@pricing_api[
|
692
|
-
@@pricing_api[region]
|
888
|
+
@@pricing_api[credentials] ||= {}
|
889
|
+
@@pricing_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "Pricing", region: region, credentials: credentials)
|
890
|
+
@@pricing_api[credentials][region]
|
693
891
|
end
|
694
892
|
|
695
893
|
# Amazon's Simple Systems Manager API
|
696
|
-
def self.ssm(region
|
894
|
+
def self.ssm(region: MU.curRegion, credentials: nil)
|
697
895
|
region ||= myRegion
|
698
|
-
@@ssm_api[
|
699
|
-
@@ssm_api[region]
|
896
|
+
@@ssm_api[credentials] ||= {}
|
897
|
+
@@ssm_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "SSM", region: region, credentials: credentials)
|
898
|
+
@@ssm_api[credentials][region]
|
700
899
|
end
|
701
900
|
|
702
901
|
# Amazon's Elasticsearch API
|
703
|
-
def self.elasticsearch(region
|
902
|
+
def self.elasticsearch(region: MU.curRegion, credentials: nil)
|
704
903
|
region ||= myRegion
|
705
|
-
@@elasticsearch_api[
|
706
|
-
@@elasticsearch_api[region]
|
904
|
+
@@elasticsearch_api[credentials] ||= {}
|
905
|
+
@@elasticsearch_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "ElasticsearchService", region: region, credentials: credentials)
|
906
|
+
@@elasticsearch_api[credentials][region]
|
707
907
|
end
|
708
908
|
|
709
909
|
# Amazon's Cognito Identity API
|
710
|
-
def self.cognito_ident(region
|
910
|
+
def self.cognito_ident(region: MU.curRegion, credentials: nil)
|
711
911
|
region ||= myRegion
|
712
|
-
@@cognito_ident_api[
|
713
|
-
@@cognito_ident_api[region]
|
912
|
+
@@cognito_ident_api[credentials] ||= {}
|
913
|
+
@@cognito_ident_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "CognitoIdentity", region: region, credentials: credentials)
|
914
|
+
@@cognito_ident_api[credentials][region]
|
714
915
|
end
|
715
916
|
|
716
917
|
# Amazon's Cognito Identity Provider API
|
717
|
-
def self.cognito_user(region
|
918
|
+
def self.cognito_user(region: MU.curRegion, credentials: nil)
|
718
919
|
region ||= myRegion
|
719
|
-
@@cognito_user_api[
|
720
|
-
@@cognito_user_api[region]
|
920
|
+
@@cognito_user_api[credentials] ||= {}
|
921
|
+
@@cognito_user_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "CognitoIdentityProvider", region: region, credentials: credentials)
|
922
|
+
@@cognito_user_api[credentials][region]
|
721
923
|
end
|
722
924
|
|
723
925
|
# Amazon's KMS API
|
724
|
-
def self.kms(region
|
926
|
+
def self.kms(region: MU.curRegion, credentials: nil)
|
725
927
|
region ||= myRegion
|
726
|
-
@@kms_api[
|
727
|
-
@@kms_api[region]
|
928
|
+
@@kms_api[credentials] ||= {}
|
929
|
+
@@kms_api[credentials][region] ||= MU::Cloud::AWS::Endpoint.new(api: "KMS", region: region, credentials: credentials)
|
930
|
+
@@kms_api[credentials][region]
|
931
|
+
end
|
932
|
+
|
933
|
+
# Amazon's Organizations API
|
934
|
+
def self.orgs(credentials: nil)
|
935
|
+
@@organizations_api ||= {}
|
936
|
+
@@organizations_api[credentials] ||= MU::Cloud::AWS::Endpoint.new(api: "Organizations", credentials: credentials)
|
937
|
+
@@organizations_api[credentials]
|
728
938
|
end
|
729
939
|
|
730
940
|
# Fetch an Amazon instance metadata parameter (example: public-ipv4).
|
@@ -734,13 +944,13 @@ module MU
|
|
734
944
|
base_url = "http://169.254.169.254/latest/meta-data/"
|
735
945
|
begin
|
736
946
|
response = nil
|
737
|
-
Timeout.timeout(
|
947
|
+
Timeout.timeout(1) do
|
738
948
|
response = open("#{base_url}/#{param}").read
|
739
949
|
end
|
740
950
|
|
741
951
|
response
|
742
952
|
rescue OpenURI::HTTPError, Timeout::Error, SocketError, Errno::ENETUNREACH, Net::HTTPServerException, Errno::EHOSTUNREACH => e
|
743
|
-
# This is
|
953
|
+
# This is normal on machines checking to see if they're AWS-hosted
|
744
954
|
logger = MU::Logger.new
|
745
955
|
logger.log "Failed metadata request #{base_url}/#{param}: #{e.inspect}", MU::DEBUG
|
746
956
|
return nil
|
@@ -844,7 +1054,7 @@ module MU
|
|
844
1054
|
rule.from_port == port and rule.to_port == port
|
845
1055
|
MU.log "Revoking old rules for port #{port.to_s} from #{sg_id}", MU::NOTICE
|
846
1056
|
begin
|
847
|
-
MU::Cloud::AWS.ec2(myRegion).revoke_security_group_ingress(
|
1057
|
+
MU::Cloud::AWS.ec2(region: myRegion).revoke_security_group_ingress(
|
848
1058
|
group_id: sg_id,
|
849
1059
|
ip_permissions: [
|
850
1060
|
{
|
@@ -871,7 +1081,7 @@ module MU
|
|
871
1081
|
}
|
872
1082
|
|
873
1083
|
begin
|
874
|
-
MU::Cloud::AWS.ec2(myRegion).authorize_security_group_ingress(
|
1084
|
+
MU::Cloud::AWS.ec2(region: myRegion).authorize_security_group_ingress(
|
875
1085
|
group_id: sg_id,
|
876
1086
|
ip_permissions: [
|
877
1087
|
{
|
@@ -919,24 +1129,41 @@ module MU
|
|
919
1129
|
class Endpoint
|
920
1130
|
@api = nil
|
921
1131
|
@region = nil
|
1132
|
+
@cred_obj = nil
|
1133
|
+
attr_reader :credentials
|
1134
|
+
attr_reader :account
|
922
1135
|
|
923
1136
|
# Create an AWS API client
|
924
1137
|
# @param region [String]: Amazon region so we know what endpoint to use
|
925
1138
|
# @param api [String]: Which API are we wrapping?
|
926
|
-
def initialize(region: MU.curRegion, api: "EC2")
|
927
|
-
@
|
1139
|
+
def initialize(region: MU.curRegion, api: "EC2", credentials: nil)
|
1140
|
+
@cred_obj = MU::Cloud::AWS.loadCredentials(credentials)
|
1141
|
+
@credentials = MU::Cloud::AWS.credConfig(credentials, name_only: true)
|
1142
|
+
|
1143
|
+
if !@cred_obj
|
1144
|
+
raise MuError, "Unable to locate valid AWS credentials for #{api} API. #{credentials ? "Credentials requested were '#{credentials}'": ""}"
|
1145
|
+
end
|
1146
|
+
|
1147
|
+
params = {}
|
1148
|
+
|
928
1149
|
if region
|
929
|
-
@
|
930
|
-
|
931
|
-
@api = Object.const_get("Aws::#{api}::Client").new
|
1150
|
+
@region = region
|
1151
|
+
params[:region] = @region
|
932
1152
|
end
|
1153
|
+
|
1154
|
+
params[:credentials] = @cred_obj
|
1155
|
+
|
1156
|
+
MU.log "Initializing #{api} object with credentials #{credentials}", MU::DEBUG, details: params
|
1157
|
+
@api = Object.const_get("Aws::#{api}::Client").new(params)
|
1158
|
+
|
1159
|
+
@api
|
933
1160
|
end
|
934
1161
|
|
935
1162
|
@instance_cache = {}
|
936
1163
|
# Catch-all for AWS client methods. Essentially a pass-through with some
|
937
1164
|
# rescues for known silly endpoint behavior.
|
938
1165
|
def method_missing(method_sym, *arguments)
|
939
|
-
|
1166
|
+
|
940
1167
|
retries = 0
|
941
1168
|
begin
|
942
1169
|
MU.log "Calling #{method_sym} in #{@region}", MU::DEBUG, details: arguments
|
@@ -949,7 +1176,7 @@ module MU
|
|
949
1176
|
retval = @api.method(method_sym).call
|
950
1177
|
end
|
951
1178
|
return retval
|
952
|
-
rescue 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 => e
|
1179
|
+
rescue 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 => e
|
953
1180
|
if e.class.name == "Seahorse::Client::NetworkingError" and e.message.match(/Name or service not known/)
|
954
1181
|
MU.log e.inspect, MU::ERR
|
955
1182
|
raise e
|
@@ -967,9 +1194,12 @@ module MU
|
|
967
1194
|
# elsif retries > 100
|
968
1195
|
# raise MuError, "Exhausted retries after #{retries} attempts while calling EC2's #{method_sym} in #{@region}. Args were: #{arguments}"
|
969
1196
|
end
|
970
|
-
MU.log "Got #{e.inspect} calling EC2's #{method_sym} in #{@region}, waiting #{interval.to_s}s and retrying. Args were: #{arguments}", debuglevel, details: caller
|
1197
|
+
MU.log "Got #{e.inspect} calling EC2's #{method_sym} in #{@region} with credentials #{@credentials}, waiting #{interval.to_s}s and retrying. Args were: #{arguments}", debuglevel, details: caller
|
971
1198
|
sleep interval
|
972
1199
|
retry
|
1200
|
+
rescue Exception => e
|
1201
|
+
MU.log "Got #{e.inspect} calling EC2's #{method_sym} in #{@region} with credentials #{@credentials}", MU::DEBUG, details: arguments
|
1202
|
+
raise e
|
973
1203
|
end
|
974
1204
|
end
|
975
1205
|
end
|
@@ -1004,6 +1234,7 @@ module MU
|
|
1004
1234
|
@@cognito_ident_api ={}
|
1005
1235
|
@@cognito_user_api ={}
|
1006
1236
|
@@kms_api ={}
|
1237
|
+
@@organizataion_api ={}
|
1007
1238
|
end
|
1008
1239
|
end
|
1009
1240
|
end
|