cloud-mu 3.1.3 → 3.3.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 +15 -3
- data/ansible/roles/mu-windows/README.md +33 -0
- data/ansible/roles/mu-windows/defaults/main.yml +2 -0
- data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
- data/ansible/roles/mu-windows/files/config.xml +76 -0
- data/ansible/roles/mu-windows/handlers/main.yml +2 -0
- data/ansible/roles/mu-windows/meta/main.yml +53 -0
- data/ansible/roles/mu-windows/tasks/main.yml +36 -0
- data/ansible/roles/mu-windows/tests/inventory +2 -0
- data/ansible/roles/mu-windows/tests/test.yml +5 -0
- data/ansible/roles/mu-windows/vars/main.yml +2 -0
- data/bin/mu-adopt +21 -13
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +52 -0
- 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 +4 -4
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +147 -37
- data/cloud-mu.gemspec +22 -20
- data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
- data/cookbooks/mu-tools/libraries/helper.rb +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/cookbooks/mu-tools/recipes/eks.rb +2 -2
- data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
- data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +18 -13
- data/extras/image-generators/AWS/win2k16.yaml +18 -13
- data/extras/image-generators/AWS/win2k19.yaml +21 -0
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +158 -111
- data/modules/mu/adoption.rb +404 -71
- data/modules/mu/cleanup.rb +221 -306
- data/modules/mu/cloud.rb +129 -1633
- 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 +926 -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 +169 -0
- data/modules/mu/config.rb +171 -1767
- 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 +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +10 -9
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +5 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +19 -10
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +10 -21
- data/modules/mu/config/ref.rb +411 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +98 -71
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +71 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +91 -68
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +43 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +410 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +218 -2612
- data/modules/mu/mommacat/daemon.rb +403 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +380 -122
- data/modules/mu/{clouds → providers}/aws/alarm.rb +7 -5
- data/modules/mu/{clouds → providers}/aws/bucket.rb +297 -59
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +37 -71
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +26 -25
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +724 -744
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +88 -70
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +220 -247
- data/modules/mu/{clouds → providers}/aws/folder.rb +8 -8
- data/modules/mu/{clouds → providers}/aws/function.rb +300 -142
- data/modules/mu/{clouds → providers}/aws/group.rb +31 -29
- data/modules/mu/{clouds → providers}/aws/habitat.rb +18 -15
- data/modules/mu/providers/aws/job.rb +466 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +66 -56
- data/modules/mu/{clouds → providers}/aws/log.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +29 -19
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +114 -16
- data/modules/mu/{clouds → providers}/aws/notifier.rb +142 -65
- data/modules/mu/{clouds → providers}/aws/role.rb +158 -118
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +201 -59
- data/modules/mu/{clouds → providers}/aws/server.rb +844 -1139
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +74 -65
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +26 -44
- data/modules/mu/{clouds → providers}/aws/user.rb +24 -25
- 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 +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +525 -931
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +97 -49
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- 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 +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- 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 +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +68 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +85 -78
- data/modules/mu/{clouds → providers}/google/database.rb +11 -21
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +140 -168
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +19 -21
- data/modules/mu/{clouds → providers}/google/role.rb +94 -58
- data/modules/mu/{clouds → providers}/google/server.rb +243 -156
- data/modules/mu/{clouds → providers}/google/server_pool.rb +26 -45
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- 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 +103 -79
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/bucket.yml +4 -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 +23 -0
- 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/includes-and-params.yaml +2 -1
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +2 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +3 -5
- data/modules/tests/win2k12.yaml +17 -5
- data/modules/tests/win2k16.yaml +25 -0
- data/modules/tests/win2k19.yaml +25 -0
- data/requirements.txt +1 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +240 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
- data/modules/mu/clouds/aws/endpoint.rb +0 -592
|
@@ -37,7 +37,7 @@ module MU
|
|
|
37
37
|
if !@config['use_if_exists']
|
|
38
38
|
raise MuError, "IAM user #{@mu_name} already exists and use_if_exists is false"
|
|
39
39
|
end
|
|
40
|
-
rescue Aws::IAM::Errors::NoSuchEntity
|
|
40
|
+
rescue Aws::IAM::Errors::NoSuchEntity
|
|
41
41
|
@config['path'] ||= "/"+@deploy.deploy_id+"/"
|
|
42
42
|
MU.log "Creating IAM user #{@config['path']}/#{@mu_name}"
|
|
43
43
|
tags = get_tag_params
|
|
@@ -109,7 +109,7 @@ module MU
|
|
|
109
109
|
# Create these if necessary, then append them to the list of
|
|
110
110
|
# attachable_policies
|
|
111
111
|
if @config['raw_policies']
|
|
112
|
-
pol_arns = MU::Cloud
|
|
112
|
+
pol_arns = MU::Cloud.resourceClass("AWS", "Role").manageRawPolicies(
|
|
113
113
|
@config['raw_policies'],
|
|
114
114
|
basename: @deploy.getResourceName(@config['name']),
|
|
115
115
|
credentials: @credentials
|
|
@@ -120,7 +120,7 @@ module MU
|
|
|
120
120
|
|
|
121
121
|
if @config['attachable_policies']
|
|
122
122
|
configured_policies = @config['attachable_policies'].map { |p|
|
|
123
|
-
|
|
123
|
+
if p.is_a?(MU::Config::Ref)
|
|
124
124
|
p.cloud_id
|
|
125
125
|
else
|
|
126
126
|
p = MU::Config::Ref.get(p)
|
|
@@ -135,7 +135,7 @@ module MU
|
|
|
135
135
|
attached_policies.each { |a|
|
|
136
136
|
if !configured_policies.include?(a.policy_arn)
|
|
137
137
|
MU.log "Removing IAM policy #{a.policy_arn} from user #{@mu_name}", MU::NOTICE
|
|
138
|
-
MU::Cloud
|
|
138
|
+
MU::Cloud.resourceClass("AWS", "Role").purgePolicy(a.policy_arn, @credentials)
|
|
139
139
|
else
|
|
140
140
|
configured_policies.delete(a.policy_arn)
|
|
141
141
|
end
|
|
@@ -151,7 +151,7 @@ module MU
|
|
|
151
151
|
end
|
|
152
152
|
|
|
153
153
|
if @config['inline_policies']
|
|
154
|
-
docs = MU::Cloud
|
|
154
|
+
docs = MU::Cloud.resourceClass("AWS", "Role").genPolicyDocument(@config['inline_policies'], deploy_obj: @deploy)
|
|
155
155
|
docs.each { |doc|
|
|
156
156
|
MU.log "Putting user policy #{doc.keys.first} to user #{@cloud_id} "
|
|
157
157
|
MU::Cloud::AWS.iam(credentials: @credentials).put_user_policy(
|
|
@@ -189,17 +189,17 @@ module MU
|
|
|
189
189
|
# Remove all users associated with the currently loaded deployment.
|
|
190
190
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
191
191
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
192
|
-
# @param region [String]: The cloud provider region
|
|
193
192
|
# @return [void]
|
|
194
|
-
def self.cleanup(noop: false,
|
|
193
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, credentials: nil, flags: {})
|
|
194
|
+
MU.log "AWS::User.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
195
195
|
|
|
196
196
|
# XXX this doesn't belong here; maybe under roles, maybe as its own stupid first-class resource
|
|
197
197
|
resp = MU::Cloud::AWS.iam(credentials: credentials).list_policies(
|
|
198
|
-
path_prefix: "/"+
|
|
198
|
+
path_prefix: "/"+deploy_id+"/"
|
|
199
199
|
)
|
|
200
200
|
if resp and resp.policies
|
|
201
201
|
resp.policies.each { |policy|
|
|
202
|
-
MU.log "Deleting policy /#{
|
|
202
|
+
MU.log "Deleting policy /#{deploy_id}/#{policy.policy_name}"
|
|
203
203
|
if !noop
|
|
204
204
|
attachments = begin
|
|
205
205
|
MU::Cloud::AWS.iam(credentials: credentials).list_entities_for_policy(
|
|
@@ -257,7 +257,7 @@ module MU
|
|
|
257
257
|
}
|
|
258
258
|
retry
|
|
259
259
|
rescue ::Aws::IAM::Errors::NoSuchEntity
|
|
260
|
-
rescue
|
|
260
|
+
rescue StandardError => e
|
|
261
261
|
MU.log e.inspect, MU::ERR, details: policy
|
|
262
262
|
end
|
|
263
263
|
end
|
|
@@ -275,14 +275,17 @@ MU.log e.inspect, MU::ERR, details: policy
|
|
|
275
275
|
).tags
|
|
276
276
|
has_nodelete = false
|
|
277
277
|
has_ourdeploy = false
|
|
278
|
+
has_ourmaster = false
|
|
278
279
|
tags.each { |tag|
|
|
279
|
-
if tag.key == "MU-ID" and tag.value ==
|
|
280
|
+
if tag.key == "MU-ID" and tag.value == deploy_id
|
|
280
281
|
has_ourdeploy = true
|
|
282
|
+
elsif tag.key == "MU-MASTER-IP" and tag.value == MU.mu_public_ip
|
|
283
|
+
has_ourmaster = true
|
|
281
284
|
elsif tag.key == "MU-NO-DELETE" and tag.value == "true"
|
|
282
285
|
has_nodelete = true
|
|
283
286
|
end
|
|
284
287
|
}
|
|
285
|
-
if has_ourdeploy and !has_nodelete
|
|
288
|
+
if has_ourdeploy and !has_nodelete and (ignoremaster or has_ourmaster)
|
|
286
289
|
MU.log "Deleting IAM user #{u.path}#{u.user_name}"
|
|
287
290
|
if !@noop
|
|
288
291
|
begin
|
|
@@ -296,7 +299,7 @@ MU.log e.inspect, MU::ERR, details: policy
|
|
|
296
299
|
group_name: g.group_name
|
|
297
300
|
)
|
|
298
301
|
}
|
|
299
|
-
|
|
302
|
+
MU::Cloud::AWS.iam(credentials: credentials).get_login_profile(
|
|
300
303
|
user_name: u.user_name
|
|
301
304
|
)
|
|
302
305
|
MU.log "Deleting IAM login profile for #{u.user_name}"
|
|
@@ -381,7 +384,7 @@ MU.log e.inspect, MU::ERR, details: policy
|
|
|
381
384
|
# Reverse-map our cloud description into a runnable config hash.
|
|
382
385
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
383
386
|
# calculate our own accordingly based on what's live in the cloud.
|
|
384
|
-
def toKitten(
|
|
387
|
+
def toKitten(**_args)
|
|
385
388
|
bok = {
|
|
386
389
|
"cloud" => "AWS",
|
|
387
390
|
"credentials" => @credentials,
|
|
@@ -428,7 +431,7 @@ MU.log e.inspect, MU::ERR, details: policy
|
|
|
428
431
|
resp.policy_names.each { |pol_name|
|
|
429
432
|
pol = MU::Cloud::AWS.iam(credentials: @credentials).get_user_policy(user_name: @cloud_id, policy_name: pol_name)
|
|
430
433
|
doc = JSON.parse(URI.decode(pol.policy_document))
|
|
431
|
-
bok["inline_policies"] = MU::Cloud
|
|
434
|
+
bok["inline_policies"] = MU::Cloud.resourceClass("AWS", "Role").doc2MuPolicies(pol.policy_name, doc, bok["inline_policies"])
|
|
432
435
|
}
|
|
433
436
|
end
|
|
434
437
|
|
|
@@ -457,12 +460,12 @@ MU.log e.inspect, MU::ERR, details: policy
|
|
|
457
460
|
end
|
|
458
461
|
|
|
459
462
|
# Cloud-specific configuration properties.
|
|
460
|
-
# @param
|
|
463
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
461
464
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
462
|
-
def self.schema(
|
|
465
|
+
def self.schema(_config)
|
|
463
466
|
toplevel_required = []
|
|
464
467
|
polschema = MU::Config::Role.schema["properties"]["policies"]
|
|
465
|
-
polschema.deep_merge!(MU::Cloud
|
|
468
|
+
polschema.deep_merge!(MU::Cloud.resourceClass("AWS", "Role").condition_schema)
|
|
466
469
|
|
|
467
470
|
schema = {
|
|
468
471
|
"inline_policies" => polschema,
|
|
@@ -514,7 +517,7 @@ style long name, like +IAMTESTS-DEV-2018112815-IS-USER-FOO+"
|
|
|
514
517
|
# If we're attaching some managed policies, make sure all of the ones
|
|
515
518
|
# that should already exist do indeed exist
|
|
516
519
|
if user['attachable_policies']
|
|
517
|
-
ok = false if !MU::Cloud
|
|
520
|
+
ok = false if !MU::Cloud.resourceClass("AWS", "Role").validateAttachablePolicies(
|
|
518
521
|
user['attachable_policies'],
|
|
519
522
|
credentials: user['credentials'],
|
|
520
523
|
region: user['region']
|
|
@@ -527,7 +530,7 @@ style long name, like +IAMTESTS-DEV-2018112815-IS-USER-FOO+"
|
|
|
527
530
|
if configurator.haveLitterMate?(group, "groups")
|
|
528
531
|
need_dependency = true
|
|
529
532
|
else
|
|
530
|
-
found = MU::Cloud
|
|
533
|
+
found = MU::Cloud.resourceClass("AWS", "Group").find(cloud_id: group)
|
|
531
534
|
if found.nil? or found.empty? or (configurator.updating and
|
|
532
535
|
found.values.first.group.path == "/"+configurator.updating+"/")
|
|
533
536
|
groupdesc = {
|
|
@@ -539,11 +542,7 @@ style long name, like +IAMTESTS-DEV-2018112815-IS-USER-FOO+"
|
|
|
539
542
|
end
|
|
540
543
|
|
|
541
544
|
if need_dependency
|
|
542
|
-
user
|
|
543
|
-
user["dependencies"] << {
|
|
544
|
-
"type" => "group",
|
|
545
|
-
"name" => group
|
|
546
|
-
}
|
|
545
|
+
MU::Config.addDependency(user, group, "group")
|
|
547
546
|
end
|
|
548
547
|
}
|
|
549
548
|
end
|
|
File without changes
|
|
@@ -42,7 +42,7 @@ if ping -c 5 8.8.8.8 > /dev/null; then
|
|
|
42
42
|
<% if !$mu.skipApplyUpdates %>
|
|
43
43
|
set +e
|
|
44
44
|
if [ ! -f /.mu-installer-ran-updates ];then
|
|
45
|
-
|
|
45
|
+
echo "Applying package updates" > /etc/nologin
|
|
46
46
|
apt-get --fix-missing -y upgrade
|
|
47
47
|
touch /.mu-installer-ran-updates
|
|
48
48
|
if [ $? -eq 0 ]
|
|
@@ -58,7 +58,7 @@ if ping -c 5 8.8.8.8 > /dev/null; then
|
|
|
58
58
|
else
|
|
59
59
|
echo "FAILED PACKAGE UPDATE" >&2
|
|
60
60
|
fi
|
|
61
|
-
|
|
61
|
+
rm -f /etc/nologin
|
|
62
62
|
fi
|
|
63
63
|
<% end %>
|
|
64
64
|
elif [ -x /usr/bin/yum ];then
|
|
@@ -94,7 +94,7 @@ if ping -c 5 8.8.8.8 > /dev/null; then
|
|
|
94
94
|
<% if !$mu.skipApplyUpdates %>
|
|
95
95
|
set +e
|
|
96
96
|
if [ ! -f /.mu-installer-ran-updates ];then
|
|
97
|
-
|
|
97
|
+
echo "Applying package updates" > /etc/nologin
|
|
98
98
|
kernel_update=`yum list updates | grep kernel`
|
|
99
99
|
yum -y update
|
|
100
100
|
touch /.mu-installer-ran-updates
|
|
@@ -108,7 +108,7 @@ if ping -c 5 8.8.8.8 > /dev/null; then
|
|
|
108
108
|
else
|
|
109
109
|
echo "FAILED PACKAGE UPDATE" >&2
|
|
110
110
|
fi
|
|
111
|
-
|
|
111
|
+
rm -f /etc/nologin
|
|
112
112
|
fi
|
|
113
113
|
<% end %>
|
|
114
114
|
fi
|
|
@@ -116,6 +116,7 @@ else
|
|
|
116
116
|
/bin/logger "***** Unable to verify internet connectivity, skipping package updates from userdata"
|
|
117
117
|
touch /.mu-installer-ran-updates
|
|
118
118
|
fi
|
|
119
|
+
rm -f /etc/nologin
|
|
119
120
|
|
|
120
121
|
AWSCLI='command -v aws'
|
|
121
122
|
PIP='command -v pip'
|
|
@@ -23,7 +23,7 @@ function log
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
function fetchSecret([string]$file){
|
|
26
|
-
log "
|
|
26
|
+
log "aws.cmd --region $region s3 cp s3://<%= $mu.adminBucketName %>/$file $tmp/$file"
|
|
27
27
|
aws.cmd --region $region s3 cp s3://<%= $mu.adminBucketName %>/$file $tmp/$file
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -245,6 +245,7 @@ if($ingroup -ne $admin_username){
|
|
|
245
245
|
net localgroup WinRMRemoteWMIUsers__ /add $admin_username
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
+
importCert "$myname-winrm.crt" "root"
|
|
248
249
|
$winrmcert = importCert "$myname-winrm.crt" "TrustedPeople"
|
|
249
250
|
Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -Value $true
|
|
250
251
|
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name LocalAccountTokenFilterPolicy -Value 1
|
|
@@ -18,6 +18,7 @@ module MU
|
|
|
18
18
|
|
|
19
19
|
# Creation of Virtual Private Clouds and associated artifacts (routes, subnets, etc).
|
|
20
20
|
class VPC < MU::Cloud::VPC
|
|
21
|
+
require 'mu/providers/aws/vpc_subnet'
|
|
21
22
|
|
|
22
23
|
# Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
|
|
23
24
|
# @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
|
|
@@ -35,78 +36,40 @@ module MU
|
|
|
35
36
|
def create
|
|
36
37
|
MU.log "Creating VPC #{@mu_name}", details: @config
|
|
37
38
|
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_vpc(cidr_block: @config['ip_block']).vpc
|
|
38
|
-
|
|
39
|
+
@cloud_id = resp.vpc_id
|
|
40
|
+
@config['vpc_id'] = @cloud_id
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
MU::MommaCat.createTag(vpc_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
|
|
42
|
-
|
|
43
|
-
if @config['tags']
|
|
44
|
-
@config['tags'].each { |tag|
|
|
45
|
-
MU::MommaCat.createTag(vpc_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
|
46
|
-
}
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
if @config['optional_tags']
|
|
50
|
-
MU::MommaCat.listOptionalTags.each { |key, value|
|
|
51
|
-
MU::MommaCat.createTag(vpc_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
|
52
|
-
}
|
|
53
|
-
end
|
|
42
|
+
tag_me
|
|
54
43
|
|
|
55
44
|
if resp.state != "available"
|
|
56
45
|
begin
|
|
57
|
-
MU.log "Waiting for VPC #{@mu_name} (#{
|
|
46
|
+
MU.log "Waiting for VPC #{@mu_name} (#{@cloud_id}) to be available", MU::NOTICE
|
|
58
47
|
sleep 5
|
|
59
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpcs(vpc_ids: [
|
|
48
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpcs(vpc_ids: [@cloud_id]).vpcs.first
|
|
60
49
|
end while resp.state != "available"
|
|
61
50
|
# There's a default route table that comes with. Let's tag it.
|
|
62
51
|
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
63
52
|
filters: [
|
|
64
53
|
{
|
|
65
54
|
name: "vpc-id",
|
|
66
|
-
values: [
|
|
55
|
+
values: [@cloud_id]
|
|
67
56
|
}
|
|
68
57
|
]
|
|
69
58
|
)
|
|
70
59
|
resp.route_tables.each { |rtb|
|
|
71
|
-
|
|
72
|
-
if @config['tags']
|
|
73
|
-
@config['tags'].each { |tag|
|
|
74
|
-
MU::MommaCat.createTag(rtb.route_table_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
|
75
|
-
}
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
MU::Cloud::AWS.createStandardTags(rtb.route_table_id, region: @config['region'], credentials: @config['credentials'])
|
|
79
|
-
|
|
80
|
-
if @config['optional_tags']
|
|
81
|
-
MU::MommaCat.listOptionalTags.each { |key, value|
|
|
82
|
-
MU::MommaCat.createTag(rtb.route_table_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
|
83
|
-
}
|
|
84
|
-
end
|
|
60
|
+
tag_me(rtb.route_table_id, @mu_name+"-#DEFAULTPRIV")
|
|
85
61
|
}
|
|
86
62
|
end
|
|
87
|
-
@config['vpc_id'] = vpc_id
|
|
88
|
-
@cloud_id = vpc_id
|
|
89
63
|
|
|
90
64
|
if @config['create_internet_gateway']
|
|
91
65
|
MU.log "Creating Internet Gateway #{@mu_name}"
|
|
92
66
|
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_internet_gateway
|
|
93
67
|
internet_gateway_id = resp.internet_gateway.internet_gateway_id
|
|
94
68
|
sleep 5
|
|
95
|
-
MU::Cloud::AWS.createStandardTags(internet_gateway_id, region: @config['region'], credentials: @config['credentials'])
|
|
96
|
-
MU::MommaCat.createTag(internet_gateway_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
|
|
97
|
-
if @config['tags']
|
|
98
|
-
@config['tags'].each { |tag|
|
|
99
|
-
MU::MommaCat.createTag(internet_gateway_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
|
100
|
-
}
|
|
101
|
-
end
|
|
102
69
|
|
|
103
|
-
|
|
104
|
-
MU::MommaCat.listOptionalTags.each { |key, value|
|
|
105
|
-
MU::MommaCat.createTag(internet_gateway_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
|
106
|
-
}
|
|
107
|
-
end
|
|
70
|
+
tag_me(internet_gateway_id)
|
|
108
71
|
|
|
109
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).attach_internet_gateway(vpc_id:
|
|
72
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).attach_internet_gateway(vpc_id: @cloud_id, internet_gateway_id: internet_gateway_id)
|
|
110
73
|
@config['internet_gateway_id'] = internet_gateway_id
|
|
111
74
|
end
|
|
112
75
|
|
|
@@ -165,237 +128,35 @@ module MU
|
|
|
165
128
|
)
|
|
166
129
|
end
|
|
167
130
|
|
|
168
|
-
nat_gateways =
|
|
169
|
-
if !@config['subnets'].nil?
|
|
170
|
-
allocation_ids = []
|
|
171
|
-
subnet_semaphore = Mutex.new
|
|
172
|
-
subnetthreads = Array.new
|
|
173
|
-
parent_thread_id = Thread.current.object_id
|
|
174
|
-
azs = []
|
|
175
|
-
@config['subnets'].each { |subnet|
|
|
176
|
-
subnet_name = @config['name']+"-"+subnet['name']
|
|
177
|
-
MU.log "Creating Subnet #{subnet_name} (#{subnet['ip_block']})", details: subnet
|
|
178
|
-
azs = MU::Cloud::AWS.listAZs(region: @config['region'], credentials: @config['credentials']) if azs.size == 0
|
|
179
|
-
if !subnet['availability_zone'].nil?
|
|
180
|
-
az = subnet['availability_zone']
|
|
181
|
-
else
|
|
182
|
-
az = azs.pop
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
subnetthreads << Thread.new {
|
|
186
|
-
MU.dupGlobals(parent_thread_id)
|
|
187
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_subnet(
|
|
188
|
-
vpc_id: vpc_id,
|
|
189
|
-
cidr_block: subnet['ip_block'],
|
|
190
|
-
availability_zone: az
|
|
191
|
-
).subnet
|
|
192
|
-
subnet_id = subnet['subnet_id'] = resp.subnet_id
|
|
193
|
-
MU::Cloud::AWS.createStandardTags(subnet_id, region: @config['region'], credentials: @config['credentials'])
|
|
194
|
-
MU::MommaCat.createTag(subnet_id, "Name", @mu_name+"-"+subnet['name'], region: @config['region'], credentials: @config['credentials'])
|
|
195
|
-
if @config['tags']
|
|
196
|
-
@config['tags'].each { |tag|
|
|
197
|
-
MU::MommaCat.createTag(subnet_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
|
198
|
-
}
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
if @config['optional_tags']
|
|
202
|
-
MU::MommaCat.listOptionalTags.each { |key, value|
|
|
203
|
-
MU::MommaCat.createTag(subnet_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
|
204
|
-
}
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
retries = 0
|
|
208
|
-
begin
|
|
209
|
-
if resp.state != "available"
|
|
210
|
-
begin
|
|
211
|
-
MU.log "Waiting for Subnet #{subnet_name} (#{subnet_id}) to be available", MU::NOTICE if retries > 0 and (retries % 3) == 0
|
|
212
|
-
sleep 5
|
|
213
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_subnets(subnet_ids: [subnet_id]).subnets.first
|
|
214
|
-
rescue Aws::EC2::Errors::InvalidSubnetIDNotFound => e
|
|
215
|
-
sleep 10
|
|
216
|
-
retry
|
|
217
|
-
end while resp.state != "available"
|
|
218
|
-
end
|
|
219
|
-
rescue NoMethodError => e
|
|
220
|
-
if retries <= 3
|
|
221
|
-
MU.log "Got bogus Aws::EmptyResponse error on #{subnet_id} (retries used: #{retries}/3)", MU::WARN
|
|
222
|
-
retries = retries + 1
|
|
223
|
-
sleep 5
|
|
224
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_subnets(subnet_ids: [subnet_id]).subnets.first
|
|
225
|
-
retry
|
|
226
|
-
else
|
|
227
|
-
raise e
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
if !subnet['route_table'].nil?
|
|
232
|
-
routes = {}
|
|
233
|
-
@config['route_tables'].each { |tbl|
|
|
234
|
-
routes[tbl['name']] = tbl
|
|
235
|
-
}
|
|
236
|
-
if routes.nil? or routes[subnet['route_table']].nil?
|
|
237
|
-
MU.log "Subnet #{subnet_name} references non-existent route #{subnet['route_table']}", MU::ERR, details: @deploy.deployment['vpcs']
|
|
238
|
-
raise MuError, "deploy failure"
|
|
239
|
-
end
|
|
240
|
-
MU.log "Associating Route Table '#{subnet['route_table']}' (#{routes[subnet['route_table']]['route_table_id']}) with #{subnet_name}"
|
|
241
|
-
retries = 0
|
|
242
|
-
begin
|
|
243
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).associate_route_table(
|
|
244
|
-
route_table_id: routes[subnet['route_table']]['route_table_id'],
|
|
245
|
-
subnet_id: subnet_id
|
|
246
|
-
)
|
|
247
|
-
rescue Aws::EC2::Errors::InvalidRouteTableIDNotFound => e
|
|
248
|
-
retries = retries + 1
|
|
249
|
-
if retries < 10
|
|
250
|
-
sleep 10
|
|
251
|
-
retry
|
|
252
|
-
else
|
|
253
|
-
raise MuError, e.inspect
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
end
|
|
257
|
-
retries = 0
|
|
258
|
-
begin
|
|
259
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_subnets(subnet_ids: [subnet_id]).subnets.first
|
|
260
|
-
rescue Aws::EC2::Errors::InvalidSubnetIDNotFound => e
|
|
261
|
-
if retries < 10
|
|
262
|
-
MU.log "Got #{e.inspect}, waiting and retrying", MU::WARN
|
|
263
|
-
sleep 10
|
|
264
|
-
retries = retries + 1
|
|
265
|
-
retry
|
|
266
|
-
end
|
|
267
|
-
raise MuError, e.inspect, e.backtrace
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
if subnet['is_public'] && subnet['create_nat_gateway']
|
|
271
|
-
MU::MommaCat.lock("nat-gateway-eipalloc")
|
|
272
|
-
filters = [{name: "domain", values: ["vpc"]}]
|
|
273
|
-
eips = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_addresses(filters: filters).addresses
|
|
274
|
-
allocation_id = nil
|
|
275
|
-
eips.each { |eip|
|
|
276
|
-
next if !eip.association_id.nil? and !eip.association_id.empty?
|
|
277
|
-
if (eip.private_ip_address.nil? || eip.private_ip_address.empty?) and MU::MommaCat.lock(eip.allocation_id, true, true)
|
|
278
|
-
if !allocation_ids.include?(eip.allocation_id)
|
|
279
|
-
allocation_id = eip.allocation_id
|
|
280
|
-
break
|
|
281
|
-
end
|
|
282
|
-
end
|
|
283
|
-
}
|
|
131
|
+
nat_gateways = create_subnets
|
|
284
132
|
|
|
285
|
-
|
|
286
|
-
allocation_id = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).allocate_address(domain: "vpc").allocation_id
|
|
287
|
-
MU::MommaCat.lock(allocation_id, false, true)
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
allocation_ids << allocation_id
|
|
291
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_nat_gateway(
|
|
292
|
-
subnet_id: subnet['subnet_id'],
|
|
293
|
-
allocation_id: allocation_id,
|
|
294
|
-
).nat_gateway
|
|
295
|
-
|
|
296
|
-
nat_gateway_id = resp.nat_gateway_id
|
|
297
|
-
attempts = 0
|
|
298
|
-
MU::MommaCat.unlock("nat-gateway-eipalloc")
|
|
299
|
-
while resp.class.name != "Aws::EC2::Types::NatGateway" or resp.state == "pending"
|
|
300
|
-
MU.log "Waiting for nat gateway #{nat_gateway_id} () to become available (EIP allocation: #{allocation_id})" if attempts % 5 == 0
|
|
301
|
-
sleep 30
|
|
302
|
-
begin
|
|
303
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_nat_gateways(nat_gateway_ids: [nat_gateway_id]).nat_gateways.first
|
|
304
|
-
rescue Aws::EmptyStructure, NoMethodError
|
|
305
|
-
sleep 5
|
|
306
|
-
retry
|
|
307
|
-
end
|
|
308
|
-
if attempts > 30
|
|
309
|
-
MU::MommaCat.unlock(allocation_id, true)
|
|
310
|
-
raise MuError, "Timed out while waiting for NAT Gateway #{nat_gateway_id}: #{resp}"
|
|
311
|
-
end
|
|
312
|
-
attempts += 1
|
|
313
|
-
end
|
|
314
|
-
MU::MommaCat.unlock(allocation_id, true)
|
|
315
|
-
|
|
316
|
-
raise MuError, "NAT Gateway failed #{nat_gateway_id}: #{resp}" if resp.state == "failed"
|
|
317
|
-
nat_gateways << {'id' => nat_gateway_id, 'availability_zone' => subnet['availability_zone']}
|
|
318
|
-
@tags.each_pair { |k, v|
|
|
319
|
-
MU::MommaCat.createTag(nat_gateway_id, k, v, region: @config['region'], credentials: @config['credentials'])
|
|
320
|
-
}
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
if subnet.has_key?("map_public_ips")
|
|
324
|
-
retries = 0
|
|
325
|
-
begin
|
|
326
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).modify_subnet_attribute(
|
|
327
|
-
subnet_id: subnet_id,
|
|
328
|
-
map_public_ip_on_launch: {
|
|
329
|
-
value: subnet['map_public_ips'],
|
|
330
|
-
}
|
|
331
|
-
)
|
|
332
|
-
rescue Aws::EC2::Errors::InvalidSubnetIDNotFound => e
|
|
333
|
-
if retries < 10
|
|
334
|
-
MU.log "Got #{e.inspect} while trying to enable map_public_ips on subnet, waiting and retrying", MU::WARN
|
|
335
|
-
sleep 10
|
|
336
|
-
retries += 1
|
|
337
|
-
retry
|
|
338
|
-
end
|
|
339
|
-
raise MuError, "Got #{e.inspect}, #{e.backtrace} while trying to enable map_public_ips on subnet"
|
|
340
|
-
end
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
if subnet["enable_traffic_logging"]
|
|
344
|
-
loggroup = @deploy.findLitterMate(name: @config['name']+"loggroup", type: "logs")
|
|
345
|
-
logrole = @deploy.findLitterMate(name: @config['name']+"logrole", type: "roles")
|
|
346
|
-
MU.log "Enabling traffic logging on Subnet #{subnet_name} in VPC #{@mu_name} to log group #{loggroup.mu_name}"
|
|
347
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_flow_logs(
|
|
348
|
-
resource_ids: [subnet_id],
|
|
349
|
-
resource_type: "Subnet",
|
|
350
|
-
traffic_type: subnet["traffic_type_to_log"],
|
|
351
|
-
log_group_name: loggroup.mu_name,
|
|
352
|
-
deliver_logs_permission_arn: logrole.cloudobj.arn
|
|
353
|
-
)
|
|
354
|
-
end
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
subnetthreads.each { |t|
|
|
359
|
-
t.join
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
notify
|
|
363
|
-
end
|
|
133
|
+
notify
|
|
364
134
|
|
|
365
135
|
if !nat_gateways.empty?
|
|
366
136
|
nat_gateways.each { |gateway|
|
|
367
137
|
@config['subnets'].each { |subnet|
|
|
368
|
-
if subnet['is_public']
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
else
|
|
389
|
-
raise e
|
|
390
|
-
end
|
|
391
|
-
rescue Aws::EC2::Errors::RouteAlreadyExists => e
|
|
392
|
-
MU.log "Attempt to create duplicate route to #{route['destination_network']} for #{gateway['id']} in #{rtb['route_table_id']}", MU::WARN
|
|
393
|
-
end
|
|
394
|
-
end
|
|
395
|
-
}
|
|
396
|
-
end
|
|
138
|
+
next if subnet['is_public'] != false or subnet['availability_zone'] != gateway['availability_zone']
|
|
139
|
+
|
|
140
|
+
@config['route_tables'].each { |rtb|
|
|
141
|
+
next if rtb['name'] != subnet['route_table']
|
|
142
|
+
rtb['routes'].each { |route|
|
|
143
|
+
next if route['gateway'] != '#NAT'
|
|
144
|
+
route_config = {
|
|
145
|
+
:route_table_id => rtb['route_table_id'],
|
|
146
|
+
:destination_cidr_block => route['destination_network'],
|
|
147
|
+
:nat_gateway_id => gateway['id']
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
MU.log "Creating route for #{route['destination_network']} through NAT gatway #{gateway['id']}", details: route_config
|
|
151
|
+
MU.retrier([Aws::EC2::Errors::InvalidNatGatewayIDNotFound], wait: 10, max: 5) {
|
|
152
|
+
begin
|
|
153
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route(route_config)
|
|
154
|
+
rescue Aws::EC2::Errors::RouteAlreadyExists
|
|
155
|
+
MU.log "Attempt to create duplicate route to #{route['destination_network']} for #{gateway['id']} in #{rtb['route_table_id']}", MU::WARN
|
|
156
|
+
end
|
|
157
|
+
}
|
|
397
158
|
}
|
|
398
|
-
|
|
159
|
+
}
|
|
399
160
|
}
|
|
400
161
|
}
|
|
401
162
|
end
|
|
@@ -403,14 +164,14 @@ module MU
|
|
|
403
164
|
if @config['enable_dns_support']
|
|
404
165
|
MU.log "Enabling DNS support in #{@mu_name}"
|
|
405
166
|
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).modify_vpc_attribute(
|
|
406
|
-
vpc_id:
|
|
167
|
+
vpc_id: @cloud_id,
|
|
407
168
|
enable_dns_support: {value: @config['enable_dns_support']}
|
|
408
169
|
)
|
|
409
170
|
end
|
|
410
171
|
if @config['enable_dns_hostnames']
|
|
411
172
|
MU.log "Enabling DNS hostnames in #{@mu_name}"
|
|
412
173
|
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).modify_vpc_attribute(
|
|
413
|
-
vpc_id:
|
|
174
|
+
vpc_id: @cloud_id,
|
|
414
175
|
enable_dns_hostnames: {value: @config['enable_dns_hostnames']}
|
|
415
176
|
)
|
|
416
177
|
end
|
|
@@ -439,29 +200,16 @@ module MU
|
|
|
439
200
|
dhcp_configurations: dhcpopts
|
|
440
201
|
)
|
|
441
202
|
dhcpopt_id = resp.dhcp_options.dhcp_options_id
|
|
442
|
-
|
|
443
|
-
MU::MommaCat.createTag(dhcpopt_id, "Name", @mu_name, region: @config['region'], credentials: @config['credentials'])
|
|
444
|
-
|
|
445
|
-
if @config['tags']
|
|
446
|
-
@config['tags'].each { |tag|
|
|
447
|
-
MU::MommaCat.createTag(dhcpopt_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
|
448
|
-
}
|
|
449
|
-
end
|
|
203
|
+
tag_me(dhcpopt_id)
|
|
450
204
|
|
|
451
|
-
|
|
452
|
-
MU::MommaCat.listOptionalTags.each { |key, value|
|
|
453
|
-
MU::MommaCat.createTag(dhcpopt_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
|
454
|
-
}
|
|
455
|
-
end
|
|
456
|
-
|
|
457
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).associate_dhcp_options(dhcp_options_id: dhcpopt_id, vpc_id: vpc_id)
|
|
205
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).associate_dhcp_options(dhcp_options_id: dhcpopt_id, vpc_id: @cloud_id)
|
|
458
206
|
end
|
|
459
207
|
notify
|
|
460
208
|
|
|
461
209
|
if !MU::Cloud::AWS.isGovCloud?(@config['region'])
|
|
462
210
|
mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu", credentials: @config['credentials']).values.first
|
|
463
211
|
if !mu_zone.nil?
|
|
464
|
-
MU::Cloud
|
|
212
|
+
MU::Cloud.resourceClass("AWS", "DNSZone").toggleVPCAccess(id: mu_zone.id, vpc_id: @cloud_id, region: @config['region'], credentials: @config['credentials'])
|
|
465
213
|
end
|
|
466
214
|
end
|
|
467
215
|
loadSubnets
|
|
@@ -472,9 +220,6 @@ module MU
|
|
|
472
220
|
# Canonical Amazon Resource Number for this resource
|
|
473
221
|
# @return [String]
|
|
474
222
|
def arn
|
|
475
|
-
puts @config['region']
|
|
476
|
-
puts MU::Cloud::AWS.credToAcct(@config['credentials'])
|
|
477
|
-
puts @cloud_id
|
|
478
223
|
"arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":ec2:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@config['credentials'])+":vpc/"+@cloud_id
|
|
479
224
|
end
|
|
480
225
|
|
|
@@ -491,202 +236,7 @@ module MU
|
|
|
491
236
|
# Generate peering connections
|
|
492
237
|
if !@config['peers'].nil? and @config['peers'].size > 0
|
|
493
238
|
@config['peers'].each { |peer|
|
|
494
|
-
|
|
495
|
-
peer_id = nil
|
|
496
|
-
peer['name'] ||= peer['vpc_name']
|
|
497
|
-
peer['id'] ||= peer['vpc_id']
|
|
498
|
-
|
|
499
|
-
# If we know this to be a sibling VPC elsewhere in our stack,
|
|
500
|
-
# go fetch it, and fix it if we've been misconfigured with a
|
|
501
|
-
# duplicate peering connection
|
|
502
|
-
if peer['vpc']['name'] and !peer['account']
|
|
503
|
-
peer_obj = @deploy.findLitterMate(name: peer['vpc']['name'], type: "vpcs")
|
|
504
|
-
if peer_obj
|
|
505
|
-
if peer_obj.config['peers']
|
|
506
|
-
skipme = false
|
|
507
|
-
peer_obj.config['peers'].each { |peerpeer|
|
|
508
|
-
if peerpeer['vpc']['name'] == @config['name'] and
|
|
509
|
-
(peer['vpc']['name'] <=> @config['name']) == -1
|
|
510
|
-
skipme = true
|
|
511
|
-
MU.log "VPCs #{peer['vpc']['name']} and #{@config['name']} both declare mutual peering connection, ignoring #{@config['name']}'s redundant declaration", MU::DEBUG
|
|
512
|
-
# XXX and if deploy_id matches or is unset
|
|
513
|
-
end
|
|
514
|
-
}
|
|
515
|
-
end
|
|
516
|
-
next if skipme
|
|
517
|
-
peer['account'] = MU::Cloud::AWS.credToAcct(peer_obj.credentials)
|
|
518
|
-
peer['vpc']['id'] = peer_obj.cloud_id
|
|
519
|
-
peer['vpc']['region'] ||= peer_obj.config['region']
|
|
520
|
-
end
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
# If we still don't know our peer's vpc identifier, go fishing
|
|
524
|
-
if !peer_obj
|
|
525
|
-
tag_key, tag_value = peer['vpc']['tag'].split(/=/, 2) if !peer['vpc']['tag'].nil?
|
|
526
|
-
if peer['vpc']['deploy_id'].nil? and peer['vpc']['id'].nil? and tag_key.nil?
|
|
527
|
-
peer['vpc']['deploy_id'] = @deploy.deploy_id
|
|
528
|
-
end
|
|
529
|
-
peer_obj = MU::MommaCat.findStray(
|
|
530
|
-
"AWS",
|
|
531
|
-
"vpcs",
|
|
532
|
-
deploy_id: peer['vpc']['deploy_id'],
|
|
533
|
-
cloud_id: peer['vpc']['id'],
|
|
534
|
-
# XXX we need a credentials argument here... maybe
|
|
535
|
-
name: peer['vpc']['name'],
|
|
536
|
-
tag_key: tag_key,
|
|
537
|
-
tag_value: tag_value,
|
|
538
|
-
dummy_ok: true,
|
|
539
|
-
region: peer['vpc']['region']
|
|
540
|
-
)
|
|
541
|
-
MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
|
|
542
|
-
raise MuError, "No result looking for #{@mu_name}'s peer VPCs (#{peer['vpc']})" if peer_obj.nil? or peer_obj.first.nil?
|
|
543
|
-
peer_obj = peer_obj.first
|
|
544
|
-
peer['account'] ||= MU::Cloud::AWS.credToAcct(peer_obj.credentials)
|
|
545
|
-
peer['vpc']['id'] ||= peer_obj.cloud_id
|
|
546
|
-
peer['vpc']['region'] ||= peer_obj.config['region']
|
|
547
|
-
end
|
|
548
|
-
|
|
549
|
-
peer_id = peer['vpc']['id']
|
|
550
|
-
peer['account'] ||= MU::Cloud::AWS.account_number
|
|
551
|
-
|
|
552
|
-
# See if the peering connection exists before we bother
|
|
553
|
-
# creating it.
|
|
554
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
|
|
555
|
-
filters: [
|
|
556
|
-
{
|
|
557
|
-
name: "requester-vpc-info.vpc-id",
|
|
558
|
-
values: [@cloud_id]
|
|
559
|
-
},
|
|
560
|
-
{
|
|
561
|
-
name: "accepter-vpc-info.vpc-id",
|
|
562
|
-
values: [peer_id.to_s]
|
|
563
|
-
}
|
|
564
|
-
]
|
|
565
|
-
)
|
|
566
|
-
|
|
567
|
-
peering_id = if !resp or !resp.vpc_peering_connections or
|
|
568
|
-
resp.vpc_peering_connections.empty?
|
|
569
|
-
|
|
570
|
-
MU.log "Setting peering connection from VPC #{@config['name']} (#{@cloud_id} in account #{MU::Cloud::AWS.credToAcct(@config['credentials'])}) to #{peer_id} in account #{peer['account']}", details: peer
|
|
571
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_vpc_peering_connection(
|
|
572
|
-
vpc_id: @cloud_id,
|
|
573
|
-
peer_vpc_id: peer_id,
|
|
574
|
-
peer_owner_id: peer['account'],
|
|
575
|
-
peer_region: peer['vpc']['region']
|
|
576
|
-
)
|
|
577
|
-
resp.vpc_peering_connection.vpc_peering_connection_id
|
|
578
|
-
else
|
|
579
|
-
resp.vpc_peering_connections.first.vpc_peering_connection_id
|
|
580
|
-
end
|
|
581
|
-
|
|
582
|
-
peering_name = @deploy.getResourceName(@config['name']+"-PEER-"+peer['vpc']['id'])
|
|
583
|
-
|
|
584
|
-
MU::Cloud::AWS.createStandardTags(peering_id, region: @config['region'], credentials: @config['credentials'])
|
|
585
|
-
MU::MommaCat.createTag(peering_id, "Name", peering_name, region: @config['region'], credentials: @config['credentials'])
|
|
586
|
-
|
|
587
|
-
if @config['optional_tags']
|
|
588
|
-
MU::MommaCat.listOptionalTags.each { |key, value|
|
|
589
|
-
MU::MommaCat.createTag(peering_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
|
590
|
-
}
|
|
591
|
-
end
|
|
592
|
-
|
|
593
|
-
if @config['tags']
|
|
594
|
-
@config['tags'].each { |tag|
|
|
595
|
-
MU::MommaCat.createTag(peering_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
|
596
|
-
}
|
|
597
|
-
end
|
|
598
|
-
|
|
599
|
-
# Create routes to our new friend.
|
|
600
|
-
MU::Cloud::AWS::VPC.listAllSubnetRouteTables(@cloud_id, region: @config['region'], credentials: @config['credentials']).each { |rtb_id|
|
|
601
|
-
my_route_config = {
|
|
602
|
-
:route_table_id => rtb_id,
|
|
603
|
-
:destination_cidr_block => peer_obj.cloud_desc.cidr_block,
|
|
604
|
-
:vpc_peering_connection_id => peering_id
|
|
605
|
-
}
|
|
606
|
-
rtbdesc = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
607
|
-
route_table_ids: [rtb_id]
|
|
608
|
-
).route_tables.first
|
|
609
|
-
already_exists = false
|
|
610
|
-
rtbdesc.routes.each { |r|
|
|
611
|
-
if r.destination_cidr_block == peer_obj.cloud_desc.cidr_block
|
|
612
|
-
if r.vpc_peering_connection_id != peering_id
|
|
613
|
-
MU.log "Attempt to create duplicate route to #{peer_obj.cloud_desc.cidr_block} from VPC #{@config['name']}", MU::ERR, details: r
|
|
614
|
-
raise MuError, "Can't create route via #{peering_id}, a route to #{peer_obj.cloud_desc.cidr_block} already exists"
|
|
615
|
-
else
|
|
616
|
-
already_exists = true
|
|
617
|
-
end
|
|
618
|
-
end
|
|
619
|
-
}
|
|
620
|
-
next if already_exists
|
|
621
|
-
|
|
622
|
-
MU.log "Creating peering route to #{peer_obj.cloud_desc.cidr_block} in #{peer['vpc']['region']} from VPC #{@config['name']} in #{@config['region']}"
|
|
623
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route(my_route_config)
|
|
624
|
-
} # MU::Cloud::AWS::VPC.listAllSubnetRouteTables
|
|
625
|
-
|
|
626
|
-
begin
|
|
627
|
-
cnxn = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
|
|
628
|
-
vpc_peering_connection_ids: [peering_id]
|
|
629
|
-
).vpc_peering_connections.first
|
|
630
|
-
|
|
631
|
-
if cnxn.status.code == "pending-acceptance"
|
|
632
|
-
if ((!peer_obj.nil? and !peer_obj.deploydata.nil? and peer_obj.deploydata['auto_accept_peers']) or $MU_CFG['allow_invade_foreign_vpcs'])
|
|
633
|
-
MU.log "Auto-accepting peering connection from VPC #{@config['name']} (#{@cloud_id}) to #{peer_id}", MU::NOTICE
|
|
634
|
-
begin
|
|
635
|
-
MU::Cloud::AWS.ec2(region: peer['vpc']['region'], credentials: peer['account']).accept_vpc_peering_connection(
|
|
636
|
-
vpc_peering_connection_id: peering_id,
|
|
637
|
-
)
|
|
638
|
-
if peer['account'] != MU::Cloud::AWS.credToAcct(@config['credentials'])
|
|
639
|
-
# this seems to take a while across accounts
|
|
640
|
-
sleep 5
|
|
641
|
-
end
|
|
642
|
-
cnxn = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
|
|
643
|
-
vpc_peering_connection_ids: [peering_id]
|
|
644
|
-
).vpc_peering_connections.first
|
|
645
|
-
rescue Aws::EC2::Errors::VpcPeeringConnectionAlreadyExists => e
|
|
646
|
-
MU.log "Attempt to create duplicate peering connection to #{peer_id} from VPC #{@config['name']}", MU::WARN
|
|
647
|
-
end
|
|
648
|
-
|
|
649
|
-
# Create routes back from our new friend to us.
|
|
650
|
-
MU::Cloud::AWS::VPC.listAllSubnetRouteTables(peer_id, region: peer['vpc']['region'], credentials: peer['account']).uniq.each { |rtb_id|
|
|
651
|
-
peer_route_config = {
|
|
652
|
-
:route_table_id => rtb_id,
|
|
653
|
-
:destination_cidr_block => @config['ip_block'],
|
|
654
|
-
:vpc_peering_connection_id => peering_id
|
|
655
|
-
}
|
|
656
|
-
begin
|
|
657
|
-
resp = MU::Cloud::AWS.ec2(region: peer['vpc']['region'], credentials: peer['account']).create_route(peer_route_config)
|
|
658
|
-
rescue Aws::EC2::Errors::RouteAlreadyExists => e
|
|
659
|
-
rtbdesc = MU::Cloud::AWS.ec2(region: peer['vpc']['region'], credentials: peer['account']).describe_route_tables(
|
|
660
|
-
route_table_ids: [rtb_id]
|
|
661
|
-
).route_tables.first
|
|
662
|
-
rtbdesc.routes.each { |r|
|
|
663
|
-
if r.destination_cidr_block == @config['ip_block']
|
|
664
|
-
if r.vpc_peering_connection_id != peering_id
|
|
665
|
-
MU.log "Attempt to create duplicate route to VPC #{@config['name']} (#{@config['ip_block']}) from peer VPC #{peer_id}'s route table #{rtb_id}", MU::ERR
|
|
666
|
-
end
|
|
667
|
-
end
|
|
668
|
-
}
|
|
669
|
-
end
|
|
670
|
-
}
|
|
671
|
-
else
|
|
672
|
-
MU.log "VPC #{peer_id} is not managed by this Mu server or is not configured to auto-accept peering requests. You must accept the peering request for '#{@config['name']}' (#{@cloud_id}) by hand.", MU::WARN, details: "In the AWS Console, go to VPC => Peering Connections and look in the Actions drop-down. You can also set 'Invade Foreign VPCs' to 'true' using mu-configure to auto-accept all peering connections within this account, regardless of whether this Mu server owns the VPCs. This setting is per-user."
|
|
673
|
-
end
|
|
674
|
-
end
|
|
675
|
-
|
|
676
|
-
if cnxn.status.code == "failed" or cnxn.status.code == "rejected" or cnxn.status.code == "expired" or cnxn.status.code == "deleted"
|
|
677
|
-
MU.log "VPC peering connection from VPC #{@config['name']} (#{@cloud_id} in #{@config['region']}) to #{peer_id} in #{peer['vpc']['region']} #{cnxn.status.code}: #{cnxn.status.message}", MU::ERR
|
|
678
|
-
begin
|
|
679
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).delete_vpc_peering_connection(
|
|
680
|
-
vpc_peering_connection_id: peering_id
|
|
681
|
-
)
|
|
682
|
-
rescue Aws::EC2::Errors::InvalidStateTransition => e
|
|
683
|
-
# XXX apparently this is normal?
|
|
684
|
-
end
|
|
685
|
-
raise MuError, "VPC peering connection from VPC #{@config['name']} (#{@cloud_id}) to #{peer_id} #{cnxn.status.code}: #{cnxn.status.message}"
|
|
686
|
-
end
|
|
687
|
-
|
|
688
|
-
end while cnxn.status.code != "active" and !((peer_obj.nil? or peer_obj.deploydata.nil? or !peer_obj.deploydata['auto_accept_peers']) and cnxn.status.code == "pending-acceptance")
|
|
689
|
-
|
|
239
|
+
peerWith(peer)
|
|
690
240
|
}
|
|
691
241
|
end
|
|
692
242
|
|
|
@@ -713,7 +263,7 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
|
|
|
713
263
|
route_config[:instance_id] = nat_instance.cloud_id
|
|
714
264
|
|
|
715
265
|
MU.log "Creating route for #{route['destination_network']} through NAT host #{nat_instance.cloud_id}", details: route_config
|
|
716
|
-
|
|
266
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route(route_config)
|
|
717
267
|
end
|
|
718
268
|
}
|
|
719
269
|
|
|
@@ -756,7 +306,7 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
|
|
|
756
306
|
map[vpc.vpc_id] = vpc
|
|
757
307
|
}
|
|
758
308
|
return map
|
|
759
|
-
rescue Aws::EC2::Errors::InvalidVpcIDNotFound
|
|
309
|
+
rescue Aws::EC2::Errors::InvalidVpcIDNotFound
|
|
760
310
|
end
|
|
761
311
|
else
|
|
762
312
|
resp = MU::Cloud::AWS.ec2(region: args[:region], credentials: args[:credentials]).describe_vpcs
|
|
@@ -774,7 +324,7 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
|
|
|
774
324
|
# Reverse-map our cloud description into a runnable config hash.
|
|
775
325
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
776
326
|
# calculate our own accordingly based on what's live in the cloud.
|
|
777
|
-
def toKitten(
|
|
327
|
+
def toKitten(**_args)
|
|
778
328
|
bok = {
|
|
779
329
|
"cloud" => "AWS",
|
|
780
330
|
"credentials" => @config['credentials'],
|
|
@@ -838,12 +388,9 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
|
|
|
838
388
|
if rtb_desc.associations
|
|
839
389
|
rtb_desc.associations.each { |assoc|
|
|
840
390
|
if assoc.subnet_id
|
|
841
|
-
if associations[assoc.subnet_id] and associations[assoc.subnet_id] != rtb['name']
|
|
842
|
-
MU.log "wait more than one route table association for #{assoc.subnet_id} what", MU::WARN, details: associations[assoc.subnet_id]+" => "+rtb['name']
|
|
843
|
-
end
|
|
844
391
|
associations[assoc.subnet_id] = rtb['name']
|
|
845
392
|
elsif assoc.gateway_id
|
|
846
|
-
MU.log "association I don't
|
|
393
|
+
MU.log " Saw a route table association I don't know how to adopt in #{@cloud_id}", MU::WARN, details: rtb_desc
|
|
847
394
|
end
|
|
848
395
|
}
|
|
849
396
|
end
|
|
@@ -903,20 +450,18 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
903
450
|
# Describe subnets associated with this VPC. We'll compose identifying
|
|
904
451
|
# information similar to what MU::Cloud.describe builds for first-class
|
|
905
452
|
# resources.
|
|
906
|
-
#
|
|
907
|
-
# that work like first-class objects. How would we enforce that?
|
|
908
|
-
# @return [Array<Hash>]: A list of cloud provider identifiers of subnets associated with this VPC.
|
|
453
|
+
# @return [Array<MU::Cloud::AWS::VPC::Subnet>]
|
|
909
454
|
def loadSubnets
|
|
910
|
-
if
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
]
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
455
|
+
return [] if !@cloud_id
|
|
456
|
+
|
|
457
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_subnets(
|
|
458
|
+
filters: [
|
|
459
|
+
{ name: "vpc-id", values: [@cloud_id] }
|
|
460
|
+
]
|
|
461
|
+
)
|
|
462
|
+
if resp.nil? or resp.subnets.nil? or resp.subnets.empty?
|
|
463
|
+
MU.log "Got empty results when trying to list subnets in #{@cloud_id}", MU::WARN
|
|
464
|
+
return []
|
|
920
465
|
end
|
|
921
466
|
|
|
922
467
|
@subnetcachesemaphore.synchronize {
|
|
@@ -927,23 +472,21 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
927
472
|
# metadata. Like ya do.
|
|
928
473
|
if !@config.nil? and @config.has_key?("subnets")
|
|
929
474
|
@config['subnets'].each { |subnet|
|
|
930
|
-
subnet['mu_name']
|
|
475
|
+
subnet['mu_name'] ||= @mu_name+"-"+subnet['name']
|
|
931
476
|
subnet['region'] = @config['region']
|
|
932
477
|
subnet['credentials'] = @config['credentials']
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
}
|
|
941
|
-
end
|
|
478
|
+
resp.subnets.each { |desc|
|
|
479
|
+
if desc.cidr_block == subnet["ip_block"]
|
|
480
|
+
subnet["tags"] = MU.structToHash(desc.tags)
|
|
481
|
+
subnet["cloud_id"] = desc.subnet_id
|
|
482
|
+
break
|
|
483
|
+
end
|
|
484
|
+
}
|
|
942
485
|
|
|
943
486
|
if subnet["cloud_id"] and !ext_ids.include?(subnet["cloud_id"])
|
|
944
487
|
@subnets << MU::Cloud::AWS::VPC::Subnet.new(self, subnet)
|
|
945
488
|
elsif !subnet["cloud_id"]
|
|
946
|
-
resp.
|
|
489
|
+
resp.subnets.each { |desc|
|
|
947
490
|
if desc.cidr_block == subnet["ip_block"]
|
|
948
491
|
subnet['cloud_id'] = desc.subnet_id
|
|
949
492
|
@subnets << MU::Cloud::AWS::VPC::Subnet.new(self, subnet)
|
|
@@ -956,21 +499,21 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
956
499
|
|
|
957
500
|
# Of course we might be loading up a dummy subnet object from a
|
|
958
501
|
# foreign or non-Mu-created VPC and subnet. So make something up.
|
|
959
|
-
if
|
|
960
|
-
resp.
|
|
961
|
-
subnet = {
|
|
962
|
-
|
|
963
|
-
|
|
502
|
+
if @subnets.empty?
|
|
503
|
+
resp.subnets.each { |desc|
|
|
504
|
+
subnet = {
|
|
505
|
+
"ip_block" => desc.cidr_block,
|
|
506
|
+
"tags" => MU.structToHash(desc.tags),
|
|
507
|
+
"cloud_id" => desc.subnet_id,
|
|
508
|
+
'region' => @config['region'],
|
|
509
|
+
'credentials' => @config['credentials'],
|
|
510
|
+
}
|
|
511
|
+
subnet['name'] = subnet["ip_block"].gsub(/[\.\/]/, "_")
|
|
964
512
|
subnet['mu_name'] = @mu_name+"-"+subnet['name']
|
|
965
|
-
|
|
966
|
-
subnet["cloud_id"] = desc.subnet_id
|
|
967
|
-
subnet['region'] = @config['region']
|
|
968
|
-
subnet['credentials'] = @config['credentials']
|
|
969
|
-
if !ext_ids.include?(desc.subnet_id)
|
|
970
|
-
@subnets << MU::Cloud::AWS::VPC::Subnet.new(self, subnet)
|
|
971
|
-
end
|
|
513
|
+
@subnets << MU::Cloud::AWS::VPC::Subnet.new(self, subnet)
|
|
972
514
|
}
|
|
973
515
|
end
|
|
516
|
+
|
|
974
517
|
return @subnets
|
|
975
518
|
}
|
|
976
519
|
end
|
|
@@ -983,13 +526,14 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
983
526
|
def findNat(nat_cloud_id: nil, nat_filter_key: nil, nat_filter_value: nil, region: MU.curRegion, credentials: nil)
|
|
984
527
|
# Discard the nat_cloud_id if it's an AWS instance ID
|
|
985
528
|
nat_cloud_id = nil if nat_cloud_id && nat_cloud_id.start_with?("i-")
|
|
529
|
+
credentials ||= @credentials
|
|
986
530
|
|
|
987
531
|
if @gateways.nil?
|
|
988
532
|
@gateways =
|
|
989
533
|
if nat_cloud_id
|
|
990
|
-
MU::Cloud::AWS.ec2(region: region, credentials:
|
|
534
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_nat_gateways(nat_gateway_ids: [nat_cloud_id])
|
|
991
535
|
elsif nat_filter_key && nat_filter_value
|
|
992
|
-
MU::Cloud::AWS.ec2(region: region, credentials:
|
|
536
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_nat_gateways(
|
|
993
537
|
filter: [
|
|
994
538
|
{
|
|
995
539
|
name: nat_filter_key,
|
|
@@ -1014,8 +558,8 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1014
558
|
|
|
1015
559
|
deploy_id = nil
|
|
1016
560
|
nat_name = nat_name.to_s if !nat_name.nil? and nat_name.class.to_s == "MU::Config::Tail"
|
|
1017
|
-
nat_ip = nat_ip.to_s if !nat_ip.nil? and nat_ip.class.to_s == "MU::Config::Tail"
|
|
1018
561
|
nat_cloud_id = nat_cloud_id.to_s if !nat_cloud_id.nil? and nat_cloud_id.class.to_s == "MU::Config::Tail"
|
|
562
|
+
nat_ip = nat_ip.to_s if !nat_ip.nil? and nat_ip.class.to_s == "MU::Config::Tail"
|
|
1019
563
|
nat_tag_key = nat_tag_key.to_s if !nat_tag_key.nil? and nat_tag_key.class.to_s == "MU::Config::Tail"
|
|
1020
564
|
nat_tag_value = nat_tag_value.to_s if !nat_tag_value.nil? and nat_tag_value.class.to_s == "MU::Config::Tail"
|
|
1021
565
|
|
|
@@ -1042,8 +586,8 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1042
586
|
found.each { |nat|
|
|
1043
587
|
# Try some AWS-specific criteria
|
|
1044
588
|
cloud_desc = nat.cloud_desc
|
|
1045
|
-
if !
|
|
1046
|
-
(cloud_desc.private_ip_address ==
|
|
589
|
+
if !nat_ip.nil? and
|
|
590
|
+
(cloud_desc.private_ip_address == nat_ip or cloud_desc.public_ip_address == nat_ip)
|
|
1047
591
|
return nat
|
|
1048
592
|
elsif cloud_desc.vpc_id == @cloud_id
|
|
1049
593
|
# XXX Strictly speaking we could have different NATs in different
|
|
@@ -1090,7 +634,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1090
634
|
if instance.nil?
|
|
1091
635
|
begin
|
|
1092
636
|
instance = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_instances(instance_ids: [instance_id]).reservations.first.instances.first
|
|
1093
|
-
rescue NoMethodError, Aws::EC2::Errors::InvalidInstanceIDNotFound
|
|
637
|
+
rescue NoMethodError, Aws::EC2::Errors::InvalidInstanceIDNotFound
|
|
1094
638
|
MU.log "Failed to identify instance #{instance_id} in MU::Cloud::AWS::VPC.getInstanceSubnets", MU::WARN
|
|
1095
639
|
return []
|
|
1096
640
|
end
|
|
@@ -1133,20 +677,19 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1133
677
|
my_subnets = MU::Cloud::AWS::VPC.getInstanceSubnets(instance: MU.myCloudDescriptor)
|
|
1134
678
|
target_subnets = MU::Cloud::AWS::VPC.getInstanceSubnets(instance: target_instance, region: region, credentials: credentials)
|
|
1135
679
|
|
|
1136
|
-
resp = nil
|
|
1137
680
|
my_subnets_key = my_subnets.join(",")
|
|
1138
681
|
target_subnets_key = target_subnets.join(",")
|
|
1139
682
|
MU::Cloud::AWS::VPC.update_route_tables_cache(my_subnets_key, region: MU.myRegion)
|
|
1140
683
|
MU::Cloud::AWS::VPC.update_route_tables_cache(target_subnets_key, region: region, credentials: credentials)
|
|
1141
684
|
|
|
1142
|
-
if MU::Cloud::AWS::VPC.
|
|
685
|
+
if MU::Cloud::AWS::VPC.can_route_to_master_peer?(my_subnets_key, target_subnets_key, instance_id)
|
|
1143
686
|
return true
|
|
1144
687
|
else
|
|
1145
688
|
# The cache can be out of date at times, check again without it
|
|
1146
689
|
MU::Cloud::AWS::VPC.update_route_tables_cache(my_subnets_key, use_cache: false, region: MU.myRegion)
|
|
1147
690
|
MU::Cloud::AWS::VPC.update_route_tables_cache(target_subnets_key, use_cache: false, region: region, credentials: credentials)
|
|
1148
691
|
|
|
1149
|
-
return MU::Cloud::AWS::VPC.
|
|
692
|
+
return MU::Cloud::AWS::VPC.can_route_to_master_peer?(my_subnets_key, target_subnets_key, instance_id)
|
|
1150
693
|
end
|
|
1151
694
|
|
|
1152
695
|
end
|
|
@@ -1185,7 +728,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1185
728
|
# @param target_subnets_key [String]: The subnet/subnets on the other side of the peered VPC.
|
|
1186
729
|
# @param instance_id [String]: The instance ID in the target subnet/subnets.
|
|
1187
730
|
# @return [Boolean]
|
|
1188
|
-
def self.
|
|
731
|
+
def self.can_route_to_master_peer?(source_subnets_key, target_subnets_key, instance_id)
|
|
1189
732
|
my_routes = []
|
|
1190
733
|
vpc_peer_mapping = {}
|
|
1191
734
|
|
|
@@ -1279,30 +822,39 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1279
822
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
1280
823
|
# @param region [String]: The cloud provider region
|
|
1281
824
|
# @return [void]
|
|
1282
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
825
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
826
|
+
MU.log "AWS::VPC.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
827
|
+
|
|
1283
828
|
tagfilters = [
|
|
1284
|
-
{name: "tag:MU-ID", values: [
|
|
829
|
+
{name: "tag:MU-ID", values: [deploy_id]}
|
|
1285
830
|
]
|
|
1286
831
|
if !ignoremaster
|
|
1287
832
|
tagfilters << {name: "tag:MU-MASTER-IP", values: [MU.mu_public_ip]}
|
|
1288
833
|
end
|
|
1289
834
|
|
|
1290
835
|
vpcs = []
|
|
1291
|
-
|
|
1292
|
-
begin
|
|
836
|
+
MU.retrier([Aws::EC2::Errors::InvalidVpcIDNotFound], wait: 5) {
|
|
1293
837
|
resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_vpcs(filters: tagfilters, max_results: 1000).vpcs
|
|
1294
838
|
vpcs = resp if !resp.empty?
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
# resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
|
|
842
|
+
# filters: [
|
|
843
|
+
# {
|
|
844
|
+
# name: "requester-vpc-info.vpc-id",
|
|
845
|
+
# values: [@cloud_id]
|
|
846
|
+
# },
|
|
847
|
+
# {
|
|
848
|
+
# name: "accepter-vpc-info.vpc-id",
|
|
849
|
+
# values: [peer_id.to_s]
|
|
850
|
+
# }
|
|
851
|
+
# ]
|
|
852
|
+
# )
|
|
1302
853
|
|
|
1303
854
|
if !vpcs.empty?
|
|
1304
855
|
gwthreads = []
|
|
1305
856
|
vpcs.each { |vpc|
|
|
857
|
+
purge_peering_connections(noop, vpc.vpc_id, region: region, credentials: credentials)
|
|
1306
858
|
# NAT gateways don't have any tags, and we can't assign them a name. Lets find them based on a VPC ID
|
|
1307
859
|
gwthreads << Thread.new {
|
|
1308
860
|
purge_nat_gateways(noop, vpc_id: vpc.vpc_id, region: region, credentials: credentials)
|
|
@@ -1322,17 +874,17 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1322
874
|
purge_vpcs(noop, tagfilters, region: region, credentials: credentials)
|
|
1323
875
|
purge_dhcpopts(noop, tagfilters, region: region, credentials: credentials)
|
|
1324
876
|
|
|
1325
|
-
unless noop
|
|
1326
|
-
MU::Cloud::AWS.iam.list_roles.roles.each{ |role|
|
|
1327
|
-
match_string = "#{
|
|
1328
|
-
}
|
|
1329
|
-
end
|
|
877
|
+
# unless noop
|
|
878
|
+
# MU::Cloud::AWS.iam.list_roles.roles.each{ |role|
|
|
879
|
+
# match_string = "#{deploy_id}.*TRAFFIC-LOG"
|
|
880
|
+
# }
|
|
881
|
+
# end
|
|
1330
882
|
end
|
|
1331
883
|
|
|
1332
884
|
# Cloud-specific configuration properties.
|
|
1333
|
-
# @param
|
|
885
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
1334
886
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
1335
|
-
def self.schema(
|
|
887
|
+
def self.schema(_config)
|
|
1336
888
|
toplevel_required = []
|
|
1337
889
|
# Flow Logs can be declared at the VPC level or the subnet level
|
|
1338
890
|
flowlogs = {
|
|
@@ -1378,11 +930,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1378
930
|
logdesc["tags"] = vpc["tags"] if !vpc["tags"].nil?
|
|
1379
931
|
# logdesc["optional_tags"] = vpc["optional_tags"] if !vpc["optional_tags"].nil?
|
|
1380
932
|
configurator.insertKitten(logdesc, "logs")
|
|
1381
|
-
vpc['
|
|
1382
|
-
vpc['dependencies'] << {
|
|
1383
|
-
"type" => "log",
|
|
1384
|
-
"name" => vpc['name']+"loggroup"
|
|
1385
|
-
}
|
|
933
|
+
MU::Config.addDependency(vpc, vpc['name']+"loggroup", "log")
|
|
1386
934
|
|
|
1387
935
|
roledesc = {
|
|
1388
936
|
"name" => vpc['name']+"logrole",
|
|
@@ -1420,15 +968,10 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1420
968
|
roledesc["tags"] = vpc["tags"] if !vpc["tags"].nil?
|
|
1421
969
|
roledesc["optional_tags"] = vpc["optional_tags"] if !vpc["optional_tags"].nil?
|
|
1422
970
|
configurator.insertKitten(roledesc, "roles")
|
|
1423
|
-
vpc['
|
|
1424
|
-
vpc['dependencies'] << {
|
|
1425
|
-
"type" => "role",
|
|
1426
|
-
"name" => vpc['name']+"logrole"
|
|
1427
|
-
}
|
|
971
|
+
MU::Config.addDependency(vpc, vpc['name']+"logrole", "role")
|
|
1428
972
|
end
|
|
1429
973
|
|
|
1430
974
|
subnet_routes = Hash.new
|
|
1431
|
-
public_routes = Array.new
|
|
1432
975
|
|
|
1433
976
|
if vpc['subnets']
|
|
1434
977
|
vpc['subnets'].each { |subnet|
|
|
@@ -1476,10 +1019,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1476
1019
|
subnet_routes[table['name']].each { |subnet|
|
|
1477
1020
|
nat_routes[subnet] = route['nat_host_name']
|
|
1478
1021
|
}
|
|
1479
|
-
vpc['
|
|
1480
|
-
"type" => "server",
|
|
1481
|
-
"name" => route['nat_host_name']
|
|
1482
|
-
}
|
|
1022
|
+
MU::Config.addDependency(vpc, route['nat_host_name'], "server", no_create_wait: true)
|
|
1483
1023
|
elsif route['gateway'] == '#NAT'
|
|
1484
1024
|
vpc['create_nat_gateway'] = true
|
|
1485
1025
|
private_rtbs << table['name']
|
|
@@ -1492,17 +1032,11 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1492
1032
|
if route['gateway'] == '#INTERNET'
|
|
1493
1033
|
if table['name'] == subnet['route_table']
|
|
1494
1034
|
subnet['is_public'] = true
|
|
1495
|
-
if vpc['create_nat_gateway']
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
subnet['create_nat_gateway'] = false
|
|
1501
|
-
else
|
|
1502
|
-
subnet['create_nat_gateway'] = true
|
|
1503
|
-
nat_gateway_added = true
|
|
1504
|
-
end
|
|
1505
|
-
end
|
|
1035
|
+
if vpc['create_nat_gateway'] and (vpc['nat_gateway_multi_az'] or !nat_gateway_added)
|
|
1036
|
+
subnet['create_nat_gateway'] = true
|
|
1037
|
+
nat_gateway_added = true
|
|
1038
|
+
else
|
|
1039
|
+
subnet['create_nat_gateway'] = false
|
|
1506
1040
|
end
|
|
1507
1041
|
else
|
|
1508
1042
|
subnet['is_public'] = false
|
|
@@ -1600,9 +1134,11 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1600
1134
|
@my_visible_cidrs[subnets]
|
|
1601
1135
|
end
|
|
1602
1136
|
|
|
1603
|
-
private
|
|
1604
1137
|
|
|
1605
1138
|
# List the route tables for each subnet in the given VPC
|
|
1139
|
+
# @param vpc_id [String]:
|
|
1140
|
+
# @param region [String]:
|
|
1141
|
+
# @param credentials [String]:
|
|
1606
1142
|
def self.listAllSubnetRouteTables(vpc_id, region: MU.curRegion, credentials: nil)
|
|
1607
1143
|
resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_subnets(
|
|
1608
1144
|
filters: [
|
|
@@ -1645,6 +1181,299 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1645
1181
|
return table_ids.uniq
|
|
1646
1182
|
end
|
|
1647
1183
|
|
|
1184
|
+
# Remove all network interfaces associated with the currently loaded deployment.
|
|
1185
|
+
# @param noop [Boolean]: If true, will only print what would be done
|
|
1186
|
+
# @param filters [Array<Hash>]: EC2 tags to filter against when search for resources to purge
|
|
1187
|
+
# @param region [String]: The cloud provider region
|
|
1188
|
+
# @return [void]
|
|
1189
|
+
def self.purge_interfaces(noop = false, filters = [{name: "tag:MU-ID", values: [MU.deploy_id]}], region: MU.curRegion, credentials: nil)
|
|
1190
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_network_interfaces(
|
|
1191
|
+
filters: filters
|
|
1192
|
+
)
|
|
1193
|
+
ifaces = resp.data.network_interfaces
|
|
1194
|
+
|
|
1195
|
+
return if ifaces.nil? or ifaces.size == 0
|
|
1196
|
+
|
|
1197
|
+
ifaces.each { |iface|
|
|
1198
|
+
if iface.vpc_id
|
|
1199
|
+
default_sg = MU::Cloud::AWS::VPC.getDefaultSg(iface.vpc_id, region: region, credentials: credentials)
|
|
1200
|
+
if default_sg and (iface.groups.size > 1 or (iface.groups.size == 1 and iface.groups.first.group_id != default_sg))
|
|
1201
|
+
MU.log "Removing extra security groups from ENI #{iface.network_interface_id}"
|
|
1202
|
+
if !noop
|
|
1203
|
+
begin
|
|
1204
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).modify_network_interface_attribute(
|
|
1205
|
+
network_interface_id: iface.network_interface_id,
|
|
1206
|
+
groups: [default_sg]
|
|
1207
|
+
)
|
|
1208
|
+
rescue ::Aws::EC2::Errors::AuthFailure
|
|
1209
|
+
MU.log "Permission denied attempting to trim Security Group list for #{iface.network_interface_id}", MU::WARN, details: iface.groups.map { |g| g.group_name }.join(",")+" => default"
|
|
1210
|
+
end
|
|
1211
|
+
end
|
|
1212
|
+
end
|
|
1213
|
+
end
|
|
1214
|
+
begin
|
|
1215
|
+
if iface.attachment and iface.attachment.status == "attached"
|
|
1216
|
+
MU.log "Detaching Network Interface #{iface.network_interface_id} from #{iface.attachment.instance_owner_id}"
|
|
1217
|
+
tried_lbs = false
|
|
1218
|
+
begin
|
|
1219
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).detach_network_interface(attachment_id: iface.attachment.attachment_id) if !noop
|
|
1220
|
+
rescue Aws::EC2::Errors::OperationNotPermitted => e
|
|
1221
|
+
MU.log "Can't detach #{iface.network_interface_id}: #{e.message}", MU::WARN, details: iface.attachment
|
|
1222
|
+
next
|
|
1223
|
+
rescue Aws::EC2::Errors::IncorrectState => e
|
|
1224
|
+
MU.log e.message, MU::WARN
|
|
1225
|
+
sleep 5
|
|
1226
|
+
retry
|
|
1227
|
+
rescue Aws::EC2::Errors::InvalidAttachmentIDNotFound => e
|
|
1228
|
+
# suits me just fine
|
|
1229
|
+
rescue Aws::EC2::Errors::AuthFailure => e
|
|
1230
|
+
if !tried_lbs and iface.attachment.instance_owner_id == "amazon-elb"
|
|
1231
|
+
MU::Cloud.resourceClass("AWS", "LoadBalancer").cleanup(
|
|
1232
|
+
noop: noop,
|
|
1233
|
+
region: region,
|
|
1234
|
+
credentials: credentials,
|
|
1235
|
+
flags: {"vpc_id" => iface.vpc_id}
|
|
1236
|
+
)
|
|
1237
|
+
tried_lbs = true
|
|
1238
|
+
retry
|
|
1239
|
+
end
|
|
1240
|
+
MU.log e.message, MU::ERR, details: iface.attachment
|
|
1241
|
+
end
|
|
1242
|
+
end
|
|
1243
|
+
MU.log "Deleting Network Interface #{iface.network_interface_id}"
|
|
1244
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_network_interface(network_interface_id: iface.network_interface_id) if !noop
|
|
1245
|
+
rescue Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound
|
|
1246
|
+
# ok then!
|
|
1247
|
+
rescue Aws::EC2::Errors::InvalidParameterValue => e
|
|
1248
|
+
MU.log e.message, MU::ERR, details: iface
|
|
1249
|
+
end
|
|
1250
|
+
}
|
|
1251
|
+
end
|
|
1252
|
+
|
|
1253
|
+
# Fetch the group id of the +default+ security group for the given VPC
|
|
1254
|
+
# @param vpc_id [String]
|
|
1255
|
+
# @param region [String]
|
|
1256
|
+
# @param credentials [String]
|
|
1257
|
+
# @return [String]
|
|
1258
|
+
def self.getDefaultSg(vpc_id, region: MU.curRegion, credentials: nil)
|
|
1259
|
+
default_sg_resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_security_groups(
|
|
1260
|
+
filters: [
|
|
1261
|
+
{ name: "group-name", values: ["default"] },
|
|
1262
|
+
{ name: "vpc-id", values: [vpc_id] }
|
|
1263
|
+
]
|
|
1264
|
+
).security_groups
|
|
1265
|
+
if default_sg_resp and default_sg_resp.size == 1
|
|
1266
|
+
return default_sg_resp.first.group_id
|
|
1267
|
+
end
|
|
1268
|
+
nil
|
|
1269
|
+
end
|
|
1270
|
+
|
|
1271
|
+
# Try to locate the default VPC for a region, and return a BoK-style
|
|
1272
|
+
# config fragment for something that might want to live in it.
|
|
1273
|
+
def self.defaultVpc(region, credentials)
|
|
1274
|
+
cfg_fragment = nil
|
|
1275
|
+
MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_vpcs.vpcs.each { |vpc|
|
|
1276
|
+
if vpc.is_default
|
|
1277
|
+
cfg_fragment = {
|
|
1278
|
+
"id" => vpc.vpc_id,
|
|
1279
|
+
"cloud" => "AWS",
|
|
1280
|
+
"region" => region,
|
|
1281
|
+
"credentials" => credentials
|
|
1282
|
+
}
|
|
1283
|
+
cfg_fragment['subnets'] = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_subnets(
|
|
1284
|
+
filters: [
|
|
1285
|
+
{
|
|
1286
|
+
name: "vpc-id",
|
|
1287
|
+
values: [vpc.vpc_id]
|
|
1288
|
+
}
|
|
1289
|
+
]
|
|
1290
|
+
).subnets.map { |s| { "subnet_id" => s.subnet_id } }
|
|
1291
|
+
break
|
|
1292
|
+
end
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
cfg_fragment
|
|
1296
|
+
end
|
|
1297
|
+
|
|
1298
|
+
# Return a {MU::Config::Ref} that indicates this VPC.
|
|
1299
|
+
# @param subnet_ids [Array<String>]: Optional list of subnet ids with which to infer a +subnet_pref+ parameter.
|
|
1300
|
+
# @return [MU::Config::Ref]
|
|
1301
|
+
def getReference(subnet_ids = [])
|
|
1302
|
+
have_private = have_public = false
|
|
1303
|
+
subnets.each { |s|
|
|
1304
|
+
next if subnet_ids and !subnet_ids.empty? and !subnet_ids.include?(s.cloud_id)
|
|
1305
|
+
if s.private?
|
|
1306
|
+
have_private = true
|
|
1307
|
+
else
|
|
1308
|
+
have_public = true
|
|
1309
|
+
end
|
|
1310
|
+
}
|
|
1311
|
+
subnet_pref = if have_private == have_public
|
|
1312
|
+
"any"
|
|
1313
|
+
elsif have_private
|
|
1314
|
+
"all_private"
|
|
1315
|
+
elsif have_public
|
|
1316
|
+
"all_public"
|
|
1317
|
+
end
|
|
1318
|
+
MU::Config::Ref.get(
|
|
1319
|
+
id: @cloud_id,
|
|
1320
|
+
cloud: "AWS",
|
|
1321
|
+
credentials: @credentials,
|
|
1322
|
+
region: @config['region'],
|
|
1323
|
+
type: "vpcs",
|
|
1324
|
+
subnet_pref: subnet_pref
|
|
1325
|
+
)
|
|
1326
|
+
end
|
|
1327
|
+
|
|
1328
|
+
private
|
|
1329
|
+
|
|
1330
|
+
def peerWith(peer)
|
|
1331
|
+
peer_ref = MU::Config::Ref.get(peer['vpc'])
|
|
1332
|
+
peer_obj = peer_ref.kitten
|
|
1333
|
+
peer_id = peer_ref.kitten.cloud_id
|
|
1334
|
+
if peer_id == @cloud_id
|
|
1335
|
+
MU.log "#{@mu_name} attempted to peer with itself (#{@cloud_id})", MU::ERR, details: peer
|
|
1336
|
+
raise "#{@mu_name} attempted to peer with itself (#{@cloud_id})"
|
|
1337
|
+
end
|
|
1338
|
+
|
|
1339
|
+
if peer_obj and peer_obj.config['peers']
|
|
1340
|
+
peer_obj.config['peers'].each { |peerpeer|
|
|
1341
|
+
if peerpeer['vpc']['name'] == @config['name'] and
|
|
1342
|
+
(peer['vpc']['name'] <=> @config['name']) == -1
|
|
1343
|
+
MU.log "VPCs #{peer['vpc']['name']} and #{@config['name']} both declare mutual peering connection, ignoring #{@config['name']}'s redundant declaration", MU::DEBUG
|
|
1344
|
+
return
|
|
1345
|
+
# XXX and if deploy_id matches or is unset
|
|
1346
|
+
end
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
peer['account'] ||= MU::Cloud::AWS.credToAcct(peer_obj.credentials)
|
|
1350
|
+
end
|
|
1351
|
+
|
|
1352
|
+
peer['account'] ||= MU::Cloud::AWS.account_number
|
|
1353
|
+
|
|
1354
|
+
# See if the peering connection exists before we bother
|
|
1355
|
+
# creating it.
|
|
1356
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
|
|
1357
|
+
filters: [
|
|
1358
|
+
{
|
|
1359
|
+
name: "requester-vpc-info.vpc-id",
|
|
1360
|
+
values: [@cloud_id]
|
|
1361
|
+
},
|
|
1362
|
+
{
|
|
1363
|
+
name: "accepter-vpc-info.vpc-id",
|
|
1364
|
+
values: [peer_id.to_s]
|
|
1365
|
+
}
|
|
1366
|
+
]
|
|
1367
|
+
)
|
|
1368
|
+
|
|
1369
|
+
peering_id = if !resp or !resp.vpc_peering_connections or
|
|
1370
|
+
resp.vpc_peering_connections.empty?
|
|
1371
|
+
|
|
1372
|
+
MU.log "Setting peering connection from VPC #{@config['name']} (#{@cloud_id} in account #{MU::Cloud::AWS.credToAcct(@config['credentials'])}) to #{peer_id} in account #{peer['account']}", details: peer
|
|
1373
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_vpc_peering_connection(
|
|
1374
|
+
vpc_id: @cloud_id,
|
|
1375
|
+
peer_vpc_id: peer_id,
|
|
1376
|
+
peer_owner_id: peer['account'],
|
|
1377
|
+
peer_region: peer_obj.config['region']
|
|
1378
|
+
)
|
|
1379
|
+
resp.vpc_peering_connection.vpc_peering_connection_id
|
|
1380
|
+
else
|
|
1381
|
+
resp.vpc_peering_connections.first.vpc_peering_connection_id
|
|
1382
|
+
end
|
|
1383
|
+
|
|
1384
|
+
peering_name = @deploy.getResourceName(@config['name']+"-PEER-"+peer_id)
|
|
1385
|
+
|
|
1386
|
+
tag_me(peering_id, peering_name)
|
|
1387
|
+
|
|
1388
|
+
# Create routes to our new friend.
|
|
1389
|
+
MU::Cloud::AWS::VPC.listAllSubnetRouteTables(@cloud_id, region: @config['region'], credentials: @config['credentials']).each { |rtb_id|
|
|
1390
|
+
my_route_config = {
|
|
1391
|
+
:route_table_id => rtb_id,
|
|
1392
|
+
:destination_cidr_block => peer_obj.cloud_desc.cidr_block,
|
|
1393
|
+
:vpc_peering_connection_id => peering_id
|
|
1394
|
+
}
|
|
1395
|
+
rtbdesc = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
1396
|
+
route_table_ids: [rtb_id]
|
|
1397
|
+
).route_tables.first
|
|
1398
|
+
already_exists = false
|
|
1399
|
+
rtbdesc.routes.each { |r|
|
|
1400
|
+
if r.destination_cidr_block == peer_obj.cloud_desc.cidr_block
|
|
1401
|
+
if r.vpc_peering_connection_id != peering_id
|
|
1402
|
+
MU.log "Attempt to create duplicate route to #{peer_obj.cloud_desc.cidr_block} from VPC #{@config['name']}", MU::ERR, details: r
|
|
1403
|
+
raise MuError, "Can't create route via #{peering_id}, a route to #{peer_obj.cloud_desc.cidr_block} already exists"
|
|
1404
|
+
else
|
|
1405
|
+
already_exists = true
|
|
1406
|
+
end
|
|
1407
|
+
end
|
|
1408
|
+
}
|
|
1409
|
+
next if already_exists
|
|
1410
|
+
|
|
1411
|
+
MU.log "Creating peering route to #{peer_obj.cloud_desc.cidr_block} in #{peer['vpc']['region']} from VPC #{@config['name']} in #{@config['region']}"
|
|
1412
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route(my_route_config)
|
|
1413
|
+
} # MU::Cloud::AWS::VPC.listAllSubnetRouteTables
|
|
1414
|
+
|
|
1415
|
+
can_auto_accept = ((!peer_obj.nil? and !peer_obj.deploydata.nil? and peer_obj.deploydata['auto_accept_peers']) or $MU_CFG['allow_invade_foreign_vpcs'])
|
|
1416
|
+
|
|
1417
|
+
cnxn = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
|
|
1418
|
+
vpc_peering_connection_ids: [peering_id]
|
|
1419
|
+
).vpc_peering_connections.first
|
|
1420
|
+
|
|
1421
|
+
loop_if = Proc.new {
|
|
1422
|
+
cnxn = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
|
|
1423
|
+
vpc_peering_connection_ids: [peering_id]
|
|
1424
|
+
).vpc_peering_connections.first
|
|
1425
|
+
((can_auto_accept and cnxn.status.code == "pending-acceptance") or (cnxn.status.code != "active" and cnxn.status.code != "pending-acceptance"))
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
MU.retrier(wait: 5, loop_if: loop_if, ignoreme: [Aws::EC2::Errors::VpcPeeringConnectionAlreadyExists, Aws::EC2::Errors::RouteAlreadyExists]) {
|
|
1429
|
+
if cnxn.status.code == "pending-acceptance"
|
|
1430
|
+
if can_auto_accept
|
|
1431
|
+
MU.log "Auto-accepting peering connection #{peering_id} from VPC #{@config['name']} (#{@cloud_id}) to #{peer_id}", MU::NOTICE
|
|
1432
|
+
MU::Cloud::AWS.ec2(region: peer_obj.config['region'], credentials: peer['account']).accept_vpc_peering_connection(
|
|
1433
|
+
vpc_peering_connection_id: peering_id,
|
|
1434
|
+
)
|
|
1435
|
+
|
|
1436
|
+
# Create routes back from our new friend to us.
|
|
1437
|
+
MU::Cloud::AWS::VPC.listAllSubnetRouteTables(peer_id, region: peer_obj.config['region'], credentials: peer['account']).uniq.each { |rtb_id|
|
|
1438
|
+
peer_route_config = {
|
|
1439
|
+
:route_table_id => rtb_id,
|
|
1440
|
+
:destination_cidr_block => @config['ip_block'],
|
|
1441
|
+
:vpc_peering_connection_id => peering_id
|
|
1442
|
+
}
|
|
1443
|
+
resp = MU::Cloud::AWS.ec2(region: peer_obj.config['region'], credentials: peer['account']).create_route(peer_route_config)
|
|
1444
|
+
}
|
|
1445
|
+
else
|
|
1446
|
+
MU.log "VPC #{peer_id} is not managed by this Mu server or is not configured to auto-accept peering requests. You must accept the peering request for '#{@config['name']}' (#{@cloud_id}) by hand.", MU::WARN, details: "In the AWS Console, go to VPC => Peering Connections and look in the Actions drop-down. You can also set 'Invade Foreign VPCs' to 'true' using mu-configure to auto-accept all peering connections within this account, regardless of whether this Mu server owns the VPCs. This setting is per-user."
|
|
1447
|
+
end
|
|
1448
|
+
end
|
|
1449
|
+
|
|
1450
|
+
if ["failed", "rejected", "expired", "deleted"].include?(cnxn.status.code)
|
|
1451
|
+
MU.log "VPC peering connection from VPC #{@config['name']} (#{@cloud_id} in #{@config['region']}) to #{peer_id} in #{peer_obj.config['region']} #{cnxn.status.code}: #{cnxn.status.message}", MU::ERR
|
|
1452
|
+
begin
|
|
1453
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).delete_vpc_peering_connection(
|
|
1454
|
+
vpc_peering_connection_id: peering_id
|
|
1455
|
+
)
|
|
1456
|
+
rescue Aws::EC2::Errors::InvalidStateTransition
|
|
1457
|
+
# XXX apparently this is normal?
|
|
1458
|
+
end
|
|
1459
|
+
raise MuError, "VPC peering connection from VPC #{@config['name']} (#{@cloud_id}) to #{peer_id} #{cnxn.status.code}: #{cnxn.status.message}"
|
|
1460
|
+
end
|
|
1461
|
+
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
end
|
|
1465
|
+
|
|
1466
|
+
def tag_me(resource_id = @cloud_id, name = @mu_name)
|
|
1467
|
+
MU::Cloud::AWS.createStandardTags(
|
|
1468
|
+
resource_id,
|
|
1469
|
+
region: @config['region'],
|
|
1470
|
+
credentials: @config['credentials'],
|
|
1471
|
+
optional: @config['optional_tags'],
|
|
1472
|
+
nametag: name,
|
|
1473
|
+
othertags: @config['tags']
|
|
1474
|
+
)
|
|
1475
|
+
end
|
|
1476
|
+
|
|
1648
1477
|
# Helper method for manufacturing route tables. Expect to be called from
|
|
1649
1478
|
# {MU::Cloud::AWS::VPC#create} or {MU::Cloud::AWS::VPC#groom}.
|
|
1650
1479
|
# @param rtb [Hash]: A route table description parsed through {MU::Config::BasketofKittens::vpcs::route_tables}.
|
|
@@ -1656,21 +1485,9 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1656
1485
|
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route_table(vpc_id: vpc_id).route_table
|
|
1657
1486
|
route_table_id = rtb['route_table_id'] = resp.route_table_id
|
|
1658
1487
|
sleep 5
|
|
1659
|
-
MU::MommaCat.createTag(route_table_id, "Name", vpc_name+"-"+rtb['name'].upcase, credentials: @config['credentials'])
|
|
1660
|
-
|
|
1661
|
-
if @config['tags']
|
|
1662
|
-
@config['tags'].each { |tag|
|
|
1663
|
-
MU::MommaCat.createTag(route_table_id, tag['key'], tag['value'], credentials: @config['credentials'])
|
|
1664
|
-
}
|
|
1665
|
-
end
|
|
1666
1488
|
|
|
1667
|
-
|
|
1668
|
-
MU::MommaCat.listOptionalTags.each { |key, value|
|
|
1669
|
-
MU::MommaCat.createTag(route_table_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
|
1670
|
-
}
|
|
1671
|
-
end
|
|
1489
|
+
tag_me(route_table_id, vpc_name+"-"+rtb['name'].upcase)
|
|
1672
1490
|
|
|
1673
|
-
MU::Cloud::AWS.createStandardTags(route_table_id, credentials: @config['credentials'])
|
|
1674
1491
|
rtb['routes'].each { |route|
|
|
1675
1492
|
if route['nat_host_id'].nil? and route['nat_host_name'].nil?
|
|
1676
1493
|
route_config = {
|
|
@@ -1693,7 +1510,6 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1693
1510
|
return rtb
|
|
1694
1511
|
end
|
|
1695
1512
|
|
|
1696
|
-
|
|
1697
1513
|
# Remove all network gateways associated with the currently loaded deployment.
|
|
1698
1514
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
1699
1515
|
# @param region [String]: The cloud provider region
|
|
@@ -1746,6 +1562,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1746
1562
|
}
|
|
1747
1563
|
return nil
|
|
1748
1564
|
end
|
|
1565
|
+
private_class_method :purge_gateways
|
|
1749
1566
|
|
|
1750
1567
|
# Remove all NAT gateways associated with the VPC of the currently loaded deployment.
|
|
1751
1568
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
@@ -1763,36 +1580,25 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1763
1580
|
).nat_gateways
|
|
1764
1581
|
|
|
1765
1582
|
threads = []
|
|
1766
|
-
|
|
1583
|
+
|
|
1767
1584
|
if !gateways.empty?
|
|
1768
1585
|
gateways.each { |gateway|
|
|
1586
|
+
next if noop
|
|
1587
|
+
MU.log "Deleting NAT Gateway #{gateway.nat_gateway_id}"
|
|
1769
1588
|
threads << Thread.new {
|
|
1770
|
-
MU.
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1589
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_nat_gateway(nat_gateway_id: gateway.nat_gateway_id)
|
|
1590
|
+
|
|
1591
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_nat_gateways(nat_gateway_ids: [gateway.nat_gateway_id]).nat_gateways.first
|
|
1592
|
+
|
|
1593
|
+
loop_if = Proc.new {
|
|
1594
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_nat_gateways(nat_gateway_ids: [gateway.nat_gateway_id]).nat_gateways.first
|
|
1595
|
+
(resp.state != "deleted" and resp.state != "failed")
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
MU.retrier([Aws::EmptyStructure, NoMethodError], ignoreme: [Aws::EC2::Errors::NatGatewayMalformed, Aws::EC2::Errors::NatGatewayNotFound], max: 50, loop_if: loop_if) { |retries, _wait|
|
|
1599
|
+
MU.log "Waiting for nat gateway #{gateway.nat_gateway_id} to delete" if retries % 3 == 0
|
|
1600
|
+
}
|
|
1776
1601
|
|
|
1777
|
-
attempts = 0
|
|
1778
|
-
while resp.state != "deleted" and resp.state != "failed"
|
|
1779
|
-
MU.log "Waiting for nat gateway #{gateway.nat_gateway_id} to delete" if attempts % 2 == 0
|
|
1780
|
-
sleep 30
|
|
1781
|
-
begin
|
|
1782
|
-
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_nat_gateways(nat_gateway_ids: [gateway.nat_gateway_id]).nat_gateways.first
|
|
1783
|
-
rescue Aws::EmptyStructure, NoMethodError
|
|
1784
|
-
sleep 5
|
|
1785
|
-
retry
|
|
1786
|
-
rescue Aws::EC2::Errors::NatGatewayNotFound
|
|
1787
|
-
MU.log "NAT gateway #{gateway.nat_gateway_id} already deleted", MU::NOTICE
|
|
1788
|
-
end
|
|
1789
|
-
MU.log "Timed out while waiting for NAT Gateway to delete #{gateway.nat_gateway_id}: #{resp}", MU::WARN if attempts > 50
|
|
1790
|
-
attempts += 1
|
|
1791
|
-
end
|
|
1792
|
-
rescue Aws::EC2::Errors::NatGatewayMalformed
|
|
1793
|
-
MU.log "NAT Gateway #{gateway.nat_gateway_id} was already deleted", MU::NOTICE
|
|
1794
|
-
end
|
|
1795
|
-
end
|
|
1796
1602
|
}
|
|
1797
1603
|
}
|
|
1798
1604
|
end
|
|
@@ -1803,6 +1609,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1803
1609
|
|
|
1804
1610
|
return nil
|
|
1805
1611
|
end
|
|
1612
|
+
private_class_method :purge_nat_gateways
|
|
1806
1613
|
|
|
1807
1614
|
# Remove all VPC endpoints associated with the VPC of the currently loaded deployment.
|
|
1808
1615
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
@@ -1820,38 +1627,21 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1820
1627
|
).vpc_endpoints
|
|
1821
1628
|
|
|
1822
1629
|
threads = []
|
|
1823
|
-
|
|
1630
|
+
|
|
1824
1631
|
if !vpc_endpoints.empty?
|
|
1825
1632
|
vpc_endpoints.each { |endpoint|
|
|
1633
|
+
MU.log "Deleting VPC endpoint #{endpoint.vpc_endpoint_id}"
|
|
1634
|
+
next if noop
|
|
1826
1635
|
threads << Thread.new {
|
|
1827
|
-
MU.
|
|
1828
|
-
MU.
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
MU.log "Waiting for VPC endpoint #{endpoint.vpc_endpoint_id} to delete" if attempts % 5 == 0
|
|
1837
|
-
sleep 30
|
|
1838
|
-
begin
|
|
1839
|
-
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpc_endpoints(vpc_endpoint_ids: [endpoint.vpc_endpoint_id]).vpc_endpoints.first
|
|
1840
|
-
rescue Aws::EmptyStructure, NoMethodError
|
|
1841
|
-
sleep 5
|
|
1842
|
-
retry
|
|
1843
|
-
rescue Aws::EC2::Errors::InvalidVpcEndpointIdNotFound
|
|
1844
|
-
MU.log "VPC endpoint #{endpoint.vpc_endpoint_id} already deleted", MU::NOTICE
|
|
1845
|
-
end
|
|
1846
|
-
MU.log "Timed out while waiting for VPC endpoint to delete #{endpoint.vpc_endpoint_id}: #{resp}", MU::WARN if attempts > 50
|
|
1847
|
-
attempts += 1
|
|
1848
|
-
end
|
|
1849
|
-
rescue Aws::EC2::Errors::VpcEndpointIdMalformed
|
|
1850
|
-
MU.log "VPC endpoint #{endpoint.vpc_endpoint_id} was already deleted", MU::NOTICE
|
|
1851
|
-
rescue Aws::EC2::Errors::InvalidVpcEndpointIdNotFound
|
|
1852
|
-
MU.log "VPC endpoint #{endpoint.vpc_endpoint_id} already deleted", MU::NOTICE
|
|
1853
|
-
end
|
|
1854
|
-
end
|
|
1636
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_vpc_endpoints(vpc_endpoint_ids: [endpoint.vpc_endpoint_id])
|
|
1637
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpc_endpoints(vpc_endpoint_ids: [endpoint.vpc_endpoint_id]).vpc_endpoints.first
|
|
1638
|
+
loop_if = Proc.new {
|
|
1639
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpc_endpoints(vpc_endpoint_ids: [endpoint.vpc_endpoint_id]).vpc_endpoints.first
|
|
1640
|
+
resp.state != "deleted"
|
|
1641
|
+
}
|
|
1642
|
+
MU.retrier([Aws::EmptyStructure, NoMethodError], ignoreme: [Aws::EC2::Errors::InvalidVpcEndpointIdNotFound, Aws::EC2::Errors::VpcEndpointIdMalformed], max: 20, wait: 10, loop_if: loop_if) { |retries, _wait|
|
|
1643
|
+
MU.log "Waiting for VPC endpoint #{endpoint.vpc_endpoint_id} to delete" if retries % 5 == 0
|
|
1644
|
+
}
|
|
1855
1645
|
}
|
|
1856
1646
|
}
|
|
1857
1647
|
end
|
|
@@ -1862,6 +1652,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1862
1652
|
|
|
1863
1653
|
return nil
|
|
1864
1654
|
end
|
|
1655
|
+
private_class_method :purge_endpoints
|
|
1865
1656
|
|
|
1866
1657
|
# Remove all route tables associated with the currently loaded deployment.
|
|
1867
1658
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
@@ -1882,7 +1673,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1882
1673
|
MU.log "Deleting Network Interface #{route.network_interface_id}"
|
|
1883
1674
|
begin
|
|
1884
1675
|
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_network_interface(network_interface_id: route.network_interface_id) if !noop
|
|
1885
|
-
rescue Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound
|
|
1676
|
+
rescue Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound
|
|
1886
1677
|
MU.log "Network Interface #{route.network_interface_id} has already been deleted", MU::WARN
|
|
1887
1678
|
end
|
|
1888
1679
|
end
|
|
@@ -1902,9 +1693,9 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1902
1693
|
table.associations.each { |assoc|
|
|
1903
1694
|
begin
|
|
1904
1695
|
MU::Cloud::AWS.ec2(credentials: credentials, region: region).disassociate_route_table(association_id: assoc.route_table_association_id) if !noop
|
|
1905
|
-
rescue Aws::EC2::Errors::InvalidAssociationIDNotFound
|
|
1696
|
+
rescue Aws::EC2::Errors::InvalidAssociationIDNotFound
|
|
1906
1697
|
MU.log "Route table association #{assoc.route_table_association_id} already removed", MU::WARN
|
|
1907
|
-
rescue Aws::EC2::Errors::InvalidParameterValue
|
|
1698
|
+
rescue Aws::EC2::Errors::InvalidParameterValue
|
|
1908
1699
|
# normal and ignorable with the default route table
|
|
1909
1700
|
can_delete = false
|
|
1910
1701
|
next
|
|
@@ -1920,124 +1711,7 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
1920
1711
|
}
|
|
1921
1712
|
return nil
|
|
1922
1713
|
end
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
# Remove all network interfaces associated with the currently loaded deployment.
|
|
1926
|
-
# @param noop [Boolean]: If true, will only print what would be done
|
|
1927
|
-
# @param filters [Array<Hash>]: EC2 tags to filter against when search for resources to purge
|
|
1928
|
-
# @param region [String]: The cloud provider region
|
|
1929
|
-
# @return [void]
|
|
1930
|
-
def self.purge_interfaces(noop = false, filters = [{name: "tag:MU-ID", values: [MU.deploy_id]}], region: MU.curRegion, credentials: nil)
|
|
1931
|
-
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_network_interfaces(
|
|
1932
|
-
filters: filters
|
|
1933
|
-
)
|
|
1934
|
-
ifaces = resp.data.network_interfaces
|
|
1935
|
-
|
|
1936
|
-
return if ifaces.nil? or ifaces.size == 0
|
|
1937
|
-
|
|
1938
|
-
ifaces.each { |iface|
|
|
1939
|
-
if iface.vpc_id
|
|
1940
|
-
default_sg_resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_security_groups(
|
|
1941
|
-
filters: [
|
|
1942
|
-
{ name: "group-name", values: ["default"] },
|
|
1943
|
-
{ name: "vpc-id", values: [iface.vpc_id] }
|
|
1944
|
-
]
|
|
1945
|
-
).security_groups
|
|
1946
|
-
if default_sg_resp and default_sg_resp.size == 1
|
|
1947
|
-
default_sg = default_sg_resp.first.group_id
|
|
1948
|
-
if iface.groups.size != 1 or
|
|
1949
|
-
iface.groups.first.group_id != default_sg
|
|
1950
|
-
MU.log "Removing extra security groups from ENI #{iface.network_interface_id}"
|
|
1951
|
-
MU::Cloud::AWS.ec2(credentials: credentials, region: region).modify_network_interface_attribute(
|
|
1952
|
-
network_interface_id: iface.network_interface_id,
|
|
1953
|
-
groups: [default_sg]
|
|
1954
|
-
)
|
|
1955
|
-
end
|
|
1956
|
-
end
|
|
1957
|
-
end
|
|
1958
|
-
begin
|
|
1959
|
-
if iface.attachment and iface.attachment.status == "attached"
|
|
1960
|
-
MU.log "Detaching Network Interface #{iface.network_interface_id} from #{iface.attachment.instance_owner_id}"
|
|
1961
|
-
tried_lbs = false
|
|
1962
|
-
begin
|
|
1963
|
-
MU::Cloud::AWS.ec2(credentials: credentials, region: region).detach_network_interface(attachment_id: iface.attachment.attachment_id) if !noop
|
|
1964
|
-
rescue Aws::EC2::Errors::OperationNotPermitted => e
|
|
1965
|
-
MU.log "Can't detach #{iface.network_interface_id}: #{e.message}", MU::WARN, details: iface.attachment
|
|
1966
|
-
next
|
|
1967
|
-
rescue Aws::EC2::Errors::InvalidAttachmentIDNotFound => e
|
|
1968
|
-
# suits me just fine
|
|
1969
|
-
rescue Aws::EC2::Errors::AuthFailure => e
|
|
1970
|
-
if !tried_lbs and iface.attachment.instance_owner_id == "amazon-elb"
|
|
1971
|
-
MU::Cloud::AWS::LoadBalancer.cleanup(
|
|
1972
|
-
noop: noop,
|
|
1973
|
-
region: region,
|
|
1974
|
-
credentials: credentials,
|
|
1975
|
-
flags: {"vpc_id" => iface.vpc_id}
|
|
1976
|
-
)
|
|
1977
|
-
tried_lbs = true
|
|
1978
|
-
retry
|
|
1979
|
-
end
|
|
1980
|
-
MU.log e.message, MU::ERR, details: iface.attachment
|
|
1981
|
-
end
|
|
1982
|
-
end
|
|
1983
|
-
MU.log "Deleting Network Interface #{iface.network_interface_id}"
|
|
1984
|
-
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_network_interface(network_interface_id: iface.network_interface_id) if !noop
|
|
1985
|
-
rescue Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound => e
|
|
1986
|
-
# ok then!
|
|
1987
|
-
rescue Aws::EC2::Errors::InvalidParameterValue => e
|
|
1988
|
-
MU.log e.message, MU::ERR, details: iface
|
|
1989
|
-
end
|
|
1990
|
-
}
|
|
1991
|
-
end
|
|
1992
|
-
|
|
1993
|
-
# Remove all subnets associated with the currently loaded deployment.
|
|
1994
|
-
# @param noop [Boolean]: If true, will only print what would be done
|
|
1995
|
-
# @param tagfilters [Array<Hash>]: EC2 tags to filter against when search for resources to purge
|
|
1996
|
-
# @param region [String]: The cloud provider region
|
|
1997
|
-
# @return [void]
|
|
1998
|
-
def self.purge_subnets(noop = false, tagfilters = [{name: "tag:MU-ID", values: [MU.deploy_id]}], region: MU.curRegion, credentials: nil)
|
|
1999
|
-
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_subnets(
|
|
2000
|
-
filters: tagfilters
|
|
2001
|
-
)
|
|
2002
|
-
subnets = resp.data.subnets
|
|
2003
|
-
|
|
2004
|
-
return if subnets.nil? or subnets.size == 0
|
|
2005
|
-
|
|
2006
|
-
retries = 0
|
|
2007
|
-
subnets.each { |subnet|
|
|
2008
|
-
MU.log "Deleting Subnet #{subnet.subnet_id}"
|
|
2009
|
-
begin
|
|
2010
|
-
if subnet.state != "available"
|
|
2011
|
-
MU.log "Waiting for #{subnet.subnet_id} to be in a removable state...", MU::NOTICE
|
|
2012
|
-
sleep 30
|
|
2013
|
-
else
|
|
2014
|
-
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_subnet(subnet_id: subnet.subnet_id) if !noop
|
|
2015
|
-
end
|
|
2016
|
-
rescue Aws::EC2::Errors::DependencyViolation => e
|
|
2017
|
-
# We're often stuck waiting for an RDS database or something else
|
|
2018
|
-
# that takes 5-ever to delete.
|
|
2019
|
-
if retries < 19
|
|
2020
|
-
loglevel = (retries > 0 and (retries % 3) == 0) ? MU::NOTICE : MU::DEBUG
|
|
2021
|
-
MU.log "#{e.message} (retry #{retries.to_s}/20)", loglevel
|
|
2022
|
-
if loglevel == MU::NOTICE
|
|
2023
|
-
MU::Cloud::AWS::VPC.purge_interfaces(noop, [{name: "subnet-id", values: [subnet.subnet_id]}], region: region, credentials: credentials)
|
|
2024
|
-
end
|
|
2025
|
-
sleep 30
|
|
2026
|
-
retries = retries + 1
|
|
2027
|
-
retry
|
|
2028
|
-
elsif retries < 20
|
|
2029
|
-
MU.log "#{e.message} (final attempt)", MU::WARN
|
|
2030
|
-
sleep 60
|
|
2031
|
-
retries = retries + 1
|
|
2032
|
-
retry
|
|
2033
|
-
else
|
|
2034
|
-
raise e
|
|
2035
|
-
end
|
|
2036
|
-
rescue Aws::EC2::Errors::InvalidSubnetIDNotFound
|
|
2037
|
-
next
|
|
2038
|
-
end while subnet.state != "available"
|
|
2039
|
-
}
|
|
2040
|
-
end
|
|
1714
|
+
private_class_method :purge_routetables
|
|
2041
1715
|
|
|
2042
1716
|
# Remove all DHCP options sets associated with the currently loaded
|
|
2043
1717
|
# deployment.
|
|
@@ -2056,7 +1730,9 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
2056
1730
|
sets.each { |optset|
|
|
2057
1731
|
begin
|
|
2058
1732
|
MU.log "Deleting DHCP Option Set #{optset.dhcp_options_id}"
|
|
2059
|
-
|
|
1733
|
+
if !noop
|
|
1734
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_dhcp_options(dhcp_options_id: optset.dhcp_options_id)
|
|
1735
|
+
end
|
|
2060
1736
|
rescue Aws::EC2::Errors::DependencyViolation => e
|
|
2061
1737
|
MU.log e.inspect, MU::ERR
|
|
2062
1738
|
# rescue Aws::EC2::Errors::InvalidSubnetIDNotFound
|
|
@@ -2065,6 +1741,62 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
2065
1741
|
end
|
|
2066
1742
|
}
|
|
2067
1743
|
end
|
|
1744
|
+
private_class_method :purge_dhcpopts
|
|
1745
|
+
|
|
1746
|
+
def self.purge_peering_connections(noop, vpc_id, region: MU.curRegion, credentials: nil)
|
|
1747
|
+
my_peer_conns = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpc_peering_connections(
|
|
1748
|
+
filters: [
|
|
1749
|
+
{
|
|
1750
|
+
name: "requester-vpc-info.vpc-id",
|
|
1751
|
+
values: [vpc_id]
|
|
1752
|
+
}
|
|
1753
|
+
]
|
|
1754
|
+
).vpc_peering_connections
|
|
1755
|
+
my_peer_conns.concat(MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpc_peering_connections(
|
|
1756
|
+
filters: [
|
|
1757
|
+
{
|
|
1758
|
+
name: "accepter-vpc-info.vpc-id",
|
|
1759
|
+
values: [vpc_id]
|
|
1760
|
+
}
|
|
1761
|
+
]
|
|
1762
|
+
).vpc_peering_connections)
|
|
1763
|
+
|
|
1764
|
+
my_peer_conns.each { |cnxn|
|
|
1765
|
+
[cnxn.accepter_vpc_info.vpc_id, cnxn.requester_vpc_info.vpc_id].each { |peer_vpc|
|
|
1766
|
+
MU::Cloud::AWS::VPC.listAllSubnetRouteTables(peer_vpc, region: region, credentials: credentials).each { |rtb_id|
|
|
1767
|
+
begin
|
|
1768
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_route_tables(
|
|
1769
|
+
route_table_ids: [rtb_id]
|
|
1770
|
+
)
|
|
1771
|
+
rescue Aws::EC2::Errors::InvalidRouteTableIDNotFound
|
|
1772
|
+
next
|
|
1773
|
+
end
|
|
1774
|
+
resp.route_tables.each { |rtb|
|
|
1775
|
+
rtb.routes.each { |route|
|
|
1776
|
+
if route.vpc_peering_connection_id == cnxn.vpc_peering_connection_id
|
|
1777
|
+
MU.log "Removing route #{route.destination_cidr_block} from route table #{rtb_id} in VPC #{peer_vpc}"
|
|
1778
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_route(
|
|
1779
|
+
route_table_id: rtb_id,
|
|
1780
|
+
destination_cidr_block: route.destination_cidr_block
|
|
1781
|
+
) if !noop
|
|
1782
|
+
end
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
MU.log "Deleting VPC peering connection #{cnxn.vpc_peering_connection_id}"
|
|
1788
|
+
begin
|
|
1789
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_vpc_peering_connection(
|
|
1790
|
+
vpc_peering_connection_id: cnxn.vpc_peering_connection_id
|
|
1791
|
+
) if !noop
|
|
1792
|
+
rescue Aws::EC2::Errors::InvalidStateTransition
|
|
1793
|
+
MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} not in removable (state #{cnxn.status.code})", MU::WARN
|
|
1794
|
+
rescue Aws::EC2::Errors::OperationNotPermitted => e
|
|
1795
|
+
MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} refuses to delete: #{e.message}", MU::WARN
|
|
1796
|
+
end
|
|
1797
|
+
}
|
|
1798
|
+
end
|
|
1799
|
+
private_class_method :purge_peering_connections
|
|
2068
1800
|
|
|
2069
1801
|
# Remove all VPCs associated with the currently loaded deployment.
|
|
2070
1802
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
@@ -2073,177 +1805,39 @@ MU.log "association I don't understand in #{@cloud_id}", MU::WARN, details: rtb_
|
|
|
2073
1805
|
# @return [void]
|
|
2074
1806
|
def self.purge_vpcs(noop = false, tagfilters = [{name: "tag:MU-ID", values: [MU.deploy_id]}], region: MU.curRegion, credentials: nil)
|
|
2075
1807
|
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_vpcs(
|
|
2076
|
-
|
|
1808
|
+
filters: tagfilters
|
|
2077
1809
|
)
|
|
2078
1810
|
|
|
2079
1811
|
vpcs = resp.data.vpcs
|
|
2080
1812
|
return if vpcs.nil? or vpcs.size == 0
|
|
2081
1813
|
|
|
2082
1814
|
vpcs.each { |vpc|
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
{
|
|
2094
|
-
name: "accepter-vpc-info.vpc-id",
|
|
2095
|
-
values: [vpc.vpc_id]
|
|
2096
|
-
}
|
|
2097
|
-
]
|
|
2098
|
-
).vpc_peering_connections)
|
|
2099
|
-
my_peer_conns.each { |cnxn|
|
|
2100
|
-
|
|
2101
|
-
[cnxn.accepter_vpc_info.vpc_id, cnxn.requester_vpc_info.vpc_id].each { |peer_vpc|
|
|
2102
|
-
MU::Cloud::AWS::VPC.listAllSubnetRouteTables(peer_vpc, region: region, credentials: credentials).each { |rtb_id|
|
|
2103
|
-
begin
|
|
2104
|
-
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_route_tables(
|
|
2105
|
-
route_table_ids: [rtb_id]
|
|
2106
|
-
)
|
|
2107
|
-
rescue Aws::EC2::Errors::InvalidRouteTableIDNotFound => e
|
|
2108
|
-
next
|
|
2109
|
-
end
|
|
2110
|
-
resp.route_tables.each { |rtb|
|
|
2111
|
-
rtb.routes.each { |route|
|
|
2112
|
-
if route.vpc_peering_connection_id == cnxn.vpc_peering_connection_id
|
|
2113
|
-
MU.log "Removing route #{route.destination_cidr_block} from route table #{rtb_id} in VPC #{peer_vpc}"
|
|
2114
|
-
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_route(
|
|
2115
|
-
route_table_id: rtb_id,
|
|
2116
|
-
destination_cidr_block: route.destination_cidr_block
|
|
2117
|
-
) if !noop
|
|
2118
|
-
end
|
|
2119
|
-
}
|
|
2120
|
-
}
|
|
2121
|
-
}
|
|
2122
|
-
}
|
|
2123
|
-
MU.log "Deleting VPC peering connection #{cnxn.vpc_peering_connection_id}"
|
|
2124
|
-
begin
|
|
2125
|
-
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_vpc_peering_connection(
|
|
2126
|
-
vpc_peering_connection_id: cnxn.vpc_peering_connection_id
|
|
2127
|
-
) if !noop
|
|
2128
|
-
rescue Aws::EC2::Errors::InvalidStateTransition => e
|
|
2129
|
-
MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} not in removable (state #{cnxn.status.code})", MU::WARN
|
|
2130
|
-
rescue Aws::EC2::Errors::OperationNotPermitted => e
|
|
2131
|
-
MU.log "VPC peering connection #{cnxn.vpc_peering_connection_id} refuses to delete: #{e.message}", MU::WARN
|
|
2132
|
-
end
|
|
1815
|
+
purge_peering_connections(noop, vpc.vpc_id, region: region, credentials: credentials)
|
|
1816
|
+
|
|
1817
|
+
on_retry = Proc.new {
|
|
1818
|
+
MU::Cloud.resourceClass("AWS", "FirewallRule").cleanup(
|
|
1819
|
+
noop: noop,
|
|
1820
|
+
region: region,
|
|
1821
|
+
credentials: credentials,
|
|
1822
|
+
flags: { "vpc_id" => vpc.vpc_id }
|
|
1823
|
+
)
|
|
1824
|
+
purge_gateways(noop, tagfilters, region: region, credentials: credentials)
|
|
2133
1825
|
}
|
|
2134
1826
|
|
|
2135
|
-
|
|
2136
|
-
begin
|
|
1827
|
+
MU.retrier([Aws::EC2::Errors::DependencyViolation], ignoreme: [Aws::EC2::Errors::InvalidVpcIDNotFound], max: 20, on_retry: on_retry) {
|
|
2137
1828
|
MU.log "Deleting VPC #{vpc.vpc_id}"
|
|
2138
1829
|
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_vpc(vpc_id: vpc.vpc_id) if !noop
|
|
2139
|
-
|
|
2140
|
-
MU.log "VPC #{vpc.vpc_id} has already been deleted", MU::WARN
|
|
2141
|
-
rescue Aws::EC2::Errors::DependencyViolation => e
|
|
2142
|
-
if retries < 5
|
|
2143
|
-
MU.log "#{vpc.vpc_id} in #{region} had hidden dependencies, will try to remove them", MU::NOTICE
|
|
2144
|
-
retries += 1
|
|
2145
|
-
# fry some common rogue resources
|
|
2146
|
-
MU::Cloud::AWS::FirewallRule.cleanup(
|
|
2147
|
-
noop: noop,
|
|
2148
|
-
region: region,
|
|
2149
|
-
credentials: credentials,
|
|
2150
|
-
flags: { "vpc_id" => vpc.vpc_id }
|
|
2151
|
-
)
|
|
2152
|
-
purge_gateways(noop, tagfilters, region: region, credentials: credentials)
|
|
2153
|
-
sleep 10
|
|
2154
|
-
retry
|
|
2155
|
-
else
|
|
2156
|
-
MU.log "Failed to remove #{vpc.vpc_id} in #{region}: #{e.message}", MU::ERR
|
|
2157
|
-
next
|
|
2158
|
-
end
|
|
2159
|
-
end
|
|
1830
|
+
}
|
|
2160
1831
|
|
|
2161
1832
|
if !MU::Cloud::AWS.isGovCloud?(region)
|
|
2162
1833
|
mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu", region: region, credentials: credentials).values.first
|
|
2163
1834
|
if !mu_zone.nil?
|
|
2164
|
-
MU::Cloud
|
|
1835
|
+
MU::Cloud.resourceClass("AWS", "DNSZone").toggleVPCAccess(id: mu_zone.id, vpc_id: vpc.vpc_id, remove: true, credentials: credentials)
|
|
2165
1836
|
end
|
|
2166
1837
|
end
|
|
2167
1838
|
}
|
|
2168
1839
|
end
|
|
2169
|
-
|
|
2170
|
-
protected
|
|
2171
|
-
|
|
2172
|
-
# Subnets are almost a first-class resource. So let's kinda sorta treat
|
|
2173
|
-
# them like one. This should only be invoked on objects that already
|
|
2174
|
-
# exists in the cloud layer.
|
|
2175
|
-
class Subnet < MU::Cloud::AWS::VPC
|
|
2176
|
-
|
|
2177
|
-
attr_reader :cloud_id
|
|
2178
|
-
attr_reader :ip_block
|
|
2179
|
-
attr_reader :mu_name
|
|
2180
|
-
attr_reader :name
|
|
2181
|
-
attr_reader :az
|
|
2182
|
-
attr_reader :cloud_desc
|
|
2183
|
-
|
|
2184
|
-
# @param parent [MU::Cloud::AWS::VPC]: The parent VPC of this subnet.
|
|
2185
|
-
# @param config [Hash<String>]:
|
|
2186
|
-
def initialize(parent, config)
|
|
2187
|
-
@parent = parent
|
|
2188
|
-
@config = MU::Config.manxify(config)
|
|
2189
|
-
@cloud_id = config['cloud_id']
|
|
2190
|
-
@mu_name = config['mu_name']
|
|
2191
|
-
@name = config['name']
|
|
2192
|
-
@deploydata = config # This is a dummy for the sake of describe()
|
|
2193
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_subnets(subnet_ids: [@cloud_id]).subnets.first
|
|
2194
|
-
@az = resp.availability_zone
|
|
2195
|
-
@ip_block = resp.cidr_block
|
|
2196
|
-
@cloud_desc = resp # XXX this really isn't the cloud implementation's business
|
|
2197
|
-
|
|
2198
|
-
end
|
|
2199
|
-
|
|
2200
|
-
# Return the cloud identifier for the default route of this subnet.
|
|
2201
|
-
def defaultRoute
|
|
2202
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
2203
|
-
filters: [{name: "association.subnet-id", values: [@cloud_id]}]
|
|
2204
|
-
)
|
|
2205
|
-
if resp.route_tables.size == 0 # use default route table for the VPC
|
|
2206
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
2207
|
-
filters: [{name: "vpc-id", values: [@parent.cloud_id]}]
|
|
2208
|
-
)
|
|
2209
|
-
end
|
|
2210
|
-
resp.route_tables.each { |route_table|
|
|
2211
|
-
route_table.routes.each { |route|
|
|
2212
|
-
if route.destination_cidr_block =="0.0.0.0/0" and route.state != "blackhole"
|
|
2213
|
-
return route.instance_id if !route.instance_id.nil?
|
|
2214
|
-
return route.gateway_id if !route.gateway_id.nil?
|
|
2215
|
-
return route.vpc_peering_connection_id if !route.vpc_peering_connection_id.nil?
|
|
2216
|
-
return route.network_interface_id if !route.network_interface_id.nil?
|
|
2217
|
-
end
|
|
2218
|
-
}
|
|
2219
|
-
}
|
|
2220
|
-
return nil
|
|
2221
|
-
end
|
|
2222
|
-
|
|
2223
|
-
# Is this subnet privately-routable only, or public?
|
|
2224
|
-
# @return [Boolean]
|
|
2225
|
-
def private?
|
|
2226
|
-
return false if @cloud_id.nil?
|
|
2227
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
2228
|
-
filters: [{name: "association.subnet-id", values: [@cloud_id]}]
|
|
2229
|
-
)
|
|
2230
|
-
if resp.route_tables.size == 0 # use default route table for the VPC
|
|
2231
|
-
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
2232
|
-
filters: [{name: "vpc-id", values: [@parent.cloud_id]}]
|
|
2233
|
-
)
|
|
2234
|
-
end
|
|
2235
|
-
resp.route_tables.each { |route_table|
|
|
2236
|
-
route_table.routes.each { |route|
|
|
2237
|
-
return false if !route.gateway_id.nil? and route.gateway_id != "local" # you can have an IgW and route it to a subset of IPs instead of 0.0.0.0/0
|
|
2238
|
-
if route.destination_cidr_block == "0.0.0.0/0"
|
|
2239
|
-
return true if !route.instance_id.nil?
|
|
2240
|
-
return true if route.nat_gateway_id
|
|
2241
|
-
end
|
|
2242
|
-
}
|
|
2243
|
-
}
|
|
2244
|
-
return true
|
|
2245
|
-
end
|
|
2246
|
-
end
|
|
1840
|
+
private_class_method :purge_vpcs
|
|
2247
1841
|
|
|
2248
1842
|
end #class
|
|
2249
1843
|
end #class
|