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.
- checksums.yaml +4 -4
- data/ansible/roles/mu-nat/tasks/main.yml +3 -0
- data/bin/mu-aws-setup +41 -7
- data/bin/mu-azure-setup +34 -0
- data/bin/mu-configure +214 -119
- data/bin/mu-gcp-setup +37 -2
- data/bin/mu-node-manage +3 -0
- data/bin/mu-refresh-ssl +67 -0
- data/bin/mu-run-tests +14 -4
- data/bin/mu-self-update +30 -10
- data/bin/mu-upload-chef-artifacts +30 -26
- data/cloud-mu.gemspec +8 -6
- data/cookbooks/mu-master/attributes/default.rb +5 -1
- data/cookbooks/mu-master/metadata.rb +2 -2
- data/cookbooks/mu-master/recipes/default.rb +81 -26
- data/cookbooks/mu-master/recipes/init.rb +197 -62
- data/cookbooks/mu-master/recipes/update_nagios_only.rb +1 -1
- data/cookbooks/mu-master/recipes/vault.rb +78 -77
- data/cookbooks/mu-master/templates/default/mods/rewrite.conf.erb +1 -0
- data/cookbooks/mu-master/templates/default/nagios.conf.erb +103 -0
- data/cookbooks/mu-master/templates/default/web_app.conf.erb +14 -30
- data/cookbooks/mu-tools/attributes/default.rb +5 -0
- data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
- data/cookbooks/mu-tools/libraries/helper.rb +12 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
- data/cookbooks/mu-tools/recipes/apply_security.rb +6 -0
- data/cookbooks/mu-tools/recipes/aws_api.rb +6 -4
- data/cookbooks/mu-tools/recipes/base_repositories.rb +1 -1
- data/cookbooks/mu-tools/recipes/gcloud.rb +2 -9
- data/cookbooks/mu-tools/recipes/google_api.rb +5 -2
- data/cookbooks/mu-tools/resources/disk.rb +108 -58
- data/extras/Gemfile.lock.bootstrap +394 -0
- data/extras/bucketstubs/error.html +0 -0
- data/extras/bucketstubs/index.html +0 -0
- data/extras/clean-stock-amis +9 -9
- data/extras/git_rpm/build.sh +20 -0
- data/extras/git_rpm/mugit.spec +53 -0
- data/extras/image-generators/VMWare/centos8.yaml +15 -0
- data/extras/openssl_rpm/build.sh +19 -0
- data/extras/openssl_rpm/mussl.spec +46 -0
- data/extras/python_rpm/muthon.spec +14 -4
- data/extras/ruby_rpm/muby.spec +9 -5
- data/extras/sqlite_rpm/build.sh +19 -0
- data/extras/sqlite_rpm/muqlite.spec +47 -0
- data/install/installer +7 -5
- data/modules/mu.rb +12 -5
- data/modules/mu/cloud/machine_images.rb +1 -1
- data/modules/mu/cloud/providers.rb +6 -1
- data/modules/mu/cloud/resource_base.rb +1 -1
- data/modules/mu/cloud/ssh_sessions.rb +4 -0
- data/modules/mu/config.rb +28 -12
- data/modules/mu/config/database.rb +2 -2
- data/modules/mu/config/firewall_rule.rb +1 -1
- data/modules/mu/config/ref.rb +2 -2
- data/modules/mu/config/schema_helpers.rb +12 -3
- data/modules/mu/config/server.rb +10 -4
- data/modules/mu/config/server_pool.rb +2 -2
- data/modules/mu/config/vpc.rb +10 -10
- data/modules/mu/defaults/AWS.yaml +32 -32
- data/modules/mu/deploy.rb +23 -10
- data/modules/mu/groomers/chef.rb +2 -2
- data/modules/mu/master.rb +49 -3
- data/modules/mu/mommacat.rb +8 -5
- data/modules/mu/mommacat/naming.rb +2 -2
- data/modules/mu/mommacat/storage.rb +22 -27
- data/modules/mu/providers/aws.rb +142 -48
- data/modules/mu/providers/aws/alarm.rb +3 -3
- data/modules/mu/providers/aws/bucket.rb +19 -19
- data/modules/mu/providers/aws/cache_cluster.rb +22 -22
- data/modules/mu/providers/aws/cdn.rb +2 -2
- data/modules/mu/providers/aws/collection.rb +14 -14
- data/modules/mu/providers/aws/container_cluster.rb +27 -27
- data/modules/mu/providers/aws/database.rb +40 -39
- data/modules/mu/providers/aws/dnszone.rb +5 -5
- data/modules/mu/providers/aws/endpoint.rb +35 -35
- data/modules/mu/providers/aws/firewall_rule.rb +26 -23
- data/modules/mu/providers/aws/function.rb +28 -28
- data/modules/mu/providers/aws/group.rb +7 -7
- data/modules/mu/providers/aws/habitat.rb +2 -2
- data/modules/mu/providers/aws/job.rb +6 -6
- data/modules/mu/providers/aws/loadbalancer.rb +34 -34
- data/modules/mu/providers/aws/log.rb +14 -14
- data/modules/mu/providers/aws/msg_queue.rb +10 -10
- data/modules/mu/providers/aws/nosqldb.rb +8 -8
- data/modules/mu/providers/aws/notifier.rb +7 -7
- data/modules/mu/providers/aws/role.rb +17 -15
- data/modules/mu/providers/aws/search_domain.rb +10 -10
- data/modules/mu/providers/aws/server.rb +176 -95
- data/modules/mu/providers/aws/server_pool.rb +65 -105
- data/modules/mu/providers/aws/storage_pool.rb +17 -9
- data/modules/mu/providers/aws/user.rb +1 -1
- data/modules/mu/providers/aws/vpc.rb +103 -51
- data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
- data/modules/mu/providers/azure.rb +78 -12
- data/modules/mu/providers/azure/server.rb +18 -3
- data/modules/mu/providers/cloudformation/server.rb +1 -1
- data/modules/mu/providers/google.rb +19 -4
- data/modules/mu/providers/google/folder.rb +6 -2
- data/modules/mu/providers/google/function.rb +65 -30
- data/modules/mu/providers/google/role.rb +1 -1
- data/modules/mu/providers/google/vpc.rb +27 -2
- data/modules/tests/aws-servers-with-handrolled-iam.yaml +37 -0
- data/modules/tests/k8s.yaml +1 -1
- 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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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
|
-
|
|
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: @
|
|
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: @
|
|
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" => @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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"] = @
|
|
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?(@
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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 #{@
|
|
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 #{@
|
|
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: @
|
|
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?
|
|
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
|
|
1230
|
-
|
|
1231
|
-
|
|
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
|
-
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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 #{@
|
|
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: @
|
|
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
|
-
|
|
1321
|
-
if
|
|
1322
|
-
|
|
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: @
|
|
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
|
-
"
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
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: @
|
|
2211
|
-
MU::Cloud.resourceClass("AWS", "Notification").subscribe(topic_arn, alarm["notification_endpoint"], alarm["notification_type"], region: @
|
|
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: @
|
|
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
|
-
|
|
2243
|
-
|
|
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 #{
|
|
2289
|
+
raise MuError, "Failed to find a role matching #{myname}"
|
|
2246
2290
|
end
|
|
2247
|
-
s3_objs = ["#{
|
|
2248
|
-
'arn:'+(MU::Cloud::AWS.isGovCloud?(
|
|
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 #{
|
|
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
|
-
|
|
2297
|
+
role_name = role.mu_name
|
|
2254
2298
|
role.cloudobj.createInstanceProfile
|
|
2255
2299
|
|
|
2256
|
-
elsif
|
|
2257
|
-
raise MuError, "#{
|
|
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
|
|
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:
|
|
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: @
|
|
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: @
|
|
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[@
|
|
2335
|
-
MU.log "AMI #{ami_ids[@
|
|
2336
|
-
MU::Cloud::AWS::Server.terminateInstance(id: @cloud_id, region: @
|
|
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
|