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
@@ -18,7 +18,7 @@ module MU
18
18
 
19
19
  # Creation of Virtual Private Clouds and associated artifacts (routes, subnets, etc).
20
20
  class VPC < MU::Cloud::VPC
21
- require 'mu/clouds/aws/vpc_subnet'
21
+ require 'mu/providers/aws/vpc_subnet'
22
22
 
23
23
  # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
24
24
  # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
@@ -209,7 +209,7 @@ module MU
209
209
  if !MU::Cloud::AWS.isGovCloud?(@config['region'])
210
210
  mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu", credentials: @config['credentials']).values.first
211
211
  if !mu_zone.nil?
212
- MU::Cloud::AWS::DNSZone.toggleVPCAccess(id: mu_zone.id, vpc_id: @cloud_id, region: @config['region'], credentials: @config['credentials'])
212
+ MU::Cloud.resourceClass("AWS", "DNSZone").toggleVPCAccess(id: mu_zone.id, vpc_id: @cloud_id, region: @config['region'], credentials: @config['credentials'])
213
213
  end
214
214
  end
215
215
  loadSubnets
@@ -822,11 +822,11 @@ module MU
822
822
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
823
823
  # @param region [String]: The cloud provider region
824
824
  # @return [void]
825
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
825
+ def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
826
826
  MU.log "AWS::VPC.cleanup: need to support flags['known']", MU::DEBUG, details: flags
827
827
 
828
828
  tagfilters = [
829
- {name: "tag:MU-ID", values: [MU.deploy_id]}
829
+ {name: "tag:MU-ID", values: [deploy_id]}
830
830
  ]
831
831
  if !ignoremaster
832
832
  tagfilters << {name: "tag:MU-MASTER-IP", values: [MU.mu_public_ip]}
@@ -838,9 +838,23 @@ module MU
838
838
  vpcs = resp if !resp.empty?
839
839
  }
840
840
 
841
+ # resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
842
+ # filters: [
843
+ # {
844
+ # name: "requester-vpc-info.vpc-id",
845
+ # values: [@cloud_id]
846
+ # },
847
+ # {
848
+ # name: "accepter-vpc-info.vpc-id",
849
+ # values: [peer_id.to_s]
850
+ # }
851
+ # ]
852
+ # )
853
+
841
854
  if !vpcs.empty?
842
855
  gwthreads = []
843
856
  vpcs.each { |vpc|
857
+ purge_peering_connections(noop, vpc.vpc_id, region: region, credentials: credentials)
844
858
  # NAT gateways don't have any tags, and we can't assign them a name. Lets find them based on a VPC ID
845
859
  gwthreads << Thread.new {
846
860
  purge_nat_gateways(noop, vpc_id: vpc.vpc_id, region: region, credentials: credentials)
@@ -862,7 +876,7 @@ module MU
862
876
 
863
877
  # unless noop
864
878
  # MU::Cloud::AWS.iam.list_roles.roles.each{ |role|
865
- # match_string = "#{MU.deploy_id}.*TRAFFIC-LOG"
879
+ # match_string = "#{deploy_id}.*TRAFFIC-LOG"
866
880
  # }
867
881
  # end
868
882
  end
@@ -916,11 +930,7 @@ module MU
916
930
  logdesc["tags"] = vpc["tags"] if !vpc["tags"].nil?
917
931
  # logdesc["optional_tags"] = vpc["optional_tags"] if !vpc["optional_tags"].nil?
918
932
  configurator.insertKitten(logdesc, "logs")
919
- vpc['dependencies'] ||= []
920
- vpc['dependencies'] << {
921
- "type" => "log",
922
- "name" => vpc['name']+"loggroup"
923
- }
933
+ MU::Config.addDependency(vpc, vpc['name']+"loggroup", "log")
924
934
 
925
935
  roledesc = {
926
936
  "name" => vpc['name']+"logrole",
@@ -958,11 +968,7 @@ module MU
958
968
  roledesc["tags"] = vpc["tags"] if !vpc["tags"].nil?
959
969
  roledesc["optional_tags"] = vpc["optional_tags"] if !vpc["optional_tags"].nil?
960
970
  configurator.insertKitten(roledesc, "roles")
961
- vpc['dependencies'] ||= []
962
- vpc['dependencies'] << {
963
- "type" => "role",
964
- "name" => vpc['name']+"logrole"
965
- }
971
+ MU::Config.addDependency(vpc, vpc['name']+"logrole", "role")
966
972
  end
967
973
 
968
974
  subnet_routes = Hash.new
@@ -1013,10 +1019,7 @@ module MU
1013
1019
  subnet_routes[table['name']].each { |subnet|
1014
1020
  nat_routes[subnet] = route['nat_host_name']
1015
1021
  }
1016
- vpc['dependencies'] << {
1017
- "type" => "server",
1018
- "name" => route['nat_host_name']
1019
- }
1022
+ MU::Config.addDependency(vpc, route['nat_host_name'], "server", no_create_wait: true)
1020
1023
  elsif route['gateway'] == '#NAT'
1021
1024
  vpc['create_nat_gateway'] = true
1022
1025
  private_rtbs << table['name']
@@ -1225,7 +1228,7 @@ module MU
1225
1228
  # suits me just fine
1226
1229
  rescue Aws::EC2::Errors::AuthFailure => e
1227
1230
  if !tried_lbs and iface.attachment.instance_owner_id == "amazon-elb"
1228
- MU::Cloud::AWS::LoadBalancer.cleanup(
1231
+ MU::Cloud.resourceClass("AWS", "LoadBalancer").cleanup(
1229
1232
  noop: noop,
1230
1233
  region: region,
1231
1234
  credentials: credentials,
@@ -1265,12 +1268,73 @@ module MU
1265
1268
  nil
1266
1269
  end
1267
1270
 
1271
+ # Try to locate the default VPC for a region, and return a BoK-style
1272
+ # config fragment for something that might want to live in it.
1273
+ def self.defaultVpc(region, credentials)
1274
+ cfg_fragment = nil
1275
+ MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_vpcs.vpcs.each { |vpc|
1276
+ if vpc.is_default
1277
+ cfg_fragment = {
1278
+ "id" => vpc.vpc_id,
1279
+ "cloud" => "AWS",
1280
+ "region" => region,
1281
+ "credentials" => credentials
1282
+ }
1283
+ cfg_fragment['subnets'] = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_subnets(
1284
+ filters: [
1285
+ {
1286
+ name: "vpc-id",
1287
+ values: [vpc.vpc_id]
1288
+ }
1289
+ ]
1290
+ ).subnets.map { |s| { "subnet_id" => s.subnet_id } }
1291
+ break
1292
+ end
1293
+ }
1294
+
1295
+ cfg_fragment
1296
+ end
1297
+
1298
+ # Return a {MU::Config::Ref} that indicates this VPC.
1299
+ # @param subnet_ids [Array<String>]: Optional list of subnet ids with which to infer a +subnet_pref+ parameter.
1300
+ # @return [MU::Config::Ref]
1301
+ def getReference(subnet_ids = [])
1302
+ have_private = have_public = false
1303
+ subnets.each { |s|
1304
+ next if subnet_ids and !subnet_ids.empty? and !subnet_ids.include?(s.cloud_id)
1305
+ if s.private?
1306
+ have_private = true
1307
+ else
1308
+ have_public = true
1309
+ end
1310
+ }
1311
+ subnet_pref = if have_private == have_public
1312
+ "any"
1313
+ elsif have_private
1314
+ "all_private"
1315
+ elsif have_public
1316
+ "all_public"
1317
+ end
1318
+ MU::Config::Ref.get(
1319
+ id: @cloud_id,
1320
+ cloud: "AWS",
1321
+ credentials: @credentials,
1322
+ region: @config['region'],
1323
+ type: "vpcs",
1324
+ subnet_pref: subnet_pref
1325
+ )
1326
+ end
1327
+
1268
1328
  private
1269
1329
 
1270
1330
  def peerWith(peer)
1271
1331
  peer_ref = MU::Config::Ref.get(peer['vpc'])
1272
1332
  peer_obj = peer_ref.kitten
1273
- peer_id = peer_ref.cloud_id
1333
+ peer_id = peer_ref.kitten.cloud_id
1334
+ if peer_id == @cloud_id
1335
+ MU.log "#{@mu_name} attempted to peer with itself (#{@cloud_id})", MU::ERR, details: peer
1336
+ raise "#{@mu_name} attempted to peer with itself (#{@cloud_id})"
1337
+ end
1274
1338
 
1275
1339
  if peer_obj and peer_obj.config['peers']
1276
1340
  peer_obj.config['peers'].each { |peerpeer|
@@ -1679,6 +1743,61 @@ module MU
1679
1743
  end
1680
1744
  private_class_method :purge_dhcpopts
1681
1745
 
1746
+ def self.purge_peering_connections(noop, vpc_id, region: MU.curRegion, credentials: nil)
1747
+ my_peer_conns = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpc_peering_connections(
1748
+ filters: [
1749
+ {
1750
+ name: "requester-vpc-info.vpc-id",
1751
+ values: [vpc_id]
1752
+ }
1753
+ ]
1754
+ ).vpc_peering_connections
1755
+ my_peer_conns.concat(MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpc_peering_connections(
1756
+ filters: [
1757
+ {
1758
+ name: "accepter-vpc-info.vpc-id",
1759
+ values: [vpc_id]
1760
+ }
1761
+ ]
1762
+ ).vpc_peering_connections)
1763
+
1764
+ my_peer_conns.each { |cnxn|
1765
+ [cnxn.accepter_vpc_info.vpc_id, cnxn.requester_vpc_info.vpc_id].each { |peer_vpc|
1766
+ MU::Cloud::AWS::VPC.listAllSubnetRouteTables(peer_vpc, region: region, credentials: credentials).each { |rtb_id|
1767
+ begin
1768
+ resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_route_tables(
1769
+ route_table_ids: [rtb_id]
1770
+ )
1771
+ rescue Aws::EC2::Errors::InvalidRouteTableIDNotFound
1772
+ next
1773
+ end
1774
+ resp.route_tables.each { |rtb|
1775
+ rtb.routes.each { |route|
1776
+ if route.vpc_peering_connection_id == cnxn.vpc_peering_connection_id
1777
+ MU.log "Removing route #{route.destination_cidr_block} from route table #{rtb_id} in VPC #{peer_vpc}"
1778
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_route(
1779
+ route_table_id: rtb_id,
1780
+ destination_cidr_block: route.destination_cidr_block
1781
+ ) if !noop
1782
+ end
1783
+ }
1784
+ }
1785
+ }
1786
+ }
1787
+ MU.log "Deleting VPC peering connection #{cnxn.vpc_peering_connection_id}"
1788
+ begin
1789
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_vpc_peering_connection(
1790
+ vpc_peering_connection_id: cnxn.vpc_peering_connection_id
1791
+ ) if !noop
1792
+ rescue Aws::EC2::Errors::InvalidStateTransition
1793
+ MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} not in removable (state #{cnxn.status.code})", MU::WARN
1794
+ rescue Aws::EC2::Errors::OperationNotPermitted => e
1795
+ MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} refuses to delete: #{e.message}", MU::WARN
1796
+ end
1797
+ }
1798
+ end
1799
+ private_class_method :purge_peering_connections
1800
+
1682
1801
  # Remove all VPCs associated with the currently loaded deployment.
1683
1802
  # @param noop [Boolean]: If true, will only print what would be done
1684
1803
  # @param tagfilters [Array<Hash>]: EC2 tags to filter against when search for resources to purge
@@ -1693,60 +1812,10 @@ module MU
1693
1812
  return if vpcs.nil? or vpcs.size == 0
1694
1813
 
1695
1814
  vpcs.each { |vpc|
1696
- my_peer_conns = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpc_peering_connections(
1697
- filters: [
1698
- {
1699
- name: "requester-vpc-info.vpc-id",
1700
- values: [vpc.vpc_id]
1701
- }
1702
- ]
1703
- ).vpc_peering_connections
1704
- my_peer_conns.concat(MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpc_peering_connections(
1705
- filters: [
1706
- {
1707
- name: "accepter-vpc-info.vpc-id",
1708
- values: [vpc.vpc_id]
1709
- }
1710
- ]
1711
- ).vpc_peering_connections)
1712
- my_peer_conns.each { |cnxn|
1713
-
1714
- [cnxn.accepter_vpc_info.vpc_id, cnxn.requester_vpc_info.vpc_id].each { |peer_vpc|
1715
- MU::Cloud::AWS::VPC.listAllSubnetRouteTables(peer_vpc, region: region, credentials: credentials).each { |rtb_id|
1716
- begin
1717
- resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_route_tables(
1718
- route_table_ids: [rtb_id]
1719
- )
1720
- rescue Aws::EC2::Errors::InvalidRouteTableIDNotFound
1721
- next
1722
- end
1723
- resp.route_tables.each { |rtb|
1724
- rtb.routes.each { |route|
1725
- if route.vpc_peering_connection_id == cnxn.vpc_peering_connection_id
1726
- MU.log "Removing route #{route.destination_cidr_block} from route table #{rtb_id} in VPC #{peer_vpc}"
1727
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_route(
1728
- route_table_id: rtb_id,
1729
- destination_cidr_block: route.destination_cidr_block
1730
- ) if !noop
1731
- end
1732
- }
1733
- }
1734
- }
1735
- }
1736
- MU.log "Deleting VPC peering connection #{cnxn.vpc_peering_connection_id}"
1737
- begin
1738
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_vpc_peering_connection(
1739
- vpc_peering_connection_id: cnxn.vpc_peering_connection_id
1740
- ) if !noop
1741
- rescue Aws::EC2::Errors::InvalidStateTransition
1742
- MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} not in removable (state #{cnxn.status.code})", MU::WARN
1743
- rescue Aws::EC2::Errors::OperationNotPermitted => e
1744
- MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} refuses to delete: #{e.message}", MU::WARN
1745
- end
1746
- }
1815
+ purge_peering_connections(noop, vpc.vpc_id, region: region, credentials: credentials)
1747
1816
 
1748
1817
  on_retry = Proc.new {
1749
- MU::Cloud::AWS::FirewallRule.cleanup(
1818
+ MU::Cloud.resourceClass("AWS", "FirewallRule").cleanup(
1750
1819
  noop: noop,
1751
1820
  region: region,
1752
1821
  credentials: credentials,
@@ -1763,7 +1832,7 @@ module MU
1763
1832
  if !MU::Cloud::AWS.isGovCloud?(region)
1764
1833
  mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu", region: region, credentials: credentials).values.first
1765
1834
  if !mu_zone.nil?
1766
- MU::Cloud::AWS::DNSZone.toggleVPCAccess(id: mu_zone.id, vpc_id: vpc.vpc_id, remove: true, credentials: credentials)
1835
+ MU::Cloud.resourceClass("AWS", "DNSZone").toggleVPCAccess(id: mu_zone.id, vpc_id: vpc.vpc_id, remove: true, credentials: credentials)
1767
1836
  end
1768
1837
  end
1769
1838
  }
@@ -47,6 +47,11 @@ module MU
47
47
  guid_chunks.join("-")
48
48
  end
49
49
 
50
+ # List all Azure subscriptions available to our credentials
51
+ def self.listHabitats(credentials = nil, use_cache: true)
52
+ []
53
+ end
54
+
50
55
  # A hook that is always called just before any of the instance method of
51
56
  # our resource implementations gets invoked, so that we can ensure that
52
57
  # repetitive setup tasks (like resolving +:resource_group+ for Azure
@@ -77,6 +82,11 @@ module MU
77
82
  [:resource_group]
78
83
  end
79
84
 
85
+ # Is this a "real" cloud provider, or a stub like CloudFormation?
86
+ def self.virtual?
87
+ false
88
+ end
89
+
80
90
  # Stub class to represent Azure's resource identifiers, which look like:
81
91
  # /subscriptions/3d20ddd8-4652-4074-adda-0d127ef1f0e0/resourceGroups/mu/providers/Microsoft.Network/virtualNetworks/mu-vnet
82
92
  # Various API calls need chunks of this in different contexts, and this
@@ -274,6 +284,9 @@ module MU
274
284
  end
275
285
  raise e
276
286
  end
287
+ if !sdk_response
288
+ raise MuError, "Nil response from Azure API attempting list_locations(#{subscription})"
289
+ end
277
290
 
278
291
  sdk_response.value.each do | region |
279
292
  @@regions.push(region.name)
@@ -218,11 +218,7 @@ module MU
218
218
  "Azure Kubernetes Service Cluster Admin Role"
219
219
  ]
220
220
  }
221
- cluster['dependencies'] ||= []
222
- cluster['dependencies'] << {
223
- "type" => "user",
224
- "name" => cluster["name"]+"user"
225
- }
221
+ MU::Config.addDependency(cluster, cluster['name']+"user", "user")
226
222
 
227
223
  ok = false if !configurator.insertKitten(svcacct_desc, "users")
228
224
 
@@ -337,7 +337,14 @@ module MU
337
337
  # We assume that any values we have in +@config+ are placeholders, and
338
338
  # calculate our own accordingly based on what's live in the cloud.
339
339
  def toKitten(**args)
340
- bok = {}
340
+
341
+ bok = {
342
+ "cloud" => "Azure",
343
+ "name" => cloud_desc.name,
344
+ "project" => @config['project'],
345
+ "credentials" => @config['credentials'],
346
+ "cloud_id" => @cloud_id.to_s
347
+ }
341
348
 
342
349
  bok
343
350
  end
@@ -146,7 +146,7 @@ module MU
146
146
  return nil if @config.nil? or @deploy.nil?
147
147
 
148
148
  nat_ssh_key = nat_ssh_user = nat_ssh_host = nil
149
- if !@config["vpc"].nil? and !MU::Cloud::Azure::VPC.haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
149
+ if !@config["vpc"].nil? and !MU::Cloud.resourceClass("Azure", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
150
150
 
151
151
  if !@nat.nil? and @nat.mu_name != @mu_name
152
152
  if @nat.cloud_desc.nil?
@@ -189,7 +189,7 @@ module MU
189
189
  end
190
190
 
191
191
  _nat_ssh_key, _nat_ssh_user, nat_ssh_host, _canonical_ip, _ssh_user, _ssh_key_name = getSSHConfig
192
- if !nat_ssh_host and !MU::Cloud::Azure::VPC.haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
192
+ if !nat_ssh_host and !MU::Cloud.resourceClass("Azure", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
193
193
  # XXX check if canonical_ip is in the private ranges
194
194
  # raise MuError, "#{node} has no NAT host configured, and I have no other route to it"
195
195
  end
@@ -384,7 +384,7 @@ module MU
384
384
  # Our deploydata gets corrupted often with server pools, this will cause us to use the wrong IP to identify a node
385
385
  # which will cause us to create certificates, DNS records and other artifacts with incorrect information which will cause our deploy to fail.
386
386
  # The cloud_id is always correct so lets use 'cloud_desc' to get the correct IPs
387
- if MU::Cloud::Azure::VPC.haveRouteToInstance?(cloud_desc, credentials: @config['credentials']) or public_ips.size == 0
387
+ if MU::Cloud.resourceClass("Azure", "VPC").haveRouteToInstance?(cloud_desc, credentials: @config['credentials']) or public_ips.size == 0
388
388
  @config['canonical_ip'] = private_ips.first
389
389
  return private_ips.first
390
390
  else
@@ -393,6 +393,28 @@ module MU
393
393
  end
394
394
  end
395
395
 
396
+ # Return all of the IP addresses, public and private, from all of our
397
+ # network interfaces.
398
+ # @return [Array<String>]
399
+ def listIPs
400
+ ips = []
401
+ cloud_desc.network_profile.network_interfaces.each { |iface|
402
+ iface_id = Id.new(iface.is_a?(Hash) ? iface['id'] : iface.id)
403
+ iface_desc = MU::Cloud::Azure.network(credentials: @credentials).network_interfaces.get(@resource_group, iface_id.to_s)
404
+ iface_desc.ip_configurations.each { |ipcfg|
405
+ ips << ipcfg.private_ipaddress
406
+ if ipcfg.respond_to?(:public_ipaddress) and ipcfg.public_ipaddress
407
+ ip_id = Id.new(ipcfg.public_ipaddress.id)
408
+ ip_desc = MU::Cloud::Azure.network(credentials: @credentials).public_ipaddresses.get(@resource_group, ip_id.to_s)
409
+ if ip_desc
410
+ ips << ip_desc.ip_address
411
+ end
412
+ end
413
+ }
414
+ }
415
+ ips
416
+ end
417
+
396
418
  # return [String]: A password string.
397
419
  def getWindowsAdminPassword
398
420
  end
@@ -430,7 +452,7 @@ module MU
430
452
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
431
453
  # @param region [String]: The cloud provider region
432
454
  # @return [void]
433
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
455
+ def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
434
456
  end
435
457
 
436
458
  # Cloud-specific configuration properties.
@@ -441,7 +463,7 @@ module MU
441
463
  hosts_schema = MU::Config::CIDR_PRIMITIVE
442
464
  hosts_schema["pattern"] = "^(\\d+\\.\\d+\\.\\d+\\.\\d+\/[0-9]{1,2}|\\*)$"
443
465
  schema = {
444
- "roles" => MU::Cloud::Azure::User.schema(config)[1]["roles"],
466
+ "roles" => MU::Cloud.resourceClass("Azure", "User").schema(config)[1]["roles"],
445
467
  "ingress_rules" => {
446
468
  "items" => {
447
469
  "properties" => {
@@ -497,8 +519,7 @@ module MU
497
519
  foundmatch = false
498
520
  MU::Cloud.availableClouds.each { |cloud|
499
521
  next if cloud == "Azure"
500
- cloudbase = Object.const_get("MU").const_get("Cloud").const_get(cloud)
501
- foreign_types = (cloudbase.listInstanceTypes).values.first
522
+ foreign_types = (MU::Cloud.cloudClass(cloud).listInstanceTypes).values.first
502
523
  if foreign_types.size == 1
503
524
  foreign_types = foreign_types.values.first
504
525
  end
@@ -590,18 +611,8 @@ module MU
590
611
  if !configurator.insertKitten(vpc, "vpcs", true)
591
612
  ok = false
592
613
  end
593
- server['dependencies'] ||= []
594
-
595
- server['dependencies'] << {
596
- "type" => "vpc",
597
- "name" => server['name']+"vpc"
598
- }
599
- # XXX what happens if there's no natstion here?
600
- server['dependencies'] << {
601
- "type" => "server",
602
- "name" => server['name']+"vpc-natstion",
603
- "phase" => "groom"
604
- }
614
+ MU::Config.addDependency(server, server['name']+"vpc", "vpc")
615
+ MU::Config.addDependency(server, server['name']+"vpc-natstion", "server", phase: "groom")
605
616
  server['vpc'] = {
606
617
  "name" => server['name']+"vpc",
607
618
  "subnet_pref" => "private"
@@ -618,17 +629,14 @@ module MU
618
629
  "credentials" => server["credentials"],
619
630
  "roles" => server["roles"]
620
631
  }
621
- server['dependencies'] ||= []
622
- server['dependencies'] << {
623
- "type" => "user",
624
- "name" => server["name"]+"user"
625
- }
632
+ MU::Config.addDependency(server, server['name']+"user", "user")
626
633
 
627
634
  ok = false if !configurator.insertKitten(svcacct_desc, "users")
628
635
 
629
636
  ok
630
637
  end
631
638
 
639
+ # stub
632
640
  def self.diskConfig(config, create = true, disk_as_url = true, credentials: nil)
633
641
  end
634
642