cloud-mu 3.1.5 → 3.3.2

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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +5 -1
  3. data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
  4. data/ansible/roles/mu-windows/files/config.xml +76 -0
  5. data/ansible/roles/mu-windows/tasks/main.yml +16 -0
  6. data/bin/mu-adopt +16 -12
  7. data/bin/mu-azure-tests +57 -0
  8. data/bin/mu-cleanup +2 -4
  9. data/bin/mu-configure +52 -0
  10. data/bin/mu-deploy +3 -3
  11. data/bin/mu-findstray-tests +25 -0
  12. data/bin/mu-gen-docs +2 -4
  13. data/bin/mu-load-config.rb +2 -1
  14. data/bin/mu-node-manage +15 -16
  15. data/bin/mu-run-tests +37 -12
  16. data/cloud-mu.gemspec +3 -3
  17. data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
  18. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
  19. data/cookbooks/mu-tools/libraries/helper.rb +1 -1
  20. data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
  21. data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
  22. data/cookbooks/mu-tools/recipes/eks.rb +2 -2
  23. data/cookbooks/mu-tools/recipes/windows-client.rb +25 -22
  24. data/extras/clean-stock-amis +25 -19
  25. data/extras/generate-stock-images +1 -0
  26. data/extras/image-generators/AWS/win2k12.yaml +2 -0
  27. data/extras/image-generators/AWS/win2k16.yaml +2 -0
  28. data/extras/image-generators/AWS/win2k19.yaml +2 -0
  29. data/modules/mommacat.ru +1 -1
  30. data/modules/mu.rb +86 -98
  31. data/modules/mu/adoption.rb +373 -58
  32. data/modules/mu/cleanup.rb +214 -303
  33. data/modules/mu/cloud.rb +128 -1733
  34. data/modules/mu/cloud/database.rb +49 -0
  35. data/modules/mu/cloud/dnszone.rb +44 -0
  36. data/modules/mu/cloud/machine_images.rb +212 -0
  37. data/modules/mu/cloud/providers.rb +81 -0
  38. data/modules/mu/cloud/resource_base.rb +929 -0
  39. data/modules/mu/cloud/server.rb +40 -0
  40. data/modules/mu/cloud/server_pool.rb +1 -0
  41. data/modules/mu/cloud/ssh_sessions.rb +228 -0
  42. data/modules/mu/cloud/winrm_sessions.rb +237 -0
  43. data/modules/mu/cloud/wrappers.rb +169 -0
  44. data/modules/mu/config.rb +123 -81
  45. data/modules/mu/config/alarm.rb +2 -6
  46. data/modules/mu/config/bucket.rb +32 -3
  47. data/modules/mu/config/cache_cluster.rb +2 -2
  48. data/modules/mu/config/cdn.rb +100 -0
  49. data/modules/mu/config/collection.rb +1 -1
  50. data/modules/mu/config/container_cluster.rb +7 -2
  51. data/modules/mu/config/database.rb +84 -105
  52. data/modules/mu/config/database.yml +1 -2
  53. data/modules/mu/config/dnszone.rb +5 -4
  54. data/modules/mu/config/doc_helpers.rb +5 -6
  55. data/modules/mu/config/endpoint.rb +2 -1
  56. data/modules/mu/config/firewall_rule.rb +3 -19
  57. data/modules/mu/config/folder.rb +1 -1
  58. data/modules/mu/config/function.rb +17 -8
  59. data/modules/mu/config/group.rb +1 -1
  60. data/modules/mu/config/habitat.rb +1 -1
  61. data/modules/mu/config/job.rb +89 -0
  62. data/modules/mu/config/loadbalancer.rb +57 -11
  63. data/modules/mu/config/log.rb +1 -1
  64. data/modules/mu/config/msg_queue.rb +1 -1
  65. data/modules/mu/config/nosqldb.rb +1 -1
  66. data/modules/mu/config/notifier.rb +8 -19
  67. data/modules/mu/config/ref.rb +92 -14
  68. data/modules/mu/config/role.rb +1 -1
  69. data/modules/mu/config/schema_helpers.rb +38 -37
  70. data/modules/mu/config/search_domain.rb +1 -1
  71. data/modules/mu/config/server.rb +12 -13
  72. data/modules/mu/config/server_pool.rb +3 -7
  73. data/modules/mu/config/storage_pool.rb +1 -1
  74. data/modules/mu/config/tail.rb +11 -0
  75. data/modules/mu/config/user.rb +1 -1
  76. data/modules/mu/config/vpc.rb +27 -23
  77. data/modules/mu/config/vpc.yml +0 -1
  78. data/modules/mu/defaults/AWS.yaml +90 -90
  79. data/modules/mu/defaults/Azure.yaml +1 -0
  80. data/modules/mu/defaults/Google.yaml +1 -0
  81. data/modules/mu/deploy.rb +34 -20
  82. data/modules/mu/groomer.rb +16 -1
  83. data/modules/mu/groomers/ansible.rb +69 -4
  84. data/modules/mu/groomers/chef.rb +51 -4
  85. data/modules/mu/logger.rb +120 -144
  86. data/modules/mu/master.rb +97 -4
  87. data/modules/mu/mommacat.rb +160 -874
  88. data/modules/mu/mommacat/daemon.rb +23 -14
  89. data/modules/mu/mommacat/naming.rb +110 -3
  90. data/modules/mu/mommacat/search.rb +497 -0
  91. data/modules/mu/mommacat/storage.rb +252 -194
  92. data/modules/mu/{clouds → providers}/README.md +1 -1
  93. data/modules/mu/{clouds → providers}/aws.rb +258 -57
  94. data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
  95. data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
  96. data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
  97. data/modules/mu/providers/aws/cdn.rb +782 -0
  98. data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
  99. data/modules/mu/{clouds → providers}/aws/container_cluster.rb +95 -84
  100. data/modules/mu/providers/aws/database.rb +1744 -0
  101. data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
  102. data/modules/mu/providers/aws/endpoint.rb +1072 -0
  103. data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
  104. data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
  105. data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
  106. data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
  107. data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
  108. data/modules/mu/providers/aws/job.rb +466 -0
  109. data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +77 -47
  110. data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
  111. data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
  112. data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
  113. data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
  114. data/modules/mu/{clouds → providers}/aws/role.rb +76 -48
  115. data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
  116. data/modules/mu/{clouds → providers}/aws/server.rb +66 -98
  117. data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
  118. data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
  119. data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
  120. data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
  121. data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
  122. data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +0 -0
  123. data/modules/mu/{clouds → providers}/aws/vpc.rb +143 -74
  124. data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
  125. data/modules/mu/{clouds → providers}/azure.rb +13 -0
  126. data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
  127. data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
  128. data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
  129. data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
  130. data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
  131. data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
  132. data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
  133. data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
  134. data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
  135. data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
  136. data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
  137. data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
  138. data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
  139. data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
  140. data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
  141. data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
  142. data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
  143. data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
  144. data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
  145. data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
  146. data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
  147. data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
  148. data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
  149. data/modules/mu/{clouds → providers}/docker.rb +0 -0
  150. data/modules/mu/{clouds → providers}/google.rb +29 -6
  151. data/modules/mu/{clouds → providers}/google/bucket.rb +4 -4
  152. data/modules/mu/{clouds → providers}/google/container_cluster.rb +38 -20
  153. data/modules/mu/{clouds → providers}/google/database.rb +5 -12
  154. data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
  155. data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
  156. data/modules/mu/{clouds → providers}/google/function.rb +6 -6
  157. data/modules/mu/{clouds → providers}/google/group.rb +9 -17
  158. data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
  159. data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
  160. data/modules/mu/{clouds → providers}/google/role.rb +50 -31
  161. data/modules/mu/{clouds → providers}/google/server.rb +41 -24
  162. data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
  163. data/modules/mu/{clouds → providers}/google/user.rb +34 -24
  164. data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
  165. data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
  166. data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
  167. data/modules/mu/{clouds → providers}/google/vpc.rb +45 -14
  168. data/modules/tests/aws-jobs-functions.yaml +46 -0
  169. data/modules/tests/centos6.yaml +15 -0
  170. data/modules/tests/centos7.yaml +15 -0
  171. data/modules/tests/centos8.yaml +12 -0
  172. data/modules/tests/ecs.yaml +2 -2
  173. data/modules/tests/eks.yaml +1 -1
  174. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  175. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  176. data/modules/tests/microservice_app.yaml +288 -0
  177. data/modules/tests/rds.yaml +108 -0
  178. data/modules/tests/regrooms/rds.yaml +123 -0
  179. data/modules/tests/server-with-scrub-muisms.yaml +1 -1
  180. data/modules/tests/super_complex_bok.yml +2 -2
  181. data/modules/tests/super_simple_bok.yml +3 -5
  182. data/spec/mu/clouds/azure_spec.rb +2 -2
  183. metadata +122 -92
  184. data/modules/mu/clouds/aws/database.rb +0 -1974
  185. data/modules/mu/clouds/aws/endpoint.rb +0 -596
@@ -163,7 +163,7 @@ module MU
163
163
  dnsthread = Thread.new {
164
164
  if !MU::Cloud::AWS.isGovCloud?
165
165
  MU.dupGlobals(parent_thread_id)
166
- generic_mu_dns = MU::Cloud::AWS::DNSZone.genericMuDNSEntry(name: @mu_name, target: "#{lb.dns_name}.", cloudclass: MU::Cloud::LoadBalancer, sync_wait: @config['dns_sync_wait'])
166
+ generic_mu_dns = MU::Cloud.resourceClass("AWS", "DNSZone").genericMuDNSEntry(name: @mu_name, target: "#{lb.dns_name}.", cloudclass: MU::Cloud::LoadBalancer, sync_wait: @config['dns_sync_wait'])
167
167
  end
168
168
  }
169
169
 
@@ -239,16 +239,35 @@ module MU
239
239
  end
240
240
  end
241
241
 
242
+ redirect_block = Proc.new { |r|
243
+ {
244
+ :protocol => r['protocol'],
245
+ :port => r['port'].to_s,
246
+ :host => r['host'],
247
+ :path => r['path'],
248
+ :query => r['query'],
249
+ :status_code => "HTTP_"+r['status_code'].to_s
250
+ }
251
+ }
252
+
242
253
  if !@config['classic']
243
254
  @config["listeners"].each { |l|
244
- if !@targetgroups.has_key?(l['targetgroup'])
245
- raise MuError, "Listener in #{@mu_name} configured for target group #{l['targetgroup']}, but I don't have data on a targetgroup by that name"
246
- end
247
- listen_descriptor = {
248
- :default_actions => [{
255
+ action = if l['redirect']
256
+ {
257
+ :type => "redirect",
258
+ :redirect_config => redirect_block.call(l['redirect'])
259
+ }
260
+ else
261
+ if !@targetgroups.has_key?(l['targetgroup'])
262
+ raise MuError, "Listener in #{@mu_name} configured for target group #{l['targetgroup']}, but I don't have data on a targetgroup by that name"
263
+ end
264
+ {
249
265
  :target_group_arn => @targetgroups[l['targetgroup']].target_group_arn,
250
266
  :type => "forward"
251
- }],
267
+ }
268
+ end
269
+ listen_descriptor = {
270
+ :default_actions => [ action ],
252
271
  :load_balancer_arn => lb.load_balancer_arn,
253
272
  :port => l['lb_port'],
254
273
  :protocol => l['lb_protocol']
@@ -276,10 +295,17 @@ module MU
276
295
  :actions => []
277
296
  }
278
297
  rule['actions'].each { |a|
279
- rule_descriptor[:actions] << {
280
- :target_group_arn => @targetgroups[a['targetgroup']].target_group_arn,
281
- :type => a['action']
282
- }
298
+ rule_descriptor[:actions] << if a['action'] == "forward"
299
+ {
300
+ :target_group_arn => @targetgroups[a['targetgroup']].target_group_arn,
301
+ :type => a['action']
302
+ }
303
+ elsif a['action'] == "redirect"
304
+ {
305
+ :redirect_config => redirect_block.call(rule['redirect']),
306
+ :type => a['action']
307
+ }
308
+ end
283
309
  }
284
310
  MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).create_rule(rule_descriptor)
285
311
  }
@@ -536,7 +562,7 @@ module MU
536
562
  }
537
563
  end
538
564
  if !MU::Cloud::AWS.isGovCloud?
539
- MU::Cloud::AWS::DNSZone.createRecordsFromConfig(@config['dns_records'], target: cloud_desc.dns_name)
565
+ MU::Cloud.resourceClass("AWS", "DNSZone").createRecordsFromConfig(@config['dns_records'], target: cloud_desc.dns_name)
540
566
  end
541
567
  end
542
568
 
@@ -557,6 +583,7 @@ module MU
557
583
  # Wrapper for cloud_desc method that deals with elb vs. elb2 resources.
558
584
  def cloud_desc(use_cache: true)
559
585
  return @cloud_desc_cache if @cloud_desc_cache and use_cache
586
+ return nil if !@cloud_id
560
587
  if @config['classic']
561
588
  @cloud_desc_cache = MU::Cloud::AWS.elb(region: @config['region'], credentials: @config['credentials']).describe_load_balancers(
562
589
  load_balancer_names: [@cloud_id]
@@ -566,13 +593,34 @@ module MU
566
593
  @cloud_desc_cache = MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).describe_load_balancers(
567
594
  names: [@cloud_id]
568
595
  ).load_balancers.first
569
- if @targetgroups.nil? and !@deploy.nil? and
570
- @deploy.deployment['loadbalancers'].has_key?(@config['name']) and
571
- @deploy.deployment['loadbalancers'][@config['name']].has_key?("targetgroups")
596
+ if @targetgroups.nil?
572
597
  @targetgroups = {}
573
- @deploy.deployment['loadbalancers'][@config['name']]["targetgroups"].each_pair { |tg_name, tg_arn|
574
- @targetgroups[tg_name] = MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).describe_target_groups(target_group_arns: [tg_arn]).target_groups.first
575
- }
598
+ if !@deploy.nil? and
599
+ @deploy.deployment['loadbalancers'] and
600
+ @deploy.deployment['loadbalancers'][@config['name']] and
601
+ @deploy.deployment['loadbalancers'][@config['name']]["targetgroups"]
602
+ @deploy.deployment['loadbalancers'][@config['name']]["targetgroups"].each_pair { |tg_name, tg_arn|
603
+ @targetgroups[tg_name] = MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).describe_target_groups(target_group_arns: [tg_arn]).target_groups.first
604
+ }
605
+ else
606
+ pp @config['targetgroups']
607
+ MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).describe_target_groups(load_balancer_arn: @cloud_desc_cache.load_balancer_arn).target_groups.each { |tg|
608
+ tg_name = tg.target_group_name
609
+ if @config['targetgroups']
610
+ @config['targetgroups'].each { |tg_cfg|
611
+ if tg_name = @deploy.getResourceName(tg_cfg["name"], max_length: 32, disallowed_chars: /[^A-Za-z0-9-]/)
612
+ tg_name = tg_cfg['name']
613
+ break
614
+ end
615
+ }
616
+ end
617
+ @targetgroups[tg_name] = tg
618
+ }
619
+ # @config['targetgroups'].each { |tg|
620
+ # tg_name = @deploy.getResourceName(tg["name"], max_length: 32, disallowed_chars: /[^A-Za-z0-9-]/)
621
+ # @targetgroups[tg_name] = MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).describe_target_groups(target_group_arns: [tg_arn]).target_groups.first
622
+ # }
623
+ end
576
624
  end
577
625
 
578
626
  return @cloud_desc_cache
@@ -645,8 +693,8 @@ module MU
645
693
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
646
694
  # @param region [String]: The cloud provider region
647
695
  # @return [void]
648
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
649
- if (MU.deploy_id.nil? or MU.deploy_id.empty?) and (!flags or !flags["vpc_id"])
696
+ def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
697
+ if (deploy_id.nil? or deploy_id.empty?) and (!flags or !flags["vpc_id"])
650
698
  raise MuError, "Can't touch ELBs without MU-ID or vpc_id flag"
651
699
  end
652
700
 
@@ -656,7 +704,7 @@ module MU
656
704
  # @param region [String]: The cloud provider region
657
705
  # @param ignoremaster [Boolean]: Whether to ignore the MU-MASTER-IP tag
658
706
  # @param classic [Boolean]: Whether to look for a classic ELB instead of an ALB (ELB2)
659
- def self.checkForTagMatch(arn, region, ignoremaster, credentials, classic = false)
707
+ def self.checkForTagMatch(arn, region, ignoremaster, credentials, classic = false, deploy_id: MU.deploy_id)
660
708
  tags = []
661
709
  if classic
662
710
  tags = MU::Cloud::AWS.elb(credentials: credentials, region: region).describe_tags(
@@ -673,7 +721,7 @@ module MU
673
721
  if !tags.nil?
674
722
  tags.each { |tag|
675
723
  saw_tags << tag.key
676
- muid_match = true if tag.key == "MU-ID" and tag.value == MU.deploy_id
724
+ muid_match = true if tag.key == "MU-ID" and tag.value == deploy_id
677
725
  mumaster_match = true if tag.key == "MU-MASTER-IP" and tag.value == MU.mu_public_ip
678
726
  }
679
727
  end
@@ -699,14 +747,14 @@ module MU
699
747
  matched = true if lb.vpc_id == flags['vpc_id']
700
748
  else
701
749
  if classic
702
- matched = self.checkForTagMatch(lb.load_balancer_name, region, ignoremaster, credentials, classic)
750
+ matched = self.checkForTagMatch(lb.load_balancer_name, region, ignoremaster, credentials, classic, deploy_id: deploy_id)
703
751
  else
704
- matched = self.checkForTagMatch(lb.load_balancer_arn, region, ignoremaster, credentials, classic)
752
+ matched = self.checkForTagMatch(lb.load_balancer_arn, region, ignoremaster, credentials, classic, deploy_id: deploy_id)
705
753
  end
706
754
  end
707
755
  if matched
708
756
  if !MU::Cloud::AWS.isGovCloud?
709
- MU::Cloud::AWS::DNSZone.genericMuDNSEntry(name: lb.load_balancer_name, target: lb.dns_name, cloudclass: MU::Cloud::LoadBalancer, delete: true) if !noop
757
+ MU::Cloud.resourceClass("AWS", "DNSZone").genericMuDNSEntry(name: lb.load_balancer_name, target: lb.dns_name, cloudclass: MU::Cloud::LoadBalancer, delete: true) if !noop
710
758
  end
711
759
  if classic
712
760
  MU.log "Removing Elastic Load Balancer #{lb.load_balancer_name}"
@@ -747,7 +795,7 @@ module MU
747
795
 
748
796
 
749
797
  tgs.each { |tg|
750
- if self.checkForTagMatch(tg.target_group_arn, region, ignoremaster, credentials)
798
+ if self.checkForTagMatch(tg.target_group_arn, region, ignoremaster, credentials, deploy_id: deploy_id)
751
799
  MU.log "Removing Load Balancer Target Group #{tg.target_group_name}"
752
800
  retries = 0
753
801
  begin
@@ -793,26 +841,7 @@ module MU
793
841
  }
794
842
  }
795
843
  },
796
- "ingress_rules" => {
797
- "items" => {
798
- "properties" => {
799
- "sgs" => {
800
- "type" => "array",
801
- "items" => {
802
- "description" => "Other AWS Security Groups; resources that are associated with this group will have this rule applied to their traffic",
803
- "type" => "string"
804
- }
805
- },
806
- "lbs" => {
807
- "type" => "array",
808
- "items" => {
809
- "description" => "AWS Load Balancers which will have this rule applied to their traffic",
810
- "type" => "string"
811
- }
812
- }
813
- }
814
- }
815
- }
844
+ "ingress_rules" => MU::Cloud.resourceClass("AWS", "FirewallRule").ingressRuleAddtlSchema
816
845
  }
817
846
  [toplevel_required, schema]
818
847
  end
@@ -830,7 +859,7 @@ module MU
830
859
  (!listener["ssl_certificate_id"].nil? and !listener["ssl_certificate_id"].empty?)
831
860
  if lb['cloud'] != "CloudFormation" # XXX or maybe do this anyway?
832
861
  begin
833
- listener["ssl_certificate_id"] = MU::Cloud::AWS.findSSLCertificate(name: listener["ssl_certificate_name"].to_s, id: listener["ssl_certificate_id"].to_s, region: lb['region'])
862
+ listener["ssl_certificate_id"] = MU::Cloud::AWS.findSSLCertificate(name: listener["ssl_certificate_name"].to_s, id: listener["ssl_certificate_id"].to_s, region: lb['region']).first
834
863
  rescue MuError
835
864
  ok = false
836
865
  next
@@ -923,6 +952,7 @@ module MU
923
952
  return matches
924
953
 
925
954
  end
955
+
926
956
  end
927
957
  end
928
958
  end
@@ -202,14 +202,14 @@ module MU
202
202
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
203
203
  # @param region [String]: The cloud provider region
204
204
  # @return [void]
205
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
205
+ def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
206
206
  MU.log "AWS::Log.cleanup: need to support flags['known']", MU::DEBUG, details: flags
207
207
  MU.log "Placeholder: AWS Log artifacts do not support tags, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: ignoremaster
208
208
 
209
209
  log_groups = self.find(credentials: credentials, region: region).values
210
210
  if !log_groups.empty?
211
211
  log_groups.each{ |lg|
212
- if lg.log_group_name.match(MU.deploy_id)
212
+ if lg.log_group_name.match(deploy_id)
213
213
  log_streams = MU::Cloud::AWS.cloudwatchlogs(credentials: credentials, region: region).describe_log_streams(log_group_name: lg.log_group_name).log_streams
214
214
  if !log_streams.empty?
215
215
  log_streams.each{ |ls|
@@ -232,9 +232,9 @@ module MU
232
232
 
233
233
  # unless noop
234
234
  # MU::Cloud::AWS.iam(credentials: credentials).list_roles.roles.each{ |role|
235
- # match_string = "#{MU.deploy_id}.*CloudTrail"
236
- # Maybe we should have a more generic way to delete IAM profiles and policies. The call itself should be moved from MU::Cloud::AWS::Server.
237
- # MU::Cloud::AWS::Server.removeIAMProfile(role.role_name) if role.role_name.match(match_string)
235
+ # match_string = "#{deploy_id}.*CloudTrail"
236
+ # Maybe we should have a more generic way to delete IAM profiles and policies. The call itself should be moved from MU::Cloud.resourceClass("AWS", "Server").
237
+ # MU::Cloud.resourceClass("AWS", "Server").removeIAMProfile(role.role_name) if role.role_name.match(match_string)
238
238
  # }
239
239
  # end
240
240
  end
@@ -80,6 +80,7 @@ module MU
80
80
  # @return [Hash]: AWS doesn't return anything but the SQS URL, so supplement with attributes
81
81
  def cloud_desc(use_cache: true)
82
82
  return @cloud_desc_cache if @cloud_desc_cache and use_cache
83
+ return nil if !@cloud_id
83
84
 
84
85
  if !@cloud_id
85
86
  resp = MU::Cloud::AWS.sqs(region: @config['region'], credentials: @config['credentials']).list_queues(
@@ -133,12 +134,12 @@ module MU
133
134
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
134
135
  # @param region [String]: The cloud provider region
135
136
  # @return [void]
136
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
137
+ def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
137
138
  MU.log "AWS::MsgQueue.cleanup: need to support flags['known']", MU::DEBUG, details: flags
138
139
  MU.log "Placeholder: AWS MsgQueue artifacts do not support tags, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: ignoremaster
139
140
 
140
141
  resp = MU::Cloud::AWS.sqs(credentials: credentials, region: region).list_queues(
141
- queue_name_prefix: MU.deploy_id
142
+ queue_name_prefix: deploy_id
142
143
  )
143
144
  if resp and resp.queue_urls
144
145
  threads = []
@@ -194,7 +195,15 @@ module MU
194
195
 
195
196
  # Go fetch its attributes
196
197
  fetch = if args[:cloud_id]
197
- [args[:cloud_id]]
198
+ if args[:cloud_id] !~ /^https?:\/\//
199
+ [begin
200
+ MU::Cloud::AWS.sqs(region: args[:region], credentials: args[:credentials]).get_queue_url(queue_name: args[:cloud_id]).queue_url
201
+ rescue Aws::SQS::Errors::NonExistentQueue
202
+ return found
203
+ end]
204
+ else
205
+ [args[:cloud_id]]
206
+ end
198
207
  else
199
208
  resp = MU::Cloud::AWS.sqs(region: args[:region], credentials: args[:credentials]).list_queues
200
209
  resp.queue_urls
@@ -327,16 +336,10 @@ module MU
327
336
  failq.delete("failqueue")
328
337
  ok = false if !configurator.insertKitten(failq, "msg_queues")
329
338
  queue['failqueue']['name'] = failq['name']
330
- queue['dependencies'] << {
331
- "name" => failq['name'],
332
- "type" => "msg_queue"
333
- }
339
+ MU::Config.addDependency(queue, failq["name"], "msg_queue")
334
340
  else
335
341
  if configurator.haveLitterMate?(queue['failqueue']['name'], "msg_queue")
336
- queue['dependencies'] << {
337
- "name" => queue['failqueue']['name'],
338
- "type" => "msg_queue"
339
- }
342
+ MU::Config.addDependency(queue, queue['failqueue']['name'], "msg_queue")
340
343
  else
341
344
  failq = MU::Cloud::AWS::MsgQueue.find(cloud_id: queue['failqueue']['name'])
342
345
  if !failq
@@ -47,7 +47,11 @@ module MU
47
47
  }
48
48
  end
49
49
 
50
+ type_map = {}
51
+
50
52
  @config['attributes'].each { |attr|
53
+ type_map[attr['name']] = attr['type']
54
+
51
55
  params[:attribute_definitions] << {
52
56
  :attribute_name => attr['name'],
53
57
  :attribute_type => attr['type']
@@ -67,6 +71,11 @@ module MU
67
71
  }
68
72
  end
69
73
  }
74
+ # apparently the HASH key always has to be before RANGE, so sort it
75
+ # lexically by that field and call it a day
76
+ params[:key_schema].sort! { |a, b|
77
+ a[:key_type] <=> b[:key_type]
78
+ }
70
79
 
71
80
  if @config['secondary_indexes']
72
81
  @config['secondary_indexes'].each { |idx|
@@ -99,7 +108,11 @@ module MU
99
108
  }
100
109
  end
101
110
 
102
- MU.log "Creating DynamoDB table #{@mu_name}", details: params
111
+ if @tags
112
+ params[:tags] = @tags.each_key.map { |k| { :key => k, :value => @tags[k] } }
113
+ end
114
+
115
+ MU.log "Creating DynamoDB table #{@mu_name}", MU::NOTICE, details: params
103
116
 
104
117
  resp = MU::Cloud::AWS.dynamo(credentials: @config['credentials'], region: @config['region']).create_table(params)
105
118
  @cloud_id = @mu_name
@@ -109,8 +122,24 @@ module MU
109
122
  sleep 5 if resp.table.table_status == "CREATING"
110
123
  end while resp.table.table_status == "CREATING"
111
124
 
112
-
113
125
  tagTable if !@config['scrub_mu_isms']
126
+
127
+ if @config['populate'] and !@config['populate'].empty?
128
+ MU.log "Preloading #{@mu_name} with #{@config['populate'].size.to_s} items"
129
+ items_to_write = @config['populate'].dup
130
+ begin
131
+ batch = items_to_write.slice!(0, (items_to_write.length >= 25 ? 25 : items_to_write.length))
132
+ begin
133
+ MU::Cloud::AWS.dynamo(credentials: @config['credentials'], region: @config['region']).batch_write_item(
134
+ request_items: {
135
+ @cloud_id => batch.map { |i| { put_request: { item: i } } }
136
+ }
137
+ )
138
+ rescue ::Aws::DynamoDB::Errors::ValidationException => e
139
+ MU.log e.message, MU::ERR, details: item
140
+ end
141
+ end while !items_to_write.empty?
142
+ end
114
143
  end
115
144
 
116
145
  # Apply tags to this DynamoDB table
@@ -143,6 +172,7 @@ module MU
143
172
  # Called automatically by {MU::Deploy#createResources}
144
173
  def groom
145
174
  tagTable if !@config['scrub_mu_isms']
175
+ MU.log "NoSQL Table #{@config['name']}: #{@cloud_id}", MU::SUMMARY
146
176
  end
147
177
 
148
178
  # Does this resource type exist as a global (cloud-wide) artifact, or
@@ -163,7 +193,7 @@ module MU
163
193
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
164
194
  # @param region [String]: The cloud provider region
165
195
  # @return [void]
166
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
196
+ def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
167
197
  MU.log "AWS::NoSQLDb.cleanup: need to support flags['known']", MU::DEBUG, details: flags
168
198
 
169
199
  resp = MU::Cloud::AWS.dynamo(credentials: credentials, region: region).list_tables
@@ -183,7 +213,7 @@ module MU
183
213
  deploy_match = false
184
214
  master_match = false
185
215
  tags.tags.each { |tag|
186
- if tag.key == "MU-ID" and tag.value == MU.deploy_id
216
+ if tag.key == "MU-ID" and tag.value == deploy_id
187
217
  deploy_match = true
188
218
  elsif tag.key == "MU-MASTER-IP" and tag.value == MU.mu_public_ip
189
219
  master_match = true
@@ -214,7 +244,8 @@ module MU
214
244
  # Return the metadata for this user cofiguration
215
245
  # @return [Hash]
216
246
  def notify
217
- MU.structToHash(cloud_desc)
247
+ return nil if !@cloud_id or !cloud_desc(use_cache: false)
248
+ MU.structToHash(cloud_desc, stringify_keys: true)
218
249
  end
219
250
 
220
251
  # Locate an existing DynamoDB table
@@ -244,6 +275,59 @@ module MU
244
275
  found
245
276
  end
246
277
 
278
+ # Reverse-map our cloud description into a runnable config hash.
279
+ # We assume that any values we have in +@config+ are placeholders, and
280
+ # calculate our own accordingly based on what's live in the cloud.
281
+ def toKitten(**_args)
282
+ bok = {
283
+ "cloud" => "AWS",
284
+ "credentials" => @config['credentials'],
285
+ "cloud_id" => @cloud_id,
286
+ "region" => @config['region']
287
+ }
288
+
289
+ if !cloud_desc
290
+ MU.log "toKitten failed to load a cloud_desc from #{@cloud_id}", MU::ERR, details: @config
291
+ return nil
292
+ end
293
+ bok['name'] = cloud_desc.table_name
294
+ bok['read_capacity'] = cloud_desc.provisioned_throughput.read_capacity_units
295
+ bok['write_capacity'] = cloud_desc.provisioned_throughput.write_capacity_units
296
+
297
+
298
+ cloud_desc.attribute_definitions.each { |attr|
299
+ bok['attributes'] ||= []
300
+ newattr = {
301
+ "name" => attr.attribute_name,
302
+ "type" => attr.attribute_type
303
+ }
304
+ if cloud_desc.key_schema
305
+ cloud_desc.key_schema.each { |key|
306
+ next if key.attribute_name == attr.attribute_name
307
+ if key.key_type == "RANGE"
308
+ newattr["primary_partition"] = true
309
+ elsif key.key_type == "HASH"
310
+ newattr["primary_sort"] = true
311
+ end
312
+ }
313
+ end
314
+ bok['attributes'] << newattr
315
+ }
316
+
317
+ if cloud_desc.stream_specification and cloud_desc.stream_specification.stream_enabled
318
+
319
+ bok['stream'] = cloud_desc.stream_specification.stream_view_type
320
+ # cloud_desc.latest_stream_arn
321
+ # MU::Cloud::AWS.dynamostream(credentials: @credentials, region: @config['region']).list_streams
322
+ end
323
+
324
+ bok["populate"] = MU::Cloud::AWS.dynamo(credentials: @credentials, region: @config['region']).scan(
325
+ table_name: @cloud_id
326
+ ).items
327
+
328
+ bok
329
+ end
330
+
247
331
  # Cloud-specific configuration properties.
248
332
  # @param _config [MU::Config]: The calling MU::Config object
249
333
  # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
@@ -252,6 +336,13 @@ module MU
252
336
 
253
337
 
254
338
  schema = {
339
+ "populate" => {
340
+ "type" => "array",
341
+ "items" => {
342
+ "type" => "object",
343
+ "description" => "Key-value pairs, compatible with the +attributes+ schema, with which to populate this +table+ during its initial creation."
344
+ }
345
+ },
255
346
  "attributes" => {
256
347
  "type" => "array",
257
348
  "minItems" => 1,