cloud-mu 3.1.6 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/bin/mu-adopt +15 -12
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +37 -1
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -1
- data/bin/mu-run-tests +37 -12
- data/cloud-mu.gemspec +4 -4
- data/cookbooks/mu-tools/attributes/default.rb +7 -0
- data/cookbooks/mu-tools/libraries/helper.rb +87 -3
- data/cookbooks/mu-tools/recipes/apply_security.rb +39 -23
- data/cookbooks/mu-tools/recipes/aws_api.rb +13 -0
- data/cookbooks/mu-tools/recipes/google_api.rb +4 -0
- data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
- data/cookbooks/mu-tools/resources/disk.rb +33 -12
- data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
- data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
- data/extras/clean-stock-amis +10 -2
- data/extras/generate-stock-images +7 -3
- 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/modules/mommacat.ru +2 -2
- data/modules/mu.rb +84 -97
- data/modules/mu/adoption.rb +359 -59
- data/modules/mu/cleanup.rb +67 -44
- data/modules/mu/cloud.rb +108 -1754
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +44 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +929 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +178 -0
- data/modules/mu/config.rb +122 -80
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +32 -3
- data/modules/mu/config/cache_cluster.rb +2 -2
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/collection.rb +1 -1
- data/modules/mu/config/container_cluster.rb +2 -2
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +5 -4
- data/modules/mu/config/doc_helpers.rb +4 -5
- data/modules/mu/config/endpoint.rb +2 -1
- data/modules/mu/config/firewall_rule.rb +3 -19
- data/modules/mu/config/folder.rb +1 -1
- data/modules/mu/config/function.rb +17 -8
- data/modules/mu/config/group.rb +1 -1
- data/modules/mu/config/habitat.rb +1 -1
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/loadbalancer.rb +57 -11
- data/modules/mu/config/log.rb +1 -1
- data/modules/mu/config/msg_queue.rb +1 -1
- data/modules/mu/config/nosqldb.rb +1 -1
- data/modules/mu/config/notifier.rb +8 -19
- data/modules/mu/config/ref.rb +81 -9
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +30 -34
- data/modules/mu/config/search_domain.rb +1 -1
- data/modules/mu/config/server.rb +5 -13
- data/modules/mu/config/server_pool.rb +3 -7
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +10 -0
- data/modules/mu/config/user.rb +1 -1
- data/modules/mu/config/vpc.rb +13 -17
- data/modules/mu/defaults/AWS.yaml +106 -106
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +33 -19
- data/modules/mu/groomer.rb +15 -0
- data/modules/mu/groomers/chef.rb +3 -0
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +22 -1
- data/modules/mu/mommacat.rb +71 -26
- data/modules/mu/mommacat/daemon.rb +23 -14
- data/modules/mu/mommacat/naming.rb +82 -3
- data/modules/mu/mommacat/search.rb +59 -16
- data/modules/mu/mommacat/storage.rb +119 -48
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +248 -62
- data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +65 -63
- data/modules/mu/providers/aws/database.rb +1747 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
- data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
- data/modules/mu/{clouds → providers}/aws/function.rb +291 -133
- data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
- data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
- data/modules/mu/providers/aws/job.rb +469 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +77 -47
- data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
- data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -78
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
- data/modules/mu/{clouds → providers}/aws/server.rb +120 -145
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
- data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/vpc.rb +141 -73
- data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
- data/modules/mu/{clouds → providers}/azure.rb +4 -1
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
- data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
- data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
- data/modules/mu/{clouds → providers}/cloudformation.rb +1 -1
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +15 -6
- data/modules/mu/{clouds → providers}/google/bucket.rb +2 -2
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +29 -14
- data/modules/mu/{clouds → providers}/google/database.rb +2 -9
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
- data/modules/mu/{clouds → providers}/google/function.rb +4 -4
- data/modules/mu/{clouds → providers}/google/group.rb +9 -17
- data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +2 -2
- data/modules/mu/{clouds → providers}/google/role.rb +46 -35
- data/modules/mu/{clouds → providers}/google/server.rb +26 -11
- data/modules/mu/{clouds → providers}/google/server_pool.rb +11 -11
- data/modules/mu/{clouds → providers}/google/user.rb +32 -22
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +38 -3
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/centos6.yaml +15 -0
- data/modules/tests/centos7.yaml +15 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +2 -2
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +2 -2
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +126 -98
- data/modules/mu/clouds/aws/database.rb +0 -1974
- data/modules/mu/clouds/aws/endpoint.rb +0 -596
|
@@ -22,9 +22,9 @@ module MU
|
|
|
22
22
|
# @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
|
|
23
23
|
def initialize(**args)
|
|
24
24
|
super
|
|
25
|
-
if @
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
describe if @mu_name and !@deploydata
|
|
26
|
+
@cloud_id ||= @deploydata['domain_name'] if @deploydata
|
|
27
|
+
|
|
28
28
|
@mu_name ||= @deploy.getResourceName(@config["name"])
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -35,7 +35,8 @@ module MU
|
|
|
35
35
|
params = genParams
|
|
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: @config['region'], credentials: @credentials).create_elasticsearch_domain(params).domain_status
|
|
39
40
|
|
|
40
41
|
tagDomain
|
|
41
42
|
|
|
@@ -44,17 +45,18 @@ module MU
|
|
|
44
45
|
# Called automatically by {MU::Deploy#createResources}
|
|
45
46
|
def groom
|
|
46
47
|
tagDomain
|
|
47
|
-
@config['domain_name'] ||= @
|
|
48
|
+
@config['domain_name'] ||= @cloud_id
|
|
48
49
|
params = genParams(cloud_desc) # get parameters that would change only
|
|
49
50
|
|
|
50
51
|
if params.size > 1
|
|
51
52
|
waitWhileProcessing # wait until the create finishes, if still going
|
|
52
53
|
|
|
53
54
|
MU.log "Updating ElasticSearch domain #{@config['domain_name']}", MU::NOTICE, details: params
|
|
54
|
-
MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @
|
|
55
|
+
MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @credentials).update_elasticsearch_domain_config(params)
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
waitWhileProcessing # don't return until creation/updating is complete
|
|
59
|
+
MU.log "Search Domain #{@config['name']}: #{cloud_desc.endpoint}", MU::SUMMARY
|
|
58
60
|
end
|
|
59
61
|
|
|
60
62
|
@cloud_desc_cache = nil
|
|
@@ -63,31 +65,30 @@ module MU
|
|
|
63
65
|
# our druthers.
|
|
64
66
|
def cloud_desc(use_cache: true)
|
|
65
67
|
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
|
66
|
-
@
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
@cloud_id ||= @config['domain_name']
|
|
69
|
+
return nil if !@cloud_id
|
|
70
|
+
MU.retrier([::Aws::ElasticsearchService::Errors::ResourceNotFoundException], wait: 10, max: 12) {
|
|
71
|
+
@cloud_desc_cache = MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @credentials).describe_elasticsearch_domain(
|
|
72
|
+
domain_name: @cloud_id
|
|
69
73
|
).domain_status
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
domain_name: @deploydata['domain_name']
|
|
73
|
-
).domain_status
|
|
74
|
-
else
|
|
75
|
-
raise MuError, "#{@mu_name} can't find its official Elasticsearch domain name!"
|
|
76
|
-
end
|
|
74
|
+
}
|
|
75
|
+
|
|
77
76
|
@cloud_desc_cache
|
|
78
77
|
end
|
|
79
78
|
|
|
80
79
|
# Canonical Amazon Resource Number for this resource
|
|
81
80
|
# @return [String]
|
|
82
81
|
def arn
|
|
83
|
-
cloud_desc
|
|
82
|
+
return nil if !cloud_desc
|
|
83
|
+
cloud_desc.arn.dup
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
# Return the metadata for this SearchDomain rule
|
|
87
87
|
# @return [Hash]
|
|
88
88
|
def notify
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
return nil if !cloud_desc(use_cache: false)
|
|
90
|
+
deploy_struct = MU.structToHash(cloud_desc, stringify_keys: true)
|
|
91
|
+
tags = MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @credentials).list_tags(arn: arn).tag_list
|
|
91
92
|
deploy_struct['tags'] = tags.map { |t| { t.key => t.value } }
|
|
92
93
|
if deploy_struct['endpoint']
|
|
93
94
|
deploy_struct['kibana'] = deploy_struct['endpoint']+"/_plugin/kibana/"
|
|
@@ -119,7 +120,7 @@ module MU
|
|
|
119
120
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
120
121
|
# @param region [String]: The cloud provider region
|
|
121
122
|
# @return [void]
|
|
122
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
123
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
123
124
|
MU.log "AWS::SearchDomain.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
124
125
|
|
|
125
126
|
list = MU::Cloud::AWS.elasticsearch(region: region, credentials: credentials).list_domain_names
|
|
@@ -135,7 +136,7 @@ module MU
|
|
|
135
136
|
deploy_match = false
|
|
136
137
|
master_match = false
|
|
137
138
|
tags.tag_list.each { |tag|
|
|
138
|
-
if tag.key == "MU-ID" and tag.value ==
|
|
139
|
+
if tag.key == "MU-ID" and tag.value == deploy_id
|
|
139
140
|
deploy_match = true
|
|
140
141
|
elsif tag.key == "MU-MASTER-IP" and tag.value == MU.mu_public_ip
|
|
141
142
|
master_match = true
|
|
@@ -156,8 +157,8 @@ module MU
|
|
|
156
157
|
begin
|
|
157
158
|
resp = MU::Cloud::AWS.iam(credentials: credentials).list_roles(marker: marker)
|
|
158
159
|
resp.roles.each{ |role|
|
|
159
|
-
# XXX Maybe we should have a more generic way to delete IAM profiles and policies. The call itself should be moved from MU::Cloud
|
|
160
|
-
# MU::Cloud
|
|
160
|
+
# XXX Maybe we should have a more generic way to delete IAM profiles and policies. The call itself should be moved from MU::Cloud.resourceClass("AWS", "Server").
|
|
161
|
+
# MU::Cloud.resourceClass("AWS", "Server").removeIAMProfile(role.role_name) if role.role_name.match(/^#{Regexp.quote(deploy_id)}/)
|
|
161
162
|
}
|
|
162
163
|
marker = resp.marker
|
|
163
164
|
end while resp.is_truncated
|
|
@@ -191,6 +192,96 @@ module MU
|
|
|
191
192
|
found
|
|
192
193
|
end
|
|
193
194
|
|
|
195
|
+
# Reverse-map our cloud description into a runnable config hash.
|
|
196
|
+
# We assume that any values we have in +@config+ are placeholders, and
|
|
197
|
+
# calculate our own accordingly based on what's live in the cloud.
|
|
198
|
+
def toKitten(**_args)
|
|
199
|
+
bok = {
|
|
200
|
+
"cloud" => "AWS",
|
|
201
|
+
"credentials" => @credentials,
|
|
202
|
+
"cloud_id" => @cloud_id,
|
|
203
|
+
"region" => @config['region']
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if !cloud_desc
|
|
207
|
+
MU.log "toKitten failed to load a cloud_desc from #{@cloud_id}", MU::ERR, details: @config
|
|
208
|
+
return nil
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
bok['name'] = cloud_desc.domain_name
|
|
212
|
+
bok['elasticsearch_version'] = cloud_desc.elasticsearch_version
|
|
213
|
+
bok['instance_count'] = cloud_desc.elasticsearch_cluster_config.instance_count
|
|
214
|
+
bok['instance_type'] = cloud_desc.elasticsearch_cluster_config.instance_type
|
|
215
|
+
bok['zone_aware'] = cloud_desc.elasticsearch_cluster_config.zone_awareness_enabled
|
|
216
|
+
|
|
217
|
+
if cloud_desc.elasticsearch_cluster_config.dedicated_master_enabled
|
|
218
|
+
bok['dedicated_masters'] = cloud_desc.elasticsearch_cluster_config.dedicated_master_count
|
|
219
|
+
bok['master_instance_type'] = cloud_desc.elasticsearch_cluster_config.dedicated_master_type
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
if cloud_desc.access_policies and !cloud_desc.access_policies.empty?
|
|
223
|
+
bok['access_policies'] = JSON.parse(cloud_desc.access_policies)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
if cloud_desc.advanced_options and !cloud_desc.advanced_options.empty?
|
|
227
|
+
bok['advanced_options'] = cloud_desc.advanced_options
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
bok['ebs_size'] = cloud_desc.ebs_options.volume_size
|
|
231
|
+
bok['ebs_type'] = cloud_desc.ebs_options.volume_type
|
|
232
|
+
bok['ebs_iops'] = cloud_desc.ebs_options.iops if cloud_desc.ebs_options.iops
|
|
233
|
+
|
|
234
|
+
if cloud_desc.snapshot_options and cloud_desc.snapshot_options.automated_snapshot_start_hour
|
|
235
|
+
bok['snapshot_hour'] = cloud_desc.snapshot_options.automated_snapshot_start_hour
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
if cloud_desc.cognito_options.user_pool_id and
|
|
239
|
+
cloud_desc.cognito_options.identity_pool_id
|
|
240
|
+
bok['user_pool_id'] = cloud_desc.cognito_options.user_pool_id
|
|
241
|
+
bok['identity_pool_id'] = cloud_desc.cognito_options.identity_pool_id
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
tags = MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @credentials).list_tags(arn: cloud_desc.arn).tag_list
|
|
245
|
+
if tags and !tags.empty?
|
|
246
|
+
bok['tags'] = MU.structToHash(tags)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
if cloud_desc.vpc_options
|
|
250
|
+
bok['vpc'] = MU::Config::Ref.get(
|
|
251
|
+
id: cloud_desc.vpc_options.vpc_id,
|
|
252
|
+
cloud: "AWS",
|
|
253
|
+
credentials: @credentials,
|
|
254
|
+
type: "vpcs",
|
|
255
|
+
region: @config['region'],
|
|
256
|
+
subnets: cloud_desc.vpc_options.subnet_ids.map { |s| { "subnet_id" => s } }
|
|
257
|
+
)
|
|
258
|
+
if cloud_desc.vpc_options.security_group_ids and
|
|
259
|
+
!cloud_desc.vpc_options.security_group_ids.empty?
|
|
260
|
+
bok['add_firewall_rules'] = cloud_desc.vpc_options.security_group_ids.map { |sg|
|
|
261
|
+
MU::Config::Ref.get(
|
|
262
|
+
id: sg,
|
|
263
|
+
cloud: "AWS",
|
|
264
|
+
credentials: @credentials,
|
|
265
|
+
region: @config['region'],
|
|
266
|
+
type: "firewall_rules",
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
if cloud_desc.log_publishing_options
|
|
273
|
+
# XXX this is primitive... there are multiple other log types now,
|
|
274
|
+
# and this should be a Ref blob, not a flat string
|
|
275
|
+
cloud_desc.log_publishing_options.each_pair { |type, whither|
|
|
276
|
+
if type == "SEARCH_SLOW_LOGS"
|
|
277
|
+
bok['slow_logs'] = whither.cloud_watch_logs_log_group_arn
|
|
278
|
+
end
|
|
279
|
+
}
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
bok
|
|
283
|
+
end
|
|
284
|
+
|
|
194
285
|
# Cloud-specific configuration properties.
|
|
195
286
|
# @param _config [MU::Config]: The calling MU::Config object
|
|
196
287
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
@@ -200,7 +291,7 @@ module MU
|
|
|
200
291
|
versions = begin
|
|
201
292
|
MU::Cloud::AWS.elasticsearch.list_elasticsearch_versions.elasticsearch_versions
|
|
202
293
|
rescue MuError
|
|
203
|
-
["7.1", "6.8", "6.7", "6.5", "6.4", "6.3", "6.2", "6.0", "5.6"]
|
|
294
|
+
["7.4", "7.1", "6.8", "6.7", "6.5", "6.4", "6.3", "6.2", "6.0", "5.6"]
|
|
204
295
|
end
|
|
205
296
|
instance_types = begin
|
|
206
297
|
MU::Cloud::AWS.elasticsearch.list_elasticsearch_instance_types(
|
|
@@ -215,6 +306,8 @@ module MU
|
|
|
215
306
|
).elasticsearch_instance_types
|
|
216
307
|
end
|
|
217
308
|
|
|
309
|
+
polschema = MU::Config::Role.schema["properties"]["policies"]
|
|
310
|
+
polschema.deep_merge!(MU::Cloud.resourceClass("AWS", "Role").condition_schema)
|
|
218
311
|
|
|
219
312
|
schema = {
|
|
220
313
|
"name" => {
|
|
@@ -236,9 +329,10 @@ module MU
|
|
|
236
329
|
"default" => 0,
|
|
237
330
|
"description" => "Separate, dedicated master node(s), over and above the search instances specified in instance_count."
|
|
238
331
|
},
|
|
332
|
+
"policies" => polschema,
|
|
239
333
|
"access_policies" => {
|
|
240
334
|
"type" => "object",
|
|
241
|
-
"description" => "An IAM policy document for access to ElasticSearch. Our parser expects this to be defined inline like the rest of your YAML/JSON Basket of Kittens, not as raw JSON. For guidance on ElasticSearch IAM capabilities, see: https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-ac.html"
|
|
335
|
+
"description" => "An IAM policy document for access to ElasticSearch (see {policies} for setting complex access policies with runtime dependencies). Our parser expects this to be defined inline like the rest of your YAML/JSON Basket of Kittens, not as raw JSON. For guidance on ElasticSearch IAM capabilities, see: https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-ac.html"
|
|
242
336
|
},
|
|
243
337
|
"master_instance_type" => {
|
|
244
338
|
"type" => "string",
|
|
@@ -246,7 +340,7 @@ module MU
|
|
|
246
340
|
},
|
|
247
341
|
"ebs_type" => {
|
|
248
342
|
"type" => "string",
|
|
249
|
-
"default" => "
|
|
343
|
+
"default" => "gp2",
|
|
250
344
|
"description" => "Type of EBS storage to use for cluster nodes. If 'none' is specified, EBS storage will not be used, but this is only valid for certain instance types.",
|
|
251
345
|
"enum" => ["standard", "gp2", "io1", "none"]
|
|
252
346
|
},
|
|
@@ -378,9 +472,9 @@ module MU
|
|
|
378
472
|
|
|
379
473
|
if dom['slow_logs']
|
|
380
474
|
if configurator.haveLitterMate?(dom['slow_logs'], "log")
|
|
381
|
-
dom
|
|
475
|
+
MU::Config.addDependency(dom, dom['slow_logs'], "log")
|
|
382
476
|
else
|
|
383
|
-
log_group = MU::Cloud
|
|
477
|
+
log_group = MU::Cloud.resourceClass("AWS", "Log").find(cloud_id: dom['slow_logs'], region: dom['region']).values.first
|
|
384
478
|
if !log_group
|
|
385
479
|
MU.log "Specified slow_logs CloudWatch log group '#{dom['slow_logs']}' in SearchDomain '#{dom['name']}' doesn't appear to exist", MU::ERR
|
|
386
480
|
ok = false
|
|
@@ -395,7 +489,7 @@ module MU
|
|
|
395
489
|
"credentials" => dom['credentials']
|
|
396
490
|
}
|
|
397
491
|
ok = false if !configurator.insertKitten(log_group, "logs")
|
|
398
|
-
dom
|
|
492
|
+
MU::Config.addDependency(dom, dom['slow_logs'], "log")
|
|
399
493
|
end
|
|
400
494
|
|
|
401
495
|
if dom['advanced_options']
|
|
@@ -456,12 +550,7 @@ module MU
|
|
|
456
550
|
]
|
|
457
551
|
}
|
|
458
552
|
configurator.insertKitten(roledesc, "roles")
|
|
459
|
-
|
|
460
|
-
dom['dependencies'] ||= []
|
|
461
|
-
dom['dependencies'] << {
|
|
462
|
-
"type" => "role",
|
|
463
|
-
"name" => dom['name']+"cognitorole"
|
|
464
|
-
}
|
|
553
|
+
MU::Config.addDependency(dom, dom['name']+"cognitorole", "role")
|
|
465
554
|
end
|
|
466
555
|
|
|
467
556
|
end
|
|
@@ -514,9 +603,51 @@ module MU
|
|
|
514
603
|
params[:snapshot_options][:automated_snapshot_start_hour] = @config['snapshot_hour']
|
|
515
604
|
end
|
|
516
605
|
|
|
517
|
-
if
|
|
518
|
-
#
|
|
519
|
-
|
|
606
|
+
if ext
|
|
607
|
+
# Despite being called access_policies, this parameter actually
|
|
608
|
+
# only accepts one policy. So, we'll munge everything we have
|
|
609
|
+
# together into one policy with multiple Statements.
|
|
610
|
+
policy = nil
|
|
611
|
+
# TODO check against ext.access_policy.options
|
|
612
|
+
|
|
613
|
+
if @config['access_policies']
|
|
614
|
+
policy = @config['access_policies']
|
|
615
|
+
# ensure the "Statement" key is cased in a predictable way
|
|
616
|
+
statement_key = nil
|
|
617
|
+
policy.each_pair { |k, v|
|
|
618
|
+
if k.downcase == "statement" and k != "Statement"
|
|
619
|
+
statement_key = k
|
|
620
|
+
break
|
|
621
|
+
end
|
|
622
|
+
}
|
|
623
|
+
if statement_key
|
|
624
|
+
policy["Statement"] = policy.delete(statement_key)
|
|
625
|
+
end
|
|
626
|
+
if !policy["Statement"].is_a?(Array)
|
|
627
|
+
policy["Statement"] = [policy["Statement"]]
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
if @config['policies']
|
|
632
|
+
@config['policies'].each { |p|
|
|
633
|
+
p['targets'].each { |t|
|
|
634
|
+
if t['path']
|
|
635
|
+
t['path'].gsub!(/#SELF/, @mu_name.downcase)
|
|
636
|
+
end
|
|
637
|
+
}
|
|
638
|
+
parsed = MU::Cloud.resourceClass("AWS", "Role").genPolicyDocument([p], deploy_obj: @deploy, bucket_style: true).first.values.first
|
|
639
|
+
|
|
640
|
+
if policy and policy["Statement"]
|
|
641
|
+
policy["Statement"].concat(parsed["Statement"])
|
|
642
|
+
else
|
|
643
|
+
policy = parsed
|
|
644
|
+
end
|
|
645
|
+
}
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
if policy
|
|
649
|
+
params[:access_policies] = JSON.generate(policy)
|
|
650
|
+
end
|
|
520
651
|
end
|
|
521
652
|
|
|
522
653
|
if @config['slow_logs']
|
|
@@ -525,7 +656,7 @@ module MU
|
|
|
525
656
|
arn = @config['slow_logs']
|
|
526
657
|
else
|
|
527
658
|
log_group = @deploy.findLitterMate(type: "log", name: @config['slow_logs'])
|
|
528
|
-
log_group = MU::Cloud
|
|
659
|
+
log_group = MU::Cloud.resourceClass("AWS", "Log").find(cloud_id: log_group.mu_name, region: log_group.cloudobj.config['region']).values.first
|
|
529
660
|
if log_group.nil? or log_group.arn.nil?
|
|
530
661
|
raise MuError, "Failed to retrieve ARN of sibling LogGroup '#{@config['slow_logs']}'"
|
|
531
662
|
end
|
|
@@ -552,7 +683,7 @@ module MU
|
|
|
552
683
|
params[:log_publishing_options]["SEARCH_SLOW_LOGS"] = {}
|
|
553
684
|
params[:log_publishing_options]["SEARCH_SLOW_LOGS"][:enabled] = true
|
|
554
685
|
params[:log_publishing_options]["SEARCH_SLOW_LOGS"][:cloud_watch_logs_log_group_arn] = arn
|
|
555
|
-
MU::Cloud
|
|
686
|
+
MU::Cloud.resourceClass("AWS", "Log").allowService("es.amazonaws.com", arn, @config['region'])
|
|
556
687
|
end
|
|
557
688
|
end
|
|
558
689
|
|
|
@@ -682,7 +813,7 @@ module MU
|
|
|
682
813
|
raise MU::MuError, "Can't tag ElasticSearch domain, cloud descriptor came back without an ARN"
|
|
683
814
|
end
|
|
684
815
|
|
|
685
|
-
MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @
|
|
816
|
+
MU::Cloud::AWS.elasticsearch(region: @config['region'], credentials: @credentials).add_tags(
|
|
686
817
|
arn: domain.arn,
|
|
687
818
|
tag_list: tags
|
|
688
819
|
)
|
|
@@ -85,11 +85,11 @@ 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,
|
|
92
|
-
"muID" =>
|
|
92
|
+
"muID" => @deploy.deploy_id,
|
|
93
93
|
"muUser" => MU.mu_user,
|
|
94
94
|
"publicIP" => MU.mu_public_ip,
|
|
95
95
|
"mommaCatPort" => MU.mommaCatPort,
|
|
@@ -145,7 +145,7 @@ module MU
|
|
|
145
145
|
raise MuError, "My second argument should be a hash of variables to pass into ERB templates"
|
|
146
146
|
end
|
|
147
147
|
$mu = OpenStruct.new(template_variables)
|
|
148
|
-
userdata_dir = File.expand_path(MU.myRoot+"/modules/mu/
|
|
148
|
+
userdata_dir = File.expand_path(MU.myRoot+"/modules/mu/providers/aws/userdata")
|
|
149
149
|
platform = "linux" if %w{centos centos6 centos7 ubuntu ubuntu14 rhel rhel7 rhel71 amazon}.include? platform
|
|
150
150
|
platform = "windows" if %w{win2k12r2 win2k12 win2k8 win2k8r2 win2k16}.include? platform
|
|
151
151
|
erbfile = "#{userdata_dir}/#{platform}.erb"
|
|
@@ -243,7 +243,7 @@ module MU
|
|
|
243
243
|
MU::Cloud::AWS.createStandardTags(
|
|
244
244
|
instance.instance_id,
|
|
245
245
|
region: @config['region'],
|
|
246
|
-
credentials: @
|
|
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: @config['region'], credentials: @
|
|
261
|
+
MU::Cloud::AWS::Server.cleanup(noop: false, ignoremaster: false, region: @config['region'], credentials: @credentials, flags: { "skipsnapshots" => true } )
|
|
262
262
|
}
|
|
263
263
|
end
|
|
264
264
|
end
|
|
@@ -299,7 +299,7 @@ module MU
|
|
|
299
299
|
raise MuError, "Got null subnet id out of #{@config['vpc']}"
|
|
300
300
|
end
|
|
301
301
|
MU.log "Deploying #{@mu_name} into VPC #{@vpc.cloud_id} Subnet #{subnet.cloud_id}"
|
|
302
|
-
|
|
302
|
+
allowBastionAccess
|
|
303
303
|
instance_descriptor[:subnet_id] = subnet.cloud_id
|
|
304
304
|
end
|
|
305
305
|
|
|
@@ -307,7 +307,7 @@ module MU
|
|
|
307
307
|
instance_descriptor[:user_data] = Base64.encode64(@userdata)
|
|
308
308
|
end
|
|
309
309
|
|
|
310
|
-
MU::Cloud::AWS::Server.waitForAMI(@config["image_id"], region: @config['region'], credentials: @
|
|
310
|
+
MU::Cloud::AWS::Server.waitForAMI(@config["image_id"], region: @config['region'], credentials: @credentials)
|
|
311
311
|
|
|
312
312
|
instance_descriptor[:block_device_mappings] = MU::Cloud::AWS::Server.configureBlockDevices(image_id: @config["image_id"], storage: @config['storage'], region: @config['region'], credentials: @credentials)
|
|
313
313
|
|
|
@@ -332,7 +332,7 @@ module MU
|
|
|
332
332
|
|
|
333
333
|
begin
|
|
334
334
|
MU.retrier([Aws::EC2::Errors::InvalidGroupNotFound, Aws::EC2::Errors::InvalidSubnetIDNotFound, Aws::EC2::Errors::InvalidParameterValue], loop_if: loop_if, loop_msg: "Waiting for run_instances to return #{@mu_name}") {
|
|
335
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
335
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).run_instances(instance_descriptor)
|
|
336
336
|
}
|
|
337
337
|
rescue Aws::EC2::Errors::InvalidRequest => e
|
|
338
338
|
MU.log e.message, MU::ERR, details: instance_descriptor
|
|
@@ -351,12 +351,12 @@ module MU
|
|
|
351
351
|
if hard
|
|
352
352
|
groupname = nil
|
|
353
353
|
if !@config['basis'].nil?
|
|
354
|
-
resp = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @
|
|
354
|
+
resp = MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @credentials).describe_auto_scaling_instances(
|
|
355
355
|
instance_ids: [@cloud_id]
|
|
356
356
|
)
|
|
357
357
|
groupname = resp.auto_scaling_instances.first.auto_scaling_group_name
|
|
358
358
|
MU.log "Pausing Autoscale processes in #{groupname}", MU::NOTICE
|
|
359
|
-
MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @
|
|
359
|
+
MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @credentials).suspend_processes(
|
|
360
360
|
auto_scaling_group_name: groupname,
|
|
361
361
|
scaling_processes: [
|
|
362
362
|
"Terminate",
|
|
@@ -365,22 +365,22 @@ module MU
|
|
|
365
365
|
end
|
|
366
366
|
begin
|
|
367
367
|
MU.log "Stopping #{@mu_name} (#{@cloud_id})", MU::NOTICE
|
|
368
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
368
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).stop_instances(
|
|
369
369
|
instance_ids: [@cloud_id]
|
|
370
370
|
)
|
|
371
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
371
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).wait_until(:instance_stopped, instance_ids: [@cloud_id]) do |waiter|
|
|
372
372
|
waiter.before_attempt do
|
|
373
373
|
MU.log "Waiting for #{@mu_name} to stop for hard reboot"
|
|
374
374
|
end
|
|
375
375
|
end
|
|
376
376
|
MU.log "Starting #{@mu_name} (#{@cloud_id})"
|
|
377
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
377
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).start_instances(
|
|
378
378
|
instance_ids: [@cloud_id]
|
|
379
379
|
)
|
|
380
380
|
ensure
|
|
381
381
|
if !groupname.nil?
|
|
382
382
|
MU.log "Resuming Autoscale processes in #{groupname}", MU::NOTICE
|
|
383
|
-
MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @
|
|
383
|
+
MU::Cloud::AWS.autoscale(region: @config['region'], credentials: @credentials).resume_processes(
|
|
384
384
|
auto_scaling_group_name: groupname,
|
|
385
385
|
scaling_processes: [
|
|
386
386
|
"Terminate",
|
|
@@ -390,7 +390,7 @@ module MU
|
|
|
390
390
|
end
|
|
391
391
|
else
|
|
392
392
|
MU.log "Rebooting #{@mu_name} (#{@cloud_id})"
|
|
393
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
393
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).reboot_instances(
|
|
394
394
|
instance_ids: [@cloud_id]
|
|
395
395
|
)
|
|
396
396
|
end
|
|
@@ -399,13 +399,13 @@ module MU
|
|
|
399
399
|
# Figure out what's needed to SSH into this server.
|
|
400
400
|
# @return [Array<String>]: nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name, alternate_names
|
|
401
401
|
def getSSHConfig
|
|
402
|
-
|
|
402
|
+
cloud_desc(use_cache: false) # make sure we're current
|
|
403
403
|
# XXX add some awesome alternate names from metadata and make sure they end
|
|
404
404
|
# up in MU::MommaCat's ssh config wangling
|
|
405
405
|
return nil if @config.nil? or @deploy.nil?
|
|
406
406
|
|
|
407
407
|
nat_ssh_key = nat_ssh_user = nat_ssh_host = nil
|
|
408
|
-
if !@config["vpc"].nil? and !MU::Cloud
|
|
408
|
+
if !@config["vpc"].nil? and !MU::Cloud.resourceClass("AWS", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @credentials)
|
|
409
409
|
if !@nat.nil?
|
|
410
410
|
if @nat.is_a?(Struct) && @nat.nat_gateway_id && @nat.nat_gateway_id.start_with?("nat-")
|
|
411
411
|
raise MuError, "Configured to use NAT Gateway, but I have no route to instance. Either use Bastion, or configure VPC peering"
|
|
@@ -444,8 +444,7 @@ module MU
|
|
|
444
444
|
# administravia for a new instance.
|
|
445
445
|
def postBoot(instance_id = nil)
|
|
446
446
|
@cloud_id ||= instance_id
|
|
447
|
-
|
|
448
|
-
@mu_name ||= node
|
|
447
|
+
_node, _config, deploydata = describe(cloud_id: @cloud_id)
|
|
449
448
|
|
|
450
449
|
raise MuError, "Couldn't find instance #{@mu_name} (#{@cloud_id})" if !cloud_desc
|
|
451
450
|
return false if !MU::MommaCat.lock(@cloud_id+"-orchestrate", true)
|
|
@@ -459,7 +458,7 @@ module MU
|
|
|
459
458
|
MU::Cloud::AWS.createStandardTags(
|
|
460
459
|
@cloud_id,
|
|
461
460
|
region: @config['region'],
|
|
462
|
-
credentials: @
|
|
461
|
+
credentials: @credentials,
|
|
463
462
|
optional: @config['optional_tags'],
|
|
464
463
|
nametag: @mu_name,
|
|
465
464
|
othertags: @config['tags']
|
|
@@ -482,7 +481,7 @@ module MU
|
|
|
482
481
|
end
|
|
483
482
|
}
|
|
484
483
|
|
|
485
|
-
|
|
484
|
+
allowBastionAccess
|
|
486
485
|
|
|
487
486
|
setAlarms
|
|
488
487
|
|
|
@@ -496,7 +495,7 @@ module MU
|
|
|
496
495
|
|
|
497
496
|
if !@config['src_dst_check'] and !@config["vpc"].nil?
|
|
498
497
|
MU.log "Disabling source_dest_check #{@mu_name} (making it NAT-worthy)"
|
|
499
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
498
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).modify_instance_attribute(
|
|
500
499
|
instance_id: @cloud_id,
|
|
501
500
|
source_dest_check: { value: false }
|
|
502
501
|
)
|
|
@@ -504,7 +503,7 @@ module MU
|
|
|
504
503
|
|
|
505
504
|
# Set console termination protection. Autoscale nodes won't set this
|
|
506
505
|
# by default.
|
|
507
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
506
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).modify_instance_attribute(
|
|
508
507
|
instance_id: @cloud_id,
|
|
509
508
|
disable_api_termination: { value: true}
|
|
510
509
|
)
|
|
@@ -575,7 +574,7 @@ module MU
|
|
|
575
574
|
regions.each { |r|
|
|
576
575
|
searches.each { |search|
|
|
577
576
|
search_threads << Thread.new(search) { |params|
|
|
578
|
-
MU.retrier([
|
|
577
|
+
MU.retrier([], wait: 5, max: 5, ignoreme: [Aws::EC2::Errors::InvalidInstanceIDNotFound]) {
|
|
579
578
|
MU::Cloud::AWS.ec2(region: r, credentials: args[:credentials]).describe_instances(params).reservations.each { |resp|
|
|
580
579
|
next if resp.nil? or resp.instances.nil?
|
|
581
580
|
resp.instances.each { |i|
|
|
@@ -605,7 +604,7 @@ module MU
|
|
|
605
604
|
def toKitten(**_args)
|
|
606
605
|
bok = {
|
|
607
606
|
"cloud" => "AWS",
|
|
608
|
-
"credentials" => @
|
|
607
|
+
"credentials" => @credentials,
|
|
609
608
|
"cloud_id" => @cloud_id,
|
|
610
609
|
"region" => @config['region']
|
|
611
610
|
}
|
|
@@ -615,7 +614,7 @@ module MU
|
|
|
615
614
|
return nil
|
|
616
615
|
end
|
|
617
616
|
|
|
618
|
-
asgs = MU::Cloud
|
|
617
|
+
asgs = MU::Cloud.resourceClass("AWS", "ServerPool").find(
|
|
619
618
|
instance_id: @cloud_id,
|
|
620
619
|
region: @config['region'],
|
|
621
620
|
credentials: @credentials
|
|
@@ -725,15 +724,15 @@ module MU
|
|
|
725
724
|
|
|
726
725
|
if int.groups.size > 0
|
|
727
726
|
|
|
728
|
-
require 'mu/
|
|
729
|
-
ifaces = MU::Cloud
|
|
727
|
+
require 'mu/providers/aws/firewall_rule'
|
|
728
|
+
ifaces = MU::Cloud.resourceClass("AWS", "FirewallRule").getAssociatedInterfaces(int.groups.map { |sg| sg.group_id }, credentials: @credentials, region: @config['region'])
|
|
730
729
|
done_local_rules = false
|
|
731
730
|
int.groups.each { |sg|
|
|
732
731
|
if !done_local_rules and ifaces[sg.group_id].size == 1
|
|
733
|
-
sg_desc = MU::Cloud
|
|
732
|
+
sg_desc = MU::Cloud.resourceClass("AWS", "FirewallRule").find(cloud_id: sg.group_id, credentials: @credentials, region: @config['region']).values.first
|
|
734
733
|
if sg_desc
|
|
735
|
-
bok["ingress_rules"] = MU::Cloud
|
|
736
|
-
bok["ingress_rules"].concat(MU::Cloud
|
|
734
|
+
bok["ingress_rules"] = MU::Cloud.resourceClass("AWS", "FirewallRule").rulesToBoK(sg_desc.ip_permissions)
|
|
735
|
+
bok["ingress_rules"].concat(MU::Cloud.resourceClass("AWS", "FirewallRule").rulesToBoK(sg_desc.ip_permissions_egress, egress: true))
|
|
737
736
|
done_local_rules = true
|
|
738
737
|
next
|
|
739
738
|
end
|
|
@@ -802,44 +801,13 @@ module MU
|
|
|
802
801
|
end
|
|
803
802
|
deploydata["region"] = @config['region'] if !@config['region'].nil?
|
|
804
803
|
if !@named
|
|
805
|
-
MU::MommaCat.nameKitten(self)
|
|
804
|
+
MU::MommaCat.nameKitten(self, no_dns: true)
|
|
806
805
|
@named = true
|
|
807
806
|
end
|
|
808
807
|
|
|
809
808
|
return deploydata
|
|
810
809
|
end
|
|
811
810
|
|
|
812
|
-
# If the specified server is in a VPC, and has a NAT, make sure we'll
|
|
813
|
-
# be letting ssh traffic in from said NAT.
|
|
814
|
-
def punchAdminNAT
|
|
815
|
-
if @config['vpc'].nil? or
|
|
816
|
-
(
|
|
817
|
-
!@config['vpc'].has_key?("nat_host_id") and
|
|
818
|
-
!@config['vpc'].has_key?("nat_host_tag") and
|
|
819
|
-
!@config['vpc'].has_key?("nat_host_ip") and
|
|
820
|
-
!@config['vpc'].has_key?("nat_host_name")
|
|
821
|
-
)
|
|
822
|
-
return nil
|
|
823
|
-
end
|
|
824
|
-
|
|
825
|
-
return nil if @nat.is_a?(Struct) && @nat.nat_gateway_id && @nat.nat_gateway_id.start_with?("nat-")
|
|
826
|
-
|
|
827
|
-
dependencies if @nat.nil?
|
|
828
|
-
if @nat.nil? or @nat.cloud_desc.nil?
|
|
829
|
-
raise MuError, "#{@mu_name} (#{MU.deploy_id}) is configured to use #{@config['vpc']} but I can't find the cloud descriptor for a matching NAT instance"
|
|
830
|
-
end
|
|
831
|
-
MU.log "Adding administrative holes for NAT host #{@nat.cloud_desc.private_ip_address} to #{@mu_name}"
|
|
832
|
-
if !@deploy.kittens['firewall_rules'].nil?
|
|
833
|
-
@deploy.kittens['firewall_rules'].values.each { |acl|
|
|
834
|
-
if acl.config["admin"]
|
|
835
|
-
acl.addRule([@nat.cloud_desc.private_ip_address], proto: "tcp")
|
|
836
|
-
acl.addRule([@nat.cloud_desc.private_ip_address], proto: "udp")
|
|
837
|
-
acl.addRule([@nat.cloud_desc.private_ip_address], proto: "icmp")
|
|
838
|
-
end
|
|
839
|
-
}
|
|
840
|
-
end
|
|
841
|
-
end
|
|
842
|
-
|
|
843
811
|
# Called automatically by {MU::Deploy#createResources}
|
|
844
812
|
def groom
|
|
845
813
|
MU::MommaCat.lock(@cloud_id+"-groom")
|
|
@@ -851,7 +819,7 @@ module MU
|
|
|
851
819
|
end
|
|
852
820
|
end
|
|
853
821
|
|
|
854
|
-
|
|
822
|
+
allowBastionAccess
|
|
855
823
|
|
|
856
824
|
tagVolumes
|
|
857
825
|
|
|
@@ -883,12 +851,25 @@ module MU
|
|
|
883
851
|
|
|
884
852
|
begin
|
|
885
853
|
getIAMProfile
|
|
854
|
+
|
|
855
|
+
dbs = @deploy.findLitterMate(type: "database", return_all: true)
|
|
856
|
+
if dbs
|
|
857
|
+
dbs.each_pair { |sib_name, sib|
|
|
858
|
+
@groomer.groomer_class.grantSecretAccess(@mu_name, sib_name, "database_credentials")
|
|
859
|
+
if sib.config and sib.config['auth_vault']
|
|
860
|
+
@groomer.groomer_class.grantSecretAccess(@mu_name, sib.config['auth_vault']['vault'], sib.config['auth_vault']['item'])
|
|
861
|
+
end
|
|
862
|
+
}
|
|
863
|
+
end
|
|
864
|
+
|
|
886
865
|
if @config['groom'].nil? or @config['groom']
|
|
887
866
|
@groomer.run(purpose: "Full Initial Run", max_retries: 15, reboot_first_fail: (windows? and @config['groomer'] != "Ansible"), timeout: @config['groomer_timeout'])
|
|
888
867
|
end
|
|
889
868
|
rescue MU::Groomer::RunError => e
|
|
869
|
+
raise e if !@config['create_image'].nil? and !@config['image_created']
|
|
890
870
|
MU.log "Proceeding after failed initial Groomer run, but #{@mu_name} may not behave as expected!", MU::WARN, details: e.message
|
|
891
871
|
rescue StandardError => e
|
|
872
|
+
raise e if !@config['create_image'].nil? and !@config['image_created']
|
|
892
873
|
MU.log "Caught #{e.inspect} on #{@mu_name} in an unexpected place (after @groomer.run on Full Initial Run)", MU::ERR
|
|
893
874
|
end
|
|
894
875
|
|
|
@@ -902,7 +883,7 @@ module MU
|
|
|
902
883
|
# Canonical Amazon Resource Number for this resource
|
|
903
884
|
# @return [String]
|
|
904
885
|
def arn
|
|
905
|
-
"arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":ec2:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@
|
|
886
|
+
"arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":ec2:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@credentials)+":instance/"+@cloud_id
|
|
906
887
|
end
|
|
907
888
|
|
|
908
889
|
@cloud_desc_cache = nil
|
|
@@ -910,11 +891,12 @@ module MU
|
|
|
910
891
|
# @return [Openstruct]
|
|
911
892
|
def cloud_desc(use_cache: true)
|
|
912
893
|
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
|
894
|
+
return nil if !@cloud_id
|
|
913
895
|
max_retries = 5
|
|
914
896
|
retries = 0
|
|
915
897
|
if !@cloud_id.nil?
|
|
916
898
|
begin
|
|
917
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
899
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_instances(instance_ids: [@cloud_id])
|
|
918
900
|
if resp and resp.reservations and resp.reservations.first and
|
|
919
901
|
resp.reservations.first.instances and
|
|
920
902
|
resp.reservations.first.instances.first
|
|
@@ -961,7 +943,7 @@ module MU
|
|
|
961
943
|
# Our deploydata gets corrupted often with server pools, this will cause us to use the wrong IP to identify a node
|
|
962
944
|
# which will cause us to create certificates, DNS records and other artifacts with incorrect information which will cause our deploy to fail.
|
|
963
945
|
# The cloud_id is always correct so lets use 'cloud_desc' to get the correct IPs
|
|
964
|
-
if MU::Cloud
|
|
946
|
+
if MU::Cloud.resourceClass("AWS", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @credentials) or @deploydata["public_ip_address"].nil?
|
|
965
947
|
@config['canonical_ip'] = cloud_desc.private_ip_address
|
|
966
948
|
@deploydata["private_ip_address"] = cloud_desc.private_ip_address
|
|
967
949
|
return cloud_desc.private_ip_address
|
|
@@ -1181,17 +1163,14 @@ module MU
|
|
|
1181
1163
|
end
|
|
1182
1164
|
end
|
|
1183
1165
|
|
|
1184
|
-
|
|
1185
|
-
describe
|
|
1186
|
-
@cloud_id = cloud_desc.instance_id
|
|
1187
|
-
end
|
|
1166
|
+
@cloud_id ||= cloud_desc(use_cache: false).instance_id
|
|
1188
1167
|
ssh_keydir = "#{Etc.getpwuid(Process.uid).dir}/.ssh"
|
|
1189
1168
|
ssh_key_name = @deploy.ssh_key_name
|
|
1190
1169
|
|
|
1191
1170
|
retries = 0
|
|
1192
1171
|
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
|
|
1193
1172
|
begin
|
|
1194
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
1173
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).wait_until(:password_data_available, instance_id: @cloud_id) do |waiter|
|
|
1195
1174
|
waiter.max_attempts = 60
|
|
1196
1175
|
waiter.before_attempt do |attempts|
|
|
1197
1176
|
MU.log "Waiting for Windows password data to be available for node #{@mu_name}", MU::NOTICE if attempts % 5 == 0
|
|
@@ -1211,7 +1190,7 @@ module MU
|
|
|
1211
1190
|
end
|
|
1212
1191
|
end
|
|
1213
1192
|
|
|
1214
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
1193
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).get_password_data(instance_id: @cloud_id)
|
|
1215
1194
|
encrypted_password = resp.password_data
|
|
1216
1195
|
|
|
1217
1196
|
# Note: This is already implemented in the decrypt_windows_password API call
|
|
@@ -1296,19 +1275,19 @@ module MU
|
|
|
1296
1275
|
def addVolume(dev, size, type: "gp2", delete_on_termination: false)
|
|
1297
1276
|
|
|
1298
1277
|
if setDeleteOntermination(dev, delete_on_termination)
|
|
1299
|
-
MU.log "A volume #{
|
|
1278
|
+
MU.log "A volume #{dev} already attached to #{self}, skipping", MU::NOTICE
|
|
1300
1279
|
return
|
|
1301
1280
|
end
|
|
1302
1281
|
|
|
1303
1282
|
MU.log "Creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
|
|
1304
|
-
creation = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
1283
|
+
creation = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).create_volume(
|
|
1305
1284
|
availability_zone: cloud_desc.placement.availability_zone,
|
|
1306
1285
|
size: size,
|
|
1307
1286
|
volume_type: type
|
|
1308
1287
|
)
|
|
1309
1288
|
|
|
1310
1289
|
MU.retrier(wait: 3, loop_if: Proc.new {
|
|
1311
|
-
creation = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
1290
|
+
creation = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_volumes(volume_ids: [creation.volume_id]).volumes.first
|
|
1312
1291
|
if !["creating", "available"].include?(creation.state)
|
|
1313
1292
|
raise MuError, "Saw state '#{creation.state}' while creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
|
|
1314
1293
|
end
|
|
@@ -1318,24 +1297,27 @@ module MU
|
|
|
1318
1297
|
|
|
1319
1298
|
if @deploy
|
|
1320
1299
|
MU::Cloud::AWS.createStandardTags(
|
|
1321
|
-
|
|
1300
|
+
creation.volume_id,
|
|
1322
1301
|
region: @config['region'],
|
|
1323
|
-
credentials: @
|
|
1302
|
+
credentials: @credentials,
|
|
1324
1303
|
optional: @config['optional_tags'],
|
|
1325
1304
|
nametag: @mu_name+"-"+dev.upcase,
|
|
1326
1305
|
othertags: @config['tags']
|
|
1327
1306
|
)
|
|
1328
1307
|
end
|
|
1329
1308
|
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1309
|
+
MU.log "Attaching #{creation.volume_id} as #{dev} to #{@cloud_id} in #{@config['region']} (credentials #{@credentials})"
|
|
1310
|
+
attachment = nil
|
|
1311
|
+
MU.retrier([Aws::EC2::Errors::IncorrectState], wait: 15, max: 4) {
|
|
1312
|
+
attachment = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).attach_volume(
|
|
1313
|
+
device: dev,
|
|
1314
|
+
instance_id: @cloud_id,
|
|
1315
|
+
volume_id: creation.volume_id
|
|
1316
|
+
)
|
|
1317
|
+
}
|
|
1335
1318
|
|
|
1336
1319
|
begin
|
|
1337
|
-
|
|
1338
|
-
attachment = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_volumes(volume_ids: [attachment.volume_id]).volumes.first.attachments.first
|
|
1320
|
+
attachment = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_volumes(volume_ids: [attachment.volume_id]).volumes.first.attachments.first
|
|
1339
1321
|
if !["attaching", "attached"].include?(attachment.state)
|
|
1340
1322
|
raise MuError, "Saw state '#{creation.state}' while creating #{size}GB #{type} volume on #{dev} for #{@cloud_id}"
|
|
1341
1323
|
end
|
|
@@ -1355,7 +1337,7 @@ module MU
|
|
|
1355
1337
|
return true
|
|
1356
1338
|
end
|
|
1357
1339
|
begin
|
|
1358
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
1340
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_instances(
|
|
1359
1341
|
instance_ids: [@cloud_id]
|
|
1360
1342
|
).reservations.each { |resp|
|
|
1361
1343
|
if !resp.nil? and !resp.instances.nil?
|
|
@@ -1476,11 +1458,11 @@ module MU
|
|
|
1476
1458
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
1477
1459
|
# @param region [String]: The cloud provider region
|
|
1478
1460
|
# @return [void]
|
|
1479
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
1461
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
1480
1462
|
onlycloud = flags["onlycloud"]
|
|
1481
1463
|
skipsnapshots = flags["skipsnapshots"]
|
|
1482
1464
|
tagfilters = [
|
|
1483
|
-
{name: "tag:MU-ID", values: [
|
|
1465
|
+
{name: "tag:MU-ID", values: [deploy_id]}
|
|
1484
1466
|
]
|
|
1485
1467
|
if !ignoremaster
|
|
1486
1468
|
tagfilters << {name: "tag:MU-MASTER-IP", values: [MU.mu_public_ip]}
|
|
@@ -1514,7 +1496,7 @@ module MU
|
|
|
1514
1496
|
threads << Thread.new(instance) { |myinstance|
|
|
1515
1497
|
MU.dupGlobals(parent_thread_id)
|
|
1516
1498
|
Thread.abort_on_exception = true
|
|
1517
|
-
MU::Cloud::AWS::Server.terminateInstance(id: myinstance.instance_id, noop: noop, onlycloud: onlycloud, region: region, deploy_id:
|
|
1499
|
+
MU::Cloud::AWS::Server.terminateInstance(id: myinstance.instance_id, noop: noop, onlycloud: onlycloud, region: region, deploy_id: deploy_id, credentials: credentials)
|
|
1518
1500
|
}
|
|
1519
1501
|
}
|
|
1520
1502
|
|
|
@@ -1525,7 +1507,7 @@ module MU
|
|
|
1525
1507
|
threads << Thread.new(volume) { |myvolume|
|
|
1526
1508
|
MU.dupGlobals(parent_thread_id)
|
|
1527
1509
|
Thread.abort_on_exception = true
|
|
1528
|
-
delete_volume(myvolume, noop, skipsnapshots, credentials: credentials)
|
|
1510
|
+
delete_volume(myvolume, noop, skipsnapshots, credentials: credentials, deploy_id: deploy_id)
|
|
1529
1511
|
}
|
|
1530
1512
|
}
|
|
1531
1513
|
|
|
@@ -1577,7 +1559,11 @@ module MU
|
|
|
1577
1559
|
return if !instance
|
|
1578
1560
|
|
|
1579
1561
|
id ||= instance.instance_id
|
|
1580
|
-
|
|
1562
|
+
begin
|
|
1563
|
+
MU::MommaCat.lock(".cleanup-"+id)
|
|
1564
|
+
rescue Errno::ENOENT => e
|
|
1565
|
+
MU.log "No lock for terminating instance #{id} due to missing metadata", MU::DEBUG
|
|
1566
|
+
end
|
|
1581
1567
|
|
|
1582
1568
|
ips, names = getAddresses(instance, region: region, credentials: credentials)
|
|
1583
1569
|
targets = ips +names
|
|
@@ -1632,7 +1618,11 @@ module MU
|
|
|
1632
1618
|
end
|
|
1633
1619
|
|
|
1634
1620
|
MU.log "#{instance.instance_id}#{server_obj ? " ("+server_obj.mu_name+")" : ""} terminated" if !noop
|
|
1635
|
-
|
|
1621
|
+
begin
|
|
1622
|
+
MU::MommaCat.unlock(".cleanup-"+id)
|
|
1623
|
+
rescue Errno::ENOENT => e
|
|
1624
|
+
MU.log "No lock for terminating instance #{id} due to missing metadata", MU::DEBUG
|
|
1625
|
+
end
|
|
1636
1626
|
|
|
1637
1627
|
end
|
|
1638
1628
|
|
|
@@ -1690,26 +1680,7 @@ module MU
|
|
|
1690
1680
|
"type" => "object"
|
|
1691
1681
|
}
|
|
1692
1682
|
},
|
|
1693
|
-
"ingress_rules" =>
|
|
1694
|
-
"items" => {
|
|
1695
|
-
"properties" => {
|
|
1696
|
-
"sgs" => {
|
|
1697
|
-
"type" => "array",
|
|
1698
|
-
"items" => {
|
|
1699
|
-
"description" => "Other AWS Security Groups; resources that are associated with this group will have this rule applied to their traffic",
|
|
1700
|
-
"type" => "string"
|
|
1701
|
-
}
|
|
1702
|
-
},
|
|
1703
|
-
"lbs" => {
|
|
1704
|
-
"type" => "array",
|
|
1705
|
-
"items" => {
|
|
1706
|
-
"description" => "AWS Load Balancers which will have this rule applied to their traffic",
|
|
1707
|
-
"type" => "string"
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
},
|
|
1683
|
+
"ingress_rules" => MU::Cloud.resourceClass("AWS", "FirewallRule").ingressRuleAddtlSchema,
|
|
1713
1684
|
"ssh_user" => {
|
|
1714
1685
|
"type" => "string",
|
|
1715
1686
|
"default" => "root",
|
|
@@ -1777,8 +1748,7 @@ module MU
|
|
|
1777
1748
|
|
|
1778
1749
|
MU::Cloud.availableClouds.each { |cloud|
|
|
1779
1750
|
next if cloud == "AWS"
|
|
1780
|
-
|
|
1781
|
-
foreign_types = (cloudbase.listInstanceTypes).values.first
|
|
1751
|
+
foreign_types = (MU::Cloud.cloudClass(cloud).listInstanceTypes).values.first
|
|
1782
1752
|
if foreign_types.size == 1
|
|
1783
1753
|
foreign_types = foreign_types.values.first
|
|
1784
1754
|
end
|
|
@@ -1845,12 +1815,7 @@ module MU
|
|
|
1845
1815
|
end
|
|
1846
1816
|
|
|
1847
1817
|
configurator.insertKitten(role, "roles")
|
|
1848
|
-
|
|
1849
|
-
server["dependencies"] ||= []
|
|
1850
|
-
server["dependencies"] << {
|
|
1851
|
-
"type" => "role",
|
|
1852
|
-
"name" => server["name"]
|
|
1853
|
-
}
|
|
1818
|
+
MU::Config.addDependency(server, server["name"], "role")
|
|
1854
1819
|
end
|
|
1855
1820
|
|
|
1856
1821
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::servers}, bare and unvalidated.
|
|
@@ -1901,10 +1866,7 @@ module MU
|
|
|
1901
1866
|
server["loadbalancers"].each { |lb|
|
|
1902
1867
|
lb["name"] ||= lb["concurrent_load_balancer"]
|
|
1903
1868
|
if lb["name"]
|
|
1904
|
-
server["
|
|
1905
|
-
"type" => "loadbalancer",
|
|
1906
|
-
"name" => lb["name"]
|
|
1907
|
-
}
|
|
1869
|
+
MU::Config.addDependency(server, lb["name"], "loadbalancer")
|
|
1908
1870
|
end
|
|
1909
1871
|
}
|
|
1910
1872
|
end
|
|
@@ -1931,7 +1893,7 @@ module MU
|
|
|
1931
1893
|
# @param volume [OpenStruct]: The cloud provider's description of the volume.
|
|
1932
1894
|
# @param region [String]: The cloud provider region
|
|
1933
1895
|
# @return [void]
|
|
1934
|
-
def self.delete_volume(volume, noop, skipsnapshots, region: MU.curRegion, credentials: nil)
|
|
1896
|
+
def self.delete_volume(volume, noop, skipsnapshots, region: MU.curRegion, credentials: nil, deploy_id: MU.deploy_id)
|
|
1935
1897
|
if !volume.nil?
|
|
1936
1898
|
resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_volumes(volume_ids: [volume.volume_id])
|
|
1937
1899
|
volume = resp.data.volumes.first
|
|
@@ -1946,9 +1908,9 @@ module MU
|
|
|
1946
1908
|
if !noop
|
|
1947
1909
|
if !skipsnapshots
|
|
1948
1910
|
if !name.nil? and !name.empty?
|
|
1949
|
-
desc = "#{
|
|
1911
|
+
desc = "#{deploy_id}-MUfinal (#{name})"
|
|
1950
1912
|
else
|
|
1951
|
-
desc = "#{
|
|
1913
|
+
desc = "#{deploy_id}-MUfinal"
|
|
1952
1914
|
end
|
|
1953
1915
|
|
|
1954
1916
|
begin
|
|
@@ -2019,6 +1981,13 @@ module MU
|
|
|
2019
1981
|
configured_storage
|
|
2020
1982
|
end
|
|
2021
1983
|
|
|
1984
|
+
# Return all of the IP addresses, public and private, from all of our
|
|
1985
|
+
# network interfaces.
|
|
1986
|
+
# @return [Array<String>]
|
|
1987
|
+
def listIPs
|
|
1988
|
+
MU::Cloud::AWS::Server.getAddresses(cloud_desc).first
|
|
1989
|
+
end
|
|
1990
|
+
|
|
2022
1991
|
private
|
|
2023
1992
|
|
|
2024
1993
|
def bootstrapGroomer
|
|
@@ -2119,7 +2088,7 @@ module MU
|
|
|
2119
2088
|
def haveElasticIP?
|
|
2120
2089
|
if !cloud_desc.public_ip_address.nil?
|
|
2121
2090
|
begin
|
|
2122
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
2091
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_addresses(public_ips: [cloud_desc.public_ip_address])
|
|
2123
2092
|
if resp.addresses.size > 0 and resp.addresses.first.instance_id == @cloud_id
|
|
2124
2093
|
return true
|
|
2125
2094
|
end
|
|
@@ -2144,7 +2113,7 @@ module MU
|
|
|
2144
2113
|
subnet = @vpc.getSubnet(cloud_id: cloud_desc.subnet_id)
|
|
2145
2114
|
|
|
2146
2115
|
_nat_ssh_key, _nat_ssh_user, nat_ssh_host, _canonical_ip, _ssh_user, _ssh_key_name = getSSHConfig
|
|
2147
|
-
if subnet.private? and !nat_ssh_host and !MU::Cloud
|
|
2116
|
+
if subnet.private? and !nat_ssh_host and !MU::Cloud.resourceClass("AWS", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @credentials)
|
|
2148
2117
|
raise MuError, "#{@mu_name} is in a private subnet (#{subnet}), but has no bastion host configured, and I have no other route to it"
|
|
2149
2118
|
end
|
|
2150
2119
|
|
|
@@ -2161,17 +2130,17 @@ module MU
|
|
|
2161
2130
|
next
|
|
2162
2131
|
end
|
|
2163
2132
|
MU.log "Adding network interface on subnet #{s.cloud_id} for #{@mu_name}"
|
|
2164
|
-
iface = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
2133
|
+
iface = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).create_network_interface(subnet_id: s.cloud_id).network_interface
|
|
2165
2134
|
MU::Cloud::AWS.createStandardTags(
|
|
2166
2135
|
iface.network_interface_id,
|
|
2167
2136
|
region: @config['region'],
|
|
2168
|
-
credentials: @
|
|
2137
|
+
credentials: @credentials,
|
|
2169
2138
|
optional: @config['optional_tags'],
|
|
2170
2139
|
nametag: @mu_name+"-ETH"+device_index.to_s,
|
|
2171
2140
|
othertags: @config['tags']
|
|
2172
2141
|
)
|
|
2173
2142
|
|
|
2174
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
2143
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).attach_network_interface(
|
|
2175
2144
|
network_interface_id: iface.network_interface_id,
|
|
2176
2145
|
instance_id: cloud_desc.instance_id,
|
|
2177
2146
|
device_index: device_index
|
|
@@ -2190,7 +2159,7 @@ module MU
|
|
|
2190
2159
|
cloud_desc.network_interfaces.each { |int|
|
|
2191
2160
|
if int.private_ip_address == cloud_desc.private_ip_address and int.private_ip_addresses.size < (@config['add_private_ips'] + 1)
|
|
2192
2161
|
MU.log "Adding #{@config['add_private_ips']} extra private IP addresses to #{cloud_desc.instance_id}"
|
|
2193
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
2162
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).assign_private_ip_addresses(
|
|
2194
2163
|
network_interface_id: int.network_interface_id,
|
|
2195
2164
|
secondary_private_ip_address_count: @config['add_private_ips'],
|
|
2196
2165
|
allow_reassignment: false
|
|
@@ -2201,14 +2170,14 @@ module MU
|
|
|
2201
2170
|
end
|
|
2202
2171
|
|
|
2203
2172
|
def tagVolumes
|
|
2204
|
-
volumes = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
2173
|
+
volumes = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).describe_volumes(filters: [name: "attachment.instance-id", values: [@cloud_id]])
|
|
2205
2174
|
volumes.each { |vol|
|
|
2206
2175
|
vol.volumes.each { |volume|
|
|
2207
2176
|
volume.attachments.each { |attachment|
|
|
2208
2177
|
MU::Cloud::AWS.createStandardTags(
|
|
2209
2178
|
attachment.volume_id,
|
|
2210
2179
|
region: @config['region'],
|
|
2211
|
-
credentials: @
|
|
2180
|
+
credentials: @credentials,
|
|
2212
2181
|
optional: @config['optional_tags'],
|
|
2213
2182
|
nametag: ["/dev/sda", "/dev/sda1"].include?(attachment.device) ? "ROOT-"+@mu_name : @mu_name+"-"+attachment.device.upcase,
|
|
2214
2183
|
othertags: @config['tags']
|
|
@@ -2236,15 +2205,17 @@ module MU
|
|
|
2236
2205
|
alarm["dimensions"] = [{:name => "InstanceId", :value => @cloud_id}]
|
|
2237
2206
|
|
|
2238
2207
|
if alarm["enable_notifications"]
|
|
2239
|
-
|
|
2240
|
-
|
|
2208
|
+
# XXX vile, this should be a sibling resource generated by the
|
|
2209
|
+
# parser
|
|
2210
|
+
topic_arn = MU::Cloud.resourceClass("AWS", "Notification").createTopic(alarm["notification_group"], region: @config["region"], credentials: @credentials)
|
|
2211
|
+
MU::Cloud.resourceClass("AWS", "Notification").subscribe(topic_arn, alarm["notification_endpoint"], alarm["notification_type"], region: @config["region"], credentials: @config["credentials"])
|
|
2241
2212
|
alarm["alarm_actions"] = [topic_arn]
|
|
2242
2213
|
alarm["ok_actions"] = [topic_arn]
|
|
2243
2214
|
end
|
|
2244
2215
|
|
|
2245
2216
|
alarm_name = alarm_obj ? alarm_obj.cloud_id : "#{@mu_name}-#{alarm['name']}".upcase
|
|
2246
2217
|
|
|
2247
|
-
MU::Cloud
|
|
2218
|
+
MU::Cloud.resourceClass("AWS", "Alarm").setAlarm(
|
|
2248
2219
|
name: alarm_name,
|
|
2249
2220
|
ok_actions: alarm["ok_actions"],
|
|
2250
2221
|
alarm_actions: alarm["alarm_actions"],
|
|
@@ -2259,7 +2230,7 @@ module MU
|
|
|
2259
2230
|
threshold: alarm["threshold"],
|
|
2260
2231
|
comparison_operator: alarm["comparison_operator"],
|
|
2261
2232
|
region: @config["region"],
|
|
2262
|
-
credentials: @
|
|
2233
|
+
credentials: @credentials
|
|
2263
2234
|
)
|
|
2264
2235
|
}
|
|
2265
2236
|
end
|
|
@@ -2269,7 +2240,10 @@ module MU
|
|
|
2269
2240
|
|
|
2270
2241
|
def getIAMProfile
|
|
2271
2242
|
arn = if @config['generate_iam_role']
|
|
2272
|
-
role = @deploy.findLitterMate(name: @config['name'], type: "roles")
|
|
2243
|
+
role = @deploy.findLitterMate(name: @config['name'], type: "roles", debug: true)
|
|
2244
|
+
if !role
|
|
2245
|
+
raise MuError, "Failed to find a role matching #{@config['name']}"
|
|
2246
|
+
end
|
|
2273
2247
|
s3_objs = ["#{@deploy.deploy_id}-secret", "#{role.mu_name}.pfx", "#{role.mu_name}.crt", "#{role.mu_name}.key", "#{role.mu_name}-winrm.crt", "#{role.mu_name}-winrm.key"].map { |file|
|
|
2274
2248
|
'arn:'+(MU::Cloud::AWS.isGovCloud?(@config['region']) ? "aws-us-gov" : "aws")+':s3:::'+MU::Cloud::AWS.adminBucketName(@credentials)+'/'+file
|
|
2275
2249
|
}
|
|
@@ -2304,8 +2278,8 @@ module MU
|
|
|
2304
2278
|
if vol[:device_name] == device
|
|
2305
2279
|
if vol[:ebs][:delete_on_termination] != delete_on_termination
|
|
2306
2280
|
vol[:ebs][:delete_on_termination] = delete_on_termination
|
|
2307
|
-
MU.log "Setting delete_on_termination flag to #{delete_on_termination.to_s} on #{@mu_name}'s #{
|
|
2308
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @
|
|
2281
|
+
MU.log "Setting delete_on_termination flag to #{delete_on_termination.to_s} on #{@mu_name}'s #{device}"
|
|
2282
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @credentials).modify_instance_attribute(
|
|
2309
2283
|
instance_id: @cloud_id,
|
|
2310
2284
|
block_device_mappings: mappings
|
|
2311
2285
|
)
|
|
@@ -2351,14 +2325,15 @@ module MU
|
|
|
2351
2325
|
make_public: img_cfg['public'],
|
|
2352
2326
|
region: @config['region'],
|
|
2353
2327
|
tags: @config['tags'],
|
|
2354
|
-
credentials: @
|
|
2328
|
+
credentials: @credentials
|
|
2355
2329
|
)
|
|
2330
|
+
|
|
2356
2331
|
@deploy.notify("images", @config['name'], ami_ids)
|
|
2357
2332
|
@config['image_created'] = true
|
|
2358
2333
|
if img_cfg['image_then_destroy']
|
|
2359
|
-
MU::Cloud::AWS::Server.waitForAMI(ami_ids[@config['region']], region: @config['region'], credentials: @
|
|
2334
|
+
MU::Cloud::AWS::Server.waitForAMI(ami_ids[@config['region']], region: @config['region'], credentials: @credentials)
|
|
2360
2335
|
MU.log "AMI #{ami_ids[@config['region']]} ready, removing source node #{@mu_name}"
|
|
2361
|
-
MU::Cloud::AWS::Server.terminateInstance(id: @cloud_id, region: @config['region'], deploy_id: @deploy.deploy_id, mu_name: @mu_name, credentials: @
|
|
2336
|
+
MU::Cloud::AWS::Server.terminateInstance(id: @cloud_id, region: @config['region'], deploy_id: @deploy.deploy_id, mu_name: @mu_name, credentials: @credentials)
|
|
2362
2337
|
destroy
|
|
2363
2338
|
end
|
|
2364
2339
|
end
|