cloud-mu 3.1.3 → 3.1.4

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +10 -2
  3. data/bin/mu-adopt +5 -1
  4. data/bin/mu-load-config.rb +2 -3
  5. data/bin/mu-run-tests +112 -27
  6. data/cloud-mu.gemspec +20 -20
  7. data/cookbooks/mu-tools/libraries/helper.rb +2 -1
  8. data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
  9. data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
  10. data/cookbooks/mu-tools/resources/disk.rb +1 -1
  11. data/extras/image-generators/Google/centos6.yaml +1 -0
  12. data/extras/image-generators/Google/centos7.yaml +1 -1
  13. data/modules/mommacat.ru +5 -15
  14. data/modules/mu.rb +10 -14
  15. data/modules/mu/adoption.rb +20 -14
  16. data/modules/mu/cleanup.rb +13 -9
  17. data/modules/mu/cloud.rb +26 -26
  18. data/modules/mu/clouds/aws.rb +100 -59
  19. data/modules/mu/clouds/aws/alarm.rb +4 -2
  20. data/modules/mu/clouds/aws/bucket.rb +25 -21
  21. data/modules/mu/clouds/aws/cache_cluster.rb +25 -23
  22. data/modules/mu/clouds/aws/collection.rb +21 -20
  23. data/modules/mu/clouds/aws/container_cluster.rb +47 -26
  24. data/modules/mu/clouds/aws/database.rb +57 -68
  25. data/modules/mu/clouds/aws/dnszone.rb +14 -14
  26. data/modules/mu/clouds/aws/endpoint.rb +20 -16
  27. data/modules/mu/clouds/aws/firewall_rule.rb +19 -16
  28. data/modules/mu/clouds/aws/folder.rb +7 -7
  29. data/modules/mu/clouds/aws/function.rb +15 -12
  30. data/modules/mu/clouds/aws/group.rb +14 -10
  31. data/modules/mu/clouds/aws/habitat.rb +16 -13
  32. data/modules/mu/clouds/aws/loadbalancer.rb +16 -15
  33. data/modules/mu/clouds/aws/log.rb +13 -10
  34. data/modules/mu/clouds/aws/msg_queue.rb +15 -8
  35. data/modules/mu/clouds/aws/nosqldb.rb +18 -11
  36. data/modules/mu/clouds/aws/notifier.rb +11 -6
  37. data/modules/mu/clouds/aws/role.rb +87 -70
  38. data/modules/mu/clouds/aws/search_domain.rb +30 -19
  39. data/modules/mu/clouds/aws/server.rb +102 -72
  40. data/modules/mu/clouds/aws/server_pool.rb +47 -28
  41. data/modules/mu/clouds/aws/storage_pool.rb +5 -6
  42. data/modules/mu/clouds/aws/user.rb +13 -10
  43. data/modules/mu/clouds/aws/vpc.rb +135 -121
  44. data/modules/mu/clouds/azure.rb +16 -9
  45. data/modules/mu/clouds/azure/container_cluster.rb +2 -3
  46. data/modules/mu/clouds/azure/firewall_rule.rb +10 -10
  47. data/modules/mu/clouds/azure/habitat.rb +8 -6
  48. data/modules/mu/clouds/azure/loadbalancer.rb +5 -5
  49. data/modules/mu/clouds/azure/role.rb +8 -10
  50. data/modules/mu/clouds/azure/server.rb +65 -25
  51. data/modules/mu/clouds/azure/user.rb +5 -7
  52. data/modules/mu/clouds/azure/vpc.rb +12 -15
  53. data/modules/mu/clouds/cloudformation.rb +8 -7
  54. data/modules/mu/clouds/cloudformation/vpc.rb +2 -4
  55. data/modules/mu/clouds/google.rb +39 -24
  56. data/modules/mu/clouds/google/bucket.rb +9 -11
  57. data/modules/mu/clouds/google/container_cluster.rb +27 -42
  58. data/modules/mu/clouds/google/database.rb +6 -9
  59. data/modules/mu/clouds/google/firewall_rule.rb +11 -10
  60. data/modules/mu/clouds/google/folder.rb +16 -9
  61. data/modules/mu/clouds/google/function.rb +127 -161
  62. data/modules/mu/clouds/google/group.rb +21 -18
  63. data/modules/mu/clouds/google/habitat.rb +18 -15
  64. data/modules/mu/clouds/google/loadbalancer.rb +14 -16
  65. data/modules/mu/clouds/google/role.rb +48 -31
  66. data/modules/mu/clouds/google/server.rb +105 -105
  67. data/modules/mu/clouds/google/server_pool.rb +12 -31
  68. data/modules/mu/clouds/google/user.rb +67 -13
  69. data/modules/mu/clouds/google/vpc.rb +58 -65
  70. data/modules/mu/config.rb +89 -1738
  71. data/modules/mu/config/bucket.rb +3 -3
  72. data/modules/mu/config/collection.rb +3 -3
  73. data/modules/mu/config/container_cluster.rb +2 -2
  74. data/modules/mu/config/dnszone.rb +5 -5
  75. data/modules/mu/config/doc_helpers.rb +517 -0
  76. data/modules/mu/config/endpoint.rb +3 -3
  77. data/modules/mu/config/firewall_rule.rb +118 -3
  78. data/modules/mu/config/folder.rb +3 -3
  79. data/modules/mu/config/function.rb +2 -2
  80. data/modules/mu/config/group.rb +3 -3
  81. data/modules/mu/config/habitat.rb +3 -3
  82. data/modules/mu/config/loadbalancer.rb +3 -3
  83. data/modules/mu/config/log.rb +3 -3
  84. data/modules/mu/config/msg_queue.rb +3 -3
  85. data/modules/mu/config/nosqldb.rb +3 -3
  86. data/modules/mu/config/notifier.rb +2 -2
  87. data/modules/mu/config/ref.rb +333 -0
  88. data/modules/mu/config/role.rb +3 -3
  89. data/modules/mu/config/schema_helpers.rb +508 -0
  90. data/modules/mu/config/search_domain.rb +3 -3
  91. data/modules/mu/config/server.rb +86 -58
  92. data/modules/mu/config/server_pool.rb +2 -2
  93. data/modules/mu/config/tail.rb +189 -0
  94. data/modules/mu/config/user.rb +3 -3
  95. data/modules/mu/config/vpc.rb +44 -4
  96. data/modules/mu/defaults/Google.yaml +2 -2
  97. data/modules/mu/deploy.rb +13 -10
  98. data/modules/mu/groomer.rb +1 -1
  99. data/modules/mu/groomers/ansible.rb +69 -24
  100. data/modules/mu/groomers/chef.rb +52 -44
  101. data/modules/mu/logger.rb +17 -14
  102. data/modules/mu/master.rb +317 -2
  103. data/modules/mu/master/chef.rb +3 -4
  104. data/modules/mu/master/ldap.rb +3 -3
  105. data/modules/mu/master/ssl.rb +12 -2
  106. data/modules/mu/mommacat.rb +85 -1766
  107. data/modules/mu/mommacat/daemon.rb +394 -0
  108. data/modules/mu/mommacat/naming.rb +366 -0
  109. data/modules/mu/mommacat/storage.rb +689 -0
  110. data/modules/tests/bucket.yml +4 -0
  111. data/modules/tests/{win2k12.yaml → needwork/win2k12.yaml} +0 -0
  112. data/modules/tests/regrooms/aws-iam.yaml +201 -0
  113. data/modules/tests/regrooms/bucket.yml +19 -0
  114. metadata +112 -102
@@ -113,7 +113,7 @@ module MU
113
113
  }
114
114
  rescue MU::Groomer::RunError => e
115
115
  MU.log "Proceeding after failed initial Groomer run, but #{member.instance_id} may not behave as expected!", MU::WARN, details: e.inspect
116
- rescue Exception => e
116
+ rescue StandardError => e
117
117
  if !member.nil? and !done
118
118
  MU.log "Aborted before I could finish setting up #{@config['name']}, cleaning it up. Stack trace will print once cleanup is complete.", MU::WARN if !@deploy.nocleanup
119
119
  MU::MommaCat.unlockAll
@@ -293,7 +293,7 @@ module MU
293
293
  MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).create_or_update_tags(tag_conf)
294
294
  current.instances.each { |instance|
295
295
  tag_conf[:tags].each { |t|
296
- MU::MommaCat.createTag(instance.instance_id, t[:key], t[:value], region: @config['region'], credentials: @config['credentials'])
296
+ MU::Cloud::AWS.createTag(instance.instance_id, t[:key], t[:value], region: @config['region'], credentials: @config['credentials'])
297
297
  }
298
298
  }
299
299
  end
@@ -305,13 +305,11 @@ module MU
305
305
  asg_options[:min_size] = @config["min_size"]
306
306
  asg_options[:max_size] = @config["max_size"]
307
307
  asg_options[:new_instances_protected_from_scale_in] = (@config['scale_in_protection'] == "all")
308
- tg_arns = []
309
308
  if asg_options[:target_group_arns]
310
309
  MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).attach_load_balancer_target_groups(
311
310
  auto_scaling_group_name: @mu_name,
312
311
  target_group_arns: asg_options[:target_group_arns]
313
312
  )
314
- tg_arns = asg_options[:target_group_arns].dup
315
313
  asg_options.delete(:target_group_arns)
316
314
  end
317
315
 
@@ -365,7 +363,6 @@ module MU
365
363
  policy_params[:target_tracking_configuration].delete(:preferred_target_group)
366
364
  if policy_params[:target_tracking_configuration][:predefined_metric_specification] and
367
365
  policy_params[:target_tracking_configuration][:predefined_metric_specification][:predefined_metric_type] == "ALBRequestCountPerTarget"
368
- lb_path = nil
369
366
  lb = @deploy.deployment["loadbalancers"].values.first
370
367
  if @deploy.deployment["loadbalancers"].size > 1
371
368
  MU.log "Multiple load balancers attached to Autoscale group #{@mu_name}, guessing wildly which one to use for TargetTrackingScaling policy", MU::WARN
@@ -415,7 +412,7 @@ module MU
415
412
  }
416
413
  if !policy_already_correct
417
414
  MU.log "Putting scaling policy #{policy_name} for #{@mu_name}", MU::NOTICE, details: policy_params
418
- resp = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).put_scaling_policy(policy_params)
415
+ MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).put_scaling_policy(policy_params)
419
416
  end
420
417
 
421
418
  }
@@ -423,12 +420,15 @@ module MU
423
420
 
424
421
  end
425
422
 
423
+ @cloud_desc_cache = nil
426
424
  # Retrieve the AWS descriptor for this Autoscale group
427
425
  # @return [OpenStruct]
428
- def cloud_desc
429
- MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_auto_scaling_groups(
426
+ def cloud_desc(use_cache: true)
427
+ return @cloud_desc_cache if @cloud_desc_cache and use_cache
428
+ @cloud_desc_cache = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_auto_scaling_groups(
430
429
  auto_scaling_group_names: [@mu_name]
431
430
  ).auto_scaling_groups.first
431
+ @cloud_desc_cache
432
432
  end
433
433
 
434
434
  # Canonical Amazon Resource Number for this resource
@@ -486,7 +486,7 @@ module MU
486
486
  # Reverse-map our cloud description into a runnable config hash.
487
487
  # We assume that any values we have in +@config+ are placeholders, and
488
488
  # calculate our own accordingly based on what's live in the cloud.
489
- def toKitten(rootparent: nil, billing: nil, habitats: nil)
489
+ def toKitten(**_args)
490
490
  bok = {
491
491
  "cloud" => "AWS",
492
492
  "credentials" => @config['credentials'],
@@ -504,7 +504,7 @@ module MU
504
504
  bok['tags'] ||= []
505
505
  bok['tags'] << { "key" => tag.key, "value" => tag.value }
506
506
  }
507
- realname = MU::Adoption.tagsToName(bok['tags'])
507
+ realname = MU::Adoption.tagsToName(bok['tags'], basename: @cloud_id)
508
508
  if realname
509
509
  bok['name'] = realname
510
510
  bok['name'].gsub!(/[^a-zA-Z0-9_\-]/, "_")
@@ -512,25 +512,45 @@ module MU
512
512
  end
513
513
  bok['name'] ||= @cloud_id
514
514
 
515
- # if cloud_desc.vpc_id
516
- # bok['vpc'] = MU::Config::Ref.get(
517
- # id: cloud_desc.vpc_id,
518
- # cloud: "AWS",
519
- # credentials: @credentials,
520
- # type: "vpcs",
521
- # )
522
- # end
515
+ bok['min_size'] = cloud_desc.min_size
516
+ bok['max_size'] = cloud_desc.max_size
523
517
 
524
- MU.log @cloud_id, MU::NOTICE, details: cloud_desc
518
+ if cloud_desc.launch_configuration_name
519
+ launch = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @credentials).describe_launch_configurations(
520
+ launch_configuration_names: [cloud_desc.launch_configuration_name]
521
+ ).launch_configurations.first
522
+ bok['basis'] = {
523
+ "launch_config" => {
524
+ "image_id" => launch.image_id,
525
+ "name" => bok['name'],
526
+ "size" => launch.instance_type
527
+ }
528
+ }
529
+ end
530
+
531
+ if cloud_desc.vpc_zone_identifier and
532
+ !cloud_desc.vpc_zone_identifier.empty?
533
+ nets = cloud_desc.vpc_zone_identifier.split(/,/)
534
+ resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_subnets(subnet_ids: nets).subnets.first
535
+ bok['vpc'] = MU::Config::Ref.get(
536
+ id: resp.vpc_id,
537
+ cloud: "AWS",
538
+ credentials: @credentials,
539
+ type: "vpcs",
540
+ subnets: nets.map { |s| { "subnet_id" => s } }
541
+ )
542
+ end
543
+
544
+ # MU.log @cloud_id, MU::NOTICE, details: cloud_desc
525
545
 
526
546
  bok
527
547
  end
528
548
 
529
549
 
530
550
  # Cloud-specific configuration properties.
531
- # @param config [MU::Config]: The calling MU::Config object
551
+ # @param _config [MU::Config]: The calling MU::Config object
532
552
  # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
533
- def self.schema(config)
553
+ def self.schema(_config)
534
554
  toplevel_required = []
535
555
 
536
556
  term_policies = MU::Cloud::AWS.credConfig ? MU::Cloud::AWS.autoscale.describe_termination_policy_types.termination_policy_types : ["AllocationStrategy", "ClosestToNextInstanceHour", "Default", "NewestInstance", "OldestInstance", "OldestLaunchConfiguration", "OldestLaunchTemplate"]
@@ -846,7 +866,7 @@ module MU
846
866
  next if !s[time]
847
867
  begin
848
868
  Time.parse(s[time])
849
- rescue Exception => e
869
+ rescue StandardError => e
850
870
  MU.log "Failed to parse #{time} '#{s[time]}' in scheduled action for AutoScale group #{pool['name']}: #{e.message}", MU::ERR
851
871
  ok = false
852
872
  end
@@ -1054,6 +1074,8 @@ module MU
1054
1074
  # @param region [String]: The cloud provider region
1055
1075
  # @return [void]
1056
1076
  def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
1077
+ MU.log "AWS::ServerPool.cleanup: need to support flags['known']", MU::DEBUG, details: flags
1078
+
1057
1079
  filters = [{name: "key", values: ["MU-ID"]}]
1058
1080
  if !ignoremaster
1059
1081
  filters << {name: "key", values: ["MU-MASTER-IP"]}
@@ -1134,7 +1156,6 @@ module MU
1134
1156
  instance_secret = Password.random(50)
1135
1157
  @deploy.saveNodeSecret("default", instance_secret, "instance_secret")
1136
1158
 
1137
- nodes_name = @deploy.getResourceName(@config['basis']["launch_config"]["name"])
1138
1159
  if !@config['basis']['launch_config']["server"].nil?
1139
1160
  #XXX this isn't how we find these; use findStray or something
1140
1161
  if @deploy.deployment["images"].nil? or @deploy.deployment["images"][@config['basis']['launch_config']["server"]].nil?
@@ -1205,7 +1226,7 @@ module MU
1205
1226
  vol.delete("encrypted")
1206
1227
  end
1207
1228
  end
1208
- mapping, cfm_mapping = MU::Cloud::AWS::Server.convertBlockDeviceMapping(vol)
1229
+ mapping, _cfm_mapping = MU::Cloud::AWS::Server.convertBlockDeviceMapping(vol)
1209
1230
  storage << mapping
1210
1231
  }
1211
1232
  end
@@ -1322,7 +1343,7 @@ module MU
1322
1343
  MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).create_launch_configuration(launch_options)
1323
1344
  rescue Aws::AutoScaling::Errors::ValidationError => e
1324
1345
  if lc_attempts > 3
1325
- MU.log "Got error while creating #{@mu_name} Launch Config#{@config['credentials'] ? " with credentials #{@config['credentials']}" : ""}: #{e.message}, retrying in 10s", MU::WARN, details: launch_options.reject { |k,v | k == :user_data }
1346
+ MU.log "Got error while creating #{@mu_name} Launch Config#{@config['credentials'] ? " with credentials #{@config['credentials']}" : ""}: #{e.message}, retrying in 10s", MU::WARN, details: launch_options.reject { |k,_v | k == :user_data }
1326
1347
  end
1327
1348
  sleep 5
1328
1349
  lc_attempts += 1
@@ -1411,7 +1432,7 @@ module MU
1411
1432
  if lb_name == lb['concurrent_load_balancer']
1412
1433
  lbs << deployed_lb["awsname"] # XXX check for classic
1413
1434
  if deployed_lb.has_key?("targetgroups")
1414
- deployed_lb["targetgroups"].each_pair { |tg_name, tg_arn|
1435
+ deployed_lb["targetgroups"].values.each { |tg_arn|
1415
1436
  tg_arns << tg_arn
1416
1437
  }
1417
1438
  end
@@ -1464,7 +1485,6 @@ module MU
1464
1485
 
1465
1486
 
1466
1487
  if @config['basis']["server"]
1467
- nodes_name = @deploy.getResourceName(@config['basis']["server"])
1468
1488
  srv_name = @config['basis']["server"]
1469
1489
  # XXX cloudformation bits
1470
1490
  if @deploy.deployment['servers'] != nil and
@@ -1473,7 +1493,6 @@ module MU
1473
1493
  end
1474
1494
  elsif @config['basis']["instance_id"]
1475
1495
  # TODO should go fetch the name tag or something
1476
- nodes_name = @deploy.getResourceName(@config['basis']["instance_id"].gsub(/-/, ""))
1477
1496
  # XXX cloudformation bits
1478
1497
  asg_options[:instance_id] = @config['basis']["instance_id"]
1479
1498
  end
@@ -246,7 +246,7 @@ module MU
246
246
  end
247
247
 
248
248
  security_groups.uniq!
249
- resp = MU::Cloud::AWS.efs(region: region).modify_mount_target_security_groups(
249
+ MU::Cloud::AWS.efs(region: region).modify_mount_target_security_groups(
250
250
  mount_target_id: cloud_id,
251
251
  security_groups: security_groups
252
252
  )
@@ -254,7 +254,6 @@ module MU
254
254
 
255
255
  # Register a description of this storage pool with this deployment's metadata.
256
256
  def notify
257
- deploy_struct = {}
258
257
  storage_pool = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).describe_file_systems(
259
258
  creation_token: @mu_name
260
259
  ).file_systems.first
@@ -355,6 +354,8 @@ module MU
355
354
  # @param region [String]: The cloud provider region in which to operate
356
355
  # @return [void]
357
356
  def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
357
+ MU.log "AWS::StoragePool.cleanup: need to support flags['known']", MU::DEBUG, details: flags
358
+
358
359
  supported_regions = %w{us-west-2 us-east-1 eu-west-1}
359
360
  if supported_regions.include?(region)
360
361
  begin
@@ -367,7 +368,6 @@ module MU
367
368
  end
368
369
 
369
370
  our_pools = []
370
- our_replication_group_ids = []
371
371
 
372
372
  if !storage_pools.empty?
373
373
  storage_pools.each{ |pool|
@@ -445,9 +445,9 @@ module MU
445
445
  end
446
446
 
447
447
  # Cloud-specific configuration properties.
448
- # @param config [MU::Config]: The calling MU::Config object
448
+ # @param _config [MU::Config]: The calling MU::Config object
449
449
  # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
450
- def self.schema(config)
450
+ def self.schema(_config)
451
451
  toplevel_required = []
452
452
  schema = {
453
453
  "ingress_rules" => {
@@ -515,7 +515,6 @@ module MU
515
515
  ok
516
516
  end
517
517
 
518
- private
519
518
  end #class
520
519
  end #class
521
520
  end
@@ -37,7 +37,7 @@ module MU
37
37
  if !@config['use_if_exists']
38
38
  raise MuError, "IAM user #{@mu_name} already exists and use_if_exists is false"
39
39
  end
40
- rescue Aws::IAM::Errors::NoSuchEntity => e
40
+ rescue Aws::IAM::Errors::NoSuchEntity
41
41
  @config['path'] ||= "/"+@deploy.deploy_id+"/"
42
42
  MU.log "Creating IAM user #{@config['path']}/#{@mu_name}"
43
43
  tags = get_tag_params
@@ -120,7 +120,7 @@ module MU
120
120
 
121
121
  if @config['attachable_policies']
122
122
  configured_policies = @config['attachable_policies'].map { |p|
123
- id = if p.is_a?(MU::Config::Ref)
123
+ if p.is_a?(MU::Config::Ref)
124
124
  p.cloud_id
125
125
  else
126
126
  p = MU::Config::Ref.get(p)
@@ -189,9 +189,9 @@ module MU
189
189
  # Remove all users associated with the currently loaded deployment.
190
190
  # @param noop [Boolean]: If true, will only print what would be done
191
191
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
192
- # @param region [String]: The cloud provider region
193
192
  # @return [void]
194
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
193
+ def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
194
+ MU.log "AWS::User.cleanup: need to support flags['known']", MU::DEBUG, details: flags
195
195
 
196
196
  # XXX this doesn't belong here; maybe under roles, maybe as its own stupid first-class resource
197
197
  resp = MU::Cloud::AWS.iam(credentials: credentials).list_policies(
@@ -257,7 +257,7 @@ module MU
257
257
  }
258
258
  retry
259
259
  rescue ::Aws::IAM::Errors::NoSuchEntity
260
- rescue Exception => e
260
+ rescue StandardError => e
261
261
  MU.log e.inspect, MU::ERR, details: policy
262
262
  end
263
263
  end
@@ -275,14 +275,17 @@ MU.log e.inspect, MU::ERR, details: policy
275
275
  ).tags
276
276
  has_nodelete = false
277
277
  has_ourdeploy = false
278
+ has_ourmaster = false
278
279
  tags.each { |tag|
279
280
  if tag.key == "MU-ID" and tag.value == MU.deploy_id
280
281
  has_ourdeploy = true
282
+ elsif tag.key == "MU-MASTER-IP" and tag.value == MU.mu_public_ip
283
+ has_ourmaster = true
281
284
  elsif tag.key == "MU-NO-DELETE" and tag.value == "true"
282
285
  has_nodelete = true
283
286
  end
284
287
  }
285
- if has_ourdeploy and !has_nodelete
288
+ if has_ourdeploy and !has_nodelete and (ignoremaster or has_ourmaster)
286
289
  MU.log "Deleting IAM user #{u.path}#{u.user_name}"
287
290
  if !@noop
288
291
  begin
@@ -296,7 +299,7 @@ MU.log e.inspect, MU::ERR, details: policy
296
299
  group_name: g.group_name
297
300
  )
298
301
  }
299
- profile = MU::Cloud::AWS.iam(credentials: credentials).get_login_profile(
302
+ MU::Cloud::AWS.iam(credentials: credentials).get_login_profile(
300
303
  user_name: u.user_name
301
304
  )
302
305
  MU.log "Deleting IAM login profile for #{u.user_name}"
@@ -381,7 +384,7 @@ MU.log e.inspect, MU::ERR, details: policy
381
384
  # Reverse-map our cloud description into a runnable config hash.
382
385
  # We assume that any values we have in +@config+ are placeholders, and
383
386
  # calculate our own accordingly based on what's live in the cloud.
384
- def toKitten(rootparent: nil, billing: nil, habitats: nil)
387
+ def toKitten(**_args)
385
388
  bok = {
386
389
  "cloud" => "AWS",
387
390
  "credentials" => @credentials,
@@ -457,9 +460,9 @@ MU.log e.inspect, MU::ERR, details: policy
457
460
  end
458
461
 
459
462
  # Cloud-specific configuration properties.
460
- # @param config [MU::Config]: The calling MU::Config object
463
+ # @param _config [MU::Config]: The calling MU::Config object
461
464
  # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
462
- def self.schema(config)
465
+ def self.schema(_config)
463
466
  toplevel_required = []
464
467
  polschema = MU::Config::Role.schema["properties"]["policies"]
465
468
  polschema.deep_merge!(MU::Cloud::AWS::Role.condition_schema)
@@ -38,17 +38,17 @@ module MU
38
38
  vpc_id = @config['vpc_id'] = resp.vpc_id
39
39
 
40
40
  MU::Cloud::AWS.createStandardTags(vpc_id, region: @config['region'], credentials: @config['credentials'])
41
- MU::MommaCat.createTag(vpc_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
41
+ MU::Cloud::AWS.createTag(vpc_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
42
42
 
43
43
  if @config['tags']
44
44
  @config['tags'].each { |tag|
45
- MU::MommaCat.createTag(vpc_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
45
+ MU::Cloud::AWS.createTag(vpc_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
46
46
  }
47
47
  end
48
48
 
49
49
  if @config['optional_tags']
50
50
  MU::MommaCat.listOptionalTags.each { |key, value|
51
- MU::MommaCat.createTag(vpc_id, key, value, region: @config['region'], credentials: @config['credentials'])
51
+ MU::Cloud::AWS.createTag(vpc_id, key, value, region: @config['region'], credentials: @config['credentials'])
52
52
  }
53
53
  end
54
54
 
@@ -68,10 +68,10 @@ module MU
68
68
  ]
69
69
  )
70
70
  resp.route_tables.each { |rtb|
71
- MU::MommaCat.createTag(rtb.route_table_id, "Name", @mu_name+"-#DEFAULTPRIV", region: @config['region'], credentials: @config['credentials'])
71
+ MU::Cloud::AWS.createTag(rtb.route_table_id, "Name", @mu_name+"-#DEFAULTPRIV", region: @config['region'], credentials: @config['credentials'])
72
72
  if @config['tags']
73
73
  @config['tags'].each { |tag|
74
- MU::MommaCat.createTag(rtb.route_table_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
74
+ MU::Cloud::AWS.createTag(rtb.route_table_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
75
75
  }
76
76
  end
77
77
 
@@ -79,7 +79,7 @@ module MU
79
79
 
80
80
  if @config['optional_tags']
81
81
  MU::MommaCat.listOptionalTags.each { |key, value|
82
- MU::MommaCat.createTag(rtb.route_table_id, key, value, region: @config['region'], credentials: @config['credentials'])
82
+ MU::Cloud::AWS.createTag(rtb.route_table_id, key, value, region: @config['region'], credentials: @config['credentials'])
83
83
  }
84
84
  end
85
85
  }
@@ -93,16 +93,16 @@ module MU
93
93
  internet_gateway_id = resp.internet_gateway.internet_gateway_id
94
94
  sleep 5
95
95
  MU::Cloud::AWS.createStandardTags(internet_gateway_id, region: @config['region'], credentials: @config['credentials'])
96
- MU::MommaCat.createTag(internet_gateway_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
96
+ MU::Cloud::AWS.createTag(internet_gateway_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
97
97
  if @config['tags']
98
98
  @config['tags'].each { |tag|
99
- MU::MommaCat.createTag(internet_gateway_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
99
+ MU::Cloud::AWS.createTag(internet_gateway_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
100
100
  }
101
101
  end
102
102
 
103
103
  if @config['optional_tags']
104
104
  MU::MommaCat.listOptionalTags.each { |key, value|
105
- MU::MommaCat.createTag(internet_gateway_id, key, value, region: @config['region'], credentials: @config['credentials'])
105
+ MU::Cloud::AWS.createTag(internet_gateway_id, key, value, region: @config['region'], credentials: @config['credentials'])
106
106
  }
107
107
  end
108
108
 
@@ -168,7 +168,6 @@ module MU
168
168
  nat_gateways = []
169
169
  if !@config['subnets'].nil?
170
170
  allocation_ids = []
171
- subnet_semaphore = Mutex.new
172
171
  subnetthreads = Array.new
173
172
  parent_thread_id = Thread.current.object_id
174
173
  azs = []
@@ -191,16 +190,16 @@ module MU
191
190
  ).subnet
192
191
  subnet_id = subnet['subnet_id'] = resp.subnet_id
193
192
  MU::Cloud::AWS.createStandardTags(subnet_id, region: @config['region'], credentials: @config['credentials'])
194
- MU::MommaCat.createTag(subnet_id, "Name", @mu_name+"-"+subnet['name'], region: @config['region'], credentials: @config['credentials'])
193
+ MU::Cloud::AWS.createTag(subnet_id, "Name", @mu_name+"-"+subnet['name'], region: @config['region'], credentials: @config['credentials'])
195
194
  if @config['tags']
196
195
  @config['tags'].each { |tag|
197
- MU::MommaCat.createTag(subnet_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
196
+ MU::Cloud::AWS.createTag(subnet_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
198
197
  }
199
198
  end
200
199
 
201
200
  if @config['optional_tags']
202
201
  MU::MommaCat.listOptionalTags.each { |key, value|
203
- MU::MommaCat.createTag(subnet_id, key, value, region: @config['region'], credentials: @config['credentials'])
202
+ MU::Cloud::AWS.createTag(subnet_id, key, value, region: @config['region'], credentials: @config['credentials'])
204
203
  }
205
204
  end
206
205
 
@@ -316,7 +315,7 @@ module MU
316
315
  raise MuError, "NAT Gateway failed #{nat_gateway_id}: #{resp}" if resp.state == "failed"
317
316
  nat_gateways << {'id' => nat_gateway_id, 'availability_zone' => subnet['availability_zone']}
318
317
  @tags.each_pair { |k, v|
319
- MU::MommaCat.createTag(nat_gateway_id, k, v, region: @config['region'], credentials: @config['credentials'])
318
+ MU::Cloud::AWS.createTag(nat_gateway_id, k, v, region: @config['region'], credentials: @config['credentials'])
320
319
  }
321
320
  end
322
321
 
@@ -440,17 +439,17 @@ module MU
440
439
  )
441
440
  dhcpopt_id = resp.dhcp_options.dhcp_options_id
442
441
  MU::Cloud::AWS.createStandardTags(dhcpopt_id, region: @config['region'], credentials: @config['credentials'])
443
- MU::MommaCat.createTag(dhcpopt_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
442
+ MU::Cloud::AWS.createTag(dhcpopt_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
444
443
 
445
444
  if @config['tags']
446
445
  @config['tags'].each { |tag|
447
- MU::MommaCat.createTag(dhcpopt_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
446
+ MU::Cloud::AWS.createTag(dhcpopt_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
448
447
  }
449
448
  end
450
449
 
451
450
  if @config['optional_tags']
452
451
  MU::MommaCat.listOptionalTags.each { |key, value|
453
- MU::MommaCat.createTag(dhcpopt_id, key, value, region: @config['region'], credentials: @config['credentials'])
452
+ MU::Cloud::AWS.createTag(dhcpopt_id, key, value, region: @config['region'], credentials: @config['credentials'])
454
453
  }
455
454
  end
456
455
 
@@ -582,17 +581,17 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
582
581
  peering_name = @deploy.getResourceName(@config['name']+"-PEER-"+peer['vpc']['id'])
583
582
 
584
583
  MU::Cloud::AWS.createStandardTags(peering_id, region: @config['region'], credentials: @config['credentials'])
585
- MU::MommaCat.createTag(peering_id, "Name", peering_name, region: @config['region'], credentials: @config['credentials'])
584
+ MU::Cloud::AWS.createTag(peering_id, "Name", peering_name, region: @config['region'], credentials: @config['credentials'])
586
585
 
587
586
  if @config['optional_tags']
588
587
  MU::MommaCat.listOptionalTags.each { |key, value|
589
- MU::MommaCat.createTag(peering_id, key, value, region: @config['region'], credentials: @config['credentials'])
588
+ MU::Cloud::AWS.createTag(peering_id, key, value, region: @config['region'], credentials: @config['credentials'])
590
589
  }
591
590
  end
592
591
 
593
592
  if @config['tags']
594
593
  @config['tags'].each { |tag|
595
- MU::MommaCat.createTag(peering_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
594
+ MU::Cloud::AWS.createTag(peering_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
596
595
  }
597
596
  end
598
597
 
@@ -713,7 +712,7 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
713
712
  route_config[:instance_id] = nat_instance.cloud_id
714
713
 
715
714
  MU.log "Creating route for #{route['destination_network']} through NAT host #{nat_instance.cloud_id}", details: route_config
716
- resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route(route_config)
715
+ MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route(route_config)
717
716
  end
718
717
  }
719
718
 
@@ -756,7 +755,7 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
756
755
  map[vpc.vpc_id] = vpc
757
756
  }
758
757
  return map
759
- rescue Aws::EC2::Errors::InvalidVpcIDNotFound => e
758
+ rescue Aws::EC2::Errors::InvalidVpcIDNotFound
760
759
  end
761
760
  else
762
761
  resp = MU::Cloud::AWS.ec2(region: args[:region], credentials: args[:credentials]).describe_vpcs
@@ -774,7 +773,7 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
774
773
  # Reverse-map our cloud description into a runnable config hash.
775
774
  # We assume that any values we have in +@config+ are placeholders, and
776
775
  # calculate our own accordingly based on what's live in the cloud.
777
- def toKitten(rootparent: nil, billing: nil, habitats: nil)
776
+ def toKitten(**_args)
778
777
  bok = {
779
778
  "cloud" => "AWS",
780
779
  "credentials" => @config['credentials'],
@@ -983,13 +982,14 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
983
982
  def findNat(nat_cloud_id: nil, nat_filter_key: nil, nat_filter_value: nil, region: MU.curRegion, credentials: nil)
984
983
  # Discard the nat_cloud_id if it's an AWS instance ID
985
984
  nat_cloud_id = nil if nat_cloud_id && nat_cloud_id.start_with?("i-")
985
+ credentials ||= @credentials
986
986
 
987
987
  if @gateways.nil?
988
988
  @gateways =
989
989
  if nat_cloud_id
990
- MU::Cloud::AWS.ec2(region: region, credentials: nil).describe_nat_gateways(nat_gateway_ids: [nat_cloud_id])
990
+ MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_nat_gateways(nat_gateway_ids: [nat_cloud_id])
991
991
  elsif nat_filter_key && nat_filter_value
992
- MU::Cloud::AWS.ec2(region: region, credentials: nil).describe_nat_gateways(
992
+ MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_nat_gateways(
993
993
  filter: [
994
994
  {
995
995
  name: nat_filter_key,
@@ -1014,8 +1014,8 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1014
1014
 
1015
1015
  deploy_id = nil
1016
1016
  nat_name = nat_name.to_s if !nat_name.nil? and nat_name.class.to_s == "MU::Config::Tail"
1017
- nat_ip = nat_ip.to_s if !nat_ip.nil? and nat_ip.class.to_s == "MU::Config::Tail"
1018
1017
  nat_cloud_id = nat_cloud_id.to_s if !nat_cloud_id.nil? and nat_cloud_id.class.to_s == "MU::Config::Tail"
1018
+ nat_ip = nat_ip.to_s if !nat_ip.nil? and nat_ip.class.to_s == "MU::Config::Tail"
1019
1019
  nat_tag_key = nat_tag_key.to_s if !nat_tag_key.nil? and nat_tag_key.class.to_s == "MU::Config::Tail"
1020
1020
  nat_tag_value = nat_tag_value.to_s if !nat_tag_value.nil? and nat_tag_value.class.to_s == "MU::Config::Tail"
1021
1021
 
@@ -1042,8 +1042,8 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1042
1042
  found.each { |nat|
1043
1043
  # Try some AWS-specific criteria
1044
1044
  cloud_desc = nat.cloud_desc
1045
- if !nat_host_ip.nil? and
1046
- (cloud_desc.private_ip_address == nat_host_ip or cloud_desc.public_ip_address == nat_host_ip)
1045
+ if !nat_ip.nil? and
1046
+ (cloud_desc.private_ip_address == nat_ip or cloud_desc.public_ip_address == nat_ip)
1047
1047
  return nat
1048
1048
  elsif cloud_desc.vpc_id == @cloud_id
1049
1049
  # XXX Strictly speaking we could have different NATs in different
@@ -1090,7 +1090,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1090
1090
  if instance.nil?
1091
1091
  begin
1092
1092
  instance = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_instances(instance_ids: [instance_id]).reservations.first.instances.first
1093
- rescue NoMethodError, Aws::EC2::Errors::InvalidInstanceIDNotFound => e
1093
+ rescue NoMethodError, Aws::EC2::Errors::InvalidInstanceIDNotFound
1094
1094
  MU.log "Failed to identify instance #{instance_id} in MU::Cloud::AWS::VPC.getInstanceSubnets", MU::WARN
1095
1095
  return []
1096
1096
  end
@@ -1133,7 +1133,6 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1133
1133
  my_subnets = MU::Cloud::AWS::VPC.getInstanceSubnets(instance: MU.myCloudDescriptor)
1134
1134
  target_subnets = MU::Cloud::AWS::VPC.getInstanceSubnets(instance: target_instance, region: region, credentials: credentials)
1135
1135
 
1136
- resp = nil
1137
1136
  my_subnets_key = my_subnets.join(",")
1138
1137
  target_subnets_key = target_subnets.join(",")
1139
1138
  MU::Cloud::AWS::VPC.update_route_tables_cache(my_subnets_key, region: MU.myRegion)
@@ -1280,6 +1279,8 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1280
1279
  # @param region [String]: The cloud provider region
1281
1280
  # @return [void]
1282
1281
  def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
1282
+ MU.log "AWS::VPC.cleanup: need to support flags['known']", MU::DEBUG, details: flags
1283
+
1283
1284
  tagfilters = [
1284
1285
  {name: "tag:MU-ID", values: [MU.deploy_id]}
1285
1286
  ]
@@ -1292,7 +1293,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1292
1293
  begin
1293
1294
  resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_vpcs(filters: tagfilters, max_results: 1000).vpcs
1294
1295
  vpcs = resp if !resp.empty?
1295
- rescue Aws::EC2::Errors::InvalidVpcIDNotFound => e
1296
+ rescue Aws::EC2::Errors::InvalidVpcIDNotFound
1296
1297
  if retries < 5
1297
1298
  sleep 5
1298
1299
  retries += 1
@@ -1322,17 +1323,17 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1322
1323
  purge_vpcs(noop, tagfilters, region: region, credentials: credentials)
1323
1324
  purge_dhcpopts(noop, tagfilters, region: region, credentials: credentials)
1324
1325
 
1325
- unless noop
1326
- MU::Cloud::AWS.iam.list_roles.roles.each{ |role|
1327
- match_string = "#{MU.deploy_id}.*TRAFFIC-LOG"
1328
- }
1329
- end
1326
+ # unless noop
1327
+ # MU::Cloud::AWS.iam.list_roles.roles.each{ |role|
1328
+ # match_string = "#{MU.deploy_id}.*TRAFFIC-LOG"
1329
+ # }
1330
+ # end
1330
1331
  end
1331
1332
 
1332
1333
  # Cloud-specific configuration properties.
1333
- # @param config [MU::Config]: The calling MU::Config object
1334
+ # @param _config [MU::Config]: The calling MU::Config object
1334
1335
  # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
1335
- def self.schema(config)
1336
+ def self.schema(_config)
1336
1337
  toplevel_required = []
1337
1338
  # Flow Logs can be declared at the VPC level or the subnet level
1338
1339
  flowlogs = {
@@ -1428,7 +1429,6 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1428
1429
  end
1429
1430
 
1430
1431
  subnet_routes = Hash.new
1431
- public_routes = Array.new
1432
1432
 
1433
1433
  if vpc['subnets']
1434
1434
  vpc['subnets'].each { |subnet|
@@ -1600,9 +1600,11 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1600
1600
  @my_visible_cidrs[subnets]
1601
1601
  end
1602
1602
 
1603
- private
1604
1603
 
1605
1604
  # List the route tables for each subnet in the given VPC
1605
+ # @param vpc_id [String]:
1606
+ # @param region [String]:
1607
+ # @param credentials [String]:
1606
1608
  def self.listAllSubnetRouteTables(vpc_id, region: MU.curRegion, credentials: nil)
1607
1609
  resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_subnets(
1608
1610
  filters: [
@@ -1645,6 +1647,81 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1645
1647
  return table_ids.uniq
1646
1648
  end
1647
1649
 
1650
+ # Remove all network interfaces associated with the currently loaded deployment.
1651
+ # @param noop [Boolean]: If true, will only print what would be done
1652
+ # @param filters [Array<Hash>]: EC2 tags to filter against when search for resources to purge
1653
+ # @param region [String]: The cloud provider region
1654
+ # @return [void]
1655
+ def self.purge_interfaces(noop = false, filters = [{name: "tag:MU-ID", values: [MU.deploy_id]}], region: MU.curRegion, credentials: nil)
1656
+ resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_network_interfaces(
1657
+ filters: filters
1658
+ )
1659
+ ifaces = resp.data.network_interfaces
1660
+
1661
+ return if ifaces.nil? or ifaces.size == 0
1662
+
1663
+ ifaces.each { |iface|
1664
+ if iface.vpc_id
1665
+ default_sg_resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_security_groups(
1666
+ filters: [
1667
+ { name: "group-name", values: ["default"] },
1668
+ { name: "vpc-id", values: [iface.vpc_id] }
1669
+ ]
1670
+ ).security_groups
1671
+ if default_sg_resp and default_sg_resp.size == 1
1672
+ default_sg = default_sg_resp.first.group_id
1673
+ if iface.groups.size > 1 or
1674
+ iface.groups.first.group_id != default_sg
1675
+ MU.log "Removing extra security groups from ENI #{iface.network_interface_id}"
1676
+ begin
1677
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).modify_network_interface_attribute(
1678
+ network_interface_id: iface.network_interface_id,
1679
+ groups: [default_sg]
1680
+ )
1681
+ rescue ::Aws::EC2::Errors::AuthFailure
1682
+ MU.log "Permission denied attempting to trim Security Group list for #{iface.network_interface_id}", MU::WARN, details: iface.groups.map { |g| g.group_name }.join(",")+" => default"
1683
+ end
1684
+ end
1685
+ end
1686
+ end
1687
+ begin
1688
+ if iface.attachment and iface.attachment.status == "attached"
1689
+ MU.log "Detaching Network Interface #{iface.network_interface_id} from #{iface.attachment.instance_owner_id}"
1690
+ tried_lbs = false
1691
+ begin
1692
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).detach_network_interface(attachment_id: iface.attachment.attachment_id) if !noop
1693
+ rescue Aws::EC2::Errors::OperationNotPermitted => e
1694
+ MU.log "Can't detach #{iface.network_interface_id}: #{e.message}", MU::WARN, details: iface.attachment
1695
+ next
1696
+ rescue Aws::EC2::Errors::InvalidAttachmentIDNotFound => e
1697
+ # suits me just fine
1698
+ rescue Aws::EC2::Errors::AuthFailure => e
1699
+ if !tried_lbs and iface.attachment.instance_owner_id == "amazon-elb"
1700
+ MU::Cloud::AWS::LoadBalancer.cleanup(
1701
+ noop: noop,
1702
+ region: region,
1703
+ credentials: credentials,
1704
+ flags: {"vpc_id" => iface.vpc_id}
1705
+ )
1706
+ tried_lbs = true
1707
+ retry
1708
+ end
1709
+ MU.log e.message, MU::ERR, details: iface.attachment
1710
+ end
1711
+ end
1712
+ MU.log "Deleting Network Interface #{iface.network_interface_id}"
1713
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_network_interface(network_interface_id: iface.network_interface_id) if !noop
1714
+ rescue Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound
1715
+ # ok then!
1716
+ rescue Aws::EC2::Errors::InvalidParameterValue => e
1717
+ MU.log e.message, MU::ERR, details: iface
1718
+ end
1719
+ }
1720
+ end
1721
+
1722
+
1723
+ private
1724
+
1648
1725
  # Helper method for manufacturing route tables. Expect to be called from
1649
1726
  # {MU::Cloud::AWS::VPC#create} or {MU::Cloud::AWS::VPC#groom}.
1650
1727
  # @param rtb [Hash]: A route table description parsed through {MU::Config::BasketofKittens::vpcs::route_tables}.
@@ -1656,17 +1733,17 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1656
1733
  resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route_table(vpc_id: vpc_id).route_table
1657
1734
  route_table_id = rtb['route_table_id'] = resp.route_table_id
1658
1735
  sleep 5
1659
- MU::MommaCat.createTag(route_table_id, "Name", vpc_name+"-"+rtb['name'].upcase, credentials: @config['credentials'])
1736
+ MU::Cloud::AWS.createTag(route_table_id, "Name", vpc_name+"-"+rtb['name'].upcase, credentials: @config['credentials'])
1660
1737
 
1661
1738
  if @config['tags']
1662
1739
  @config['tags'].each { |tag|
1663
- MU::MommaCat.createTag(route_table_id, tag['key'], tag['value'], credentials: @config['credentials'])
1740
+ MU::Cloud::AWS.createTag(route_table_id, tag['key'], tag['value'], credentials: @config['credentials'])
1664
1741
  }
1665
1742
  end
1666
1743
 
1667
1744
  if @config['optional_tags']
1668
1745
  MU::MommaCat.listOptionalTags.each { |key, value|
1669
- MU::MommaCat.createTag(route_table_id, key, value, region: @config['region'], credentials: @config['credentials'])
1746
+ MU::Cloud::AWS.createTag(route_table_id, key, value, region: @config['region'], credentials: @config['credentials'])
1670
1747
  }
1671
1748
  end
1672
1749
 
@@ -1693,7 +1770,6 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1693
1770
  return rtb
1694
1771
  end
1695
1772
 
1696
-
1697
1773
  # Remove all network gateways associated with the currently loaded deployment.
1698
1774
  # @param noop [Boolean]: If true, will only print what would be done
1699
1775
  # @param region [String]: The cloud provider region
@@ -1746,6 +1822,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1746
1822
  }
1747
1823
  return nil
1748
1824
  end
1825
+ private_class_method :purge_gateways
1749
1826
 
1750
1827
  # Remove all NAT gateways associated with the VPC of the currently loaded deployment.
1751
1828
  # @param noop [Boolean]: If true, will only print what would be done
@@ -1803,6 +1880,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1803
1880
 
1804
1881
  return nil
1805
1882
  end
1883
+ private_class_method :purge_nat_gateways
1806
1884
 
1807
1885
  # Remove all VPC endpoints associated with the VPC of the currently loaded deployment.
1808
1886
  # @param noop [Boolean]: If true, will only print what would be done
@@ -1862,6 +1940,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1862
1940
 
1863
1941
  return nil
1864
1942
  end
1943
+ private_class_method :purge_endpoints
1865
1944
 
1866
1945
  # Remove all route tables associated with the currently loaded deployment.
1867
1946
  # @param noop [Boolean]: If true, will only print what would be done
@@ -1882,7 +1961,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1882
1961
  MU.log "Deleting Network Interface #{route.network_interface_id}"
1883
1962
  begin
1884
1963
  MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_network_interface(network_interface_id: route.network_interface_id) if !noop
1885
- rescue Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound => e
1964
+ rescue Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound
1886
1965
  MU.log "Network Interface #{route.network_interface_id} has already been deleted", MU::WARN
1887
1966
  end
1888
1967
  end
@@ -1902,9 +1981,9 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1902
1981
  table.associations.each { |assoc|
1903
1982
  begin
1904
1983
  MU::Cloud::AWS.ec2(credentials: credentials, region: region).disassociate_route_table(association_id: assoc.route_table_association_id) if !noop
1905
- rescue Aws::EC2::Errors::InvalidAssociationIDNotFound => e
1984
+ rescue Aws::EC2::Errors::InvalidAssociationIDNotFound
1906
1985
  MU.log "Route table association #{assoc.route_table_association_id} already removed", MU::WARN
1907
- rescue Aws::EC2::Errors::InvalidParameterValue => e
1986
+ rescue Aws::EC2::Errors::InvalidParameterValue
1908
1987
  # normal and ignorable with the default route table
1909
1988
  can_delete = false
1910
1989
  next
@@ -1920,75 +1999,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
1920
1999
  }
1921
2000
  return nil
1922
2001
  end
1923
-
1924
-
1925
- # Remove all network interfaces associated with the currently loaded deployment.
1926
- # @param noop [Boolean]: If true, will only print what would be done
1927
- # @param filters [Array<Hash>]: EC2 tags to filter against when search for resources to purge
1928
- # @param region [String]: The cloud provider region
1929
- # @return [void]
1930
- def self.purge_interfaces(noop = false, filters = [{name: "tag:MU-ID", values: [MU.deploy_id]}], region: MU.curRegion, credentials: nil)
1931
- resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_network_interfaces(
1932
- filters: filters
1933
- )
1934
- ifaces = resp.data.network_interfaces
1935
-
1936
- return if ifaces.nil? or ifaces.size == 0
1937
-
1938
- ifaces.each { |iface|
1939
- if iface.vpc_id
1940
- default_sg_resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_security_groups(
1941
- filters: [
1942
- { name: "group-name", values: ["default"] },
1943
- { name: "vpc-id", values: [iface.vpc_id] }
1944
- ]
1945
- ).security_groups
1946
- if default_sg_resp and default_sg_resp.size == 1
1947
- default_sg = default_sg_resp.first.group_id
1948
- if iface.groups.size != 1 or
1949
- iface.groups.first.group_id != default_sg
1950
- MU.log "Removing extra security groups from ENI #{iface.network_interface_id}"
1951
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).modify_network_interface_attribute(
1952
- network_interface_id: iface.network_interface_id,
1953
- groups: [default_sg]
1954
- )
1955
- end
1956
- end
1957
- end
1958
- begin
1959
- if iface.attachment and iface.attachment.status == "attached"
1960
- MU.log "Detaching Network Interface #{iface.network_interface_id} from #{iface.attachment.instance_owner_id}"
1961
- tried_lbs = false
1962
- begin
1963
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).detach_network_interface(attachment_id: iface.attachment.attachment_id) if !noop
1964
- rescue Aws::EC2::Errors::OperationNotPermitted => e
1965
- MU.log "Can't detach #{iface.network_interface_id}: #{e.message}", MU::WARN, details: iface.attachment
1966
- next
1967
- rescue Aws::EC2::Errors::InvalidAttachmentIDNotFound => e
1968
- # suits me just fine
1969
- rescue Aws::EC2::Errors::AuthFailure => e
1970
- if !tried_lbs and iface.attachment.instance_owner_id == "amazon-elb"
1971
- MU::Cloud::AWS::LoadBalancer.cleanup(
1972
- noop: noop,
1973
- region: region,
1974
- credentials: credentials,
1975
- flags: {"vpc_id" => iface.vpc_id}
1976
- )
1977
- tried_lbs = true
1978
- retry
1979
- end
1980
- MU.log e.message, MU::ERR, details: iface.attachment
1981
- end
1982
- end
1983
- MU.log "Deleting Network Interface #{iface.network_interface_id}"
1984
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_network_interface(network_interface_id: iface.network_interface_id) if !noop
1985
- rescue Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound => e
1986
- # ok then!
1987
- rescue Aws::EC2::Errors::InvalidParameterValue => e
1988
- MU.log e.message, MU::ERR, details: iface
1989
- end
1990
- }
1991
- end
2002
+ private_class_method :purge_routetables
1992
2003
 
1993
2004
  # Remove all subnets associated with the currently loaded deployment.
1994
2005
  # @param noop [Boolean]: If true, will only print what would be done
@@ -2038,6 +2049,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
2038
2049
  end while subnet.state != "available"
2039
2050
  }
2040
2051
  end
2052
+ private_class_method :purge_subnets
2041
2053
 
2042
2054
  # Remove all DHCP options sets associated with the currently loaded
2043
2055
  # deployment.
@@ -2056,7 +2068,9 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
2056
2068
  sets.each { |optset|
2057
2069
  begin
2058
2070
  MU.log "Deleting DHCP Option Set #{optset.dhcp_options_id}"
2059
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_dhcp_options(dhcp_options_id: optset.dhcp_options_id)
2071
+ if !noop
2072
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_dhcp_options(dhcp_options_id: optset.dhcp_options_id)
2073
+ end
2060
2074
  rescue Aws::EC2::Errors::DependencyViolation => e
2061
2075
  MU.log e.inspect, MU::ERR
2062
2076
  # rescue Aws::EC2::Errors::InvalidSubnetIDNotFound
@@ -2065,6 +2079,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
2065
2079
  end
2066
2080
  }
2067
2081
  end
2082
+ private_class_method :purge_dhcpopts
2068
2083
 
2069
2084
  # Remove all VPCs associated with the currently loaded deployment.
2070
2085
  # @param noop [Boolean]: If true, will only print what would be done
@@ -2104,7 +2119,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
2104
2119
  resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_route_tables(
2105
2120
  route_table_ids: [rtb_id]
2106
2121
  )
2107
- rescue Aws::EC2::Errors::InvalidRouteTableIDNotFound => e
2122
+ rescue Aws::EC2::Errors::InvalidRouteTableIDNotFound
2108
2123
  next
2109
2124
  end
2110
2125
  resp.route_tables.each { |rtb|
@@ -2125,7 +2140,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
2125
2140
  MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_vpc_peering_connection(
2126
2141
  vpc_peering_connection_id: cnxn.vpc_peering_connection_id
2127
2142
  ) if !noop
2128
- rescue Aws::EC2::Errors::InvalidStateTransition => e
2143
+ rescue Aws::EC2::Errors::InvalidStateTransition
2129
2144
  MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} not in removable (state #{cnxn.status.code})", MU::WARN
2130
2145
  rescue Aws::EC2::Errors::OperationNotPermitted => e
2131
2146
  MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} refuses to delete: #{e.message}", MU::WARN
@@ -2166,8 +2181,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
2166
2181
  end
2167
2182
  }
2168
2183
  end
2169
-
2170
- protected
2184
+ private_class_method :purge_vpcs
2171
2185
 
2172
2186
  # Subnets are almost a first-class resource. So let's kinda sorta treat
2173
2187
  # them like one. This should only be invoked on objects that already