cloud-mu 1.9.0.pre.beta → 2.0.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- 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
|