cloud-mu 3.1.5 → 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
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