cloud-mu 3.4.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ansible/roles/mu-nat/tasks/main.yml +3 -0
- data/bin/mu-aws-setup +41 -7
- data/bin/mu-azure-setup +34 -0
- data/bin/mu-configure +214 -119
- data/bin/mu-gcp-setup +37 -2
- data/bin/mu-node-manage +3 -0
- data/bin/mu-refresh-ssl +67 -0
- data/bin/mu-run-tests +14 -4
- data/bin/mu-self-update +30 -10
- data/bin/mu-upload-chef-artifacts +30 -26
- data/cloud-mu.gemspec +8 -6
- data/cookbooks/mu-master/attributes/default.rb +5 -1
- data/cookbooks/mu-master/metadata.rb +2 -2
- data/cookbooks/mu-master/recipes/default.rb +81 -26
- data/cookbooks/mu-master/recipes/init.rb +197 -62
- data/cookbooks/mu-master/recipes/update_nagios_only.rb +1 -1
- data/cookbooks/mu-master/recipes/vault.rb +78 -77
- data/cookbooks/mu-master/templates/default/mods/rewrite.conf.erb +1 -0
- data/cookbooks/mu-master/templates/default/nagios.conf.erb +103 -0
- data/cookbooks/mu-master/templates/default/web_app.conf.erb +14 -30
- data/cookbooks/mu-tools/attributes/default.rb +5 -0
- data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
- data/cookbooks/mu-tools/libraries/helper.rb +12 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
- data/cookbooks/mu-tools/recipes/apply_security.rb +6 -0
- data/cookbooks/mu-tools/recipes/aws_api.rb +6 -4
- data/cookbooks/mu-tools/recipes/base_repositories.rb +1 -1
- data/cookbooks/mu-tools/recipes/gcloud.rb +2 -9
- data/cookbooks/mu-tools/recipes/google_api.rb +5 -2
- data/cookbooks/mu-tools/resources/disk.rb +108 -58
- data/extras/Gemfile.lock.bootstrap +394 -0
- data/extras/bucketstubs/error.html +0 -0
- data/extras/bucketstubs/index.html +0 -0
- data/extras/clean-stock-amis +9 -9
- data/extras/git_rpm/build.sh +20 -0
- data/extras/git_rpm/mugit.spec +53 -0
- data/extras/image-generators/VMWare/centos8.yaml +15 -0
- data/extras/openssl_rpm/build.sh +19 -0
- data/extras/openssl_rpm/mussl.spec +46 -0
- data/extras/python_rpm/muthon.spec +14 -4
- data/extras/ruby_rpm/muby.spec +9 -5
- data/extras/sqlite_rpm/build.sh +19 -0
- data/extras/sqlite_rpm/muqlite.spec +47 -0
- data/install/installer +7 -5
- data/modules/mu.rb +12 -5
- data/modules/mu/cloud/machine_images.rb +1 -1
- data/modules/mu/cloud/providers.rb +6 -1
- data/modules/mu/cloud/resource_base.rb +1 -1
- data/modules/mu/cloud/ssh_sessions.rb +4 -0
- data/modules/mu/config.rb +28 -12
- data/modules/mu/config/database.rb +2 -2
- data/modules/mu/config/firewall_rule.rb +1 -1
- data/modules/mu/config/ref.rb +2 -2
- data/modules/mu/config/schema_helpers.rb +12 -3
- data/modules/mu/config/server.rb +10 -4
- data/modules/mu/config/server_pool.rb +2 -2
- data/modules/mu/config/vpc.rb +10 -10
- data/modules/mu/defaults/AWS.yaml +32 -32
- data/modules/mu/deploy.rb +23 -10
- data/modules/mu/groomers/chef.rb +2 -2
- data/modules/mu/master.rb +49 -3
- data/modules/mu/mommacat.rb +8 -5
- data/modules/mu/mommacat/naming.rb +2 -2
- data/modules/mu/mommacat/storage.rb +22 -27
- data/modules/mu/providers/aws.rb +142 -48
- data/modules/mu/providers/aws/alarm.rb +3 -3
- data/modules/mu/providers/aws/bucket.rb +19 -19
- data/modules/mu/providers/aws/cache_cluster.rb +22 -22
- data/modules/mu/providers/aws/cdn.rb +2 -2
- data/modules/mu/providers/aws/collection.rb +14 -14
- data/modules/mu/providers/aws/container_cluster.rb +27 -27
- data/modules/mu/providers/aws/database.rb +40 -39
- data/modules/mu/providers/aws/dnszone.rb +5 -5
- data/modules/mu/providers/aws/endpoint.rb +35 -35
- data/modules/mu/providers/aws/firewall_rule.rb +26 -23
- data/modules/mu/providers/aws/function.rb +28 -28
- data/modules/mu/providers/aws/group.rb +7 -7
- data/modules/mu/providers/aws/habitat.rb +2 -2
- data/modules/mu/providers/aws/job.rb +6 -6
- data/modules/mu/providers/aws/loadbalancer.rb +34 -34
- data/modules/mu/providers/aws/log.rb +14 -14
- data/modules/mu/providers/aws/msg_queue.rb +10 -10
- data/modules/mu/providers/aws/nosqldb.rb +8 -8
- data/modules/mu/providers/aws/notifier.rb +7 -7
- data/modules/mu/providers/aws/role.rb +17 -15
- data/modules/mu/providers/aws/search_domain.rb +10 -10
- data/modules/mu/providers/aws/server.rb +176 -95
- data/modules/mu/providers/aws/server_pool.rb +65 -105
- data/modules/mu/providers/aws/storage_pool.rb +17 -9
- data/modules/mu/providers/aws/user.rb +1 -1
- data/modules/mu/providers/aws/vpc.rb +103 -51
- data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
- data/modules/mu/providers/azure.rb +78 -12
- data/modules/mu/providers/azure/server.rb +18 -3
- data/modules/mu/providers/cloudformation/server.rb +1 -1
- data/modules/mu/providers/google.rb +19 -4
- data/modules/mu/providers/google/folder.rb +6 -2
- data/modules/mu/providers/google/function.rb +65 -30
- data/modules/mu/providers/google/role.rb +1 -1
- data/modules/mu/providers/google/vpc.rb +27 -2
- data/modules/tests/aws-servers-with-handrolled-iam.yaml +37 -0
- data/modules/tests/k8s.yaml +1 -1
- metadata +24 -8
|
@@ -430,7 +430,7 @@ MU.log e.inspect, MU::ERR, details: policy
|
|
|
430
430
|
if resp and resp.policy_names and resp.policy_names.size > 0
|
|
431
431
|
resp.policy_names.each { |pol_name|
|
|
432
432
|
pol = MU::Cloud::AWS.iam(credentials: @credentials).get_user_policy(user_name: @cloud_id, policy_name: pol_name)
|
|
433
|
-
doc = JSON.parse(
|
|
433
|
+
doc = JSON.parse(CGI.unescape(pol.policy_document))
|
|
434
434
|
bok["inline_policies"] = MU::Cloud.resourceClass("AWS", "Role").doc2MuPolicies(pol.policy_name, doc, bok["inline_policies"])
|
|
435
435
|
}
|
|
436
436
|
end
|
|
@@ -35,7 +35,7 @@ module MU
|
|
|
35
35
|
# Called automatically by {MU::Deploy#createResources}
|
|
36
36
|
def create
|
|
37
37
|
MU.log "Creating VPC #{@mu_name}", details: @config
|
|
38
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
38
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_vpc(cidr_block: @config['ip_block']).vpc
|
|
39
39
|
@cloud_id = resp.vpc_id
|
|
40
40
|
@config['vpc_id'] = @cloud_id
|
|
41
41
|
|
|
@@ -45,10 +45,10 @@ module MU
|
|
|
45
45
|
begin
|
|
46
46
|
MU.log "Waiting for VPC #{@mu_name} (#{@cloud_id}) to be available", MU::NOTICE
|
|
47
47
|
sleep 5
|
|
48
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
48
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_vpcs(vpc_ids: [@cloud_id]).vpcs.first
|
|
49
49
|
end while resp.state != "available"
|
|
50
50
|
# There's a default route table that comes with. Let's tag it.
|
|
51
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
51
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_route_tables(
|
|
52
52
|
filters: [
|
|
53
53
|
{
|
|
54
54
|
name: "vpc-id",
|
|
@@ -63,13 +63,13 @@ module MU
|
|
|
63
63
|
|
|
64
64
|
if @config['create_internet_gateway']
|
|
65
65
|
MU.log "Creating Internet Gateway #{@mu_name}"
|
|
66
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
66
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_internet_gateway
|
|
67
67
|
internet_gateway_id = resp.internet_gateway.internet_gateway_id
|
|
68
68
|
sleep 5
|
|
69
69
|
|
|
70
70
|
tag_me(internet_gateway_id)
|
|
71
71
|
|
|
72
|
-
MU::Cloud::AWS.ec2(region: @
|
|
72
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).attach_internet_gateway(vpc_id: @cloud_id, internet_gateway_id: internet_gateway_id)
|
|
73
73
|
@config['internet_gateway_id'] = internet_gateway_id
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -93,7 +93,7 @@ module MU
|
|
|
93
93
|
config[:policy_document] = statement.to_json
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
96
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_vpc_endpoint(config).vpc_endpoint
|
|
97
97
|
endpoint_id = resp.vpc_endpoint_id
|
|
98
98
|
MU.log "Creating VPC endpoint #{endpoint_id}"
|
|
99
99
|
attempts = 0
|
|
@@ -102,7 +102,7 @@ module MU
|
|
|
102
102
|
MU.log "Waiting for VPC endpoint #{endpoint_id} to become available" if attempts % 5 == 0
|
|
103
103
|
sleep 10
|
|
104
104
|
begin
|
|
105
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
105
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_vpc_endpoints(vpc_endpoint_ids: [endpoint_id]).vpc_endpoints.first
|
|
106
106
|
rescue Aws::EmptyStructure, NoMethodError
|
|
107
107
|
sleep 5
|
|
108
108
|
retry
|
|
@@ -119,7 +119,7 @@ module MU
|
|
|
119
119
|
logrole = @deploy.findLitterMate(name: @config['name']+"logrole", type: "roles")
|
|
120
120
|
|
|
121
121
|
MU.log "Enabling traffic logging on VPC #{@mu_name} to log group #{loggroup.mu_name}"
|
|
122
|
-
MU::Cloud::AWS.ec2(region: @
|
|
122
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_flow_logs(
|
|
123
123
|
resource_ids: [@cloud_id],
|
|
124
124
|
resource_type: "VPC",
|
|
125
125
|
traffic_type: "ALL",
|
|
@@ -150,7 +150,7 @@ module MU
|
|
|
150
150
|
MU.log "Creating route for #{route['destination_network']} through NAT gatway #{gateway['id']}", details: route_config
|
|
151
151
|
MU.retrier([Aws::EC2::Errors::InvalidNatGatewayIDNotFound], wait: 10, max: 5) {
|
|
152
152
|
begin
|
|
153
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
153
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_route(route_config)
|
|
154
154
|
rescue Aws::EC2::Errors::RouteAlreadyExists
|
|
155
155
|
MU.log "Attempt to create duplicate route to #{route['destination_network']} for #{gateway['id']} in #{rtb['route_table_id']}", MU::WARN
|
|
156
156
|
end
|
|
@@ -163,14 +163,14 @@ module MU
|
|
|
163
163
|
|
|
164
164
|
if @config['enable_dns_support']
|
|
165
165
|
MU.log "Enabling DNS support in #{@mu_name}"
|
|
166
|
-
MU::Cloud::AWS.ec2(region: @
|
|
166
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).modify_vpc_attribute(
|
|
167
167
|
vpc_id: @cloud_id,
|
|
168
168
|
enable_dns_support: {value: @config['enable_dns_support']}
|
|
169
169
|
)
|
|
170
170
|
end
|
|
171
171
|
if @config['enable_dns_hostnames']
|
|
172
172
|
MU.log "Enabling DNS hostnames in #{@mu_name}"
|
|
173
|
-
MU::Cloud::AWS.ec2(region: @
|
|
173
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).modify_vpc_attribute(
|
|
174
174
|
vpc_id: @cloud_id,
|
|
175
175
|
enable_dns_hostnames: {value: @config['enable_dns_hostnames']}
|
|
176
176
|
)
|
|
@@ -196,20 +196,20 @@ module MU
|
|
|
196
196
|
dhcpopts << {key: "netbios-name-servers", values: @config['dhcp']['netbios_servers']}
|
|
197
197
|
end
|
|
198
198
|
|
|
199
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
199
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_dhcp_options(
|
|
200
200
|
dhcp_configurations: dhcpopts
|
|
201
201
|
)
|
|
202
202
|
dhcpopt_id = resp.dhcp_options.dhcp_options_id
|
|
203
203
|
tag_me(dhcpopt_id)
|
|
204
204
|
|
|
205
|
-
MU::Cloud::AWS.ec2(region: @
|
|
205
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).associate_dhcp_options(dhcp_options_id: dhcpopt_id, vpc_id: @cloud_id)
|
|
206
206
|
end
|
|
207
207
|
notify
|
|
208
208
|
|
|
209
|
-
if !MU::Cloud::AWS.isGovCloud?(@
|
|
210
|
-
mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu", credentials: @
|
|
209
|
+
if !MU::Cloud::AWS.isGovCloud?(@region)
|
|
210
|
+
mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu", credentials: @credentials).values.first
|
|
211
211
|
if !mu_zone.nil?
|
|
212
|
-
MU::Cloud.resourceClass("AWS", "DNSZone").toggleVPCAccess(id: mu_zone.id, vpc_id: @cloud_id, region: @
|
|
212
|
+
MU::Cloud.resourceClass("AWS", "DNSZone").toggleVPCAccess(id: mu_zone.id, vpc_id: @cloud_id, region: @region, credentials: @credentials)
|
|
213
213
|
end
|
|
214
214
|
end
|
|
215
215
|
loadSubnets
|
|
@@ -220,7 +220,7 @@ module MU
|
|
|
220
220
|
# Canonical Amazon Resource Number for this resource
|
|
221
221
|
# @return [String]
|
|
222
222
|
def arn
|
|
223
|
-
"arn:"+(MU::Cloud::AWS.isGovCloud?(@
|
|
223
|
+
"arn:"+(MU::Cloud::AWS.isGovCloud?(@region) ? "aws-us-gov" : "aws")+":ec2:"+@region+":"+MU::Cloud::AWS.credToAcct(@credentials)+":vpc/"+@cloud_id
|
|
224
224
|
end
|
|
225
225
|
|
|
226
226
|
# Describe this VPC
|
|
@@ -263,7 +263,7 @@ module MU
|
|
|
263
263
|
route_config[:instance_id] = nat_instance.cloud_id
|
|
264
264
|
|
|
265
265
|
MU.log "Creating route for #{route['destination_network']} through NAT host #{nat_instance.cloud_id}", details: route_config
|
|
266
|
-
MU::Cloud::AWS.ec2(region: @
|
|
266
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_route(route_config)
|
|
267
267
|
end
|
|
268
268
|
}
|
|
269
269
|
|
|
@@ -327,9 +327,9 @@ module MU
|
|
|
327
327
|
def toKitten(**_args)
|
|
328
328
|
bok = {
|
|
329
329
|
"cloud" => "AWS",
|
|
330
|
-
"credentials" => @
|
|
330
|
+
"credentials" => @credentials,
|
|
331
331
|
"cloud_id" => @cloud_id,
|
|
332
|
-
"region" => @
|
|
332
|
+
"region" => @region
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
if !cloud_desc
|
|
@@ -352,7 +352,7 @@ module MU
|
|
|
352
352
|
|
|
353
353
|
bok['create_bastion'] = false # XXX figure out a way to detect this
|
|
354
354
|
|
|
355
|
-
logs = MU::Cloud::AWS.ec2(region: @
|
|
355
|
+
logs = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_flow_logs(filter: [{ "name" => "resource-id", "values" => [@cloud_id] }])
|
|
356
356
|
if logs and logs.flow_logs and !logs.flow_logs.empty?
|
|
357
357
|
bok['enable_traffic_logging'] = true
|
|
358
358
|
bok['traffic_type_to_log'] = logs.flow_logs.first.traffic_type.downcase
|
|
@@ -362,13 +362,13 @@ module MU
|
|
|
362
362
|
end
|
|
363
363
|
end
|
|
364
364
|
|
|
365
|
-
nats = MU::Cloud::AWS.ec2(region: @
|
|
365
|
+
nats = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_nat_gateways(filter: [{ "name" => "vpc-id", "values" => [@cloud_id] }])
|
|
366
366
|
if nats and nats.nat_gateways and !nats.nat_gateways.empty?
|
|
367
367
|
bok['create_nat_gateway'] = true
|
|
368
368
|
bok['nat_gateway_multi_az'] = true if nats.nat_gateways.size > 1
|
|
369
369
|
end
|
|
370
370
|
|
|
371
|
-
rtbs = MU::Cloud::AWS::VPC.get_route_tables(vpc_ids: [@cloud_id], region: @
|
|
371
|
+
rtbs = MU::Cloud::AWS::VPC.get_route_tables(vpc_ids: [@cloud_id], region: @region, credentials: @credentials)
|
|
372
372
|
|
|
373
373
|
associations = {}
|
|
374
374
|
if rtbs and !rtbs.empty?
|
|
@@ -454,13 +454,13 @@ module MU
|
|
|
454
454
|
def loadSubnets
|
|
455
455
|
return [] if !@cloud_id
|
|
456
456
|
|
|
457
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
457
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_subnets(
|
|
458
458
|
filters: [
|
|
459
459
|
{ name: "vpc-id", values: [@cloud_id] }
|
|
460
460
|
]
|
|
461
461
|
)
|
|
462
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
|
|
463
|
+
MU.log "Got empty results when trying to list subnets in #{@cloud_id} (#{@region})", MU::WARN
|
|
464
464
|
return []
|
|
465
465
|
end
|
|
466
466
|
|
|
@@ -473,8 +473,8 @@ module MU
|
|
|
473
473
|
if !@config.nil? and @config.has_key?("subnets")
|
|
474
474
|
@config['subnets'].each { |subnet|
|
|
475
475
|
subnet['mu_name'] ||= @mu_name+"-"+subnet['name']
|
|
476
|
-
subnet['region'] = @
|
|
477
|
-
subnet['credentials'] = @
|
|
476
|
+
subnet['region'] = @region
|
|
477
|
+
subnet['credentials'] = @credentials
|
|
478
478
|
resp.subnets.each { |desc|
|
|
479
479
|
if desc.cidr_block == subnet["ip_block"]
|
|
480
480
|
subnet["tags"] = MU.structToHash(desc.tags)
|
|
@@ -500,15 +500,32 @@ module MU
|
|
|
500
500
|
# Of course we might be loading up a dummy subnet object from a
|
|
501
501
|
# foreign or non-Mu-created VPC and subnet. So make something up.
|
|
502
502
|
if @subnets.empty?
|
|
503
|
+
nets_by_block = {}
|
|
504
|
+
|
|
505
|
+
# Attempt to dig the canonical resource name out of
|
|
506
|
+
# deployment metadata, if it exists
|
|
507
|
+
if @deploy and @deploy.deployment and
|
|
508
|
+
@deploy.deployment['vpcs'] and
|
|
509
|
+
@deploy.deployment['vpcs'][@config['name']] and
|
|
510
|
+
@deploy.deployment['vpcs'][@config['name']]['subnets']
|
|
511
|
+
@deploy.deployment['vpcs'][@config['name']]['subnets'].each { |s|
|
|
512
|
+
nets_by_block[s["ip_block"]] = s
|
|
513
|
+
}
|
|
514
|
+
end
|
|
515
|
+
|
|
503
516
|
resp.subnets.each { |desc|
|
|
504
517
|
subnet = {
|
|
505
518
|
"ip_block" => desc.cidr_block,
|
|
506
519
|
"tags" => MU.structToHash(desc.tags),
|
|
507
520
|
"cloud_id" => desc.subnet_id,
|
|
508
|
-
'region' => @
|
|
509
|
-
'credentials' => @
|
|
521
|
+
'region' => @region,
|
|
522
|
+
'credentials' => @credentials,
|
|
510
523
|
}
|
|
511
|
-
|
|
524
|
+
if nets_by_block[desc.cidr_block] and
|
|
525
|
+
nets_by_block[desc.cidr_block]["name"]
|
|
526
|
+
subnet['name'] = nets_by_block[desc.cidr_block]["name"]
|
|
527
|
+
end
|
|
528
|
+
subnet['name'] ||= subnet["ip_block"].gsub(/[\.\/]/, "_")
|
|
512
529
|
subnet['mu_name'] = @mu_name+"-"+subnet['name']
|
|
513
530
|
@subnets << MU::Cloud::AWS::VPC::Subnet.new(self, subnet)
|
|
514
531
|
}
|
|
@@ -571,7 +588,7 @@ module MU
|
|
|
571
588
|
@config['cloud'],
|
|
572
589
|
"server",
|
|
573
590
|
name: nat_name,
|
|
574
|
-
region: @
|
|
591
|
+
region: @region,
|
|
575
592
|
cloud_id: nat_cloud_id,
|
|
576
593
|
deploy_id: deploy_id,
|
|
577
594
|
tag_key: nat_tag_key,
|
|
@@ -838,7 +855,7 @@ module MU
|
|
|
838
855
|
vpcs = resp if !resp.empty?
|
|
839
856
|
}
|
|
840
857
|
|
|
841
|
-
# resp = MU::Cloud::AWS.ec2(region: @
|
|
858
|
+
# resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_vpc_peering_connections(
|
|
842
859
|
# filters: [
|
|
843
860
|
# {
|
|
844
861
|
# name: "requester-vpc-info.vpc-id",
|
|
@@ -873,6 +890,7 @@ module MU
|
|
|
873
890
|
purge_subnets(noop, tagfilters, region: region, credentials: credentials)
|
|
874
891
|
purge_vpcs(noop, tagfilters, region: region, credentials: credentials)
|
|
875
892
|
purge_dhcpopts(noop, tagfilters, region: region, credentials: credentials)
|
|
893
|
+
purge_eips(noop, tagfilters, region: region, credentials: credentials)
|
|
876
894
|
|
|
877
895
|
# unless noop
|
|
878
896
|
# MU::Cloud::AWS.iam.list_roles.roles.each{ |role|
|
|
@@ -1019,7 +1037,7 @@ module MU
|
|
|
1019
1037
|
subnet_routes[table['name']].each { |subnet|
|
|
1020
1038
|
nat_routes[subnet] = route['nat_host_name']
|
|
1021
1039
|
}
|
|
1022
|
-
MU::Config.addDependency(vpc, route['nat_host_name'], "server",
|
|
1040
|
+
MU::Config.addDependency(vpc, route['nat_host_name'], "server", my_phase: "groom")
|
|
1023
1041
|
elsif route['gateway'] == '#NAT'
|
|
1024
1042
|
vpc['create_nat_gateway'] = true
|
|
1025
1043
|
private_rtbs << table['name']
|
|
@@ -1118,7 +1136,7 @@ module MU
|
|
|
1118
1136
|
if subnets and subnets.size > 0
|
|
1119
1137
|
filters << { :name => "association.subnet-id", :values => subnets }
|
|
1120
1138
|
end
|
|
1121
|
-
tables = MU::Cloud::AWS.ec2(region: @
|
|
1139
|
+
tables = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_route_tables(
|
|
1122
1140
|
filters: filters
|
|
1123
1141
|
)
|
|
1124
1142
|
cidrs = []
|
|
@@ -1319,7 +1337,7 @@ module MU
|
|
|
1319
1337
|
id: @cloud_id,
|
|
1320
1338
|
cloud: "AWS",
|
|
1321
1339
|
credentials: @credentials,
|
|
1322
|
-
region: @
|
|
1340
|
+
region: @region,
|
|
1323
1341
|
type: "vpcs",
|
|
1324
1342
|
subnet_pref: subnet_pref
|
|
1325
1343
|
)
|
|
@@ -1356,7 +1374,7 @@ module MU
|
|
|
1356
1374
|
|
|
1357
1375
|
# See if the peering connection exists before we bother
|
|
1358
1376
|
# creating it.
|
|
1359
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
1377
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_vpc_peering_connections(
|
|
1360
1378
|
filters: [
|
|
1361
1379
|
{
|
|
1362
1380
|
name: "requester-vpc-info.vpc-id",
|
|
@@ -1372,8 +1390,8 @@ module MU
|
|
|
1372
1390
|
peering_id = if !resp or !resp.vpc_peering_connections or
|
|
1373
1391
|
resp.vpc_peering_connections.empty?
|
|
1374
1392
|
|
|
1375
|
-
MU.log "Setting peering connection from VPC #{@config['name']} (#{@cloud_id} in account #{MU::Cloud::AWS.credToAcct(@
|
|
1376
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
1393
|
+
MU.log "Setting peering connection from VPC #{@config['name']} (#{@cloud_id} in account #{MU::Cloud::AWS.credToAcct(@credentials)}) to #{peer_id} in account #{peer['account']}", details: peer
|
|
1394
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_vpc_peering_connection(
|
|
1377
1395
|
vpc_id: @cloud_id,
|
|
1378
1396
|
peer_vpc_id: peer_id,
|
|
1379
1397
|
peer_owner_id: peer['account'],
|
|
@@ -1389,13 +1407,13 @@ module MU
|
|
|
1389
1407
|
tag_me(peering_id, peering_name)
|
|
1390
1408
|
|
|
1391
1409
|
# Create routes to our new friend.
|
|
1392
|
-
MU::Cloud::AWS::VPC.listAllSubnetRouteTables(@cloud_id, region: @
|
|
1410
|
+
MU::Cloud::AWS::VPC.listAllSubnetRouteTables(@cloud_id, region: @region, credentials: @credentials).each { |rtb_id|
|
|
1393
1411
|
my_route_config = {
|
|
1394
1412
|
:route_table_id => rtb_id,
|
|
1395
1413
|
:destination_cidr_block => peer_obj.cloud_desc.cidr_block,
|
|
1396
1414
|
:vpc_peering_connection_id => peering_id
|
|
1397
1415
|
}
|
|
1398
|
-
rtbdesc = MU::Cloud::AWS.ec2(region: @
|
|
1416
|
+
rtbdesc = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_route_tables(
|
|
1399
1417
|
route_table_ids: [rtb_id]
|
|
1400
1418
|
).route_tables.first
|
|
1401
1419
|
already_exists = false
|
|
@@ -1411,18 +1429,18 @@ module MU
|
|
|
1411
1429
|
}
|
|
1412
1430
|
next if already_exists
|
|
1413
1431
|
|
|
1414
|
-
MU.log "Creating peering route to #{peer_obj.cloud_desc.cidr_block} in #{peer['vpc']['region']} from VPC #{@config['name']} in #{@
|
|
1415
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
1432
|
+
MU.log "Creating peering route to #{peer_obj.cloud_desc.cidr_block} in #{peer['vpc']['region']} from VPC #{@config['name']} in #{@region}"
|
|
1433
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_route(my_route_config)
|
|
1416
1434
|
} # MU::Cloud::AWS::VPC.listAllSubnetRouteTables
|
|
1417
1435
|
|
|
1418
1436
|
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'])
|
|
1419
1437
|
|
|
1420
|
-
cnxn = MU::Cloud::AWS.ec2(region: @
|
|
1438
|
+
cnxn = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_vpc_peering_connections(
|
|
1421
1439
|
vpc_peering_connection_ids: [peering_id]
|
|
1422
1440
|
).vpc_peering_connections.first
|
|
1423
1441
|
|
|
1424
1442
|
loop_if = Proc.new {
|
|
1425
|
-
cnxn = MU::Cloud::AWS.ec2(region: @
|
|
1443
|
+
cnxn = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_vpc_peering_connections(
|
|
1426
1444
|
vpc_peering_connection_ids: [peering_id]
|
|
1427
1445
|
).vpc_peering_connections.first
|
|
1428
1446
|
((can_auto_accept and cnxn.status.code == "pending-acceptance") or (cnxn.status.code != "active" and cnxn.status.code != "pending-acceptance"))
|
|
@@ -1451,9 +1469,9 @@ module MU
|
|
|
1451
1469
|
end
|
|
1452
1470
|
|
|
1453
1471
|
if ["failed", "rejected", "expired", "deleted"].include?(cnxn.status.code)
|
|
1454
|
-
MU.log "VPC peering connection from VPC #{@config['name']} (#{@cloud_id} in #{@
|
|
1472
|
+
MU.log "VPC peering connection from VPC #{@config['name']} (#{@cloud_id} in #{@region}) to #{peer_id} in #{peer_obj.config['region']} #{cnxn.status.code}: #{cnxn.status.message}", MU::ERR
|
|
1455
1473
|
begin
|
|
1456
|
-
MU::Cloud::AWS.ec2(region: @
|
|
1474
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).delete_vpc_peering_connection(
|
|
1457
1475
|
vpc_peering_connection_id: peering_id
|
|
1458
1476
|
)
|
|
1459
1477
|
rescue Aws::EC2::Errors::InvalidStateTransition
|
|
@@ -1469,8 +1487,8 @@ module MU
|
|
|
1469
1487
|
def tag_me(resource_id = @cloud_id, name = @mu_name)
|
|
1470
1488
|
MU::Cloud::AWS.createStandardTags(
|
|
1471
1489
|
resource_id,
|
|
1472
|
-
region: @
|
|
1473
|
-
credentials: @
|
|
1490
|
+
region: @region,
|
|
1491
|
+
credentials: @credentials,
|
|
1474
1492
|
optional: @config['optional_tags'],
|
|
1475
1493
|
nametag: name,
|
|
1476
1494
|
othertags: @config['tags']
|
|
@@ -1484,8 +1502,8 @@ module MU
|
|
|
1484
1502
|
def createRouteTable(rtb)
|
|
1485
1503
|
vpc_id = @cloud_id
|
|
1486
1504
|
vpc_name = @config['name']
|
|
1487
|
-
MU.setVar("curRegion", @
|
|
1488
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
1505
|
+
MU.setVar("curRegion", @region) if !@region.nil?
|
|
1506
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_route_table(vpc_id: vpc_id).route_table
|
|
1489
1507
|
route_table_id = rtb['route_table_id'] = resp.route_table_id
|
|
1490
1508
|
sleep 5
|
|
1491
1509
|
|
|
@@ -1506,7 +1524,7 @@ module MU
|
|
|
1506
1524
|
unless route['gateway'] == '#NAT'
|
|
1507
1525
|
# Need to change the order of how things are created to create the route here
|
|
1508
1526
|
MU.log "Creating route for #{route['destination_network']}", details: route_config
|
|
1509
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
1527
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_route(route_config)
|
|
1510
1528
|
end
|
|
1511
1529
|
end
|
|
1512
1530
|
}
|
|
@@ -1614,6 +1632,40 @@ module MU
|
|
|
1614
1632
|
end
|
|
1615
1633
|
private_class_method :purge_nat_gateways
|
|
1616
1634
|
|
|
1635
|
+
# Remove all Elastic IPs from the currently loaded deployment.
|
|
1636
|
+
# @param noop [Boolean]: If true, will only print what would be done
|
|
1637
|
+
# @param tagfilters [Array<Hash>]: EC2 tags to filter against when search for resources to purge
|
|
1638
|
+
# @param region [String]: The cloud provider region
|
|
1639
|
+
# @return [void]
|
|
1640
|
+
def self.purge_eips(noop = false, tagfilters = [{name: "tag:MU-ID", values: [MU.deploy_id]}], region: MU.curRegion, credentials: nil)
|
|
1641
|
+
eips = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_addresses(
|
|
1642
|
+
filters: tagfilters
|
|
1643
|
+
).addresses
|
|
1644
|
+
|
|
1645
|
+
threads = []
|
|
1646
|
+
|
|
1647
|
+
if !eips.empty?
|
|
1648
|
+
eips.each { |eip|
|
|
1649
|
+
MU.log "Releasing EIP #{eip.public_ip} (#{eip.allocation_id})"
|
|
1650
|
+
next if noop
|
|
1651
|
+
if eip.association_id
|
|
1652
|
+
MU.log "Tags tell me I should release EIP #{eip.public_ip} (#{eip.allocation_id}), but it appears to be associated with something", MU::WARN, details: eip
|
|
1653
|
+
next
|
|
1654
|
+
end
|
|
1655
|
+
threads << Thread.new {
|
|
1656
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).release_address(allocation_id: eip.allocation_id)
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
end
|
|
1660
|
+
|
|
1661
|
+
threads.each { |t|
|
|
1662
|
+
t.join
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
return nil
|
|
1666
|
+
end
|
|
1667
|
+
private_class_method :purge_eips
|
|
1668
|
+
|
|
1617
1669
|
# Remove all VPC endpoints associated with the VPC of the currently loaded deployment.
|
|
1618
1670
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
1619
1671
|
# @param vpc_id [String]: The cloud provider's unique VPC identifier
|
|
@@ -29,18 +29,21 @@ module MU
|
|
|
29
29
|
attr_reader :mu_name
|
|
30
30
|
attr_reader :name
|
|
31
31
|
attr_reader :az
|
|
32
|
+
attr_reader :config
|
|
32
33
|
attr_reader :cloud_desc
|
|
33
34
|
|
|
34
35
|
# @param parent [MU::Cloud::AWS::VPC]: The parent VPC of this subnet.
|
|
35
36
|
# @param config [Hash<String>]:
|
|
36
37
|
def initialize(parent, config)
|
|
37
|
-
@parent = parent
|
|
38
38
|
@config = MU::Config.manxify(config)
|
|
39
|
+
MU::Cloud::AWS.resourceInitHook(self, @deploy)
|
|
40
|
+
@parent = parent
|
|
39
41
|
@cloud_id = config['cloud_id']
|
|
42
|
+
@credentials ||= config['credentials']
|
|
40
43
|
@mu_name = config['mu_name']
|
|
41
44
|
@name = config['name']
|
|
42
45
|
@deploydata = config # This is a dummy for the sake of describe()
|
|
43
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
46
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_subnets(subnet_ids: [@cloud_id]).subnets.first
|
|
44
47
|
@az = resp.availability_zone
|
|
45
48
|
@ip_block = resp.cidr_block
|
|
46
49
|
@cloud_desc = resp # XXX this really isn't the cloud implementation's business
|
|
@@ -50,11 +53,11 @@ module MU
|
|
|
50
53
|
# Return the cloud identifier for the default route of this subnet.
|
|
51
54
|
# @return [String,nil]
|
|
52
55
|
def defaultRoute
|
|
53
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
56
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_route_tables(
|
|
54
57
|
filters: [{name: "association.subnet-id", values: [@cloud_id]}]
|
|
55
58
|
)
|
|
56
59
|
if resp.route_tables.size == 0 # use default route table for the VPC
|
|
57
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
60
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_route_tables(
|
|
58
61
|
filters: [{name: "vpc-id", values: [@parent.cloud_id]}]
|
|
59
62
|
)
|
|
60
63
|
end
|
|
@@ -75,11 +78,11 @@ module MU
|
|
|
75
78
|
# @return [Boolean]
|
|
76
79
|
def private?
|
|
77
80
|
return false if @cloud_id.nil?
|
|
78
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
81
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_route_tables(
|
|
79
82
|
filters: [{name: "association.subnet-id", values: [@cloud_id]}]
|
|
80
83
|
)
|
|
81
84
|
if resp.route_tables.size == 0 # use default route table for the VPC
|
|
82
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
85
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_route_tables(
|
|
83
86
|
filters: [{name: "vpc-id", values: [@parent.cloud_id]}]
|
|
84
87
|
)
|
|
85
88
|
end
|
|
@@ -106,14 +109,14 @@ module MU
|
|
|
106
109
|
|
|
107
110
|
subnetthreads = Array.new
|
|
108
111
|
|
|
109
|
-
azs = MU::Cloud::AWS.listAZs(region: @
|
|
112
|
+
azs = MU::Cloud::AWS.listAZs(region: @region, credentials: @credentials)
|
|
110
113
|
@config['subnets'].each { |subnet|
|
|
111
114
|
subnet_name = @config['name']+"-"+subnet['name']
|
|
112
115
|
az = subnet['availability_zone'] ? subnet['availability_zone'] : azs.op
|
|
113
116
|
MU.log "Creating Subnet #{subnet_name} (#{subnet['ip_block']}) in #{az}", details: subnet
|
|
114
117
|
|
|
115
118
|
subnetthreads << Thread.new {
|
|
116
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
119
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_subnet(
|
|
117
120
|
vpc_id: @cloud_id,
|
|
118
121
|
cidr_block: subnet['ip_block'],
|
|
119
122
|
availability_zone: az
|
|
@@ -123,7 +126,7 @@ module MU
|
|
|
123
126
|
tag_me(subnet_id, @mu_name+"-"+subnet['name'])
|
|
124
127
|
|
|
125
128
|
loop_if = Proc.new {
|
|
126
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
129
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_subnets(subnet_ids: [subnet_id]).subnets.first
|
|
127
130
|
(!resp or resp.state != "available")
|
|
128
131
|
}
|
|
129
132
|
|
|
@@ -141,7 +144,7 @@ module MU
|
|
|
141
144
|
end
|
|
142
145
|
MU.log "Associating Route Table '#{subnet['route_table']}' (#{routes[subnet['route_table']]['route_table_id']}) with #{subnet_name}"
|
|
143
146
|
MU.retrier([Aws::EC2::Errors::InvalidRouteTableIDNotFound], wait: 10, max: 10) {
|
|
144
|
-
MU::Cloud::AWS.ec2(region: @
|
|
147
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).associate_route_table(
|
|
145
148
|
route_table_id: routes[subnet['route_table']]['route_table_id'],
|
|
146
149
|
subnet_id: subnet_id
|
|
147
150
|
)
|
|
@@ -150,7 +153,7 @@ module MU
|
|
|
150
153
|
|
|
151
154
|
if subnet.has_key?("map_public_ips")
|
|
152
155
|
MU.retrier([Aws::EC2::Errors::InvalidSubnetIDNotFound], wait: 10, max: 10) {
|
|
153
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
156
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).modify_subnet_attribute(
|
|
154
157
|
subnet_id: subnet_id,
|
|
155
158
|
map_public_ip_on_launch: {
|
|
156
159
|
value: subnet['map_public_ips'],
|
|
@@ -167,7 +170,7 @@ module MU
|
|
|
167
170
|
loggroup = @deploy.findLitterMate(name: @config['name']+"loggroup", type: "logs")
|
|
168
171
|
logrole = @deploy.findLitterMate(name: @config['name']+"logrole", type: "roles")
|
|
169
172
|
MU.log "Enabling traffic logging on Subnet #{subnet_name} in VPC #{@mu_name} to log group #{loggroup.mu_name}"
|
|
170
|
-
MU::Cloud::AWS.ec2(region: @
|
|
173
|
+
MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_flow_logs(
|
|
171
174
|
resource_ids: [subnet_id],
|
|
172
175
|
resource_type: "Subnet",
|
|
173
176
|
traffic_type: subnet["traffic_type_to_log"],
|
|
@@ -188,30 +191,31 @@ module MU
|
|
|
188
191
|
def allocate_eip_for_nat
|
|
189
192
|
MU::MommaCat.lock("nat-gateway-eipalloc")
|
|
190
193
|
|
|
191
|
-
eips = MU::Cloud::AWS.ec2(region: @
|
|
192
|
-
filters: [
|
|
193
|
-
{
|
|
194
|
-
name: "domain",
|
|
195
|
-
values: ["vpc"]
|
|
196
|
-
}
|
|
197
|
-
]
|
|
198
|
-
).addresses
|
|
199
|
-
|
|
200
|
-
allocation_id = nil
|
|
201
|
-
eips.each { |eip|
|
|
202
|
-
next if !eip.association_id.nil? and !eip.association_id.empty?
|
|
203
|
-
if (eip.private_ip_address.nil? || eip.private_ip_address.empty?) and MU::MommaCat.lock(eip.allocation_id, true, true)
|
|
204
|
-
if !@eip_allocation_ids.include?(eip.allocation_id)
|
|
205
|
-
allocation_id = eip.allocation_id
|
|
206
|
-
break
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if allocation_id.nil?
|
|
212
|
-
allocation_id = MU::Cloud::AWS.ec2(region: @
|
|
213
|
-
|
|
214
|
-
|
|
194
|
+
# eips = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_addresses(
|
|
195
|
+
# filters: [
|
|
196
|
+
# {
|
|
197
|
+
# name: "domain",
|
|
198
|
+
# values: ["vpc"]
|
|
199
|
+
# }
|
|
200
|
+
# ]
|
|
201
|
+
# ).addresses
|
|
202
|
+
|
|
203
|
+
# allocation_id = nil
|
|
204
|
+
# eips.each { |eip|
|
|
205
|
+
# next if !eip.association_id.nil? and !eip.association_id.empty?
|
|
206
|
+
# if (eip.private_ip_address.nil? || eip.private_ip_address.empty?) and MU::MommaCat.lock(eip.allocation_id, true, true)
|
|
207
|
+
# if !@eip_allocation_ids.include?(eip.allocation_id)
|
|
208
|
+
# allocation_id = eip.allocation_id
|
|
209
|
+
# break
|
|
210
|
+
# end
|
|
211
|
+
# end
|
|
212
|
+
# }
|
|
213
|
+
|
|
214
|
+
# if allocation_id.nil?
|
|
215
|
+
allocation_id = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).allocate_address(domain: "vpc").allocation_id
|
|
216
|
+
tag_me(allocation_id)
|
|
217
|
+
# MU::MommaCat.lock(allocation_id, false, true)
|
|
218
|
+
# end
|
|
215
219
|
|
|
216
220
|
@eip_allocation_ids << allocation_id
|
|
217
221
|
|
|
@@ -223,15 +227,15 @@ module MU
|
|
|
223
227
|
def create_nat_gateway(subnet)
|
|
224
228
|
allocation_id = allocate_eip_for_nat
|
|
225
229
|
|
|
226
|
-
nat_gateway_id = MU::Cloud::AWS.ec2(region: @
|
|
230
|
+
nat_gateway_id = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_nat_gateway(
|
|
227
231
|
subnet_id: subnet['subnet_id'],
|
|
228
232
|
allocation_id: allocation_id,
|
|
229
233
|
).nat_gateway.nat_gateway_id
|
|
230
234
|
|
|
231
235
|
ensure_unlock = Proc.new { MU::MommaCat.unlock(allocation_id, true) }
|
|
232
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
236
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_nat_gateways(nat_gateway_ids: [nat_gateway_id]).nat_gateways.first
|
|
233
237
|
loop_if = Proc.new {
|
|
234
|
-
resp = MU::Cloud::AWS.ec2(region: @
|
|
238
|
+
resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_nat_gateways(nat_gateway_ids: [nat_gateway_id]).nat_gateways.first
|
|
235
239
|
resp.class != Aws::EC2::Types::NatGateway or resp.state == "pending"
|
|
236
240
|
}
|
|
237
241
|
|