cloud-mu 1.9.0.pre.beta → 2.0.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Berksfile +16 -54
- data/Berksfile.lock +14 -62
- data/bin/mu-aws-setup +131 -108
- data/bin/mu-configure +311 -74
- data/bin/mu-gcp-setup +84 -62
- data/bin/mu-load-config.rb +46 -2
- data/bin/mu-self-update +11 -9
- data/bin/mu-upload-chef-artifacts +4 -4
- data/{mu.gemspec → cloud-mu.gemspec} +2 -2
- data/cookbooks/awscli/Berksfile +8 -0
- data/cookbooks/mu-activedirectory/Berksfile +11 -0
- data/cookbooks/mu-firewall/Berksfile +9 -0
- data/cookbooks/mu-firewall/metadata.rb +1 -1
- data/cookbooks/mu-glusterfs/Berksfile +10 -0
- data/cookbooks/mu-jenkins/Berksfile +14 -0
- data/cookbooks/mu-master/Berksfile +23 -0
- data/cookbooks/mu-master/attributes/default.rb +1 -1
- data/cookbooks/mu-master/metadata.rb +2 -2
- data/cookbooks/mu-master/recipes/default.rb +1 -1
- data/cookbooks/mu-master/recipes/init.rb +7 -3
- data/cookbooks/mu-master/recipes/ssl-certs.rb +1 -0
- data/cookbooks/mu-mongo/Berksfile +10 -0
- data/cookbooks/mu-openvpn/Berksfile +11 -0
- data/cookbooks/mu-php54/Berksfile +13 -0
- data/cookbooks/mu-splunk/Berksfile +10 -0
- data/cookbooks/mu-tools/Berksfile +21 -0
- data/cookbooks/mu-tools/files/default/Mu_CA.pem +15 -15
- data/cookbooks/mu-utility/Berksfile +9 -0
- data/cookbooks/mu-utility/metadata.rb +2 -1
- data/cookbooks/nagios/Berksfile +7 -4
- data/cookbooks/s3fs/Berksfile +9 -0
- data/environments/dev.json +6 -6
- data/environments/prod.json +6 -6
- data/modules/mu.rb +20 -42
- data/modules/mu/cleanup.rb +102 -100
- data/modules/mu/cloud.rb +90 -28
- data/modules/mu/clouds/aws.rb +449 -218
- data/modules/mu/clouds/aws/alarm.rb +29 -17
- data/modules/mu/clouds/aws/cache_cluster.rb +78 -64
- data/modules/mu/clouds/aws/collection.rb +25 -18
- data/modules/mu/clouds/aws/container_cluster.rb +73 -66
- data/modules/mu/clouds/aws/database.rb +124 -116
- data/modules/mu/clouds/aws/dnszone.rb +27 -20
- data/modules/mu/clouds/aws/firewall_rule.rb +30 -22
- data/modules/mu/clouds/aws/folder.rb +18 -3
- data/modules/mu/clouds/aws/function.rb +77 -23
- data/modules/mu/clouds/aws/group.rb +19 -12
- data/modules/mu/clouds/aws/habitat.rb +153 -0
- data/modules/mu/clouds/aws/loadbalancer.rb +59 -52
- data/modules/mu/clouds/aws/log.rb +30 -23
- data/modules/mu/clouds/aws/msg_queue.rb +29 -20
- data/modules/mu/clouds/aws/notifier.rb +222 -0
- data/modules/mu/clouds/aws/role.rb +178 -90
- data/modules/mu/clouds/aws/search_domain.rb +40 -24
- data/modules/mu/clouds/aws/server.rb +169 -137
- data/modules/mu/clouds/aws/server_pool.rb +60 -83
- data/modules/mu/clouds/aws/storage_pool.rb +59 -31
- data/modules/mu/clouds/aws/user.rb +36 -27
- data/modules/mu/clouds/aws/userdata/linux.erb +101 -93
- data/modules/mu/clouds/aws/vpc.rb +250 -189
- data/modules/mu/clouds/azure.rb +132 -0
- data/modules/mu/clouds/cloudformation.rb +65 -1
- data/modules/mu/clouds/cloudformation/alarm.rb +8 -0
- data/modules/mu/clouds/cloudformation/cache_cluster.rb +7 -0
- data/modules/mu/clouds/cloudformation/collection.rb +7 -0
- data/modules/mu/clouds/cloudformation/database.rb +7 -0
- data/modules/mu/clouds/cloudformation/dnszone.rb +7 -0
- data/modules/mu/clouds/cloudformation/firewall_rule.rb +9 -2
- data/modules/mu/clouds/cloudformation/loadbalancer.rb +7 -0
- data/modules/mu/clouds/cloudformation/log.rb +7 -0
- data/modules/mu/clouds/cloudformation/server.rb +7 -0
- data/modules/mu/clouds/cloudformation/server_pool.rb +7 -0
- data/modules/mu/clouds/cloudformation/vpc.rb +7 -0
- data/modules/mu/clouds/google.rb +214 -110
- data/modules/mu/clouds/google/container_cluster.rb +42 -24
- data/modules/mu/clouds/google/database.rb +15 -6
- data/modules/mu/clouds/google/firewall_rule.rb +17 -25
- data/modules/mu/clouds/google/group.rb +13 -5
- data/modules/mu/clouds/google/habitat.rb +105 -0
- data/modules/mu/clouds/google/loadbalancer.rb +28 -20
- data/modules/mu/clouds/google/server.rb +93 -354
- data/modules/mu/clouds/google/server_pool.rb +18 -10
- data/modules/mu/clouds/google/user.rb +22 -14
- data/modules/mu/clouds/google/vpc.rb +97 -69
- data/modules/mu/config.rb +133 -38
- data/modules/mu/config/alarm.rb +25 -0
- data/modules/mu/config/cache_cluster.rb +5 -3
- data/modules/mu/config/cache_cluster.yml +23 -0
- data/modules/mu/config/database.rb +25 -16
- data/modules/mu/config/database.yml +3 -3
- data/modules/mu/config/function.rb +1 -2
- data/modules/mu/config/{project.rb → habitat.rb} +10 -10
- data/modules/mu/config/notifier.rb +85 -0
- data/modules/mu/config/notifier.yml +9 -0
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/search_domain.yml +2 -2
- data/modules/mu/config/server.rb +13 -1
- data/modules/mu/config/server.yml +3 -3
- data/modules/mu/config/server_pool.rb +3 -1
- data/modules/mu/config/storage_pool.rb +3 -1
- data/modules/mu/config/storage_pool.yml +19 -0
- data/modules/mu/config/vpc.rb +70 -8
- data/modules/mu/groomers/chef.rb +2 -3
- data/modules/mu/kittens.rb +500 -122
- data/modules/mu/master.rb +5 -5
- data/modules/mu/mommacat.rb +151 -91
- data/modules/tests/super_complex_bok.yml +12 -0
- data/modules/tests/super_simple_bok.yml +12 -0
- data/spec/mu/clouds/azure_spec.rb +82 -0
- data/spec/spec_helper.rb +105 -0
- metadata +26 -5
- data/modules/mu/clouds/aws/notification.rb +0 -139
- data/modules/mu/config/notification.rb +0 -44
@@ -42,7 +42,8 @@ module MU
|
|
42
42
|
params = genParams
|
43
43
|
|
44
44
|
MU.log "Creating ElasticSearch domain #{@config['domain_name']}", details: params
|
45
|
-
|
45
|
+
pp params
|
46
|
+
resp = MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @config['credentials']).create_elasticsearch_domain(params).domain_status
|
46
47
|
|
47
48
|
tagDomain
|
48
49
|
|
@@ -58,7 +59,7 @@ module MU
|
|
58
59
|
waitWhileProcessing # wait until the create finishes, if still going
|
59
60
|
|
60
61
|
MU.log "Updating ElasticSearch domain #{@config['domain_name']}", MU::NOTICE, details: params
|
61
|
-
MU::Cloud::AWS.elasticsearch(@config['region']).update_elasticsearch_domain_config(params)
|
62
|
+
MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @config['credentials']).update_elasticsearch_domain_config(params)
|
62
63
|
end
|
63
64
|
|
64
65
|
waitWhileProcessing # don't return until creation/updating is complete
|
@@ -69,11 +70,11 @@ module MU
|
|
69
70
|
# our druthers.
|
70
71
|
def cloud_desc
|
71
72
|
if @config['domain_name']
|
72
|
-
MU::Cloud::AWS.elasticsearch(@config['region']).describe_elasticsearch_domain(
|
73
|
+
MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @config['credentials']).describe_elasticsearch_domain(
|
73
74
|
domain_name: @config['domain_name']
|
74
75
|
).domain_status
|
75
|
-
elsif @deploydata['domain_name']
|
76
|
-
MU::Cloud::AWS.elasticsearch(@config['region']).describe_elasticsearch_domain(
|
76
|
+
elsif @deploydata and @deploydata['domain_name']
|
77
|
+
MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @config['credentials']).describe_elasticsearch_domain(
|
77
78
|
domain_name: @deploydata['domain_name']
|
78
79
|
).domain_status
|
79
80
|
else
|
@@ -91,7 +92,7 @@ module MU
|
|
91
92
|
# @return [Hash]
|
92
93
|
def notify
|
93
94
|
deploy_struct = MU.structToHash(cloud_desc)
|
94
|
-
tags = MU::Cloud::AWS.elasticsearch(@config['region']).list_tags(arn: deploy_struct[:arn]).tag_list
|
95
|
+
tags = MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @config['credentials']).list_tags(arn: deploy_struct[:arn]).tag_list
|
95
96
|
deploy_struct['tags'] = tags.map { |t| { t.key => t.value } }
|
96
97
|
if deploy_struct['endpoint']
|
97
98
|
deploy_struct['kibana'] = deploy_struct['endpoint']+"/_plugin/kibana/"
|
@@ -100,23 +101,30 @@ module MU
|
|
100
101
|
deploy_struct
|
101
102
|
end
|
102
103
|
|
104
|
+
# Does this resource type exist as a global (cloud-wide) artifact, or
|
105
|
+
# is it localized to a region/zone?
|
106
|
+
# @return [Boolean]
|
107
|
+
def self.isGlobal?
|
108
|
+
false
|
109
|
+
end
|
110
|
+
|
103
111
|
# Remove all search_domains associated with the currently loaded deployment.
|
104
112
|
# @param noop [Boolean]: If true, will only print what would be done
|
105
113
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
106
114
|
# @param region [String]: The cloud provider region
|
107
115
|
# @return [void]
|
108
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, flags: {})
|
109
|
-
list = MU::Cloud::AWS.elasticsearch(region).list_domain_names
|
116
|
+
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
117
|
+
list = MU::Cloud::AWS.elasticsearch(region: region).list_domain_names
|
110
118
|
if list and list.domain_names and list.domain_names.size > 0
|
111
|
-
descs = MU::Cloud::AWS.elasticsearch(region).describe_elasticsearch_domains(domain_names: list.domain_names.map { |d| d.domain_name } )
|
119
|
+
descs = MU::Cloud::AWS.elasticsearch(region: region).describe_elasticsearch_domains(domain_names: list.domain_names.map { |d| d.domain_name } )
|
112
120
|
|
113
121
|
descs.domain_status_list.each { |domain|
|
114
|
-
tags = MU::Cloud::AWS.elasticsearch(region).list_tags(arn: domain.arn)
|
122
|
+
tags = MU::Cloud::AWS.elasticsearch(region: region).list_tags(arn: domain.arn)
|
115
123
|
tags.tag_list.each { |tag|
|
116
124
|
if tag.key == "MU-ID" and tag.value == MU.deploy_id
|
117
125
|
MU.log "Deleting ElasticSearch Domain #{domain.domain_name}"
|
118
126
|
if !noop
|
119
|
-
MU::Cloud::AWS.elasticsearch(region).delete_elasticsearch_domain(domain_name: domain.domain_name)
|
127
|
+
MU::Cloud::AWS.elasticsearch(region: region).delete_elasticsearch_domain(domain_name: domain.domain_name)
|
120
128
|
end
|
121
129
|
break
|
122
130
|
end
|
@@ -142,14 +150,14 @@ module MU
|
|
142
150
|
# @param region [String]: The cloud provider region.
|
143
151
|
# @param flags [Hash]: Optional flags
|
144
152
|
# @return [OpenStruct]: The cloud provider's complete descriptions of matching search_domain.
|
145
|
-
def self.find(cloud_id: nil, region: MU.curRegion, flags: {})
|
153
|
+
def self.find(cloud_id: nil, region: MU.curRegion, credentials: nil, flags: {})
|
146
154
|
if cloud_id
|
147
155
|
# Annoyingly, we might expect one of several possible artifacts,
|
148
156
|
# since AWS couldn't decide what the real identifier of these
|
149
157
|
# things should be
|
150
|
-
list = MU::Cloud::AWS.elasticsearch(region).list_domain_names
|
158
|
+
list = MU::Cloud::AWS.elasticsearch(region: region, credentials: credentials).list_domain_names
|
151
159
|
if list and list.domain_names and list.domain_names.size > 0
|
152
|
-
descs = MU::Cloud::AWS.elasticsearch(region).describe_elasticsearch_domains(domain_names: list.domain_names.map { |d| d.domain_name } )
|
160
|
+
descs = MU::Cloud::AWS.elasticsearch(region: region, credentials: credentials).describe_elasticsearch_domains(domain_names: list.domain_names.map { |d| d.domain_name } )
|
153
161
|
descs.domain_status_list.each { |domain|
|
154
162
|
return domain if domain.arn == cloud_id
|
155
163
|
return domain if domain.domain_name == cloud_id
|
@@ -180,6 +188,10 @@ module MU
|
|
180
188
|
end
|
181
189
|
|
182
190
|
schema = {
|
191
|
+
"name" => {
|
192
|
+
"type" => "string",
|
193
|
+
"pattern" => '^[a-z][a-z0-9\-]+$'
|
194
|
+
},
|
183
195
|
"elasticsearch_version" => {
|
184
196
|
"type" => "string",
|
185
197
|
"default" => versions.first,
|
@@ -269,12 +281,12 @@ module MU
|
|
269
281
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
270
282
|
def self.validateConfig(dom, configurator)
|
271
283
|
ok = true
|
272
|
-
versions = MU::Cloud::AWS.elasticsearch(dom['region']).list_elasticsearch_versions.elasticsearch_versions
|
284
|
+
versions = MU::Cloud::AWS.elasticsearch(region: dom['region']).list_elasticsearch_versions.elasticsearch_versions
|
273
285
|
if !versions.include?(dom["elasticsearch_version"])
|
274
286
|
MU.log "Invalid ElasticSearch version '#{dom["elasticsearch_version"]}' in SearchDomain '#{dom['name']}'", MU::ERR, details: versions
|
275
287
|
ok = false
|
276
288
|
else
|
277
|
-
resp = MU::Cloud::AWS.elasticsearch(dom['region']).list_elasticsearch_instance_types(
|
289
|
+
resp = MU::Cloud::AWS.elasticsearch(region: dom['region']).list_elasticsearch_instance_types(
|
278
290
|
elasticsearch_version: dom["elasticsearch_version"]
|
279
291
|
)
|
280
292
|
|
@@ -330,7 +342,7 @@ module MU
|
|
330
342
|
if configurator.haveLitterMate?(dom['slow_logs'], "log")
|
331
343
|
dom['dependencies'] << { "name" => dom['slow_logs'], "type" => "log" }
|
332
344
|
else
|
333
|
-
log_group = MU::Cloud::AWS::Log.find(cloud_id: dom['slow_logs'], region: dom['region'])
|
345
|
+
log_group = MU::Cloud::AWS::Log.find(cloud_id: dom['slow_logs'], region: dom['region']).values.first
|
334
346
|
if !log_group
|
335
347
|
MU.log "Specified slow_logs CloudWatch log group '#{dom['slow_logs']}' in SearchDomain '#{dom['name']}' doesn't appear to exist", MU::ERR
|
336
348
|
ok = false
|
@@ -340,7 +352,10 @@ module MU
|
|
340
352
|
end
|
341
353
|
else
|
342
354
|
dom['slow_logs'] = dom['name']+"-slowlog"
|
343
|
-
log_group = {
|
355
|
+
log_group = {
|
356
|
+
"name" => dom['slow_logs'],
|
357
|
+
"credentials" => dom['credentials']
|
358
|
+
}
|
344
359
|
ok = false if !configurator.insertKitten(log_group, "logs")
|
345
360
|
dom['dependencies'] << { "name" => dom['slow_logs'], "type" => "log" }
|
346
361
|
end
|
@@ -353,7 +368,7 @@ module MU
|
|
353
368
|
|
354
369
|
if dom['cognito']
|
355
370
|
begin
|
356
|
-
MU::Cloud::AWS.cognito_ident(dom['region']).describe_identity_pool(
|
371
|
+
MU::Cloud::AWS.cognito_ident(region: dom['region']).describe_identity_pool(
|
357
372
|
identity_pool_id: dom['cognito']['identity_pool_id']
|
358
373
|
)
|
359
374
|
rescue ::Aws::CognitoIdentity::Errors::ValidationException, Aws::CognitoIdentity::Errors::ResourceNotFoundException => e
|
@@ -361,7 +376,7 @@ module MU
|
|
361
376
|
ok = false
|
362
377
|
end
|
363
378
|
begin
|
364
|
-
MU::Cloud::AWS.cognito_user(dom['region']).describe_user_pool(
|
379
|
+
MU::Cloud::AWS.cognito_user(region: dom['region']).describe_user_pool(
|
365
380
|
user_pool_id: dom['cognito']['user_pool_id']
|
366
381
|
)
|
367
382
|
rescue ::Aws::CognitoIdentityProvider::Errors::InvalidParameterException, Aws::CognitoIdentityProvider::Errors::ResourceNotFoundException => e
|
@@ -373,10 +388,10 @@ module MU
|
|
373
388
|
rolename = dom['cognito']['role_arn'].sub(/.*?:role\/([a-z0-9-]+)$/, '\1')
|
374
389
|
begin
|
375
390
|
if !dom['cognito']['role_arn'].match(/^arn:/)
|
376
|
-
role = MU::Cloud::AWS.iam
|
391
|
+
role = MU::Cloud::AWS.iam.get_role(role_name: rolename)
|
377
392
|
dom['cognito']['role_arn'] = role.role.arn
|
378
393
|
end
|
379
|
-
pols = MU::Cloud::AWS.iam
|
394
|
+
pols = MU::Cloud::AWS.iam.list_attached_role_policies(role_name: rolename).attached_policies
|
380
395
|
found = false
|
381
396
|
pols.each { |policy|
|
382
397
|
found = true if policy.policy_name == "AmazonESCognitoAccess"
|
@@ -391,6 +406,7 @@ module MU
|
|
391
406
|
else
|
392
407
|
roledesc = {
|
393
408
|
"name" => dom['name']+"cognitorole",
|
409
|
+
"credentials" => dom['credentials'],
|
394
410
|
"can_assume" => [
|
395
411
|
{
|
396
412
|
"entity_id" => "es.amazonaws.com",
|
@@ -471,7 +487,7 @@ module MU
|
|
471
487
|
arn = @config['slow_logs']
|
472
488
|
else
|
473
489
|
log_group = @deploy.findLitterMate(type: "log", name: @config['slow_logs'])
|
474
|
-
log_group = MU::Cloud::AWS::Log.find(cloud_id: log_group.mu_name, region: log_group.cloudobj.config['region'])
|
490
|
+
log_group = MU::Cloud::AWS::Log.find(cloud_id: log_group.mu_name, region: log_group.cloudobj.config['region']).values.first
|
475
491
|
if log_group.nil? or log_group.arn.nil?
|
476
492
|
raise MuError, "Failed to retrieve ARN of sibling LogGroup '#{@config['slow_logs']}'"
|
477
493
|
end
|
@@ -619,7 +635,7 @@ module MU
|
|
619
635
|
raise MU::MuError, "Can't tag ElasticSearch domain, cloud descriptor came back without an ARN"
|
620
636
|
end
|
621
637
|
|
622
|
-
MU::Cloud::AWS.elasticsearch(@config['region']).add_tags(
|
638
|
+
MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @config['credentials']).add_tags(
|
623
639
|
arn: domain.arn,
|
624
640
|
tag_list: tags
|
625
641
|
)
|
@@ -210,15 +210,15 @@ module MU
|
|
210
210
|
# @param tag_value [String]: The value of the tag to attach.
|
211
211
|
# @param region [String]: The cloud provider region
|
212
212
|
# @return [void]
|
213
|
-
def self.tagVolumes(instance_id, device: nil, tag_name: "MU-ID", tag_value: MU.deploy_id, region: MU.curRegion)
|
214
|
-
MU::Cloud::AWS.ec2(region).describe_volumes(filters: [name: "attachment.instance-id", values: [instance_id]]).each { |vol|
|
213
|
+
def self.tagVolumes(instance_id, device: nil, tag_name: "MU-ID", tag_value: MU.deploy_id, region: MU.curRegion, credentials: nil)
|
214
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_volumes(filters: [name: "attachment.instance-id", values: [instance_id]]).each { |vol|
|
215
215
|
vol.volumes.each { |volume|
|
216
216
|
volume.attachments.each { |attachment|
|
217
217
|
vol_parent = attachment.instance_id
|
218
218
|
vol_id = attachment.volume_id
|
219
219
|
vol_dev = attachment.device
|
220
220
|
if vol_parent == instance_id and (vol_dev == device or device.nil?)
|
221
|
-
MU::MommaCat.createTag(vol_id, tag_name, tag_value, region: region)
|
221
|
+
MU::MommaCat.createTag(vol_id, tag_name, tag_value, region: region, credentials: credentials)
|
222
222
|
break
|
223
223
|
end
|
224
224
|
}
|
@@ -246,8 +246,8 @@ module MU
|
|
246
246
|
end
|
247
247
|
MU::MommaCat.unlock(instance.instance_id+"-create")
|
248
248
|
else
|
249
|
-
MU::MommaCat.createStandardTags(instance.instance_id, region: @config['region'])
|
250
|
-
MU::MommaCat.createTag(instance.instance_id, "Name", @mu_name, region: @config['region'])
|
249
|
+
MU::MommaCat.createStandardTags(instance.instance_id, region: @config['region'], credentials: @config['credentials'])
|
250
|
+
MU::MommaCat.createTag(instance.instance_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
|
251
251
|
end
|
252
252
|
done = true
|
253
253
|
rescue Exception => e
|
@@ -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,
|
261
|
+
MU::Cloud::AWS::Server.cleanup(noop: false, ignoremaster: false, region: @config['region'], credentials: @config['credentials'], flags: { "skipsnapshots" => true } )
|
262
262
|
}
|
263
263
|
end
|
264
264
|
end
|
@@ -286,7 +286,6 @@ module MU
|
|
286
286
|
|
287
287
|
arn = nil
|
288
288
|
if @config['generate_iam_role']
|
289
|
-
# @config['iam_role'], @cfm_role_name, @cfm_prof_name, arn = MU::Cloud::AWS::Server.createIAMProfile(@mu_name, base_profile: @config['iam_role'], extra_policies: @config['iam_policies'])
|
290
289
|
role = @deploy.findLitterMate(name: @config['name'], type: "roles")
|
291
290
|
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|
|
292
291
|
'arn:'+(MU::Cloud::AWS.isGovCloud?(@config['region']) ? "aws-us-gov" : "aws")+':s3:::'+MU.adminBucketName+'/'+file
|
@@ -349,10 +348,10 @@ module MU
|
|
349
348
|
instance_descriptor[:user_data] = Base64.encode64(@userdata)
|
350
349
|
end
|
351
350
|
|
352
|
-
MU::Cloud::AWS::Server.waitForAMI(@config["ami_id"], region: @config['region'])
|
351
|
+
MU::Cloud::AWS::Server.waitForAMI(@config["ami_id"], region: @config['region'], credentials: @config['credentials'])
|
353
352
|
|
354
353
|
# Figure out which devices are embedded in the AMI already.
|
355
|
-
image = MU::Cloud::AWS.ec2(@config['region']).describe_images(image_ids: [@config["ami_id"]]).images.first
|
354
|
+
image = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_images(image_ids: [@config["ami_id"]]).images.first
|
356
355
|
ext_disks = {}
|
357
356
|
if !image.block_device_mappings.nil?
|
358
357
|
image.block_device_mappings.each { |disk|
|
@@ -391,7 +390,7 @@ module MU
|
|
391
390
|
|
392
391
|
retries = 0
|
393
392
|
begin
|
394
|
-
response = MU::Cloud::AWS.ec2(@config['region']).run_instances(instance_descriptor)
|
393
|
+
response = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).run_instances(instance_descriptor)
|
395
394
|
rescue Aws::EC2::Errors::InvalidGroupNotFound, Aws::EC2::Errors::InvalidSubnetIDNotFound, Aws::EC2::Errors::InvalidParameterValue => e
|
396
395
|
if retries < 10
|
397
396
|
if retries > 7
|
@@ -419,40 +418,40 @@ module MU
|
|
419
418
|
if hard
|
420
419
|
groupname = nil
|
421
420
|
if !@config['basis'].nil?
|
422
|
-
resp = MU::Cloud::AWS.autoscale(@config['region']).describe_auto_scaling_instances(
|
421
|
+
resp = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).describe_auto_scaling_instances(
|
423
422
|
instance_ids: [@cloud_id]
|
424
423
|
)
|
425
424
|
groupname = resp.auto_scaling_instances.first.auto_scaling_group_name
|
426
425
|
MU.log "Pausing Autoscale processes in #{groupname}", MU::NOTICE
|
427
|
-
MU::Cloud::AWS.autoscale(@config['region']).suspend_processes(
|
426
|
+
MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).suspend_processes(
|
428
427
|
auto_scaling_group_name: groupname
|
429
428
|
)
|
430
429
|
end
|
431
430
|
begin
|
432
431
|
MU.log "Stopping #{@mu_name} (#{@cloud_id})", MU::NOTICE
|
433
|
-
MU::Cloud::AWS.ec2(@config['region']).stop_instances(
|
432
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).stop_instances(
|
434
433
|
instance_ids: [@cloud_id]
|
435
434
|
)
|
436
|
-
MU::Cloud::AWS.ec2(@config['region']).wait_until(:instance_stopped, instance_ids: [@cloud_id]) do |waiter|
|
435
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).wait_until(:instance_stopped, instance_ids: [@cloud_id]) do |waiter|
|
437
436
|
waiter.before_attempt do |attempts|
|
438
437
|
MU.log "Waiting for #{@mu_name} to stop for hard reboot"
|
439
438
|
end
|
440
439
|
end
|
441
440
|
MU.log "Starting #{@mu_name} (#{@cloud_id})"
|
442
|
-
MU::Cloud::AWS.ec2(@config['region']).start_instances(
|
441
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).start_instances(
|
443
442
|
instance_ids: [@cloud_id]
|
444
443
|
)
|
445
444
|
ensure
|
446
445
|
if !groupname.nil?
|
447
446
|
MU.log "Resuming Autoscale processes in #{groupname}", MU::NOTICE
|
448
|
-
MU::Cloud::AWS.autoscale(@config['region']).resume_processes(
|
447
|
+
MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @config['credentials']).resume_processes(
|
449
448
|
auto_scaling_group_name: groupname
|
450
449
|
)
|
451
450
|
end
|
452
451
|
end
|
453
452
|
else
|
454
453
|
MU.log "Rebooting #{@mu_name} (#{@cloud_id})"
|
455
|
-
MU::Cloud::AWS.ec2(@config['region']).reboot_instances(
|
454
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).reboot_instances(
|
456
455
|
instance_ids: [@cloud_id]
|
457
456
|
)
|
458
457
|
end
|
@@ -468,7 +467,7 @@ module MU
|
|
468
467
|
return nil if @config.nil? or @deploy.nil?
|
469
468
|
|
470
469
|
nat_ssh_key = nat_ssh_user = nat_ssh_host = nil
|
471
|
-
if !@config["vpc"].nil? and !MU::Cloud::AWS::VPC.haveRouteToInstance?(cloud_desc, region: @config['region'])
|
470
|
+
if !@config["vpc"].nil? and !MU::Cloud::AWS::VPC.haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
|
472
471
|
if !@nat.nil?
|
473
472
|
if @nat.is_a?(Struct) && @nat.nat_gateway_id && @nat.nat_gateway_id.start_with?("nat-")
|
474
473
|
raise MuError, "Configured to use NAT Gateway, but I have no route to instance. Either use Bastion, or configure VPC peering"
|
@@ -516,18 +515,18 @@ module MU
|
|
516
515
|
return false if !MU::MommaCat.lock(instance.instance_id+"-orchestrate", true)
|
517
516
|
return false if !MU::MommaCat.lock(instance.instance_id+"-groom", true)
|
518
517
|
|
519
|
-
MU::MommaCat.createStandardTags(instance.instance_id, region: @config['region'])
|
520
|
-
MU::MommaCat.createTag(instance.instance_id, "Name", node, region: @config['region'])
|
518
|
+
MU::MommaCat.createStandardTags(instance.instance_id, region: @config['region'], credentials: @config['credentials'])
|
519
|
+
MU::MommaCat.createTag(instance.instance_id, "Name", node, region: @config['region'], credentials: @config['credentials'])
|
521
520
|
|
522
521
|
if @config['optional_tags']
|
523
522
|
MU::MommaCat.listOptionalTags.each { |key, value|
|
524
|
-
MU::MommaCat.createTag(instance.instance_id, key, value, region: @config['region'])
|
523
|
+
MU::MommaCat.createTag(instance.instance_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
525
524
|
}
|
526
525
|
end
|
527
526
|
|
528
527
|
if !@config['tags'].nil?
|
529
528
|
@config['tags'].each { |tag|
|
530
|
-
MU::MommaCat.createTag(instance.instance_id, tag['key'], tag['value'], region: @config['region'])
|
529
|
+
MU::MommaCat.createTag(instance.instance_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
531
530
|
}
|
532
531
|
end
|
533
532
|
MU.log "Tagged #{node} (#{instance.instance_id}) with MU-ID=#{MU.deploy_id}", MU::DEBUG
|
@@ -552,7 +551,7 @@ module MU
|
|
552
551
|
end
|
553
552
|
sleep 40
|
554
553
|
# Get a fresh AWS descriptor
|
555
|
-
instance = MU::Cloud::Server.find(cloud_id: @cloud_id, region: @config['region']).values.first
|
554
|
+
instance = MU::Cloud::Server.find(cloud_id: @cloud_id, region: @config['region'], credentials: @config['credentials']).values.first
|
556
555
|
if instance and instance.state.name == "terminated"
|
557
556
|
raise MuError, "EC2 instance #{node} (#{@cloud_id}) terminating during bootstrap!"
|
558
557
|
end
|
@@ -572,6 +571,8 @@ module MU
|
|
572
571
|
|
573
572
|
# If we came up via AutoScale, the Alarm module won't have had our
|
574
573
|
# instance ID to associate us with itself. So invoke that here.
|
574
|
+
# XXX might be possible to do this with regular alarm resources and
|
575
|
+
# dependencies now
|
575
576
|
if !@config['basis'].nil? and @config["alarms"] and !@config["alarms"].empty?
|
576
577
|
@config["alarms"].each { |alarm|
|
577
578
|
alarm_obj = MU::MommaCat.findStray(
|
@@ -584,8 +585,8 @@ module MU
|
|
584
585
|
alarm["dimensions"] = [{:name => "InstanceId", :value => @cloud_id}]
|
585
586
|
|
586
587
|
if alarm["enable_notifications"]
|
587
|
-
topic_arn = MU::Cloud::AWS::Notification.createTopic(alarm["notification_group"], region: @config["region"])
|
588
|
-
MU::Cloud::AWS::Notification.subscribe(arn: topic_arn, protocol: alarm["notification_type"], endpoint: alarm["notification_endpoint"], region: @config["region"])
|
588
|
+
topic_arn = MU::Cloud::AWS::Notification.createTopic(alarm["notification_group"], region: @config["region"], credentials: @config['credentials'])
|
589
|
+
MU::Cloud::AWS::Notification.subscribe(arn: topic_arn, protocol: alarm["notification_type"], endpoint: alarm["notification_endpoint"], region: @config["region"], credentials: @config["credentials"])
|
589
590
|
alarm["alarm_actions"] = [topic_arn]
|
590
591
|
alarm["ok_actions"] = [topic_arn]
|
591
592
|
end
|
@@ -606,7 +607,8 @@ module MU
|
|
606
607
|
evaluation_periods: alarm["evaluation_periods"],
|
607
608
|
threshold: alarm["threshold"],
|
608
609
|
comparison_operator: alarm["comparison_operator"],
|
609
|
-
region: @config["region"]
|
610
|
+
region: @config["region"],
|
611
|
+
credentials: @config['credentials']
|
610
612
|
)
|
611
613
|
}
|
612
614
|
end
|
@@ -635,7 +637,7 @@ module MU
|
|
635
637
|
|
636
638
|
if !@config['src_dst_check'] and !@config["vpc"].nil?
|
637
639
|
MU.log "Disabling source_dest_check #{node} (making it NAT-worthy)"
|
638
|
-
MU::Cloud::AWS.ec2(@config['region']).modify_instance_attribute(
|
640
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).modify_instance_attribute(
|
639
641
|
instance_id: @cloud_id,
|
640
642
|
source_dest_check: {:value => false}
|
641
643
|
)
|
@@ -643,7 +645,7 @@ module MU
|
|
643
645
|
|
644
646
|
# Set console termination protection. Autoscale nodes won't set this
|
645
647
|
# by default.
|
646
|
-
MU::Cloud::AWS.ec2(@config['region']).modify_instance_attribute(
|
648
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).modify_instance_attribute(
|
647
649
|
instance_id: @cloud_id,
|
648
650
|
disable_api_termination: {:value => true}
|
649
651
|
)
|
@@ -651,7 +653,7 @@ module MU
|
|
651
653
|
has_elastic_ip = false
|
652
654
|
if !instance.public_ip_address.nil?
|
653
655
|
begin
|
654
|
-
resp = MU::Cloud::AWS.ec2(
|
656
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_addresses(public_ips: [instance.public_ip_address])
|
655
657
|
if resp.addresses.size > 0 and resp.addresses.first.instance_id == @cloud_id
|
656
658
|
has_elastic_ip = true
|
657
659
|
end
|
@@ -737,7 +739,7 @@ module MU
|
|
737
739
|
end
|
738
740
|
|
739
741
|
nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name = getSSHConfig
|
740
|
-
if subnet.private? and !nat_ssh_host and !MU::Cloud::AWS::VPC.haveRouteToInstance?(cloud_desc, region: @config['region'])
|
742
|
+
if subnet.private? and !nat_ssh_host and !MU::Cloud::AWS::VPC.haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
|
741
743
|
raise MuError, "#{node} is in a private subnet (#{subnet}), but has no NAT host configured, and I have no other route to it"
|
742
744
|
end
|
743
745
|
|
@@ -749,23 +751,23 @@ module MU
|
|
749
751
|
@vpc.subnets { |subnet|
|
750
752
|
subnet_id = subnet.cloud_id
|
751
753
|
MU.log "Adding network interface on subnet #{subnet_id} for #{node}"
|
752
|
-
iface = MU::Cloud::AWS.ec2(@config['region']).create_network_interface(subnet_id: subnet_id).network_interface
|
753
|
-
MU::MommaCat.createStandardTags(iface.network_interface_id, region: @config['region'])
|
754
|
-
MU::MommaCat.createTag(iface.network_interface_id, "Name", node+"-ETH"+device_index.to_s, region: @config['region'])
|
754
|
+
iface = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_network_interface(subnet_id: subnet_id).network_interface
|
755
|
+
MU::MommaCat.createStandardTags(iface.network_interface_id, region: @config['region'], credentials: @config['credentials'])
|
756
|
+
MU::MommaCat.createTag(iface.network_interface_id, "Name", node+"-ETH"+device_index.to_s, region: @config['region'], credentials: @config['credentials'])
|
755
757
|
|
756
758
|
if @config['optional_tags']
|
757
759
|
MU::MommaCat.listOptionalTags.each { |key, value|
|
758
|
-
MU::MommaCat.createTag(iface.network_interface_id, key, value, region: @config['region'])
|
760
|
+
MU::MommaCat.createTag(iface.network_interface_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
759
761
|
}
|
760
762
|
end
|
761
763
|
|
762
764
|
if !@config['tags'].nil?
|
763
765
|
@config['tags'].each { |tag|
|
764
|
-
MU::MommaCat.createTag(iface.network_interface_id, tag['key'], tag['value'], region: @config['region'])
|
766
|
+
MU::MommaCat.createTag(iface.network_interface_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
765
767
|
}
|
766
768
|
end
|
767
769
|
|
768
|
-
MU::Cloud::AWS.ec2(@config['region']).attach_network_interface(
|
770
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).attach_network_interface(
|
769
771
|
network_interface_id: iface.network_interface_id,
|
770
772
|
instance_id: instance.instance_id,
|
771
773
|
device_index: device_index
|
@@ -805,29 +807,29 @@ module MU
|
|
805
807
|
|
806
808
|
# Tag volumes with all our standard tags.
|
807
809
|
# Maybe replace tagVolumes with this? There is one more place tagVolumes is called from
|
808
|
-
volumes = MU::Cloud::AWS.ec2(@config['region']).describe_volumes(filters: [name: "attachment.instance-id", values: [instance.instance_id]])
|
810
|
+
volumes = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_volumes(filters: [name: "attachment.instance-id", values: [instance.instance_id]])
|
809
811
|
volumes.each { |vol|
|
810
812
|
vol.volumes.each { |volume|
|
811
813
|
volume.attachments.each { |attachment|
|
812
814
|
MU::MommaCat.listStandardTags.each_pair { |key, value|
|
813
|
-
MU::MommaCat.createTag(attachment.volume_id, key, value, region: @config['region'])
|
815
|
+
MU::MommaCat.createTag(attachment.volume_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
814
816
|
|
815
817
|
if attachment.device == "/dev/sda" or attachment.device == "/dev/sda1"
|
816
|
-
MU::MommaCat.createTag(attachment.volume_id, "Name", "ROOT-#{MU.deploy_id}-#{@config["name"].upcase}", region: @config['region'])
|
818
|
+
MU::MommaCat.createTag(attachment.volume_id, "Name", "ROOT-#{MU.deploy_id}-#{@config["name"].upcase}", region: @config['region'], credentials: @config['credentials'])
|
817
819
|
else
|
818
|
-
MU::MommaCat.createTag(attachment.volume_id, "Name", "#{MU.deploy_id}-#{@config["name"].upcase}-#{attachment.device.upcase}", region: @config['region'])
|
820
|
+
MU::MommaCat.createTag(attachment.volume_id, "Name", "#{MU.deploy_id}-#{@config["name"].upcase}-#{attachment.device.upcase}", region: @config['region'], credentials: @config['credentials'])
|
819
821
|
end
|
820
822
|
}
|
821
823
|
|
822
824
|
if @config['optional_tags']
|
823
825
|
MU::MommaCat.listOptionalTags.each { |key, value|
|
824
|
-
MU::MommaCat.createTag(attachment.volume_id, key, value, region: @config['region'])
|
826
|
+
MU::MommaCat.createTag(attachment.volume_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
825
827
|
}
|
826
828
|
end
|
827
829
|
|
828
830
|
if @config['tags']
|
829
831
|
@config['tags'].each { |tag|
|
830
|
-
MU::MommaCat.createTag(attachment.volume_id, tag['key'], tag['value'], region: @config['region'])
|
832
|
+
MU::MommaCat.createTag(attachment.volume_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
831
833
|
}
|
832
834
|
end
|
833
835
|
}
|
@@ -842,7 +844,7 @@ module MU
|
|
842
844
|
instance.network_interfaces.each { |int|
|
843
845
|
if int.private_ip_address == instance.private_ip_address and int.private_ip_addresses.size < (@config['add_private_ips'] + 1)
|
844
846
|
MU.log "Adding #{@config['add_private_ips']} extra private IP addresses to #{instance.instance_id}"
|
845
|
-
MU::Cloud::AWS.ec2(@config['region']).assign_private_ip_addresses(
|
847
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).assign_private_ip_addresses(
|
846
848
|
network_interface_id: int.network_interface_id,
|
847
849
|
secondary_private_ip_address_count: @config['add_private_ips'],
|
848
850
|
allow_reassignment: false
|
@@ -853,31 +855,33 @@ module MU
|
|
853
855
|
end
|
854
856
|
|
855
857
|
begin
|
856
|
-
if
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
@
|
861
|
-
|
862
|
-
if !@groomer.haveBootstrapped?
|
863
|
-
session = getWinRMSession(50, 60, reboot_on_problems: true)
|
864
|
-
initialWinRMTasks(session)
|
865
|
-
begin
|
866
|
-
session.close
|
867
|
-
rescue Exception
|
868
|
-
# this is allowed to fail- we're probably rebooting anyway
|
858
|
+
if @config['groom'].nil? or @config['groom']
|
859
|
+
if windows?
|
860
|
+
# kick off certificate generation early; WinRM will need it
|
861
|
+
cert, key = @deploy.nodeSSLCerts(self)
|
862
|
+
if @config.has_key?("basis")
|
863
|
+
@deploy.nodeSSLCerts(self, true)
|
869
864
|
end
|
870
|
-
|
871
|
-
|
872
|
-
session
|
873
|
-
|
874
|
-
|
875
|
-
|
865
|
+
if !@groomer.haveBootstrapped?
|
866
|
+
session = getWinRMSession(50, 60, reboot_on_problems: true)
|
867
|
+
initialWinRMTasks(session)
|
868
|
+
begin
|
869
|
+
session.close
|
870
|
+
rescue Exception
|
871
|
+
# this is allowed to fail- we're probably rebooting anyway
|
872
|
+
end
|
873
|
+
else # for an existing Windows node: WinRM, then SSH if it fails
|
874
|
+
begin
|
875
|
+
session = getWinRMSession(1, 60)
|
876
|
+
rescue Exception # yeah, yeah
|
877
|
+
session = getSSHSession(1, 60)
|
878
|
+
# XXX maybe loop at least once if this also fails?
|
879
|
+
end
|
876
880
|
end
|
881
|
+
else
|
882
|
+
session = getSSHSession(40, 30)
|
883
|
+
initialSSHTasks(session)
|
877
884
|
end
|
878
|
-
else
|
879
|
-
session = getSSHSession(40, 30)
|
880
|
-
initialSSHTasks(session)
|
881
885
|
end
|
882
886
|
rescue BootstrapTempFail
|
883
887
|
sleep 45
|
@@ -922,14 +926,16 @@ module MU
|
|
922
926
|
# we're done.
|
923
927
|
if @groomer.haveBootstrapped?
|
924
928
|
MU.log "Node #{node} has already been bootstrapped, skipping groomer setup.", MU::NOTICE
|
925
|
-
@
|
929
|
+
if @config['groom'].nil? or @config['groom']
|
930
|
+
@groomer.saveDeployData
|
931
|
+
end
|
926
932
|
MU::MommaCat.unlock(instance.instance_id+"-orchestrate")
|
927
933
|
MU::MommaCat.unlock(instance.instance_id+"-groom")
|
928
934
|
return true
|
929
935
|
end
|
930
936
|
|
931
937
|
begin
|
932
|
-
@groomer.bootstrap
|
938
|
+
@groomer.bootstrap if @config['groom'].nil? or @config['groom']
|
933
939
|
rescue MU::Groomer::RunError
|
934
940
|
MU::MommaCat.unlock(instance.instance_id+"-groom")
|
935
941
|
MU::MommaCat.unlock(instance.instance_id+"-orchestrate")
|
@@ -954,11 +960,11 @@ module MU
|
|
954
960
|
# @param region [String]: The cloud provider region
|
955
961
|
# @param tag_key [String]: A tag key to search.
|
956
962
|
# @param tag_value [String]: The value of the tag specified by tag_key to match when searching by tag.
|
957
|
-
# @param ip [String]: An IP address associated with the instance
|
958
963
|
# @param flags [Hash]: Optional flags
|
959
964
|
# @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching instances
|
960
|
-
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil,
|
965
|
+
def self.find(cloud_id: nil, region: MU.curRegion, tag_key: "Name", tag_value: nil, credentials: nil, flags: {})
|
961
966
|
# XXX put that 'ip' value into opts
|
967
|
+
ip ||= flags['ip']
|
962
968
|
instance = nil
|
963
969
|
if !region.nil?
|
964
970
|
regions = [region]
|
@@ -977,7 +983,7 @@ module MU
|
|
977
983
|
MU.log "Hunting for instance with cloud id '#{cloud_id}' in #{region}", MU::DEBUG
|
978
984
|
retries = 0
|
979
985
|
begin
|
980
|
-
MU::Cloud::AWS.ec2(region).describe_instances(
|
986
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_instances(
|
981
987
|
instance_ids: [cloud_id],
|
982
988
|
filters: [
|
983
989
|
{name: "instance-state-name", values: ["running", "pending"]}
|
@@ -1018,7 +1024,7 @@ module MU
|
|
1018
1024
|
if instance.nil? and !ip.nil?
|
1019
1025
|
MU.log "Hunting for instance by IP '#{ip}'", MU::DEBUG
|
1020
1026
|
["ip-address", "private-ip-address"].each { |filter|
|
1021
|
-
response = MU::Cloud::AWS.ec2(region).describe_instances(
|
1027
|
+
response = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_instances(
|
1022
1028
|
filters: [
|
1023
1029
|
{name: filter, values: [ip]},
|
1024
1030
|
{name: "instance-state-name", values: ["running", "pending"]}
|
@@ -1035,7 +1041,7 @@ module MU
|
|
1035
1041
|
# Fine, let's try it by tag.
|
1036
1042
|
if !tag_value.nil?
|
1037
1043
|
MU.log "Searching for instance by tag '#{tag_key}=#{tag_value}'", MU::DEBUG
|
1038
|
-
MU::Cloud::AWS.ec2(region).describe_instances(
|
1044
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_instances(
|
1039
1045
|
filters: [
|
1040
1046
|
{name: "tag:#{tag_key}", values: [tag_value]},
|
1041
1047
|
{name: "instance-state-name", values: ["running", "pending"]}
|
@@ -1158,7 +1164,7 @@ module MU
|
|
1158
1164
|
|
1159
1165
|
punchAdminNAT
|
1160
1166
|
|
1161
|
-
MU::Cloud::AWS::Server.tagVolumes(@cloud_id)
|
1167
|
+
MU::Cloud::AWS::Server.tagVolumes(@cloud_id, credentials: @config['credentials'])
|
1162
1168
|
|
1163
1169
|
# If we have a loadbalancer configured, attach us to it
|
1164
1170
|
if !@config['loadbalancers'].nil?
|
@@ -1182,10 +1188,14 @@ module MU
|
|
1182
1188
|
# }
|
1183
1189
|
# end
|
1184
1190
|
|
1185
|
-
@
|
1191
|
+
if @config['groom'].nil? or @config['groom']
|
1192
|
+
@groomer.saveDeployData
|
1193
|
+
end
|
1186
1194
|
|
1187
1195
|
begin
|
1188
|
-
@
|
1196
|
+
if @config['groom'].nil? or @config['groom']
|
1197
|
+
@groomer.run(purpose: "Full Initial Run", max_retries: 15, reboot_first_fail: windows?, timeout: @config['groomer_timeout'])
|
1198
|
+
end
|
1189
1199
|
rescue MU::Groomer::RunError => e
|
1190
1200
|
MU.log "Proceeding after failed initial Groomer run, but #{node} may not behave as expected!", MU::WARN, details: e.message
|
1191
1201
|
rescue Exception => e
|
@@ -1221,13 +1231,15 @@ module MU
|
|
1221
1231
|
copy_to_regions: img_cfg['copy_to_regions'],
|
1222
1232
|
make_public: img_cfg['public'],
|
1223
1233
|
region: @config['region'],
|
1224
|
-
tags: @config['tags']
|
1234
|
+
tags: @config['tags'],
|
1235
|
+
credentials: @config['credentials']
|
1236
|
+
)
|
1225
1237
|
@deploy.notify("images", @config['name'], {"image_id" => ami_id})
|
1226
1238
|
@config['image_created'] = true
|
1227
1239
|
if img_cfg['image_then_destroy']
|
1228
|
-
MU::Cloud::AWS::Server.waitForAMI(ami_id, region: @config['region'])
|
1240
|
+
MU::Cloud::AWS::Server.waitForAMI(ami_id, region: @config['region'], credentials: @config['credentials'])
|
1229
1241
|
MU.log "AMI #{ami_id} ready, removing source node #{node}"
|
1230
|
-
MU::Cloud::AWS::Server.terminateInstance(id: @cloud_id, region: @config['region'], deploy_id: @deploy.deploy_id, mu_name: @mu_name)
|
1242
|
+
MU::Cloud::AWS::Server.terminateInstance(id: @cloud_id, region: @config['region'], deploy_id: @deploy.deploy_id, mu_name: @mu_name, credentials: @config['credentials'])
|
1231
1243
|
destroy
|
1232
1244
|
end
|
1233
1245
|
end
|
@@ -1238,7 +1250,7 @@ module MU
|
|
1238
1250
|
# Canonical Amazon Resource Number for this resource
|
1239
1251
|
# @return [String]
|
1240
1252
|
def arn
|
1241
|
-
"arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":ec2:"+@config['region']+":"+MU.
|
1253
|
+
"arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":ec2:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@config['credentials'])+":instance/"+@cloud_id
|
1242
1254
|
end
|
1243
1255
|
|
1244
1256
|
def cloud_desc
|
@@ -1246,7 +1258,7 @@ module MU
|
|
1246
1258
|
retries = 0
|
1247
1259
|
if !@cloud_id.nil?
|
1248
1260
|
begin
|
1249
|
-
return MU::Cloud::AWS.ec2(@config['region']).describe_instances(instance_ids: [@cloud_id]).reservations.first.instances.first
|
1261
|
+
return MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_instances(instance_ids: [@cloud_id]).reservations.first.instances.first
|
1250
1262
|
rescue Aws::EC2::Errors::InvalidInstanceIDNotFound
|
1251
1263
|
return nil
|
1252
1264
|
rescue NoMethodError => e
|
@@ -1291,7 +1303,7 @@ module MU
|
|
1291
1303
|
# Our deploydata gets corrupted often with server pools, this will cause us to use the wrong IP to identify a node
|
1292
1304
|
# which will cause us to create certificates, DNS records and other artifacts with incorrect information which will cause our deploy to fail.
|
1293
1305
|
# The cloud_id is always correct so lets use 'cloud_desc' to get the correct IPs
|
1294
|
-
if MU::Cloud::AWS::VPC.haveRouteToInstance?(cloud_desc, region: @config['region']) or @deploydata["public_ip_address"].nil?
|
1306
|
+
if MU::Cloud::AWS::VPC.haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials']) or @deploydata["public_ip_address"].nil?
|
1295
1307
|
@config['canonical_ip'] = instance.private_ip_address
|
1296
1308
|
@deploydata["private_ip_address"] = instance.private_ip_address
|
1297
1309
|
return instance.private_ip_address
|
@@ -1311,7 +1323,7 @@ module MU
|
|
1311
1323
|
# @param copy_to_regions [Array<String>]: Copy the resulting AMI into the listed regions.
|
1312
1324
|
# @param tags [Array<String>]: Extra/override tags to apply to the image.
|
1313
1325
|
# @return [String]: The cloud provider identifier of the new machine image.
|
1314
|
-
def self.createImage(name: nil, instance_id: nil, storage: {}, exclude_storage: false, make_public: false, region: MU.curRegion, copy_to_regions: [], tags: [])
|
1326
|
+
def self.createImage(name: nil, instance_id: nil, storage: {}, exclude_storage: false, make_public: false, region: MU.curRegion, copy_to_regions: [], tags: [], credentials: nil)
|
1315
1327
|
ami_descriptor = {
|
1316
1328
|
:instance_id => instance_id,
|
1317
1329
|
:name => name,
|
@@ -1344,18 +1356,18 @@ module MU
|
|
1344
1356
|
MU.log "Creating AMI from #{name}", details: ami_descriptor
|
1345
1357
|
resp = nil
|
1346
1358
|
begin
|
1347
|
-
resp = MU::Cloud::AWS.ec2(region).create_image(ami_descriptor)
|
1359
|
+
resp = MU::Cloud::AWS.ec2(region: region).create_image(ami_descriptor)
|
1348
1360
|
rescue Aws::EC2::Errors::InvalidAMINameDuplicate => e
|
1349
1361
|
MU.log "AMI #{name} already exists, skipping", MU::WARN
|
1350
1362
|
return nil
|
1351
1363
|
end
|
1352
1364
|
ami = resp.image_id
|
1353
|
-
MU::MommaCat.createStandardTags(ami, region: region)
|
1354
|
-
MU::MommaCat.createTag(ami, "Name", name, region: region)
|
1365
|
+
MU::MommaCat.createStandardTags(ami, region: region, credentials: credentials)
|
1366
|
+
MU::MommaCat.createTag(ami, "Name", name, region: region, credentials: credentials)
|
1355
1367
|
MU.log "AMI of #{name} in region #{region}: #{ami}"
|
1356
1368
|
if make_public
|
1357
|
-
MU::Cloud::AWS::Server.waitForAMI(ami, region: region)
|
1358
|
-
MU::Cloud::AWS.ec2(region).modify_image_attribute(
|
1369
|
+
MU::Cloud::AWS::Server.waitForAMI(ami, region: region, credentials: credentials)
|
1370
|
+
MU::Cloud::AWS.ec2(region: region).modify_image_attribute(
|
1359
1371
|
image_id: ami,
|
1360
1372
|
launch_permission: {add: [{group: "all"}]},
|
1361
1373
|
attribute: "launchPermission"
|
@@ -1364,12 +1376,12 @@ module MU
|
|
1364
1376
|
copythreads = []
|
1365
1377
|
if !copy_to_regions.nil? and copy_to_regions.size > 0
|
1366
1378
|
parent_thread_id = Thread.current.object_id
|
1367
|
-
MU::Cloud::AWS::Server.waitForAMI(ami, region: region) if !make_public
|
1379
|
+
MU::Cloud::AWS::Server.waitForAMI(ami, region: region, credentials: credentials) if !make_public
|
1368
1380
|
copy_to_regions.each { |r|
|
1369
1381
|
next if r == region
|
1370
1382
|
copythreads << Thread.new {
|
1371
1383
|
MU.dupGlobals(parent_thread_id)
|
1372
|
-
copy = MU::Cloud::AWS.ec2(r).copy_image(
|
1384
|
+
copy = MU::Cloud::AWS.ec2(region: r).copy_image(
|
1373
1385
|
source_region: region,
|
1374
1386
|
source_image_id: ami,
|
1375
1387
|
name: name,
|
@@ -1378,15 +1390,15 @@ module MU
|
|
1378
1390
|
MU.log "Initiated copy of #{ami} from #{region} to #{r}: #{copy.image_id}"
|
1379
1391
|
|
1380
1392
|
MU::MommaCat.createStandardTags(copy.image_id, region: r)
|
1381
|
-
MU::MommaCat.createTag(copy.image_id, "Name", name, region: r)
|
1393
|
+
MU::MommaCat.createTag(copy.image_id, "Name", name, region: r, credentials: credentials)
|
1382
1394
|
if !tags.nil?
|
1383
1395
|
tags.each { |tag|
|
1384
|
-
MU::MommaCat.createTag(instance.instance_id, tag['key'], tag['value'], region: r)
|
1396
|
+
MU::MommaCat.createTag(instance.instance_id, tag['key'], tag['value'], region: r, credentials: credentials)
|
1385
1397
|
}
|
1386
1398
|
end
|
1387
|
-
MU::Cloud::AWS::Server.waitForAMI(copy.image_id, region: r)
|
1399
|
+
MU::Cloud::AWS::Server.waitForAMI(copy.image_id, region: r, credentials: credentials)
|
1388
1400
|
if make_public
|
1389
|
-
MU::Cloud::AWS.ec2(r).modify_image_attribute(
|
1401
|
+
MU::Cloud::AWS.ec2(region: r).modify_image_attribute(
|
1390
1402
|
image_id: copy.image_id,
|
1391
1403
|
launch_permission: {add: [{group: "all"}]},
|
1392
1404
|
attribute: "launchPermission"
|
@@ -1408,12 +1420,12 @@ module MU
|
|
1408
1420
|
# flagged as ready.
|
1409
1421
|
# @param image_id [String]: The machine image to wait for.
|
1410
1422
|
# @param region [String]: The cloud provider region
|
1411
|
-
def self.waitForAMI(image_id, region: MU.curRegion)
|
1423
|
+
def self.waitForAMI(image_id, region: MU.curRegion, credentials: nil)
|
1412
1424
|
MU.log "Checking to see if AMI #{image_id} is available", MU::DEBUG
|
1413
1425
|
|
1414
1426
|
retries = 0
|
1415
1427
|
begin
|
1416
|
-
images = MU::Cloud::AWS.ec2(region).describe_images(image_ids: [image_id]).images
|
1428
|
+
images = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_images(image_ids: [image_id]).images
|
1417
1429
|
if images.nil? or images.size == 0
|
1418
1430
|
raise MuError, "No such AMI #{image_id} found"
|
1419
1431
|
end
|
@@ -1497,7 +1509,7 @@ module MU
|
|
1497
1509
|
retries = 0
|
1498
1510
|
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
|
1499
1511
|
begin
|
1500
|
-
MU::Cloud::AWS.ec2(@config['region']).wait_until(:password_data_available, instance_id: @cloud_id) do |waiter|
|
1512
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).wait_until(:password_data_available, instance_id: @cloud_id) do |waiter|
|
1501
1513
|
waiter.max_attempts = 60
|
1502
1514
|
waiter.before_attempt do |attempts|
|
1503
1515
|
MU.log "Waiting for Windows password data to be available for node #{@mu_name}", MU::NOTICE if attempts % 5 == 0
|
@@ -1517,7 +1529,7 @@ module MU
|
|
1517
1529
|
end
|
1518
1530
|
end
|
1519
1531
|
|
1520
|
-
resp = MU::Cloud::AWS.ec2(@config['region']).get_password_data(instance_id: @cloud_id)
|
1532
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).get_password_data(instance_id: @cloud_id)
|
1521
1533
|
encrypted_password = resp.password_data
|
1522
1534
|
|
1523
1535
|
# Note: This is already implemented in the decrypt_windows_password API call
|
@@ -1544,9 +1556,9 @@ module MU
|
|
1544
1556
|
filters << {name: "public-ip", values: [ip]} if ip != nil
|
1545
1557
|
|
1546
1558
|
if filters.size > 0
|
1547
|
-
resp = MU::Cloud::AWS.ec2(region).describe_addresses(filters: filters)
|
1559
|
+
resp = MU::Cloud::AWS.ec2(region: region).describe_addresses(filters: filters)
|
1548
1560
|
else
|
1549
|
-
resp = MU::Cloud::AWS.ec2(region).describe_addresses()
|
1561
|
+
resp = MU::Cloud::AWS.ec2(region: region).describe_addresses()
|
1550
1562
|
end
|
1551
1563
|
resp.addresses.each { |address|
|
1552
1564
|
return address if (address.network_interface_id.nil? || address.network_interface_id.empty?) && !@eips_used.include?(address.public_ip)
|
@@ -1559,10 +1571,10 @@ module MU
|
|
1559
1571
|
end
|
1560
1572
|
end
|
1561
1573
|
if !classic
|
1562
|
-
resp = MU::Cloud::AWS.ec2(region).allocate_address(domain: "vpc")
|
1574
|
+
resp = MU::Cloud::AWS.ec2(region: region).allocate_address(domain: "vpc")
|
1563
1575
|
new_ip = resp.public_ip
|
1564
1576
|
else
|
1565
|
-
new_ip = MU::Cloud::AWS.ec2(region).allocate_address().public_ip
|
1577
|
+
new_ip = MU::Cloud::AWS.ec2(region: region).allocate_address().public_ip
|
1566
1578
|
end
|
1567
1579
|
filters = [{name: "public-ip", values: [new_ip]}]
|
1568
1580
|
if resp.domain
|
@@ -1578,7 +1590,7 @@ module MU
|
|
1578
1590
|
begin
|
1579
1591
|
begin
|
1580
1592
|
sleep 5
|
1581
|
-
resp = MU::Cloud::AWS.ec2(region).describe_addresses(
|
1593
|
+
resp = MU::Cloud::AWS.ec2(region: region).describe_addresses(
|
1582
1594
|
filters: filters
|
1583
1595
|
)
|
1584
1596
|
addr = resp.addresses.first
|
@@ -1602,7 +1614,7 @@ module MU
|
|
1602
1614
|
return true
|
1603
1615
|
end
|
1604
1616
|
az = nil
|
1605
|
-
MU::Cloud::AWS.ec2(@config['region']).describe_instances(
|
1617
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_instances(
|
1606
1618
|
instance_ids: [@cloud_id]
|
1607
1619
|
).reservations.each { |resp|
|
1608
1620
|
if !resp.nil? and !resp.instances.nil?
|
@@ -1618,14 +1630,14 @@ module MU
|
|
1618
1630
|
end
|
1619
1631
|
}
|
1620
1632
|
MU.log "Creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
|
1621
|
-
creation = MU::Cloud::AWS.ec2(@config['region']).create_volume(
|
1633
|
+
creation = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_volume(
|
1622
1634
|
availability_zone: az,
|
1623
1635
|
size: size,
|
1624
1636
|
volume_type: type
|
1625
1637
|
)
|
1626
1638
|
begin
|
1627
1639
|
sleep 3
|
1628
|
-
creation = MU::Cloud::AWS.ec2(@config['region']).describe_volumes(volume_ids: [creation.volume_id]).volumes.first
|
1640
|
+
creation = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_volumes(volume_ids: [creation.volume_id]).volumes.first
|
1629
1641
|
if !["creating", "available"].include?(creation.state)
|
1630
1642
|
raise MuError, "Saw state '#{creation.state}' while creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
|
1631
1643
|
end
|
@@ -1633,12 +1645,12 @@ module MU
|
|
1633
1645
|
|
1634
1646
|
if @deploy
|
1635
1647
|
MU::MommaCat.listStandardTags.each_pair { |key, value|
|
1636
|
-
MU::MommaCat.createTag(creation.volume_id, key, value, region: @config['region'])
|
1648
|
+
MU::MommaCat.createTag(creation.volume_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
1637
1649
|
}
|
1638
|
-
MU::MommaCat.createTag(creation.volume_id, "Name", "#{MU.deploy_id}-#{@config["name"].upcase}-#{dev.upcase}", region: @config['region'])
|
1650
|
+
MU::MommaCat.createTag(creation.volume_id, "Name", "#{MU.deploy_id}-#{@config["name"].upcase}-#{dev.upcase}", region: @config['region'], credentials: @config['credentials'])
|
1639
1651
|
end
|
1640
1652
|
|
1641
|
-
attachment = MU::Cloud::AWS.ec2(@config['region']).attach_volume(
|
1653
|
+
attachment = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).attach_volume(
|
1642
1654
|
device: dev,
|
1643
1655
|
instance_id: @cloud_id,
|
1644
1656
|
volume_id: creation.volume_id
|
@@ -1646,7 +1658,7 @@ module MU
|
|
1646
1658
|
|
1647
1659
|
begin
|
1648
1660
|
sleep 3
|
1649
|
-
attachment = MU::Cloud::AWS.ec2(@config['region']).describe_volumes(volume_ids: [attachment.volume_id]).volumes.first.attachments.first
|
1661
|
+
attachment = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_volumes(volume_ids: [attachment.volume_id]).volumes.first.attachments.first
|
1650
1662
|
if !["attaching", "attached"].include?(attachment.state)
|
1651
1663
|
raise MuError, "Saw state '#{creation.state}' while creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
|
1652
1664
|
end
|
@@ -1662,7 +1674,7 @@ module MU
|
|
1662
1674
|
return true
|
1663
1675
|
end
|
1664
1676
|
begin
|
1665
|
-
MU::Cloud::AWS.ec2(@config['region']).describe_instances(
|
1677
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_instances(
|
1666
1678
|
instance_ids: [@cloud_id]
|
1667
1679
|
).reservations.each { |resp|
|
1668
1680
|
if !resp.nil? and !resp.instances.nil?
|
@@ -1694,7 +1706,7 @@ module MU
|
|
1694
1706
|
@eip_semaphore.synchronize {
|
1695
1707
|
if !ip.nil?
|
1696
1708
|
filters = [{name: "public-ip", values: [ip]}]
|
1697
|
-
resp = MU::Cloud::AWS.ec2(region).describe_addresses(filters: filters)
|
1709
|
+
resp = MU::Cloud::AWS.ec2(region: region).describe_addresses(filters: filters)
|
1698
1710
|
if @eips_used.include?(ip)
|
1699
1711
|
is_free = false
|
1700
1712
|
resp.addresses.each { |address|
|
@@ -1726,12 +1738,12 @@ module MU
|
|
1726
1738
|
attempts = 0
|
1727
1739
|
begin
|
1728
1740
|
if classic
|
1729
|
-
resp = MU::Cloud::AWS.ec2(region).associate_address(
|
1741
|
+
resp = MU::Cloud::AWS.ec2(region: region).associate_address(
|
1730
1742
|
instance_id: instance_id,
|
1731
1743
|
public_ip: elastic_ip.public_ip
|
1732
1744
|
)
|
1733
1745
|
else
|
1734
|
-
resp = MU::Cloud::AWS.ec2(region).associate_address(
|
1746
|
+
resp = MU::Cloud::AWS.ec2(region: region).associate_address(
|
1735
1747
|
instance_id: instance_id,
|
1736
1748
|
allocation_id: elastic_ip.allocation_id,
|
1737
1749
|
allow_reassociation: false
|
@@ -1747,7 +1759,7 @@ module MU
|
|
1747
1759
|
raise MuError "#{e.message} associating #{elastic_ip.allocation_id} with #{instance_id}"
|
1748
1760
|
rescue Aws::EC2::Errors::ResourceAlreadyAssociated => e
|
1749
1761
|
# A previous association attempt may have succeeded, albeit slowly.
|
1750
|
-
resp = MU::Cloud::AWS.ec2(region).describe_addresses(
|
1762
|
+
resp = MU::Cloud::AWS.ec2(region: region).describe_addresses(
|
1751
1763
|
allocation_ids: [elastic_ip.allocation_id]
|
1752
1764
|
)
|
1753
1765
|
first_addr = resp.addresses.first
|
@@ -1759,14 +1771,14 @@ module MU
|
|
1759
1771
|
end
|
1760
1772
|
end
|
1761
1773
|
|
1762
|
-
instance = MU::Cloud::AWS.ec2(region).describe_instances(instance_ids: [instance_id]).reservations.first.instances.first
|
1774
|
+
instance = MU::Cloud::AWS.ec2(region: region).describe_instances(instance_ids: [instance_id]).reservations.first.instances.first
|
1763
1775
|
waited = false
|
1764
1776
|
if instance.public_ip_address != elastic_ip.public_ip
|
1765
1777
|
waited = true
|
1766
1778
|
begin
|
1767
1779
|
sleep 10
|
1768
1780
|
MU.log "Waiting for Elastic IP association of #{elastic_ip.public_ip} to #{instance_id} to take effect", MU::NOTICE
|
1769
|
-
instance = MU::Cloud::AWS.ec2(region).describe_instances(instance_ids: [instance_id]).reservations.first.instances.first
|
1781
|
+
instance = MU::Cloud::AWS.ec2(region: region).describe_instances(instance_ids: [instance_id]).reservations.first.instances.first
|
1770
1782
|
end while instance.public_ip_address != elastic_ip.public_ip
|
1771
1783
|
end
|
1772
1784
|
|
@@ -1775,12 +1787,21 @@ module MU
|
|
1775
1787
|
return elastic_ip.public_ip
|
1776
1788
|
end
|
1777
1789
|
|
1790
|
+
# Does this resource type exist as a global (cloud-wide) artifact, or
|
1791
|
+
# is it localized to a region/zone?
|
1792
|
+
# @return [Boolean]
|
1793
|
+
def self.isGlobal?
|
1794
|
+
false
|
1795
|
+
end
|
1796
|
+
|
1778
1797
|
# Remove all instances associated with the currently loaded deployment. Also cleans up associated volumes, droppings in the MU master's /etc/hosts and ~/.ssh, and in whatever Groomer was used.
|
1779
1798
|
# @param noop [Boolean]: If true, will only print what would be done
|
1780
1799
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
1781
1800
|
# @param region [String]: The cloud provider region
|
1782
1801
|
# @return [void]
|
1783
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion,
|
1802
|
+
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
1803
|
+
onlycloud = flags["onlycloud"]
|
1804
|
+
skipsnapshots = flags["skipsnapshots"]
|
1784
1805
|
tagfilters = [
|
1785
1806
|
{name: "tag:MU-ID", values: [MU.deploy_id]}
|
1786
1807
|
]
|
@@ -1794,7 +1815,7 @@ module MU
|
|
1794
1815
|
# Build a list of instances we need to clean up. We guard against
|
1795
1816
|
# accidental deletion here by requiring someone to have hand-terminated
|
1796
1817
|
# these, by default.
|
1797
|
-
resp = MU::Cloud::AWS.ec2(region).describe_instances(
|
1818
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_instances(
|
1798
1819
|
filters: tagfilters
|
1799
1820
|
)
|
1800
1821
|
|
@@ -1817,18 +1838,18 @@ module MU
|
|
1817
1838
|
threads << Thread.new(instance) { |myinstance|
|
1818
1839
|
MU.dupGlobals(parent_thread_id)
|
1819
1840
|
Thread.abort_on_exception = true
|
1820
|
-
MU::Cloud::AWS::Server.terminateInstance(id: myinstance.instance_id, noop: noop, onlycloud: onlycloud, region: region, deploy_id: MU.deploy_id)
|
1841
|
+
MU::Cloud::AWS::Server.terminateInstance(id: myinstance.instance_id, noop: noop, onlycloud: onlycloud, region: region, deploy_id: MU.deploy_id, credentials: credentials)
|
1821
1842
|
}
|
1822
1843
|
}
|
1823
1844
|
|
1824
|
-
resp = MU::Cloud::AWS.ec2(region).describe_volumes(
|
1845
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_volumes(
|
1825
1846
|
filters: tagfilters
|
1826
1847
|
)
|
1827
1848
|
resp.data.volumes.each { |volume|
|
1828
1849
|
threads << Thread.new(volume) { |myvolume|
|
1829
1850
|
MU.dupGlobals(parent_thread_id)
|
1830
1851
|
Thread.abort_on_exception = true
|
1831
|
-
MU::Cloud::AWS::Server.delete_volume(myvolume, noop, skipsnapshots)
|
1852
|
+
MU::Cloud::AWS::Server.delete_volume(myvolume, noop, skipsnapshots, credentials: credentials)
|
1832
1853
|
}
|
1833
1854
|
}
|
1834
1855
|
|
@@ -1843,12 +1864,12 @@ module MU
|
|
1843
1864
|
# @param id [String]: The cloud provider's identifier for the instance, to use if the full description is not available.
|
1844
1865
|
# @param region [String]: The cloud provider region
|
1845
1866
|
# @return [void]
|
1846
|
-
def self.terminateInstance(instance: nil, noop: false, id: nil, onlycloud: false, region: MU.curRegion, deploy_id: MU.deploy_id, mu_name: nil)
|
1867
|
+
def self.terminateInstance(instance: nil, noop: false, id: nil, onlycloud: false, region: MU.curRegion, deploy_id: MU.deploy_id, mu_name: nil, credentials: nil)
|
1847
1868
|
ips = Array.new
|
1848
1869
|
if !instance
|
1849
1870
|
if id
|
1850
1871
|
begin
|
1851
|
-
resp = MU::Cloud::AWS.ec2(region).describe_instances(instance_ids: [id])
|
1872
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_instances(instance_ids: [id])
|
1852
1873
|
rescue Aws::EC2::Errors::InvalidInstanceIDNotFound => e
|
1853
1874
|
MU.log "Instance #{id} no longer exists", MU::WARN
|
1854
1875
|
end
|
@@ -1880,26 +1901,26 @@ module MU
|
|
1880
1901
|
).first
|
1881
1902
|
|
1882
1903
|
begin
|
1883
|
-
MU::Cloud::AWS.ec2(region).describe_instances(instance_ids: [id])
|
1904
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_instances(instance_ids: [id])
|
1884
1905
|
rescue Aws::EC2::Errors::InvalidInstanceIDNotFound => e
|
1885
1906
|
MU.log "Instance #{id} no longer exists", MU::DEBUG
|
1886
1907
|
end
|
1887
1908
|
|
1888
|
-
if !server_obj.nil? and MU::Cloud::AWS.hosted and !MU::Cloud::AWS.isGovCloud?
|
1909
|
+
if !server_obj.nil? and MU::Cloud::AWS.hosted? and !MU::Cloud::AWS.isGovCloud?
|
1889
1910
|
# DNS cleanup is now done in MU::Cloud::DNSZone. Keeping this for now
|
1890
1911
|
cleaned_dns = false
|
1891
1912
|
mu_name = server_obj.mu_name
|
1892
|
-
mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu").values.first
|
1913
|
+
mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu", credentials: credentials).values.first
|
1893
1914
|
if !mu_zone.nil?
|
1894
1915
|
zone_rrsets = []
|
1895
|
-
rrsets = MU::Cloud::AWS.route53(
|
1916
|
+
rrsets = MU::Cloud::AWS.route53(credentials: credentials).list_resource_record_sets(hosted_zone_id: mu_zone.id)
|
1896
1917
|
rrsets.resource_record_sets.each{ |record|
|
1897
1918
|
zone_rrsets << record
|
1898
1919
|
}
|
1899
1920
|
|
1900
1921
|
# AWS API returns a maximum of 100 results. DNS zones are likely to have more than 100 records, lets page and make sure we grab all records in a given zone
|
1901
1922
|
while rrsets.next_record_name && rrsets.next_record_type
|
1902
|
-
rrsets = MU::Cloud::AWS.route53(
|
1923
|
+
rrsets = MU::Cloud::AWS.route53(credentials: credentials).list_resource_record_sets(hosted_zone_id: mu_zone.id, start_record_name: rrsets.next_record_name, start_record_type: rrsets.next_record_type)
|
1903
1924
|
rrsets.resource_record_sets.each{ |record|
|
1904
1925
|
zone_rrsets << record
|
1905
1926
|
}
|
@@ -2002,14 +2023,14 @@ module MU
|
|
2002
2023
|
MU.log "Terminating #{instance.instance_id} (#{name}) #{noop}"
|
2003
2024
|
if !noop
|
2004
2025
|
begin
|
2005
|
-
MU::Cloud::AWS.ec2(region).modify_instance_attribute(
|
2026
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).modify_instance_attribute(
|
2006
2027
|
instance_id: instance.instance_id,
|
2007
2028
|
disable_api_termination: {value: false}
|
2008
2029
|
)
|
2009
|
-
MU::Cloud::AWS.ec2(region).terminate_instances(instance_ids: [instance.instance_id])
|
2030
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).terminate_instances(instance_ids: [instance.instance_id])
|
2010
2031
|
# Small race window here with the state changing from under us
|
2011
2032
|
rescue Aws::EC2::Errors::IncorrectInstanceState => e
|
2012
|
-
resp = MU::Cloud::AWS.ec2(region).describe_instances(instance_ids: [id])
|
2033
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_instances(instance_ids: [id])
|
2013
2034
|
if !resp.nil? and !resp.reservations.nil? and !resp.reservations.first.nil?
|
2014
2035
|
instance = resp.reservations.first.instances.first
|
2015
2036
|
if !instance.nil? and instance.state.name != "terminated" and instance.state.name != "terminating"
|
@@ -2026,7 +2047,7 @@ module MU
|
|
2026
2047
|
end
|
2027
2048
|
while instance.state.name != "terminated" and !noop
|
2028
2049
|
sleep 30
|
2029
|
-
instance_response = MU::Cloud::AWS.ec2(region).describe_instances(instance_ids: [instance.instance_id])
|
2050
|
+
instance_response = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_instances(instance_ids: [instance.instance_id])
|
2030
2051
|
instance = instance_response.reservations.first.instances.first
|
2031
2052
|
end
|
2032
2053
|
MU.log "#{instance.instance_id} (#{name}) terminated" if !noop
|
@@ -2156,6 +2177,7 @@ module MU
|
|
2156
2177
|
else
|
2157
2178
|
role = {
|
2158
2179
|
"name" => server["name"],
|
2180
|
+
"credentials" => server["credentials"],
|
2159
2181
|
"can_assume" => [
|
2160
2182
|
{
|
2161
2183
|
"entity_id" => "ec2.amazonaws.com",
|
@@ -2241,9 +2263,9 @@ module MU
|
|
2241
2263
|
# @param id [String]: The cloud provider's identifier for the volume, to use if the full description is not available.
|
2242
2264
|
# @param region [String]: The cloud provider region
|
2243
2265
|
# @return [void]
|
2244
|
-
def self.delete_volume(volume, noop, skipsnapshots, id: nil, region: MU.curRegion)
|
2266
|
+
def self.delete_volume(volume, noop, skipsnapshots, id: nil, region: MU.curRegion, credentials: nil)
|
2245
2267
|
if !volume.nil?
|
2246
|
-
resp = MU::Cloud::AWS.ec2(region).describe_volumes(volume_ids: [volume.volume_id])
|
2268
|
+
resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_volumes(volume_ids: [volume.volume_id])
|
2247
2269
|
volume = resp.data.volumes.first
|
2248
2270
|
end
|
2249
2271
|
name = ""
|
@@ -2260,15 +2282,25 @@ module MU
|
|
2260
2282
|
desc = "#{MU.deploy_id}-MUfinal"
|
2261
2283
|
end
|
2262
2284
|
|
2263
|
-
|
2285
|
+
begin
|
2286
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).create_snapshot(
|
2264
2287
|
volume_id: volume.volume_id,
|
2265
2288
|
description: desc
|
2266
|
-
|
2289
|
+
)
|
2290
|
+
rescue Aws::EC2::Errors::IncorrectState => e
|
2291
|
+
if e.message.match(/'deleting'/)
|
2292
|
+
MU.log "Cannot snapshot volume '#{name}', is already being deleted", MU::WARN
|
2293
|
+
end
|
2294
|
+
end
|
2267
2295
|
end
|
2268
2296
|
|
2269
2297
|
retries = 0
|
2270
2298
|
begin
|
2271
|
-
MU::Cloud::AWS.ec2(region).delete_volume(volume_id: volume.volume_id)
|
2299
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).delete_volume(volume_id: volume.volume_id)
|
2300
|
+
rescue Aws::EC2::Errors::IncorrectState => e
|
2301
|
+
MU.log "Volume #{volume.volume_id} (#{name}) in incorrect state (#{e.message}), will retry", MU::WARN
|
2302
|
+
sleep 30
|
2303
|
+
retry
|
2272
2304
|
rescue Aws::EC2::Errors::InvalidVolumeNotFound
|
2273
2305
|
MU.log "Volume #{volume.volume_id} (#{name}) disappeared before I could remove it!", MU::WARN
|
2274
2306
|
rescue Aws::EC2::Errors::VolumeInUse
|