cloud-mu 3.3.0 → 3.5.1
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 +36 -2
- 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 +9 -7
- 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 +12 -0
- data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
- data/cookbooks/mu-tools/libraries/helper.rb +98 -4
- data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
- data/cookbooks/mu-tools/recipes/apply_security.rb +31 -9
- data/cookbooks/mu-tools/recipes/aws_api.rb +8 -2
- 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 +7 -0
- data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
- data/cookbooks/mu-tools/resources/disk.rb +113 -42
- data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
- data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
- 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 +11 -3
- data/extras/generate-stock-images +6 -3
- data/extras/git_rpm/build.sh +20 -0
- data/extras/git_rpm/mugit.spec +53 -0
- data/extras/image-generators/AWS/centos7.yaml +19 -16
- data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
- data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -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/mommacat.ru +2 -2
- 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 +7 -4
- data/modules/mu/cloud/ssh_sessions.rb +5 -1
- data/modules/mu/cloud/wrappers.rb +16 -7
- 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 +3 -3
- 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 +96 -96
- data/modules/mu/deploy.rb +27 -14
- data/modules/mu/groomers/chef.rb +2 -2
- data/modules/mu/master.rb +49 -3
- data/modules/mu/mommacat.rb +27 -9
- data/modules/mu/mommacat/naming.rb +2 -2
- data/modules/mu/mommacat/search.rb +16 -5
- data/modules/mu/mommacat/storage.rb +67 -32
- data/modules/mu/providers/aws.rb +185 -71
- 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 +49 -45
- 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 +35 -32
- 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 +35 -32
- data/modules/mu/providers/aws/loadbalancer.rb +58 -37
- 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 +69 -47
- data/modules/mu/providers/aws/search_domain.rb +10 -10
- data/modules/mu/providers/aws/server.rb +198 -110
- data/modules/mu/providers/aws/server_pool.rb +71 -119
- 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 +106 -51
- data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
- data/modules/mu/providers/azure.rb +82 -16
- data/modules/mu/providers/azure/server.rb +18 -3
- data/modules/mu/providers/cloudformation/server.rb +1 -1
- data/modules/mu/providers/google.rb +20 -5
- 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 +2 -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 +32 -15
|
@@ -36,7 +36,7 @@ module MU
|
|
|
36
36
|
|
|
37
37
|
MU.log "Creating ElasticSearch domain #{@config['domain_name']}", details: params
|
|
38
38
|
@cloud_id = @config['domain_name']
|
|
39
|
-
MU::Cloud::AWS.elasticsearch(region: @
|
|
39
|
+
MU::Cloud::AWS.elasticsearch(region: @region, credentials: @credentials).create_elasticsearch_domain(params).domain_status
|
|
40
40
|
|
|
41
41
|
tagDomain
|
|
42
42
|
|
|
@@ -52,7 +52,7 @@ module MU
|
|
|
52
52
|
waitWhileProcessing # wait until the create finishes, if still going
|
|
53
53
|
|
|
54
54
|
MU.log "Updating ElasticSearch domain #{@config['domain_name']}", MU::NOTICE, details: params
|
|
55
|
-
MU::Cloud::AWS.elasticsearch(region: @
|
|
55
|
+
MU::Cloud::AWS.elasticsearch(region: @region, credentials: @credentials).update_elasticsearch_domain_config(params)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
waitWhileProcessing # don't return until creation/updating is complete
|
|
@@ -68,7 +68,7 @@ module MU
|
|
|
68
68
|
@cloud_id ||= @config['domain_name']
|
|
69
69
|
return nil if !@cloud_id
|
|
70
70
|
MU.retrier([::Aws::ElasticsearchService::Errors::ResourceNotFoundException], wait: 10, max: 12) {
|
|
71
|
-
@cloud_desc_cache = MU::Cloud::AWS.elasticsearch(region: @
|
|
71
|
+
@cloud_desc_cache = MU::Cloud::AWS.elasticsearch(region: @region, credentials: @credentials).describe_elasticsearch_domain(
|
|
72
72
|
domain_name: @cloud_id
|
|
73
73
|
).domain_status
|
|
74
74
|
}
|
|
@@ -88,7 +88,7 @@ module MU
|
|
|
88
88
|
def notify
|
|
89
89
|
return nil if !cloud_desc(use_cache: false)
|
|
90
90
|
deploy_struct = MU.structToHash(cloud_desc, stringify_keys: true)
|
|
91
|
-
tags = MU::Cloud::AWS.elasticsearch(region: @
|
|
91
|
+
tags = MU::Cloud::AWS.elasticsearch(region: @region, credentials: @credentials).list_tags(arn: arn).tag_list
|
|
92
92
|
deploy_struct['tags'] = tags.map { |t| { t.key => t.value } }
|
|
93
93
|
if deploy_struct['endpoint']
|
|
94
94
|
deploy_struct['kibana'] = deploy_struct['endpoint']+"/_plugin/kibana/"
|
|
@@ -200,7 +200,7 @@ module MU
|
|
|
200
200
|
"cloud" => "AWS",
|
|
201
201
|
"credentials" => @credentials,
|
|
202
202
|
"cloud_id" => @cloud_id,
|
|
203
|
-
"region" => @
|
|
203
|
+
"region" => @region
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
if !cloud_desc
|
|
@@ -241,7 +241,7 @@ module MU
|
|
|
241
241
|
bok['identity_pool_id'] = cloud_desc.cognito_options.identity_pool_id
|
|
242
242
|
end
|
|
243
243
|
|
|
244
|
-
tags = MU::Cloud::AWS.elasticsearch(region: @
|
|
244
|
+
tags = MU::Cloud::AWS.elasticsearch(region: @region, credentials: @credentials).list_tags(arn: cloud_desc.arn).tag_list
|
|
245
245
|
if tags and !tags.empty?
|
|
246
246
|
bok['tags'] = MU.structToHash(tags)
|
|
247
247
|
end
|
|
@@ -252,7 +252,7 @@ module MU
|
|
|
252
252
|
cloud: "AWS",
|
|
253
253
|
credentials: @credentials,
|
|
254
254
|
type: "vpcs",
|
|
255
|
-
region: @
|
|
255
|
+
region: @region,
|
|
256
256
|
subnets: cloud_desc.vpc_options.subnet_ids.map { |s| { "subnet_id" => s } }
|
|
257
257
|
)
|
|
258
258
|
if cloud_desc.vpc_options.security_group_ids and
|
|
@@ -262,7 +262,7 @@ module MU
|
|
|
262
262
|
id: sg,
|
|
263
263
|
cloud: "AWS",
|
|
264
264
|
credentials: @credentials,
|
|
265
|
-
region: @
|
|
265
|
+
region: @region,
|
|
266
266
|
type: "firewall_rules",
|
|
267
267
|
)
|
|
268
268
|
}
|
|
@@ -683,7 +683,7 @@ module MU
|
|
|
683
683
|
params[:log_publishing_options]["SEARCH_SLOW_LOGS"] = {}
|
|
684
684
|
params[:log_publishing_options]["SEARCH_SLOW_LOGS"][:enabled] = true
|
|
685
685
|
params[:log_publishing_options]["SEARCH_SLOW_LOGS"][:cloud_watch_logs_log_group_arn] = arn
|
|
686
|
-
MU::Cloud.resourceClass("AWS", "Log").allowService("es.amazonaws.com", arn, @
|
|
686
|
+
MU::Cloud.resourceClass("AWS", "Log").allowService("es.amazonaws.com", arn, @region)
|
|
687
687
|
end
|
|
688
688
|
end
|
|
689
689
|
|
|
@@ -813,7 +813,7 @@ module MU
|
|
|
813
813
|
raise MU::MuError, "Can't tag ElasticSearch domain, cloud descriptor came back without an ARN"
|
|
814
814
|
end
|
|
815
815
|
|
|
816
|
-
MU::Cloud::AWS.elasticsearch(region: @
|
|
816
|
+
MU::Cloud::AWS.elasticsearch(region: @region, credentials: @credentials).add_tags(
|
|
817
817
|
arn: domain.arn,
|
|
818
818
|
tag_list: tags
|
|
819
819
|
)
|
|
@@ -85,7 +85,7 @@ module MU
|
|
|
85
85
|
MU::Cloud.fetchUserdata(
|
|
86
86
|
platform: @config["platform"],
|
|
87
87
|
cloud: "AWS",
|
|
88
|
-
credentials: @
|
|
88
|
+
credentials: @credentials,
|
|
89
89
|
template_variables: {
|
|
90
90
|
"deployKey" => Base64.urlsafe_encode64(@deploy.public_key),
|
|
91
91
|
"deploySSHKey" => @deploy.ssh_public_key,
|
|
@@ -242,8 +242,8 @@ module MU
|
|
|
242
242
|
else
|
|
243
243
|
MU::Cloud::AWS.createStandardTags(
|
|
244
244
|
instance.instance_id,
|
|
245
|
-
region: @
|
|
246
|
-
credentials: @
|
|
245
|
+
region: @region,
|
|
246
|
+
credentials: @credentials,
|
|
247
247
|
optional: @config['optional_tags'],
|
|
248
248
|
nametag: @mu_name,
|
|
249
249
|
othertags: @config['tags']
|
|
@@ -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,8 +476,8 @@ module MU
|
|
|
457
476
|
|
|
458
477
|
MU::Cloud::AWS.createStandardTags(
|
|
459
478
|
@cloud_id,
|
|
460
|
-
region: @
|
|
461
|
-
credentials: @
|
|
479
|
+
region: @region,
|
|
480
|
+
credentials: @credentials,
|
|
462
481
|
optional: @config['optional_tags'],
|
|
463
482
|
nametag: @mu_name,
|
|
464
483
|
othertags: @config['tags']
|
|
@@ -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
|
|
@@ -574,7 +600,7 @@ module MU
|
|
|
574
600
|
regions.each { |r|
|
|
575
601
|
searches.each { |search|
|
|
576
602
|
search_threads << Thread.new(search) { |params|
|
|
577
|
-
MU.retrier([
|
|
603
|
+
MU.retrier([], wait: 5, max: 5, ignoreme: [Aws::EC2::Errors::InvalidInstanceIDNotFound]) {
|
|
578
604
|
MU::Cloud::AWS.ec2(region: r, credentials: args[:credentials]).describe_instances(params).reservations.each { |resp|
|
|
579
605
|
next if resp.nil? or resp.instances.nil?
|
|
580
606
|
resp.instances.each { |i|
|
|
@@ -604,9 +630,9 @@ module MU
|
|
|
604
630
|
def toKitten(**_args)
|
|
605
631
|
bok = {
|
|
606
632
|
"cloud" => "AWS",
|
|
607
|
-
"credentials" => @
|
|
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?
|
|
@@ -1275,19 +1298,19 @@ module MU
|
|
|
1275
1298
|
def addVolume(dev, size, type: "gp2", delete_on_termination: false)
|
|
1276
1299
|
|
|
1277
1300
|
if setDeleteOntermination(dev, delete_on_termination)
|
|
1278
|
-
MU.log "A volume #{
|
|
1301
|
+
MU.log "A volume #{dev} already attached to #{self}, skipping", MU::NOTICE
|
|
1279
1302
|
return
|
|
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,27 +1321,35 @@ module MU
|
|
|
1298
1321
|
if @deploy
|
|
1299
1322
|
MU::Cloud::AWS.createStandardTags(
|
|
1300
1323
|
creation.volume_id,
|
|
1301
|
-
region: @
|
|
1302
|
-
credentials: @
|
|
1324
|
+
region: @region,
|
|
1325
|
+
credentials: @credentials,
|
|
1303
1326
|
optional: @config['optional_tags'],
|
|
1304
1327
|
nametag: @mu_name+"-"+dev.upcase,
|
|
1305
1328
|
othertags: @config['tags']
|
|
1306
1329
|
)
|
|
1307
1330
|
end
|
|
1308
1331
|
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1332
|
+
MU.log "Attaching #{creation.volume_id} as #{dev} to #{@cloud_id} in #{@region} (credentials #{@credentials})"
|
|
1333
|
+
attachment = nil
|
|
1334
|
+
MU.retrier([Aws::EC2::Errors::IncorrectState], wait: 15, max: 4) {
|
|
1335
|
+
attachment = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).attach_volume(
|
|
1336
|
+
device: dev,
|
|
1337
|
+
instance_id: @cloud_id,
|
|
1338
|
+
volume_id: creation.volume_id
|
|
1339
|
+
)
|
|
1340
|
+
}
|
|
1314
1341
|
|
|
1315
1342
|
begin
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
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
|
|
1320
1351
|
end
|
|
1321
|
-
end while attachment.state != "attached"
|
|
1352
|
+
end while attachment.nil? or attachment.state != "attached"
|
|
1322
1353
|
|
|
1323
1354
|
# Set delete_on_termination, which for some reason is an instance
|
|
1324
1355
|
# attribute and not on the attachment
|
|
@@ -1334,7 +1365,7 @@ module MU
|
|
|
1334
1365
|
return true
|
|
1335
1366
|
end
|
|
1336
1367
|
begin
|
|
1337
|
-
MU::Cloud::AWS.ec2(region: @
|
|
1368
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_instances(
|
|
1338
1369
|
instance_ids: [@cloud_id]
|
|
1339
1370
|
).reservations.each { |resp|
|
|
1340
1371
|
if !resp.nil? and !resp.instances.nil?
|
|
@@ -1385,7 +1416,7 @@ module MU
|
|
|
1385
1416
|
}
|
|
1386
1417
|
end
|
|
1387
1418
|
end
|
|
1388
|
-
elastic_ip = findFreeElasticIp(classic: classic, ip: ip)
|
|
1419
|
+
elastic_ip = findFreeElasticIp(classic: classic, ip: ip, credentials: credentials)
|
|
1389
1420
|
if !ip.nil? and (elastic_ip.nil? or ip != elastic_ip.public_ip)
|
|
1390
1421
|
raise MuError, "Requested EIP #{ip}, but this IP does not exist or is not available"
|
|
1391
1422
|
end
|
|
@@ -1737,6 +1768,7 @@ module MU
|
|
|
1737
1768
|
return size
|
|
1738
1769
|
end
|
|
1739
1770
|
|
|
1771
|
+
|
|
1740
1772
|
return size if types.has_key?(size)
|
|
1741
1773
|
|
|
1742
1774
|
if size.nil? or !types.has_key?(size)
|
|
@@ -1782,7 +1814,8 @@ module MU
|
|
|
1782
1814
|
def self.generateStandardRole(server, configurator)
|
|
1783
1815
|
role = {
|
|
1784
1816
|
"name" => server["name"],
|
|
1785
|
-
"
|
|
1817
|
+
"bare_policies" => !server['generate_iam_role'],
|
|
1818
|
+
"strip_path" => server["role_strip_path"],
|
|
1786
1819
|
"can_assume" => [
|
|
1787
1820
|
{
|
|
1788
1821
|
"entity_id" => "ec2.amazonaws.com",
|
|
@@ -1801,6 +1834,7 @@ module MU
|
|
|
1801
1834
|
}
|
|
1802
1835
|
]
|
|
1803
1836
|
}
|
|
1837
|
+
role["credentials"] = server["credentials"] if server["credentials"]
|
|
1804
1838
|
if server['iam_policies']
|
|
1805
1839
|
role['iam_policies'] = server['iam_policies'].dup
|
|
1806
1840
|
end
|
|
@@ -1834,9 +1868,10 @@ module MU
|
|
|
1834
1868
|
MU.log "Cannot mix iam_policies with generate_iam_role set to false", MU::ERR
|
|
1835
1869
|
ok = false
|
|
1836
1870
|
end
|
|
1837
|
-
else
|
|
1838
|
-
generateStandardRole(server, configurator)
|
|
1839
1871
|
end
|
|
1872
|
+
|
|
1873
|
+
generateStandardRole(server, configurator)
|
|
1874
|
+
|
|
1840
1875
|
if !server['create_image'].nil?
|
|
1841
1876
|
if server['create_image'].has_key?('copy_to_regions') and
|
|
1842
1877
|
(server['create_image']['copy_to_regions'].nil? or
|
|
@@ -2085,7 +2120,7 @@ module MU
|
|
|
2085
2120
|
def haveElasticIP?
|
|
2086
2121
|
if !cloud_desc.public_ip_address.nil?
|
|
2087
2122
|
begin
|
|
2088
|
-
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])
|
|
2089
2124
|
if resp.addresses.size > 0 and resp.addresses.first.instance_id == @cloud_id
|
|
2090
2125
|
return true
|
|
2091
2126
|
end
|
|
@@ -2100,9 +2135,9 @@ module MU
|
|
|
2100
2135
|
def configureNetworking
|
|
2101
2136
|
if !@config['static_ip'].nil?
|
|
2102
2137
|
if !@config['static_ip']['ip'].nil?
|
|
2103
|
-
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)
|
|
2104
2139
|
elsif !haveElasticIP?
|
|
2105
|
-
MU::Cloud::AWS::Server.associateElasticIp(@cloud_id, classic: @vpc.nil
|
|
2140
|
+
MU::Cloud::AWS::Server.associateElasticIp(@cloud_id, classic: @vpc.nil?, credentials: @credentials)
|
|
2106
2141
|
end
|
|
2107
2142
|
end
|
|
2108
2143
|
|
|
@@ -2110,7 +2145,7 @@ module MU
|
|
|
2110
2145
|
subnet = @vpc.getSubnet(cloud_id: cloud_desc.subnet_id)
|
|
2111
2146
|
|
|
2112
2147
|
_nat_ssh_key, _nat_ssh_user, nat_ssh_host, _canonical_ip, _ssh_user, _ssh_key_name = getSSHConfig
|
|
2113
|
-
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)
|
|
2114
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"
|
|
2115
2150
|
end
|
|
2116
2151
|
|
|
@@ -2127,17 +2162,17 @@ module MU
|
|
|
2127
2162
|
next
|
|
2128
2163
|
end
|
|
2129
2164
|
MU.log "Adding network interface on subnet #{s.cloud_id} for #{@mu_name}"
|
|
2130
|
-
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
|
|
2131
2166
|
MU::Cloud::AWS.createStandardTags(
|
|
2132
2167
|
iface.network_interface_id,
|
|
2133
|
-
region: @
|
|
2134
|
-
credentials: @
|
|
2168
|
+
region: @region,
|
|
2169
|
+
credentials: @credentials,
|
|
2135
2170
|
optional: @config['optional_tags'],
|
|
2136
2171
|
nametag: @mu_name+"-ETH"+device_index.to_s,
|
|
2137
2172
|
othertags: @config['tags']
|
|
2138
2173
|
)
|
|
2139
2174
|
|
|
2140
|
-
MU::Cloud::AWS.ec2(region: @
|
|
2175
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).attach_network_interface(
|
|
2141
2176
|
network_interface_id: iface.network_interface_id,
|
|
2142
2177
|
instance_id: cloud_desc.instance_id,
|
|
2143
2178
|
device_index: device_index
|
|
@@ -2156,7 +2191,7 @@ module MU
|
|
|
2156
2191
|
cloud_desc.network_interfaces.each { |int|
|
|
2157
2192
|
if int.private_ip_address == cloud_desc.private_ip_address and int.private_ip_addresses.size < (@config['add_private_ips'] + 1)
|
|
2158
2193
|
MU.log "Adding #{@config['add_private_ips']} extra private IP addresses to #{cloud_desc.instance_id}"
|
|
2159
|
-
MU::Cloud::AWS.ec2(region: @
|
|
2194
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).assign_private_ip_addresses(
|
|
2160
2195
|
network_interface_id: int.network_interface_id,
|
|
2161
2196
|
secondary_private_ip_address_count: @config['add_private_ips'],
|
|
2162
2197
|
allow_reassignment: false
|
|
@@ -2167,14 +2202,14 @@ module MU
|
|
|
2167
2202
|
end
|
|
2168
2203
|
|
|
2169
2204
|
def tagVolumes
|
|
2170
|
-
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]])
|
|
2171
2206
|
volumes.each { |vol|
|
|
2172
2207
|
vol.volumes.each { |volume|
|
|
2173
2208
|
volume.attachments.each { |attachment|
|
|
2174
2209
|
MU::Cloud::AWS.createStandardTags(
|
|
2175
2210
|
attachment.volume_id,
|
|
2176
|
-
region: @
|
|
2177
|
-
credentials: @
|
|
2211
|
+
region: @region,
|
|
2212
|
+
credentials: @credentials,
|
|
2178
2213
|
optional: @config['optional_tags'],
|
|
2179
2214
|
nametag: ["/dev/sda", "/dev/sda1"].include?(attachment.device) ? "ROOT-"+@mu_name : @mu_name+"-"+attachment.device.upcase,
|
|
2180
2215
|
othertags: @config['tags']
|
|
@@ -2195,7 +2230,7 @@ module MU
|
|
|
2195
2230
|
alarm_obj = MU::MommaCat.findStray(
|
|
2196
2231
|
"AWS",
|
|
2197
2232
|
"alarms",
|
|
2198
|
-
region: @
|
|
2233
|
+
region: @region,
|
|
2199
2234
|
deploy_id: @deploy.deploy_id,
|
|
2200
2235
|
name: alarm['name']
|
|
2201
2236
|
).first
|
|
@@ -2204,8 +2239,8 @@ module MU
|
|
|
2204
2239
|
if alarm["enable_notifications"]
|
|
2205
2240
|
# XXX vile, this should be a sibling resource generated by the
|
|
2206
2241
|
# parser
|
|
2207
|
-
topic_arn = MU::Cloud.resourceClass("AWS", "Notification").createTopic(alarm["notification_group"], region: @
|
|
2208
|
-
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)
|
|
2209
2244
|
alarm["alarm_actions"] = [topic_arn]
|
|
2210
2245
|
alarm["ok_actions"] = [topic_arn]
|
|
2211
2246
|
end
|
|
@@ -2226,36 +2261,88 @@ module MU
|
|
|
2226
2261
|
evaluation_periods: alarm["evaluation_periods"],
|
|
2227
2262
|
threshold: alarm["threshold"],
|
|
2228
2263
|
comparison_operator: alarm["comparison_operator"],
|
|
2229
|
-
region: @
|
|
2230
|
-
credentials: @
|
|
2264
|
+
region: @region,
|
|
2265
|
+
credentials: @credentials
|
|
2231
2266
|
)
|
|
2232
2267
|
}
|
|
2233
2268
|
end
|
|
2234
2269
|
end
|
|
2235
2270
|
|
|
2236
|
-
# We have issues sometimes where our dns_records are pointing at the wrong node name and IP address.
|
|
2237
|
-
|
|
2238
2271
|
def getIAMProfile
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
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)
|
|
2288
|
+
if !role
|
|
2289
|
+
raise MuError, "Failed to find a role matching #{myname}"
|
|
2290
|
+
end
|
|
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
|
|
2243
2293
|
}
|
|
2244
|
-
MU.log "Adding S3 read permissions to #{
|
|
2294
|
+
MU.log "Adding S3 read permissions to #{myname}'s IAM profile", MU::NOTICE, details: s3_objs
|
|
2245
2295
|
role.cloudobj.injectPolicyTargets("MuSecrets", s3_objs)
|
|
2246
2296
|
|
|
2247
|
-
|
|
2297
|
+
role_name = role.mu_name
|
|
2248
2298
|
role.cloudobj.createInstanceProfile
|
|
2249
2299
|
|
|
2250
|
-
elsif
|
|
2251
|
-
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
|
|
2252
2314
|
end
|
|
2253
2315
|
|
|
2254
|
-
|
|
2255
|
-
|
|
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
|
|
2339
|
+
end
|
|
2340
|
+
|
|
2341
|
+
if !role_name.nil?
|
|
2342
|
+
if arn and want_arn
|
|
2256
2343
|
return {arn: arn}
|
|
2257
2344
|
else
|
|
2258
|
-
return {name:
|
|
2345
|
+
return {name: role_name}
|
|
2259
2346
|
end
|
|
2260
2347
|
end
|
|
2261
2348
|
|
|
@@ -2272,8 +2359,8 @@ module MU
|
|
|
2272
2359
|
if vol[:device_name] == device
|
|
2273
2360
|
if vol[:ebs][:delete_on_termination] != delete_on_termination
|
|
2274
2361
|
vol[:ebs][:delete_on_termination] = delete_on_termination
|
|
2275
|
-
MU.log "Setting delete_on_termination flag to #{delete_on_termination.to_s} on #{@mu_name}'s #{
|
|
2276
|
-
MU::Cloud::AWS.ec2(region: @
|
|
2362
|
+
MU.log "Setting delete_on_termination flag to #{delete_on_termination.to_s} on #{@mu_name}'s #{device}"
|
|
2363
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).modify_instance_attribute(
|
|
2277
2364
|
instance_id: @cloud_id,
|
|
2278
2365
|
block_device_mappings: mappings
|
|
2279
2366
|
)
|
|
@@ -2317,16 +2404,17 @@ module MU
|
|
|
2317
2404
|
exclude_storage: img_cfg['image_exclude_storage'],
|
|
2318
2405
|
copy_to_regions: img_cfg['copy_to_regions'],
|
|
2319
2406
|
make_public: img_cfg['public'],
|
|
2320
|
-
region: @
|
|
2407
|
+
region: @region,
|
|
2321
2408
|
tags: @config['tags'],
|
|
2322
|
-
credentials: @
|
|
2409
|
+
credentials: @credentials
|
|
2323
2410
|
)
|
|
2411
|
+
|
|
2324
2412
|
@deploy.notify("images", @config['name'], ami_ids)
|
|
2325
2413
|
@config['image_created'] = true
|
|
2326
2414
|
if img_cfg['image_then_destroy']
|
|
2327
|
-
MU::Cloud::AWS::Server.waitForAMI(ami_ids[@
|
|
2328
|
-
MU.log "AMI #{ami_ids[@
|
|
2329
|
-
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)
|
|
2330
2418
|
destroy
|
|
2331
2419
|
end
|
|
2332
2420
|
end
|