cloud-mu 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/bin/mu-adopt +12 -1
  4. data/bin/mu-load-config.rb +2 -1
  5. data/bin/mu-run-tests +14 -2
  6. data/cloud-mu.gemspec +3 -3
  7. data/modules/mu.rb +2 -2
  8. data/modules/mu/adoption.rb +5 -5
  9. data/modules/mu/cleanup.rb +47 -25
  10. data/modules/mu/cloud.rb +29 -1
  11. data/modules/mu/cloud/dnszone.rb +0 -2
  12. data/modules/mu/cloud/resource_base.rb +9 -3
  13. data/modules/mu/cloud/wrappers.rb +4 -0
  14. data/modules/mu/config.rb +1 -1
  15. data/modules/mu/config/bucket.rb +31 -2
  16. data/modules/mu/config/cache_cluster.rb +1 -1
  17. data/modules/mu/config/cdn.rb +100 -0
  18. data/modules/mu/config/container_cluster.rb +1 -1
  19. data/modules/mu/config/database.rb +1 -1
  20. data/modules/mu/config/dnszone.rb +4 -3
  21. data/modules/mu/config/endpoint.rb +1 -0
  22. data/modules/mu/config/function.rb +16 -7
  23. data/modules/mu/config/job.rb +89 -0
  24. data/modules/mu/config/notifier.rb +7 -18
  25. data/modules/mu/config/ref.rb +53 -7
  26. data/modules/mu/config/server.rb +1 -1
  27. data/modules/mu/config/vpc.rb +1 -0
  28. data/modules/mu/defaults/AWS.yaml +26 -26
  29. data/modules/mu/deploy.rb +13 -0
  30. data/modules/mu/master.rb +21 -0
  31. data/modules/mu/mommacat.rb +1 -0
  32. data/modules/mu/mommacat/daemon.rb +13 -7
  33. data/modules/mu/providers/aws.rb +115 -16
  34. data/modules/mu/providers/aws/alarm.rb +2 -2
  35. data/modules/mu/providers/aws/bucket.rb +274 -40
  36. data/modules/mu/providers/aws/cache_cluster.rb +4 -4
  37. data/modules/mu/providers/aws/cdn.rb +782 -0
  38. data/modules/mu/providers/aws/collection.rb +2 -2
  39. data/modules/mu/providers/aws/container_cluster.rb +57 -37
  40. data/modules/mu/providers/aws/database.rb +11 -11
  41. data/modules/mu/providers/aws/dnszone.rb +24 -7
  42. data/modules/mu/providers/aws/endpoint.rb +535 -50
  43. data/modules/mu/providers/aws/firewall_rule.rb +6 -3
  44. data/modules/mu/providers/aws/folder.rb +1 -1
  45. data/modules/mu/providers/aws/function.rb +288 -125
  46. data/modules/mu/providers/aws/group.rb +9 -7
  47. data/modules/mu/providers/aws/habitat.rb +2 -2
  48. data/modules/mu/providers/aws/job.rb +466 -0
  49. data/modules/mu/providers/aws/loadbalancer.rb +9 -8
  50. data/modules/mu/providers/aws/log.rb +3 -3
  51. data/modules/mu/providers/aws/msg_queue.rb +12 -3
  52. data/modules/mu/providers/aws/nosqldb.rb +96 -5
  53. data/modules/mu/providers/aws/notifier.rb +135 -63
  54. data/modules/mu/providers/aws/role.rb +51 -37
  55. data/modules/mu/providers/aws/search_domain.rb +165 -29
  56. data/modules/mu/providers/aws/server.rb +12 -9
  57. data/modules/mu/providers/aws/server_pool.rb +26 -13
  58. data/modules/mu/providers/aws/storage_pool.rb +2 -2
  59. data/modules/mu/providers/aws/user.rb +4 -4
  60. data/modules/mu/providers/aws/userdata/linux.erb +5 -4
  61. data/modules/mu/providers/aws/vpc.rb +3 -3
  62. data/modules/mu/providers/azure/server.rb +2 -1
  63. data/modules/mu/providers/google.rb +1 -0
  64. data/modules/mu/providers/google/bucket.rb +1 -1
  65. data/modules/mu/providers/google/container_cluster.rb +1 -1
  66. data/modules/mu/providers/google/database.rb +1 -1
  67. data/modules/mu/providers/google/firewall_rule.rb +1 -1
  68. data/modules/mu/providers/google/folder.rb +1 -1
  69. data/modules/mu/providers/google/function.rb +1 -1
  70. data/modules/mu/providers/google/group.rb +1 -1
  71. data/modules/mu/providers/google/habitat.rb +1 -1
  72. data/modules/mu/providers/google/loadbalancer.rb +1 -1
  73. data/modules/mu/providers/google/role.rb +4 -2
  74. data/modules/mu/providers/google/server.rb +1 -1
  75. data/modules/mu/providers/google/server_pool.rb +1 -1
  76. data/modules/mu/providers/google/user.rb +1 -1
  77. data/modules/mu/providers/google/vpc.rb +1 -1
  78. data/modules/tests/aws-jobs-functions.yaml +46 -0
  79. data/modules/tests/centos6.yaml +4 -0
  80. data/modules/tests/centos7.yaml +4 -0
  81. data/modules/tests/ecs.yaml +2 -2
  82. data/modules/tests/eks.yaml +1 -1
  83. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  84. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  85. data/modules/tests/microservice_app.yaml +288 -0
  86. data/modules/tests/rds.yaml +5 -5
  87. data/modules/tests/regrooms/rds.yaml +5 -5
  88. data/modules/tests/server-with-scrub-muisms.yaml +1 -1
  89. data/modules/tests/super_complex_bok.yml +2 -2
  90. data/modules/tests/super_simple_bok.yml +2 -2
  91. metadata +12 -4
@@ -546,7 +546,7 @@ module MU
546
546
  "additionalProperties" => false,
547
547
  "description" => "Create individual server instances.",
548
548
  "properties" => {
549
- "dns_records" => MU::Config::DNSZone.records_primitive(need_target: false, default_type: "A", need_zone: true),
549
+ "dns_records" => MU::Config::DNSZone.records_primitive(need_target: false, default_type: "A", need_zone: true, embedded_type: "server"),
550
550
  "bastion" => {
551
551
  "type" => "boolean",
552
552
  "default" => false,
@@ -417,6 +417,7 @@ module MU
417
417
  using_default_cidr = false
418
418
  if !vpc['ip_block']
419
419
  if configurator.updating and configurator.existing_deploy and
420
+ configurator.existing_deploy.original_config and
420
421
  configurator.existing_deploy.original_config['vpcs']
421
422
  configurator.existing_deploy.original_config['vpcs'].each { |v|
422
423
  if v['name'].to_s == vpc['name'].to_s
@@ -1,5 +1,5 @@
1
1
  ---
2
- rhel71: &4
2
+ rhel71: &5
3
3
  us-east-1: ami-0f05fce24aa75ba9f
4
4
  ap-northeast-1: ami-0c0ec19eb19055763
5
5
  ap-northeast-2: ami-0717ac5c67c99f745
@@ -16,23 +16,23 @@ rhel71: &4
16
16
  us-east-2: ami-02f6682c7816b3cfc
17
17
  us-west-1: ami-04898e596c06e802b
18
18
  us-west-2: ami-02db5457189a8a8c2
19
- centos6: &3
20
- us-east-1: ami-0ccdc671f12147a1d
21
- us-east-2: ami-00d0e8bc2f05ab949
22
- ap-northeast-1: ami-0726801ceef87f5f8
23
- ap-northeast-2: ami-05fa4afc4a0493b0a
24
- ap-south-1: ami-0d6e4f3b6592b3139
25
- ap-southeast-1: ami-0c988e3dc80b14653
26
- ap-southeast-2: ami-02ac856fd094675ef
27
- ca-central-1: ami-0ce7e343953af2292
28
- eu-central-1: ami-0ce8317423cea27b8
29
- eu-north-1: ami-0a923b493d5fc9743
30
- eu-west-1: ami-06e0f02328921c865
31
- eu-west-2: ami-07ae118c8814df140
32
- eu-west-3: ami-03c1017cd1ccc6e9d
33
- sa-east-1: ami-05212ae133b9c3ba1
34
- us-west-1: ami-0b05ec54412b9f8b0
35
- us-west-2: ami-0447e036b102b2ca0
19
+ centos6: &4
20
+ us-east-1: ami-009723c5c7f8fbc75
21
+ us-east-2: ami-0781f11395714cd39
22
+ ap-northeast-1: ami-07fa5a8795da2b6bc
23
+ ap-northeast-2: ami-0219f0a7c979ff63f
24
+ ap-south-1: ami-0f24817242c401740
25
+ ap-southeast-1: ami-042ef2e0643e8e207
26
+ ap-southeast-2: ami-09fc51de648afa168
27
+ ca-central-1: ami-0dc643db74edc5aa5
28
+ eu-central-1: ami-0628759cb297569d5
29
+ eu-north-1: ami-0aed023791f886315
30
+ eu-west-1: ami-0f87f0f252ff03622
31
+ eu-west-2: ami-00abb555d5a460afe
32
+ eu-west-3: ami-0ccd93d454c2418a2
33
+ sa-east-1: ami-01e10ea6ea72534ae
34
+ us-west-1: ami-01fee56b9ee690ffe
35
+ us-west-2: ami-08bcdb944f185e2a8
36
36
  centos7:
37
37
  us-east-1: ami-067256ca1497c924d
38
38
  ap-northeast-1: ami-07c1e51354fdfd362
@@ -50,7 +50,7 @@ centos7:
50
50
  us-east-2: ami-0292786917d1e3015
51
51
  us-west-1: ami-0ba622529dcdff2bb
52
52
  us-west-2: ami-079a309ca6261d7f6
53
- ubuntu16: &2
53
+ ubuntu16: &3
54
54
  us-east-1: ami-bcdc16c6
55
55
  us-west-1: ami-1b17257b
56
56
  us-west-2: ami-19e92861
@@ -89,7 +89,7 @@ win2k12r2: &1
89
89
  ap-northeast-2: ami-0368c224de1d20502
90
90
  ap-southeast-1: ami-028ef74e1edc3943a
91
91
  ap-southeast-2: ami-09e03eab1b1bc151b
92
- win2k16: &5
92
+ win2k16: &2
93
93
  us-east-1: ami-02801a2c8dcbfb883
94
94
  us-east-2: ami-0ca4f779a2a58a7ea
95
95
  ca-central-1: ami-05d3854d9d6e9bcc5
@@ -137,9 +137,9 @@ amazon:
137
137
  ap-southeast-1: ami-b953f2da
138
138
  ap-southeast-2: ami-db704cb8
139
139
  win2k12: *1
140
- windows: *5
141
- ubuntu: *2
142
- centos: *3
143
- rhel7: *4
144
- rhel: *4
145
- linux: *3
140
+ windows: *2
141
+ ubuntu: *3
142
+ centos: *4
143
+ rhel7: *5
144
+ rhel: *5
145
+ linux: *4
@@ -312,6 +312,17 @@ module MU
312
312
 
313
313
  @mommacat.save!
314
314
 
315
+ # XXX Functions have a special behavior where we re-invoke their groom
316
+ # methods one more time at the end, so we can guarantee their
317
+ # environments are fully populated with all sibling resource idents
318
+ # regardless of dependency order. This is, obviously, a disgusting
319
+ # hack, and we should revisit our dependency language in the next big
320
+ # release.
321
+ if !@main_config["functions"].nil? and
322
+ @main_config["functions"].size > 0
323
+ createResources(@main_config["functions"], "groom")
324
+ end
325
+
315
326
  rescue StandardError => e
316
327
  MU.log e.class.name, MU::ERR, details: caller
317
328
 
@@ -733,7 +744,9 @@ MESSAGE_END
733
744
  sleep 10+Random.rand(20)
734
745
  retry
735
746
  end
747
+
736
748
  end
749
+
737
750
  end
738
751
 
739
752
  end #class
@@ -880,5 +880,26 @@ module MU
880
880
  end
881
881
  end
882
882
 
883
+ # Recursively zip a directory
884
+ # @param srcdir [String]
885
+ # @param outfile [String]
886
+ def self.zipDir(srcdir, outfile)
887
+ require 'zip'
888
+ ::Zip::File.open(outfile, ::Zip::File::CREATE) { |zipfile|
889
+ addpath = Proc.new { |zip_path, parent_path|
890
+ Dir.entries(parent_path).reject{ |d| [".", ".."].include?(d) }.each { |entry|
891
+ src = File.join(parent_path, entry)
892
+ dst = File.join(zip_path, entry).sub(/^\//, '')
893
+ if File.directory?(src)
894
+ addpath.call(dst, src)
895
+ else
896
+ zipfile.add(dst, src)
897
+ end
898
+ }
899
+ }
900
+ addpath.call("", srcdir)
901
+ }
902
+ end
903
+
883
904
  end
884
905
  end
@@ -811,6 +811,7 @@ MAIL_HEAD_END
811
811
 
812
812
  threads = []
813
813
  update_servers.each { |sibling|
814
+ next if sibling.config.has_key?("groom") and !sibling.config["groom"]
814
815
  threads << Thread.new {
815
816
  Thread.abort_on_exception = true
816
817
  Thread.current.thread_variable_set("name", "sync-"+sibling.mu_name.downcase)
@@ -288,8 +288,8 @@ module MU
288
288
 
289
289
  # Path to the PID file used by the Momma Cat daemon
290
290
  # @return [String]
291
- def self.daemonPidFile
292
- base = (Process.uid == 0 and !MU.localOnly) ? "/var" : MU.dataDir
291
+ def self.daemonPidFile(root = false)
292
+ base = ((Process.uid == 0 or root) and !MU.localOnly) ? "/var" : MU.dataDir
293
293
  "#{base}/run/mommacat.pid"
294
294
  end
295
295
 
@@ -306,8 +306,14 @@ module MU
306
306
  Dir.mkdir(dir)
307
307
  end
308
308
  }
309
- return 0 if status
309
+ if (Process.uid != 0 and
310
+ (!$MU_CFG['overridden_keys'] or !$MU_CFG['overridden_keys'].include?("mommacat_port")) and
311
+ status(true)
312
+ ) or status
313
+ return 0
314
+ end
310
315
 
316
+ File.unlink(daemonPidFile) if File.exists?(daemonPidFile)
311
317
  MU.log "Starting Momma Cat on port #{MU.mommaCatPort}, logging to #{daemonLogFile}, PID file #{daemonPidFile}"
312
318
  origdir = Dir.getwd
313
319
  Dir.chdir(MU.myRoot+"/modules")
@@ -346,12 +352,12 @@ module MU
346
352
 
347
353
  # Return true if the Momma Cat daemon appears to be running
348
354
  # @return [Boolean]
349
- def self.status
355
+ def self.status(root = false)
350
356
  if MU.inGem? and MU.muCfg['disable_mommacat']
351
357
  return true
352
358
  end
353
- if File.exist?(daemonPidFile)
354
- pid = File.read(daemonPidFile).chomp.to_i
359
+ if File.exist?(daemonPidFile(root))
360
+ pid = File.read(daemonPidFile(root)).chomp.to_i
355
361
  begin
356
362
  Process.getpgid(pid)
357
363
  MU.log "Momma Cat running with pid #{pid.to_s}", (@@notified_on_pid[pid] ? MU::DEBUG : MU::INFO) # shush
@@ -360,7 +366,7 @@ module MU
360
366
  rescue Errno::ESRCH
361
367
  end
362
368
  end
363
- MU.log "Momma Cat daemon not running", MU::NOTICE, details: daemonPidFile
369
+ MU.log "Momma Cat daemon not running", MU::NOTICE, details: daemonPidFile(root)
364
370
  false
365
371
  end
366
372
 
@@ -844,6 +844,8 @@ end
844
844
  @@instance_types
845
845
  end
846
846
 
847
+ @@certificates = {}
848
+
847
849
  # AWS can stash API-available certificates in Amazon Certificate Manager
848
850
  # or in IAM. Rather than make people crazy trying to get the syntax
849
851
  # correct in our Baskets of Kittens, let's have a helper that tries to do
@@ -852,21 +854,24 @@ end
852
854
  # @param name [String]: The name of the cert. For IAM certs this can be any IAM name; for ACM, it's usually the domain name. If multiple matches are found, or no matches, an exception is raised.
853
855
  # @param id [String]: The ARN of a known certificate. We just validate that it exists. This is ignored if a name parameter is supplied.
854
856
  # @return [String]: The ARN of a matching certificate that is known to exist. If it is an ACM certificate, we also know that it is not expired.
855
- def self.findSSLCertificate(name: nil, id: nil, region: myRegion)
856
- if name.nil? and name.empty? and id.nil? and id.empty?
857
+ def self.findSSLCertificate(name: nil, id: nil, region: myRegion, credentials: nil, raise_on_missing: true)
858
+ if (name.nil? or name.empty?) and (id.nil? or id.empty?)
857
859
  raise MuError, "Can't call findSSLCertificate without specifying either a name or an id"
858
860
  end
861
+ if id and @@certificates[id]
862
+ return [id, @@certificates[id]]
863
+ end
859
864
 
860
865
  if !name.nil? and !name.empty?
861
866
  matches = []
862
- acmcerts = MU::Cloud::AWS.acm(region: region).list_certificates(
867
+ acmcerts = MU::Cloud::AWS.acm(region: region, credentials: credentials).list_certificates(
863
868
  certificate_statuses: ["ISSUED"]
864
869
  )
865
870
  acmcerts.certificate_summary_list.each { |cert|
866
871
  matches << cert.certificate_arn if cert.domain_name == name
867
872
  }
868
873
  begin
869
- iamcert = MU::Cloud::AWS.iam.get_server_certificate(
874
+ iamcert = MU::Cloud::AWS.iam(credentials: credentials).get_server_certificate(
870
875
  server_certificate_name: name
871
876
  )
872
877
  rescue Aws::IAM::Errors::ValidationError, Aws::IAM::Errors::NoSuchEntity
@@ -876,32 +881,45 @@ end
876
881
  matches << iamcert.server_certificate.server_certificate_metadata.arn
877
882
  end
878
883
  if matches.size == 1
879
- return matches.first
884
+ id = matches.first
880
885
  elsif matches.size == 0
881
- raise MuError, "No IAM or ACM certificate named #{name} was found in #{region}"
886
+ if raise_on_missing
887
+ raise MuError, "No IAM or ACM certificate named #{name} was found in #{region}"
888
+ else
889
+ return nil
890
+ end
882
891
  elsif matches.size > 1
883
892
  raise MuError, "Multiple certificates named #{name} were found in #{region}. Remove extras or use ssl_certificate_id to supply the exact ARN of the one you want to use."
884
893
  end
885
894
  end
886
895
 
896
+ domains = []
897
+
887
898
  if id.match(/^arn:aws(?:-us-gov)?:acm/)
888
- resp = MU::Cloud::AWS.acm(region: region).get_certificate(
899
+ resp = MU::Cloud::AWS.acm(region: region).describe_certificate(
889
900
  certificate_arn: id
890
901
  )
891
- if resp.nil?
902
+
903
+ if resp.nil? or resp.certificate.nil?
892
904
  raise MuError, "No such ACM certificate '#{id}'"
893
905
  end
906
+ domains << resp.certificate.domain_name
907
+ if resp.certificate.subject_alternative_names
908
+ domains.concat(resp.certificate.subject_alternative_names)
909
+ end
894
910
  elsif id.match(/^arn:aws(?:-us-gov)?:iam/)
895
911
  resp = MU::Cloud::AWS.iam.list_server_certificates
896
912
  if resp.nil?
897
913
  raise MuError, "No such IAM certificate '#{id}'"
898
914
  end
899
915
  resp.server_certificate_metadata_list.each { |cert|
916
+
900
917
  if cert.arn == id
901
918
  if cert.expiration < Time.now
902
919
  MU.log "IAM SSL certificate #{cert.server_certificate_name} (#{id}) is EXPIRED", MU::WARN
903
920
  end
904
- return id
921
+ @@certificates[id] = [cert.server_certificate_name]
922
+ return [id, [cert.server_certificate_name]]
905
923
  end
906
924
  }
907
925
  raise MuError, "No such IAM certificate '#{id}'"
@@ -909,7 +927,56 @@ end
909
927
  raise MuError, "The format of '#{id}' doesn't look like an ARN for either Amazon Certificate Manager or IAM"
910
928
  end
911
929
 
912
- id
930
+ @@certificates[id] = domains.uniq
931
+ [id, domains.uniq]
932
+ end
933
+
934
+ # Given a domain name and an ACM or IAM certificate identifier, sort out
935
+ # whether the domain name is "covered" by the certificate
936
+ # @param name [String]
937
+ # @param cert_id [String]
938
+ # @return [Boolean]
939
+ def self.nameMatchesCertificate(name, cert_id)
940
+ _id, domains = findSSLCertificate(id: cert_id)
941
+ return false if !domains
942
+ domains.each { |dom|
943
+ if dom == name or
944
+ (dom =~ /^\*/ and name =~ /.*#{Regexp.quote(dom[1..-1])}/)
945
+ return true
946
+ end
947
+ }
948
+ false
949
+ end
950
+
951
+ # Given a {MU::Config::Ref} block for an IAM or ACM SSL certificate,
952
+ # look up and validate the specified certificate. This is intended to be
953
+ # invoked from resource implementations' +validateConfig+ methods.
954
+ # @param certblock [Hash,MU::Config::Ref]:
955
+ # @param region [String]: Default region to use when looking up the certificate, if its configuration block does not specify any
956
+ # @param credentials [String]: Default credentials to use when looking up the certificate, if its configuration block does not specify any
957
+ # @return [Boolean]
958
+ def self.resolveSSLCertificate(certblock, region: nil, credentials: nil)
959
+ return false if !certblock
960
+ ok = true
961
+
962
+ certblock['region'] ||= region if !certblock['id']
963
+ certblock['credentials'] ||= credentials
964
+ cert_arn, cert_domains = MU::Cloud::AWS.findSSLCertificate(
965
+ name: certblock["name"],
966
+ id: certblock["id"],
967
+ region: certblock['region'],
968
+ credentials: certblock['credentials']
969
+ )
970
+
971
+ if cert_arn
972
+ certblock['id'] ||= cert_arn
973
+ end
974
+
975
+ ['region', 'credentials'].each { |field|
976
+ certblock.delete(field) if certblock[field].nil?
977
+ }
978
+
979
+ [cert_arn, cert_domains]
913
980
  end
914
981
 
915
982
  # Amazon Certificate Manager API
@@ -1029,6 +1096,14 @@ end
1029
1096
  @@cloudwatchlogs_api[credentials][region]
1030
1097
  end
1031
1098
 
1099
+ # Amazon's CloudWatchEvents API
1100
+ def self.cloudwatchevents(region: MU.curRegion, credentials: nil)
1101
+ region ||= myRegion
1102
+ @@cloudwatchevents_api[credentials] ||= {}
1103
+ @@cloudwatchevents_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "CloudWatchEvents", region: region, credentials: credentials)
1104
+ @@cloudwatchevents_api[credentials][region]
1105
+ end
1106
+
1032
1107
  # Amazon's CloudFront API
1033
1108
  def self.cloudfront(region: MU.curRegion, credentials: nil)
1034
1109
  region ||= myRegion
@@ -1117,6 +1192,14 @@ end
1117
1192
  @@dynamo_api[credentials][region]
1118
1193
  end
1119
1194
 
1195
+ # Amazon's DynamoStream API
1196
+ def self.dynamostream(region: MU.curRegion, credentials: nil)
1197
+ region ||= myRegion
1198
+ @@dynamostream_api[credentials] ||= {}
1199
+ @@dynamostream_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "DynamoDBStreams", region: region, credentials: credentials)
1200
+ @@dynamostream_api[credentials][region]
1201
+ end
1202
+
1120
1203
  # Amazon's Pricing API
1121
1204
  def self.pricing(region: MU.curRegion, credentials: nil)
1122
1205
  region ||= myRegion
@@ -1165,6 +1248,14 @@ end
1165
1248
  @@kms_api[credentials][region]
1166
1249
  end
1167
1250
 
1251
+ # Amazon's CloudFront API
1252
+ def self.cloudfront(region: MU.curRegion, credentials: nil)
1253
+ region ||= myRegion
1254
+ @@cloudfront_api[credentials] ||= {}
1255
+ @@cloudfront_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "CloudFront", region: region, credentials: credentials)
1256
+ @@cloudfront_api[credentials][region]
1257
+ end
1258
+
1168
1259
  # Amazon's Organizations API
1169
1260
  def self.orgs(credentials: nil)
1170
1261
  @@organizations_api ||= {}
@@ -1461,6 +1552,7 @@ end
1461
1552
  require "aws-sdk-core/ecs"
1462
1553
  require "aws-sdk-core/eks"
1463
1554
  require "aws-sdk-core/cloudwatchlogs"
1555
+ require "aws-sdk-core/cloudwatchevents"
1464
1556
  require "aws-sdk-core/elasticloadbalancing"
1465
1557
  require "aws-sdk-core/elasticloadbalancingv2"
1466
1558
  require "aws-sdk-core/autoscaling"
@@ -1481,13 +1573,17 @@ end
1481
1573
 
1482
1574
  if !retval.nil?
1483
1575
  begin
1484
- page_markers = [:marker, :next_token]
1576
+ page_markers = {
1577
+ :marker => :marker,
1578
+ :next_token => :next_token,
1579
+ :next_marker => :marker
1580
+ }
1485
1581
  paginator = nil
1486
1582
  new_page = nil
1487
- [:next_token, :marker].each { |m|
1583
+ page_markers.each_key { |m|
1488
1584
  if !retval.nil? and retval.respond_to?(m)
1489
1585
  paginator = m
1490
- new_page = retval.send(paginator)
1586
+ new_page = retval.send(m)
1491
1587
  break
1492
1588
  end
1493
1589
  }
@@ -1506,12 +1602,12 @@ end
1506
1602
  if new_args.is_a?(Array)
1507
1603
  new_args << {} if new_args.empty?
1508
1604
  if new_args.size == 1 and new_args.first.is_a?(Hash)
1509
- new_args[0][paginator] = new_page
1605
+ new_args[0][page_markers[paginator]] = new_page
1510
1606
  else
1511
1607
  MU.log "I don't know how to insert a #{paginator} into these arguments for #{method_sym}", MU::WARN, details: new_args
1512
1608
  end
1513
1609
  elsif new_args.is_a?(Hash)
1514
- new_args[paginator] = new_page
1610
+ new_args[page_markers[paginator]] = new_page
1515
1611
  end
1516
1612
 
1517
1613
  MU.log "Attempting magic pagination for #{method_sym}", MU::DEBUG, details: new_args
@@ -1535,7 +1631,7 @@ end
1535
1631
  end
1536
1632
 
1537
1633
  return retval
1538
- rescue Aws::RDS::Errors::Throttling, Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException, Net::ReadTimeout, Faraday::TimeoutError, Aws::CloudWatchLogs::Errors::ThrottlingException => e
1634
+ rescue Aws::Lambda::Errors::TooManyRequestsException, Aws::RDS::Errors::Throttling, Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException, Net::ReadTimeout, Faraday::TimeoutError, Aws::CloudWatchLogs::Errors::ThrottlingException => e
1539
1635
  if e.class.name == "Seahorse::Client::NetworkingError" and e.message.match(/Name or service not known/)
1540
1636
  MU.log e.inspect, MU::ERR
1541
1637
  raise e
@@ -1577,6 +1673,7 @@ end
1577
1673
  @@wafglobal = {}
1578
1674
  @@waf = {}
1579
1675
  @@cloudwatchlogs_api = {}
1676
+ @@cloudwatchevents_api = {}
1580
1677
  @@cloudfront_api = {}
1581
1678
  @@elasticache_api = {}
1582
1679
  @@sns_api = {}
@@ -1595,6 +1692,8 @@ end
1595
1692
  @@kms_api ={}
1596
1693
  @@organization_api ={}
1597
1694
  @@dynamo_api ={}
1695
+ @@dynamostream_api ={}
1696
+ @@cloudfront_api ={}
1598
1697
  end
1599
1698
  end
1600
1699
  end