cloud-mu 3.4.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/ansible/roles/mu-nat/tasks/main.yml +3 -0
  3. data/bin/mu-aws-setup +41 -7
  4. data/bin/mu-azure-setup +34 -0
  5. data/bin/mu-configure +214 -119
  6. data/bin/mu-gcp-setup +37 -2
  7. data/bin/mu-node-manage +3 -0
  8. data/bin/mu-refresh-ssl +67 -0
  9. data/bin/mu-run-tests +14 -4
  10. data/bin/mu-self-update +30 -10
  11. data/bin/mu-upload-chef-artifacts +30 -26
  12. data/cloud-mu.gemspec +8 -6
  13. data/cookbooks/mu-master/attributes/default.rb +5 -1
  14. data/cookbooks/mu-master/metadata.rb +2 -2
  15. data/cookbooks/mu-master/recipes/default.rb +81 -26
  16. data/cookbooks/mu-master/recipes/init.rb +197 -62
  17. data/cookbooks/mu-master/recipes/update_nagios_only.rb +1 -1
  18. data/cookbooks/mu-master/recipes/vault.rb +78 -77
  19. data/cookbooks/mu-master/templates/default/mods/rewrite.conf.erb +1 -0
  20. data/cookbooks/mu-master/templates/default/nagios.conf.erb +103 -0
  21. data/cookbooks/mu-master/templates/default/web_app.conf.erb +14 -30
  22. data/cookbooks/mu-tools/attributes/default.rb +5 -0
  23. data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
  24. data/cookbooks/mu-tools/libraries/helper.rb +12 -2
  25. data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
  26. data/cookbooks/mu-tools/recipes/apply_security.rb +6 -0
  27. data/cookbooks/mu-tools/recipes/aws_api.rb +6 -4
  28. data/cookbooks/mu-tools/recipes/base_repositories.rb +1 -1
  29. data/cookbooks/mu-tools/recipes/gcloud.rb +2 -9
  30. data/cookbooks/mu-tools/recipes/google_api.rb +5 -2
  31. data/cookbooks/mu-tools/resources/disk.rb +108 -58
  32. data/extras/Gemfile.lock.bootstrap +394 -0
  33. data/extras/bucketstubs/error.html +0 -0
  34. data/extras/bucketstubs/index.html +0 -0
  35. data/extras/clean-stock-amis +9 -9
  36. data/extras/git_rpm/build.sh +20 -0
  37. data/extras/git_rpm/mugit.spec +53 -0
  38. data/extras/image-generators/VMWare/centos8.yaml +15 -0
  39. data/extras/openssl_rpm/build.sh +19 -0
  40. data/extras/openssl_rpm/mussl.spec +46 -0
  41. data/extras/python_rpm/muthon.spec +14 -4
  42. data/extras/ruby_rpm/muby.spec +9 -5
  43. data/extras/sqlite_rpm/build.sh +19 -0
  44. data/extras/sqlite_rpm/muqlite.spec +47 -0
  45. data/install/installer +7 -5
  46. data/modules/mu.rb +12 -5
  47. data/modules/mu/cloud/machine_images.rb +1 -1
  48. data/modules/mu/cloud/providers.rb +6 -1
  49. data/modules/mu/cloud/resource_base.rb +1 -1
  50. data/modules/mu/cloud/ssh_sessions.rb +4 -0
  51. data/modules/mu/config.rb +28 -12
  52. data/modules/mu/config/database.rb +2 -2
  53. data/modules/mu/config/firewall_rule.rb +1 -1
  54. data/modules/mu/config/ref.rb +2 -2
  55. data/modules/mu/config/schema_helpers.rb +12 -3
  56. data/modules/mu/config/server.rb +10 -4
  57. data/modules/mu/config/server_pool.rb +2 -2
  58. data/modules/mu/config/vpc.rb +10 -10
  59. data/modules/mu/defaults/AWS.yaml +32 -32
  60. data/modules/mu/deploy.rb +23 -10
  61. data/modules/mu/groomers/chef.rb +2 -2
  62. data/modules/mu/master.rb +49 -3
  63. data/modules/mu/mommacat.rb +8 -5
  64. data/modules/mu/mommacat/naming.rb +2 -2
  65. data/modules/mu/mommacat/storage.rb +22 -27
  66. data/modules/mu/providers/aws.rb +142 -48
  67. data/modules/mu/providers/aws/alarm.rb +3 -3
  68. data/modules/mu/providers/aws/bucket.rb +19 -19
  69. data/modules/mu/providers/aws/cache_cluster.rb +22 -22
  70. data/modules/mu/providers/aws/cdn.rb +2 -2
  71. data/modules/mu/providers/aws/collection.rb +14 -14
  72. data/modules/mu/providers/aws/container_cluster.rb +27 -27
  73. data/modules/mu/providers/aws/database.rb +40 -39
  74. data/modules/mu/providers/aws/dnszone.rb +5 -5
  75. data/modules/mu/providers/aws/endpoint.rb +35 -35
  76. data/modules/mu/providers/aws/firewall_rule.rb +26 -23
  77. data/modules/mu/providers/aws/function.rb +28 -28
  78. data/modules/mu/providers/aws/group.rb +7 -7
  79. data/modules/mu/providers/aws/habitat.rb +2 -2
  80. data/modules/mu/providers/aws/job.rb +6 -6
  81. data/modules/mu/providers/aws/loadbalancer.rb +34 -34
  82. data/modules/mu/providers/aws/log.rb +14 -14
  83. data/modules/mu/providers/aws/msg_queue.rb +10 -10
  84. data/modules/mu/providers/aws/nosqldb.rb +8 -8
  85. data/modules/mu/providers/aws/notifier.rb +7 -7
  86. data/modules/mu/providers/aws/role.rb +17 -15
  87. data/modules/mu/providers/aws/search_domain.rb +10 -10
  88. data/modules/mu/providers/aws/server.rb +176 -95
  89. data/modules/mu/providers/aws/server_pool.rb +65 -105
  90. data/modules/mu/providers/aws/storage_pool.rb +17 -9
  91. data/modules/mu/providers/aws/user.rb +1 -1
  92. data/modules/mu/providers/aws/vpc.rb +103 -51
  93. data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
  94. data/modules/mu/providers/azure.rb +78 -12
  95. data/modules/mu/providers/azure/server.rb +18 -3
  96. data/modules/mu/providers/cloudformation/server.rb +1 -1
  97. data/modules/mu/providers/google.rb +19 -4
  98. data/modules/mu/providers/google/folder.rb +6 -2
  99. data/modules/mu/providers/google/function.rb +65 -30
  100. data/modules/mu/providers/google/role.rb +1 -1
  101. data/modules/mu/providers/google/vpc.rb +27 -2
  102. data/modules/tests/aws-servers-with-handrolled-iam.yaml +37 -0
  103. data/modules/tests/k8s.yaml +1 -1
  104. metadata +24 -8
@@ -242,7 +242,7 @@ module MU
242
242
  else
243
243
  MU::Cloud::AWS.createStandardTags(
244
244
  instance.instance_id,
245
- region: @config['region'],
245
+ region: @region,
246
246
  credentials: @credentials,
247
247
  optional: @config['optional_tags'],
248
248
  nametag: @mu_name,
@@ -258,7 +258,7 @@ module MU
258
258
  parent_thread_id = Thread.current.object_id
259
259
  Thread.new {
260
260
  MU.dupGlobals(parent_thread_id)
261
- MU::Cloud::AWS::Server.cleanup(noop: false, ignoremaster: false, region: @config['region'], credentials: @credentials, flags: { "skipsnapshots" => true } )
261
+ MU::Cloud::AWS::Server.cleanup(noop: false, ignoremaster: false, region: @region, credentials: @credentials, flags: { "skipsnapshots" => true } )
262
262
  }
263
263
  end
264
264
  end
@@ -307,9 +307,9 @@ module MU
307
307
  instance_descriptor[:user_data] = Base64.encode64(@userdata)
308
308
  end
309
309
 
310
- MU::Cloud::AWS::Server.waitForAMI(@config["image_id"], region: @config['region'], credentials: @credentials)
310
+ MU::Cloud::AWS::Server.waitForAMI(@config["image_id"], region: @region, credentials: @credentials)
311
311
 
312
- instance_descriptor[:block_device_mappings] = MU::Cloud::AWS::Server.configureBlockDevices(image_id: @config["image_id"], storage: @config['storage'], region: @config['region'], credentials: @credentials)
312
+ instance_descriptor[:block_device_mappings] = MU::Cloud::AWS::Server.configureBlockDevices(image_id: @config["image_id"], storage: @config['storage'], region: @region, credentials: @credentials)
313
313
 
314
314
  instance_descriptor[:monitoring] = {enabled: @config['monitoring']}
315
315
 
@@ -330,10 +330,26 @@ module MU
330
330
  resp.nil? or resp.instances.nil? or instance.nil?
331
331
  }
332
332
 
333
+ bad_subnets = []
334
+ mysubnet_ids = if mySubnets
335
+ mySubnets.map { |s| s.cloud_id }
336
+ end
333
337
  begin
334
338
  MU.retrier([Aws::EC2::Errors::InvalidGroupNotFound, Aws::EC2::Errors::InvalidSubnetIDNotFound, Aws::EC2::Errors::InvalidParameterValue], loop_if: loop_if, loop_msg: "Waiting for run_instances to return #{@mu_name}") {
335
- resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).run_instances(instance_descriptor)
339
+ resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).run_instances(instance_descriptor)
336
340
  }
341
+ rescue Aws::EC2::Errors::Unsupported => e
342
+ bad_subnets << instance_descriptor[:subnet_id]
343
+ better_subnet = (mysubnet_ids - bad_subnets).sample
344
+ if e.message !~ /is not supported in your requested Availability Zone/ and
345
+ (mysubnet_ids.nil? or mysubnet_ids.empty? or
346
+ mysubnet_ids.size == bad_subnets.size or
347
+ better_subnet.nil? or better_subnet == "")
348
+ raise MuError.new e.message, details: mysubnet_ids
349
+ end
350
+ instance_descriptor[:subnet_id] = (mysubnet_ids - bad_subnets).sample
351
+ MU.log "One or more subnets does not support this instance type, attempting with #{instance_descriptor[:subnet_id]} instead", MU::WARN, details: bad_subnets
352
+ retry
337
353
  rescue Aws::EC2::Errors::InvalidRequest => e
338
354
  MU.log e.message, MU::ERR, details: instance_descriptor
339
355
  raise e
@@ -351,12 +367,12 @@ module MU
351
367
  if hard
352
368
  groupname = nil
353
369
  if !@config['basis'].nil?
354
- resp = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @credentials).describe_auto_scaling_instances(
370
+ resp = MU::Cloud::AWS.autoscale(region: @region, credentials: @credentials).describe_auto_scaling_instances(
355
371
  instance_ids: [@cloud_id]
356
372
  )
357
373
  groupname = resp.auto_scaling_instances.first.auto_scaling_group_name
358
374
  MU.log "Pausing Autoscale processes in #{groupname}", MU::NOTICE
359
- MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @credentials).suspend_processes(
375
+ MU::Cloud::AWS.autoscale(region: @region, credentials: @credentials).suspend_processes(
360
376
  auto_scaling_group_name: groupname,
361
377
  scaling_processes: [
362
378
  "Terminate",
@@ -365,22 +381,22 @@ module MU
365
381
  end
366
382
  begin
367
383
  MU.log "Stopping #{@mu_name} (#{@cloud_id})", MU::NOTICE
368
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).stop_instances(
384
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).stop_instances(
369
385
  instance_ids: [@cloud_id]
370
386
  )
371
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).wait_until(:instance_stopped, instance_ids: [@cloud_id]) do |waiter|
387
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).wait_until(:instance_stopped, instance_ids: [@cloud_id]) do |waiter|
372
388
  waiter.before_attempt do
373
389
  MU.log "Waiting for #{@mu_name} to stop for hard reboot"
374
390
  end
375
391
  end
376
392
  MU.log "Starting #{@mu_name} (#{@cloud_id})"
377
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).start_instances(
393
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).start_instances(
378
394
  instance_ids: [@cloud_id]
379
395
  )
380
396
  ensure
381
397
  if !groupname.nil?
382
398
  MU.log "Resuming Autoscale processes in #{groupname}", MU::NOTICE
383
- MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @credentials).resume_processes(
399
+ MU::Cloud::AWS.autoscale(region: @region, credentials: @credentials).resume_processes(
384
400
  auto_scaling_group_name: groupname,
385
401
  scaling_processes: [
386
402
  "Terminate",
@@ -390,7 +406,7 @@ module MU
390
406
  end
391
407
  else
392
408
  MU.log "Rebooting #{@mu_name} (#{@cloud_id})"
393
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).reboot_instances(
409
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).reboot_instances(
394
410
  instance_ids: [@cloud_id]
395
411
  )
396
412
  end
@@ -405,7 +421,7 @@ module MU
405
421
  return nil if @config.nil? or @deploy.nil?
406
422
 
407
423
  nat_ssh_key = nat_ssh_user = nat_ssh_host = nil
408
- if !@config["vpc"].nil? and !MU::Cloud.resourceClass("AWS", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @credentials)
424
+ if !@config["vpc"].nil? and !MU::Cloud.resourceClass("AWS", "VPC").haveRouteToInstance?(cloud_desc, region: @region, credentials: @credentials)
409
425
  if !@nat.nil?
410
426
  if @nat.is_a?(Struct) && @nat.nat_gateway_id && @nat.nat_gateway_id.start_with?("nat-")
411
427
  raise MuError, "Configured to use NAT Gateway, but I have no route to instance. Either use Bastion, or configure VPC peering"
@@ -449,6 +465,9 @@ module MU
449
465
  raise MuError, "Couldn't find instance #{@mu_name} (#{@cloud_id})" if !cloud_desc
450
466
  return false if !MU::MommaCat.lock(@cloud_id+"-orchestrate", true)
451
467
  return false if !MU::MommaCat.lock(@cloud_id+"-groom", true)
468
+
469
+ getIAMProfile
470
+
452
471
  finish = Proc.new { |status|
453
472
  MU::MommaCat.unlock(@cloud_id+"-orchestrate")
454
473
  MU::MommaCat.unlock(@cloud_id+"-groom")
@@ -457,7 +476,7 @@ module MU
457
476
 
458
477
  MU::Cloud::AWS.createStandardTags(
459
478
  @cloud_id,
460
- region: @config['region'],
479
+ region: @region,
461
480
  credentials: @credentials,
462
481
  optional: @config['optional_tags'],
463
482
  nametag: @mu_name,
@@ -474,7 +493,15 @@ module MU
474
493
  }
475
494
  MU.retrier([Aws::EC2::Errors::ServiceError], max: 30, wait: 40, loop_if: loop_if) { |retries, _wait|
476
495
  if cloud_desc and cloud_desc.state.name == "terminated"
477
- raise MuError, "#{@cloud_id} appears to have been terminated mid-bootstrap!"
496
+ logs = if !@config['basis'].nil?
497
+ pool = @deploy.findLitterMate(type: "server_pools", name: @config["name"])
498
+ if pool
499
+ MU::Cloud::AWS.autoscale(region: @region, credentials: @credentials).describe_scaling_activities(auto_scaling_group_name: pool.cloud_id).activities
500
+ else
501
+ nil
502
+ end
503
+ end
504
+ raise MuError.new, "#{@cloud_id} appears to have been terminated mid-bootstrap!", details: logs
478
505
  end
479
506
  if retries % 3 == 0
480
507
  MU.log "Waiting for EC2 instance #{@mu_name} (#{@cloud_id}) to be ready...", MU::NOTICE
@@ -495,7 +522,7 @@ module MU
495
522
 
496
523
  if !@config['src_dst_check'] and !@config["vpc"].nil?
497
524
  MU.log "Disabling source_dest_check #{@mu_name} (making it NAT-worthy)"
498
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).modify_instance_attribute(
525
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).modify_instance_attribute(
499
526
  instance_id: @cloud_id,
500
527
  source_dest_check: { value: false }
501
528
  )
@@ -503,7 +530,7 @@ module MU
503
530
 
504
531
  # Set console termination protection. Autoscale nodes won't set this
505
532
  # by default.
506
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).modify_instance_attribute(
533
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).modify_instance_attribute(
507
534
  instance_id: @cloud_id,
508
535
  disable_api_termination: { value: true}
509
536
  )
@@ -516,7 +543,6 @@ module MU
516
543
  notify
517
544
  end
518
545
 
519
- getIAMProfile
520
546
  finish.call(false) if !bootstrapGroomer
521
547
 
522
548
  # Make sure we got our name written everywhere applicable
@@ -606,7 +632,7 @@ module MU
606
632
  "cloud" => "AWS",
607
633
  "credentials" => @credentials,
608
634
  "cloud_id" => @cloud_id,
609
- "region" => @config['region']
635
+ "region" => @region
610
636
  }
611
637
 
612
638
  if !cloud_desc
@@ -616,7 +642,7 @@ module MU
616
642
 
617
643
  asgs = MU::Cloud.resourceClass("AWS", "ServerPool").find(
618
644
  instance_id: @cloud_id,
619
- region: @config['region'],
645
+ region: @region,
620
646
  credentials: @credentials
621
647
  )
622
648
  if asgs.size > 0
@@ -651,7 +677,7 @@ module MU
651
677
 
652
678
  bok['image_id'] = cloud_desc.image_id
653
679
 
654
- ami = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_images(image_ids: [bok['image_id']]).images.first
680
+ ami = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_images(image_ids: [bok['image_id']]).images.first
655
681
 
656
682
  if ami.nil? or ami.empty?
657
683
  MU.log "#{@mu_name} source image #{bok['image_id']} no longer exists", MU::WARN
@@ -660,7 +686,7 @@ module MU
660
686
 
661
687
  if cloud_desc.block_device_mappings and !cloud_desc.block_device_mappings.empty?
662
688
  vol_map = {}
663
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_volumes(
689
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_volumes(
664
690
  volume_ids: cloud_desc.block_device_mappings.map { |d| d.ebs.volume_id if d.ebs }
665
691
  ).volumes.each { |vol|
666
692
  vol_map[vol.volume_id] = vol
@@ -696,7 +722,7 @@ module MU
696
722
  id: int.vpc_id,
697
723
  cloud: "AWS",
698
724
  credentials: @credentials,
699
- region: @config['region'],
725
+ region: @region,
700
726
  subnet_id: int.subnet_id,
701
727
  habitat: MU::Config::Ref.get(
702
728
  id: int.owner_id,
@@ -725,11 +751,11 @@ module MU
725
751
  if int.groups.size > 0
726
752
 
727
753
  require 'mu/providers/aws/firewall_rule'
728
- ifaces = MU::Cloud.resourceClass("AWS", "FirewallRule").getAssociatedInterfaces(int.groups.map { |sg| sg.group_id }, credentials: @credentials, region: @config['region'])
754
+ ifaces = MU::Cloud.resourceClass("AWS", "FirewallRule").getAssociatedInterfaces(int.groups.map { |sg| sg.group_id }, credentials: @credentials, region: @region)
729
755
  done_local_rules = false
730
756
  int.groups.each { |sg|
731
757
  if !done_local_rules and ifaces[sg.group_id].size == 1
732
- sg_desc = MU::Cloud.resourceClass("AWS", "FirewallRule").find(cloud_id: sg.group_id, credentials: @credentials, region: @config['region']).values.first
758
+ sg_desc = MU::Cloud.resourceClass("AWS", "FirewallRule").find(cloud_id: sg.group_id, credentials: @credentials, region: @region).values.first
733
759
  if sg_desc
734
760
  bok["ingress_rules"] = MU::Cloud.resourceClass("AWS", "FirewallRule").rulesToBoK(sg_desc.ip_permissions)
735
761
  bok["ingress_rules"].concat(MU::Cloud.resourceClass("AWS", "FirewallRule").rulesToBoK(sg_desc.ip_permissions_egress, egress: true))
@@ -743,7 +769,7 @@ module MU
743
769
  cloud: "AWS",
744
770
  credentials: @credentials,
745
771
  type: "firewall_rules",
746
- region: @config['region']
772
+ region: @region
747
773
  )
748
774
  }
749
775
  end
@@ -799,7 +825,7 @@ module MU
799
825
  if !@config['chef_data'].nil?
800
826
  deploydata.merge!(@config['chef_data'])
801
827
  end
802
- deploydata["region"] = @config['region'] if !@config['region'].nil?
828
+ deploydata["region"] = @region if !@region.nil?
803
829
  if !@named
804
830
  MU::MommaCat.nameKitten(self, no_dns: true)
805
831
  @named = true
@@ -883,7 +909,7 @@ module MU
883
909
  # Canonical Amazon Resource Number for this resource
884
910
  # @return [String]
885
911
  def arn
886
- "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":ec2:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@credentials)+":instance/"+@cloud_id
912
+ "arn:"+(MU::Cloud::AWS.isGovCloud?(@region) ? "aws-us-gov" : "aws")+":ec2:"+@region+":"+MU::Cloud::AWS.credToAcct(@credentials)+":instance/"+@cloud_id
887
913
  end
888
914
 
889
915
  @cloud_desc_cache = nil
@@ -896,7 +922,7 @@ module MU
896
922
  retries = 0
897
923
  if !@cloud_id.nil?
898
924
  begin
899
- resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_instances(instance_ids: [@cloud_id])
925
+ resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_instances(instance_ids: [@cloud_id])
900
926
  if resp and resp.reservations and resp.reservations.first and
901
927
  resp.reservations.first.instances and
902
928
  resp.reservations.first.instances.first
@@ -943,7 +969,7 @@ module MU
943
969
  # Our deploydata gets corrupted often with server pools, this will cause us to use the wrong IP to identify a node
944
970
  # which will cause us to create certificates, DNS records and other artifacts with incorrect information which will cause our deploy to fail.
945
971
  # The cloud_id is always correct so lets use 'cloud_desc' to get the correct IPs
946
- if MU::Cloud.resourceClass("AWS", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @credentials) or @deploydata["public_ip_address"].nil?
972
+ if MU::Cloud.resourceClass("AWS", "VPC").haveRouteToInstance?(cloud_desc, region: @region, credentials: @credentials) or @deploydata["public_ip_address"].nil?
947
973
  @config['canonical_ip'] = cloud_desc.private_ip_address
948
974
  @deploydata["private_ip_address"] = cloud_desc.private_ip_address
949
975
  return cloud_desc.private_ip_address
@@ -1170,7 +1196,7 @@ module MU
1170
1196
  retries = 0
1171
1197
  MU.log "Waiting for Windows instance password to be set by Amazon and flagged as available from the API. Note- if you're using a source AMI that already has its password set, this may fail. You'll want to set use_cloud_provider_windows_password to false if this is the case.", MU::NOTICE
1172
1198
  begin
1173
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).wait_until(:password_data_available, instance_id: @cloud_id) do |waiter|
1199
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).wait_until(:password_data_available, instance_id: @cloud_id) do |waiter|
1174
1200
  waiter.max_attempts = 60
1175
1201
  waiter.before_attempt do |attempts|
1176
1202
  MU.log "Waiting for Windows password data to be available for node #{@mu_name}", MU::NOTICE if attempts % 5 == 0
@@ -1182,15 +1208,15 @@ module MU
1182
1208
  rescue Aws::Waiters::Errors::TooManyAttemptsError => e
1183
1209
  if retries < 2
1184
1210
  retries = retries + 1
1185
- MU.log "wait_until(:password_data_available, instance_id: #{@cloud_id}) in #{@config['region']} never got a good response, retrying (#{retries}/2)", MU::WARN, details: e.inspect
1211
+ MU.log "wait_until(:password_data_available, instance_id: #{@cloud_id}) in #{@region} never got a good response, retrying (#{retries}/2)", MU::WARN, details: e.inspect
1186
1212
  retry
1187
1213
  else
1188
- MU.log "wait_until(:password_data_available, instance_id: #{@cloud_id}) in #{@config['region']} never returned- this image may not be configured to have its password set by AWS.", MU::ERR
1214
+ MU.log "wait_until(:password_data_available, instance_id: #{@cloud_id}) in #{@region} never returned- this image may not be configured to have its password set by AWS.", MU::ERR
1189
1215
  return nil
1190
1216
  end
1191
1217
  end
1192
1218
 
1193
- resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).get_password_data(instance_id: @cloud_id)
1219
+ resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).get_password_data(instance_id: @cloud_id)
1194
1220
  encrypted_password = resp.password_data
1195
1221
 
1196
1222
  # Note: This is already implemented in the decrypt_windows_password API call
@@ -1209,7 +1235,7 @@ module MU
1209
1235
  # instead of VPC.
1210
1236
  # @param ip [String]: Request a specific IP address.
1211
1237
  # @param region [String]: The cloud provider region
1212
- def self.findFreeElasticIp(classic: false, ip: nil, region: MU.curRegion)
1238
+ def self.findFreeElasticIp(classic: false, ip: nil, region: MU.curRegion, credentials: nil)
1213
1239
  filters = Array.new
1214
1240
  if !classic
1215
1241
  filters << {name: "domain", values: ["vpc"]}
@@ -1219,25 +1245,22 @@ module MU
1219
1245
  filters << {name: "public-ip", values: [ip]} if ip != nil
1220
1246
 
1221
1247
  if filters.size > 0
1222
- resp = MU::Cloud::AWS.ec2(region: region).describe_addresses(filters: filters)
1248
+ resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_addresses(filters: filters)
1223
1249
  else
1224
- resp = MU::Cloud::AWS.ec2(region: region).describe_addresses()
1250
+ resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_addresses
1225
1251
  end
1226
1252
  resp.addresses.each { |address|
1227
- return address if (address.network_interface_id.nil? || address.network_interface_id.empty?) && !@eips_used.include?(address.public_ip)
1253
+ return address if (address.network_interface_id.nil? or address.network_interface_id.empty?) or !@eips_used.include?(address.public_ip)
1228
1254
  }
1229
- if ip != nil
1230
- if !classic
1231
- raise MuError, "Requested EIP #{ip}, but no such IP exists or is avaulable in VPC"
1232
- else
1233
- raise MuError, "Requested EIP #{ip}, but no such IP exists or is available in EC2 Classic"
1234
- end
1255
+ if !ip.nil?
1256
+ mode = classic ? "EC2 Classic" : "VPC"
1257
+ raise MuError.new "Requested EIP #{ip}, but no such IP exists or is available in #{mode} mode#{credentials ? " with credentials #{credentials}" : ""}", details: { "describe_address filters" => filters, "describe_address response" => resp }
1235
1258
  end
1236
1259
  if !classic
1237
- resp = MU::Cloud::AWS.ec2(region: region).allocate_address(domain: "vpc")
1260
+ resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).allocate_address(domain: "vpc")
1238
1261
  new_ip = resp.public_ip
1239
1262
  else
1240
- new_ip = MU::Cloud::AWS.ec2(region: region).allocate_address().public_ip
1263
+ new_ip = MU::Cloud::AWS.ec2(region: region, credentials: credentials).allocate_address().public_ip
1241
1264
  end
1242
1265
  filters = [{name: "public-ip", values: [new_ip]}]
1243
1266
  if resp.domain
@@ -1253,8 +1276,8 @@ module MU
1253
1276
  begin
1254
1277
  begin
1255
1278
  sleep 5
1256
- resp = MU::Cloud::AWS.ec2(region: region).describe_addresses(
1257
- filters: filters
1279
+ resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_addresses(
1280
+ filters: filters
1258
1281
  )
1259
1282
  addr = resp.addresses.first
1260
1283
  end while resp.addresses.size < 1 or addr.public_ip.nil?
@@ -1280,14 +1303,14 @@ module MU
1280
1303
  end
1281
1304
 
1282
1305
  MU.log "Creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
1283
- creation = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).create_volume(
1306
+ creation = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_volume(
1284
1307
  availability_zone: cloud_desc.placement.availability_zone,
1285
1308
  size: size,
1286
1309
  volume_type: type
1287
1310
  )
1288
1311
 
1289
1312
  MU.retrier(wait: 3, loop_if: Proc.new {
1290
- creation = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_volumes(volume_ids: [creation.volume_id]).volumes.first
1313
+ creation = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_volumes(volume_ids: [creation.volume_id]).volumes.first
1291
1314
  if !["creating", "available"].include?(creation.state)
1292
1315
  raise MuError, "Saw state '#{creation.state}' while creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
1293
1316
  end
@@ -1298,7 +1321,7 @@ module MU
1298
1321
  if @deploy
1299
1322
  MU::Cloud::AWS.createStandardTags(
1300
1323
  creation.volume_id,
1301
- region: @config['region'],
1324
+ region: @region,
1302
1325
  credentials: @credentials,
1303
1326
  optional: @config['optional_tags'],
1304
1327
  nametag: @mu_name+"-"+dev.upcase,
@@ -1306,10 +1329,10 @@ module MU
1306
1329
  )
1307
1330
  end
1308
1331
 
1309
- MU.log "Attaching #{creation.volume_id} as #{dev} to #{@cloud_id} in #{@config['region']} (credentials #{@credentials})"
1332
+ MU.log "Attaching #{creation.volume_id} as #{dev} to #{@cloud_id} in #{@region} (credentials #{@credentials})"
1310
1333
  attachment = nil
1311
1334
  MU.retrier([Aws::EC2::Errors::IncorrectState], wait: 15, max: 4) {
1312
- attachment = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).attach_volume(
1335
+ attachment = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).attach_volume(
1313
1336
  device: dev,
1314
1337
  instance_id: @cloud_id,
1315
1338
  volume_id: creation.volume_id
@@ -1317,11 +1340,16 @@ module MU
1317
1340
  }
1318
1341
 
1319
1342
  begin
1320
- attachment = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_volumes(volume_ids: [attachment.volume_id]).volumes.first.attachments.first
1321
- if !["attaching", "attached"].include?(attachment.state)
1322
- raise MuError, "Saw state '#{creation.state}' while creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
1343
+ att_resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_volumes(volume_ids: [attachment.volume_id])
1344
+ if att_resp and att_resp.volumes and !att_resp.volumes.empty? and
1345
+ att_resp.volumes.first.attachments and
1346
+ !att_resp.volumes.first.attachments.empty?
1347
+ attachment = att_resp.volumes.first.attachments.first
1348
+ if !attachment.nil? and !["attaching", "attached"].include?(attachment.state)
1349
+ raise MuError, "Saw state '#{creation.state}' while creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
1350
+ end
1323
1351
  end
1324
- end while attachment.state != "attached"
1352
+ end while attachment.nil? or attachment.state != "attached"
1325
1353
 
1326
1354
  # Set delete_on_termination, which for some reason is an instance
1327
1355
  # attribute and not on the attachment
@@ -1337,7 +1365,7 @@ module MU
1337
1365
  return true
1338
1366
  end
1339
1367
  begin
1340
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_instances(
1368
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_instances(
1341
1369
  instance_ids: [@cloud_id]
1342
1370
  ).reservations.each { |resp|
1343
1371
  if !resp.nil? and !resp.instances.nil?
@@ -1388,7 +1416,7 @@ module MU
1388
1416
  }
1389
1417
  end
1390
1418
  end
1391
- elastic_ip = findFreeElasticIp(classic: classic, ip: ip)
1419
+ elastic_ip = findFreeElasticIp(classic: classic, ip: ip, credentials: credentials)
1392
1420
  if !ip.nil? and (elastic_ip.nil? or ip != elastic_ip.public_ip)
1393
1421
  raise MuError, "Requested EIP #{ip}, but this IP does not exist or is not available"
1394
1422
  end
@@ -1740,6 +1768,7 @@ module MU
1740
1768
  return size
1741
1769
  end
1742
1770
 
1771
+
1743
1772
  return size if types.has_key?(size)
1744
1773
 
1745
1774
  if size.nil? or !types.has_key?(size)
@@ -1785,7 +1814,8 @@ module MU
1785
1814
  def self.generateStandardRole(server, configurator)
1786
1815
  role = {
1787
1816
  "name" => server["name"],
1788
- "credentials" => server["credentials"],
1817
+ "bare_policies" => !server['generate_iam_role'],
1818
+ "strip_path" => server["role_strip_path"],
1789
1819
  "can_assume" => [
1790
1820
  {
1791
1821
  "entity_id" => "ec2.amazonaws.com",
@@ -1804,6 +1834,7 @@ module MU
1804
1834
  }
1805
1835
  ]
1806
1836
  }
1837
+ role["credentials"] = server["credentials"] if server["credentials"]
1807
1838
  if server['iam_policies']
1808
1839
  role['iam_policies'] = server['iam_policies'].dup
1809
1840
  end
@@ -1837,9 +1868,10 @@ module MU
1837
1868
  MU.log "Cannot mix iam_policies with generate_iam_role set to false", MU::ERR
1838
1869
  ok = false
1839
1870
  end
1840
- else
1841
- generateStandardRole(server, configurator)
1842
1871
  end
1872
+
1873
+ generateStandardRole(server, configurator)
1874
+
1843
1875
  if !server['create_image'].nil?
1844
1876
  if server['create_image'].has_key?('copy_to_regions') and
1845
1877
  (server['create_image']['copy_to_regions'].nil? or
@@ -2088,7 +2120,7 @@ module MU
2088
2120
  def haveElasticIP?
2089
2121
  if !cloud_desc.public_ip_address.nil?
2090
2122
  begin
2091
- resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_addresses(public_ips: [cloud_desc.public_ip_address])
2123
+ resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_addresses(public_ips: [cloud_desc.public_ip_address])
2092
2124
  if resp.addresses.size > 0 and resp.addresses.first.instance_id == @cloud_id
2093
2125
  return true
2094
2126
  end
@@ -2103,9 +2135,9 @@ module MU
2103
2135
  def configureNetworking
2104
2136
  if !@config['static_ip'].nil?
2105
2137
  if !@config['static_ip']['ip'].nil?
2106
- MU::Cloud::AWS::Server.associateElasticIp(@cloud_id, classic: @vpc.nil?, ip: @config['static_ip']['ip'])
2138
+ MU::Cloud::AWS::Server.associateElasticIp(@cloud_id, classic: @vpc.nil?, ip: @config['static_ip']['ip'], credentials: @credentials)
2107
2139
  elsif !haveElasticIP?
2108
- MU::Cloud::AWS::Server.associateElasticIp(@cloud_id, classic: @vpc.nil?)
2140
+ MU::Cloud::AWS::Server.associateElasticIp(@cloud_id, classic: @vpc.nil?, credentials: @credentials)
2109
2141
  end
2110
2142
  end
2111
2143
 
@@ -2113,7 +2145,7 @@ module MU
2113
2145
  subnet = @vpc.getSubnet(cloud_id: cloud_desc.subnet_id)
2114
2146
 
2115
2147
  _nat_ssh_key, _nat_ssh_user, nat_ssh_host, _canonical_ip, _ssh_user, _ssh_key_name = getSSHConfig
2116
- if subnet.private? and !nat_ssh_host and !MU::Cloud.resourceClass("AWS", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @credentials)
2148
+ if subnet.private? and !nat_ssh_host and !MU::Cloud.resourceClass("AWS", "VPC").haveRouteToInstance?(cloud_desc, region: @region, credentials: @credentials)
2117
2149
  raise MuError, "#{@mu_name} is in a private subnet (#{subnet}), but has no bastion host configured, and I have no other route to it"
2118
2150
  end
2119
2151
 
@@ -2130,17 +2162,17 @@ module MU
2130
2162
  next
2131
2163
  end
2132
2164
  MU.log "Adding network interface on subnet #{s.cloud_id} for #{@mu_name}"
2133
- iface = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).create_network_interface(subnet_id: s.cloud_id).network_interface
2165
+ iface = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_network_interface(subnet_id: s.cloud_id).network_interface
2134
2166
  MU::Cloud::AWS.createStandardTags(
2135
2167
  iface.network_interface_id,
2136
- region: @config['region'],
2168
+ region: @region,
2137
2169
  credentials: @credentials,
2138
2170
  optional: @config['optional_tags'],
2139
2171
  nametag: @mu_name+"-ETH"+device_index.to_s,
2140
2172
  othertags: @config['tags']
2141
2173
  )
2142
2174
 
2143
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).attach_network_interface(
2175
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).attach_network_interface(
2144
2176
  network_interface_id: iface.network_interface_id,
2145
2177
  instance_id: cloud_desc.instance_id,
2146
2178
  device_index: device_index
@@ -2159,7 +2191,7 @@ module MU
2159
2191
  cloud_desc.network_interfaces.each { |int|
2160
2192
  if int.private_ip_address == cloud_desc.private_ip_address and int.private_ip_addresses.size < (@config['add_private_ips'] + 1)
2161
2193
  MU.log "Adding #{@config['add_private_ips']} extra private IP addresses to #{cloud_desc.instance_id}"
2162
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).assign_private_ip_addresses(
2194
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).assign_private_ip_addresses(
2163
2195
  network_interface_id: int.network_interface_id,
2164
2196
  secondary_private_ip_address_count: @config['add_private_ips'],
2165
2197
  allow_reassignment: false
@@ -2170,13 +2202,13 @@ module MU
2170
2202
  end
2171
2203
 
2172
2204
  def tagVolumes
2173
- volumes = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_volumes(filters: [name: "attachment.instance-id", values: [@cloud_id]])
2205
+ volumes = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_volumes(filters: [name: "attachment.instance-id", values: [@cloud_id]])
2174
2206
  volumes.each { |vol|
2175
2207
  vol.volumes.each { |volume|
2176
2208
  volume.attachments.each { |attachment|
2177
2209
  MU::Cloud::AWS.createStandardTags(
2178
2210
  attachment.volume_id,
2179
- region: @config['region'],
2211
+ region: @region,
2180
2212
  credentials: @credentials,
2181
2213
  optional: @config['optional_tags'],
2182
2214
  nametag: ["/dev/sda", "/dev/sda1"].include?(attachment.device) ? "ROOT-"+@mu_name : @mu_name+"-"+attachment.device.upcase,
@@ -2198,7 +2230,7 @@ module MU
2198
2230
  alarm_obj = MU::MommaCat.findStray(
2199
2231
  "AWS",
2200
2232
  "alarms",
2201
- region: @config["region"],
2233
+ region: @region,
2202
2234
  deploy_id: @deploy.deploy_id,
2203
2235
  name: alarm['name']
2204
2236
  ).first
@@ -2207,8 +2239,8 @@ module MU
2207
2239
  if alarm["enable_notifications"]
2208
2240
  # XXX vile, this should be a sibling resource generated by the
2209
2241
  # parser
2210
- topic_arn = MU::Cloud.resourceClass("AWS", "Notification").createTopic(alarm["notification_group"], region: @config["region"], credentials: @credentials)
2211
- MU::Cloud.resourceClass("AWS", "Notification").subscribe(topic_arn, alarm["notification_endpoint"], alarm["notification_type"], region: @config["region"], credentials: @config["credentials"])
2242
+ topic_arn = MU::Cloud.resourceClass("AWS", "Notification").createTopic(alarm["notification_group"], region: @region, credentials: @credentials)
2243
+ MU::Cloud.resourceClass("AWS", "Notification").subscribe(topic_arn, alarm["notification_endpoint"], alarm["notification_type"], region: @region, credentials: @credentials)
2212
2244
  alarm["alarm_actions"] = [topic_arn]
2213
2245
  alarm["ok_actions"] = [topic_arn]
2214
2246
  end
@@ -2229,39 +2261,88 @@ module MU
2229
2261
  evaluation_periods: alarm["evaluation_periods"],
2230
2262
  threshold: alarm["threshold"],
2231
2263
  comparison_operator: alarm["comparison_operator"],
2232
- region: @config["region"],
2264
+ region: @region,
2233
2265
  credentials: @credentials
2234
2266
  )
2235
2267
  }
2236
2268
  end
2237
2269
  end
2238
2270
 
2239
- # We have issues sometimes where our dns_records are pointing at the wrong node name and IP address.
2240
-
2241
2271
  def getIAMProfile
2242
- arn = if @config['generate_iam_role']
2243
- role = @deploy.findLitterMate(name: @config['name'], type: "roles", debug: true)
2272
+ self.class.getIAMProfile(
2273
+ @config['name'],
2274
+ @deploy,
2275
+ generated: @config['generate_iam_role'],
2276
+ role_name: @config['iam_role'],
2277
+ region: @region,
2278
+ credentials: @credentials,
2279
+ want_arn: true
2280
+ )
2281
+ end
2282
+
2283
+ # XXX move to public section
2284
+ def self.getIAMProfile(myname, deploy, generated: true, role_name: nil, region: nil, credentials: nil, want_arn: false)
2285
+
2286
+ arn = if generated
2287
+ role = deploy.findLitterMate(name: myname, type: "roles", debug: true)
2244
2288
  if !role
2245
- raise MuError, "Failed to find a role matching #{@config['name']}"
2289
+ raise MuError, "Failed to find a role matching #{myname}"
2246
2290
  end
2247
- s3_objs = ["#{@deploy.deploy_id}-secret", "#{role.mu_name}.pfx", "#{role.mu_name}.crt", "#{role.mu_name}.key", "#{role.mu_name}-winrm.crt", "#{role.mu_name}-winrm.key"].map { |file|
2248
- 'arn:'+(MU::Cloud::AWS.isGovCloud?(@config['region']) ? "aws-us-gov" : "aws")+':s3:::'+MU::Cloud::AWS.adminBucketName(@credentials)+'/'+file
2291
+ s3_objs = ["#{deploy.deploy_id}-secret", "#{role.mu_name}.pfx", "#{role.mu_name}.crt", "#{role.mu_name}.key", "#{role.mu_name}-winrm.crt", "#{role.mu_name}-winrm.key"].map { |file|
2292
+ 'arn:'+(MU::Cloud::AWS.isGovCloud?(region) ? "aws-us-gov" : "aws")+':s3:::'+MU::Cloud::AWS.adminBucketName(credentials)+'/'+file
2249
2293
  }
2250
- MU.log "Adding S3 read permissions to #{@mu_name}'s IAM profile", MU::NOTICE, details: s3_objs
2294
+ MU.log "Adding S3 read permissions to #{myname}'s IAM profile", MU::NOTICE, details: s3_objs
2251
2295
  role.cloudobj.injectPolicyTargets("MuSecrets", s3_objs)
2252
2296
 
2253
- @config['iam_role'] = role.mu_name
2297
+ role_name = role.mu_name
2254
2298
  role.cloudobj.createInstanceProfile
2255
2299
 
2256
- elsif @config['iam_role'].nil?
2257
- raise MuError, "#{@mu_name} has generate_iam_role set to false, but no iam_role assigned."
2300
+ elsif role_name.nil?
2301
+ raise MuError, "#{myname} has generate_iam_role set to false, but no iam_role assigned."
2302
+ else
2303
+ begin
2304
+ ext_prof = MU::Cloud::AWS.iam(credentials: credentials).get_instance_profile(instance_profile_name: role_name)
2305
+ role_name = ext_prof.instance_profile.instance_profile_name
2306
+ ext_prof.instance_profile.arn
2307
+ rescue Aws::IAM::Errors::NoSuchEntity
2308
+ role = MU::MommaCat.findStray("AWS", "role", cloud_id: role_name, dummy_ok: true, credentials: credentials).first
2309
+ if !role
2310
+ raise MuError, "#{myname} specified iam_role '#{role_name}', but I can't find a role with that name to use when creating an instance profile"
2311
+ end
2312
+ role.cloudobj.createInstanceProfile
2313
+ end
2314
+ end
2315
+
2316
+ role_or_policy = deploy.findLitterMate(name: myname, type: "roles")
2317
+
2318
+ # Make sure our permissions to read our identity secrets are set
2319
+ s3_objs = [
2320
+ "#{deploy.deploy_id}-secret",
2321
+ "#{role_or_policy.mu_name}.pfx",
2322
+ "#{role_or_policy.mu_name}.crt",
2323
+ "#{role_or_policy.mu_name}.key",
2324
+ "#{role_or_policy.mu_name}-winrm.crt",
2325
+ "#{role_or_policy.mu_name}-winrm.key"].map { |file|
2326
+ 'arn:'+(MU::Cloud::AWS.isGovCloud?(region) ? "aws-us-gov" : "aws")+':s3:::'+MU::Cloud::AWS.adminBucketName(credentials)+'/'+file
2327
+ }
2328
+ if generated
2329
+ role_or_policy.injectPolicyTargets("MuSecrets", s3_objs)
2330
+ elsif role_name
2331
+ realrole = MU::MommaCat.findStray("AWS", "role", cloud_id: role_name, dummy_ok: true, credentials: credentials).first
2332
+ if !role_or_policy
2333
+ raise MuError, "I should have a bare policy littermate named #{name} but I can't find it"
2334
+ end
2335
+ if realrole
2336
+ role_or_policy.bindTo("role", realrole.cloud_id)
2337
+ realrole.injectPolicyTargets(role_or_policy.mu_name+"-MUSECRETS", s3_objs)
2338
+ end
2258
2339
  end
2259
2340
 
2260
- if !@config["iam_role"].nil?
2261
- if arn
2341
+ if !role_name.nil?
2342
+ if arn and want_arn
2262
2343
  return {arn: arn}
2263
2344
  else
2264
- return {name: @config["iam_role"]}
2345
+ return {name: role_name}
2265
2346
  end
2266
2347
  end
2267
2348
 
@@ -2279,7 +2360,7 @@ module MU
2279
2360
  if vol[:ebs][:delete_on_termination] != delete_on_termination
2280
2361
  vol[:ebs][:delete_on_termination] = delete_on_termination
2281
2362
  MU.log "Setting delete_on_termination flag to #{delete_on_termination.to_s} on #{@mu_name}'s #{device}"
2282
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).modify_instance_attribute(
2363
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).modify_instance_attribute(
2283
2364
  instance_id: @cloud_id,
2284
2365
  block_device_mappings: mappings
2285
2366
  )
@@ -2323,7 +2404,7 @@ module MU
2323
2404
  exclude_storage: img_cfg['image_exclude_storage'],
2324
2405
  copy_to_regions: img_cfg['copy_to_regions'],
2325
2406
  make_public: img_cfg['public'],
2326
- region: @config['region'],
2407
+ region: @region,
2327
2408
  tags: @config['tags'],
2328
2409
  credentials: @credentials
2329
2410
  )
@@ -2331,9 +2412,9 @@ module MU
2331
2412
  @deploy.notify("images", @config['name'], ami_ids)
2332
2413
  @config['image_created'] = true
2333
2414
  if img_cfg['image_then_destroy']
2334
- MU::Cloud::AWS::Server.waitForAMI(ami_ids[@config['region']], region: @config['region'], credentials: @credentials)
2335
- MU.log "AMI #{ami_ids[@config['region']]} ready, removing source node #{@mu_name}"
2336
- MU::Cloud::AWS::Server.terminateInstance(id: @cloud_id, region: @config['region'], deploy_id: @deploy.deploy_id, mu_name: @mu_name, credentials: @credentials)
2415
+ MU::Cloud::AWS::Server.waitForAMI(ami_ids[@region], region: @region, credentials: @credentials)
2416
+ MU.log "AMI #{ami_ids[@region]} ready, removing source node #{@mu_name}"
2417
+ MU::Cloud::AWS::Server.terminateInstance(id: @cloud_id, region: @region, deploy_id: @deploy.deploy_id, mu_name: @mu_name, credentials: @credentials)
2337
2418
  destroy
2338
2419
  end
2339
2420
  end