cloud-mu 3.3.0 → 3.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/ansible/roles/mu-nat/tasks/main.yml +3 -0
  3. data/bin/mu-aws-setup +41 -7
  4. data/bin/mu-azure-setup +36 -2
  5. data/bin/mu-configure +214 -119
  6. data/bin/mu-gcp-setup +37 -2
  7. data/bin/mu-node-manage +3 -0
  8. data/bin/mu-refresh-ssl +67 -0
  9. data/bin/mu-run-tests +14 -4
  10. data/bin/mu-self-update +30 -10
  11. data/bin/mu-upload-chef-artifacts +30 -26
  12. data/cloud-mu.gemspec +9 -7
  13. data/cookbooks/mu-master/attributes/default.rb +5 -1
  14. data/cookbooks/mu-master/metadata.rb +2 -2
  15. data/cookbooks/mu-master/recipes/default.rb +81 -26
  16. data/cookbooks/mu-master/recipes/init.rb +197 -62
  17. data/cookbooks/mu-master/recipes/update_nagios_only.rb +1 -1
  18. data/cookbooks/mu-master/recipes/vault.rb +78 -77
  19. data/cookbooks/mu-master/templates/default/mods/rewrite.conf.erb +1 -0
  20. data/cookbooks/mu-master/templates/default/nagios.conf.erb +103 -0
  21. data/cookbooks/mu-master/templates/default/web_app.conf.erb +14 -30
  22. data/cookbooks/mu-tools/attributes/default.rb +12 -0
  23. data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
  24. data/cookbooks/mu-tools/libraries/helper.rb +98 -4
  25. data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
  26. data/cookbooks/mu-tools/recipes/apply_security.rb +31 -9
  27. data/cookbooks/mu-tools/recipes/aws_api.rb +8 -2
  28. data/cookbooks/mu-tools/recipes/base_repositories.rb +1 -1
  29. data/cookbooks/mu-tools/recipes/gcloud.rb +2 -9
  30. data/cookbooks/mu-tools/recipes/google_api.rb +7 -0
  31. data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
  32. data/cookbooks/mu-tools/resources/disk.rb +113 -42
  33. data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
  34. data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
  35. data/extras/Gemfile.lock.bootstrap +394 -0
  36. data/extras/bucketstubs/error.html +0 -0
  37. data/extras/bucketstubs/index.html +0 -0
  38. data/extras/clean-stock-amis +11 -3
  39. data/extras/generate-stock-images +6 -3
  40. data/extras/git_rpm/build.sh +20 -0
  41. data/extras/git_rpm/mugit.spec +53 -0
  42. data/extras/image-generators/AWS/centos7.yaml +19 -16
  43. data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
  44. data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -0
  45. data/extras/image-generators/VMWare/centos8.yaml +15 -0
  46. data/extras/openssl_rpm/build.sh +19 -0
  47. data/extras/openssl_rpm/mussl.spec +46 -0
  48. data/extras/python_rpm/muthon.spec +14 -4
  49. data/extras/ruby_rpm/muby.spec +9 -5
  50. data/extras/sqlite_rpm/build.sh +19 -0
  51. data/extras/sqlite_rpm/muqlite.spec +47 -0
  52. data/install/installer +7 -5
  53. data/modules/mommacat.ru +2 -2
  54. data/modules/mu.rb +12 -5
  55. data/modules/mu/cloud/machine_images.rb +1 -1
  56. data/modules/mu/cloud/providers.rb +6 -1
  57. data/modules/mu/cloud/resource_base.rb +7 -4
  58. data/modules/mu/cloud/ssh_sessions.rb +5 -1
  59. data/modules/mu/cloud/wrappers.rb +16 -7
  60. data/modules/mu/config.rb +28 -12
  61. data/modules/mu/config/database.rb +2 -2
  62. data/modules/mu/config/firewall_rule.rb +1 -1
  63. data/modules/mu/config/ref.rb +3 -3
  64. data/modules/mu/config/schema_helpers.rb +12 -3
  65. data/modules/mu/config/server.rb +10 -4
  66. data/modules/mu/config/server_pool.rb +2 -2
  67. data/modules/mu/config/vpc.rb +10 -10
  68. data/modules/mu/defaults/AWS.yaml +96 -96
  69. data/modules/mu/deploy.rb +27 -14
  70. data/modules/mu/groomers/chef.rb +2 -2
  71. data/modules/mu/master.rb +49 -3
  72. data/modules/mu/mommacat.rb +27 -9
  73. data/modules/mu/mommacat/naming.rb +2 -2
  74. data/modules/mu/mommacat/search.rb +16 -5
  75. data/modules/mu/mommacat/storage.rb +67 -32
  76. data/modules/mu/providers/aws.rb +185 -71
  77. data/modules/mu/providers/aws/alarm.rb +3 -3
  78. data/modules/mu/providers/aws/bucket.rb +19 -19
  79. data/modules/mu/providers/aws/cache_cluster.rb +22 -22
  80. data/modules/mu/providers/aws/cdn.rb +2 -2
  81. data/modules/mu/providers/aws/collection.rb +14 -14
  82. data/modules/mu/providers/aws/container_cluster.rb +27 -27
  83. data/modules/mu/providers/aws/database.rb +49 -45
  84. data/modules/mu/providers/aws/dnszone.rb +5 -5
  85. data/modules/mu/providers/aws/endpoint.rb +35 -35
  86. data/modules/mu/providers/aws/firewall_rule.rb +26 -23
  87. data/modules/mu/providers/aws/function.rb +35 -32
  88. data/modules/mu/providers/aws/group.rb +7 -7
  89. data/modules/mu/providers/aws/habitat.rb +2 -2
  90. data/modules/mu/providers/aws/job.rb +35 -32
  91. data/modules/mu/providers/aws/loadbalancer.rb +58 -37
  92. data/modules/mu/providers/aws/log.rb +14 -14
  93. data/modules/mu/providers/aws/msg_queue.rb +10 -10
  94. data/modules/mu/providers/aws/nosqldb.rb +8 -8
  95. data/modules/mu/providers/aws/notifier.rb +7 -7
  96. data/modules/mu/providers/aws/role.rb +69 -47
  97. data/modules/mu/providers/aws/search_domain.rb +10 -10
  98. data/modules/mu/providers/aws/server.rb +198 -110
  99. data/modules/mu/providers/aws/server_pool.rb +71 -119
  100. data/modules/mu/providers/aws/storage_pool.rb +17 -9
  101. data/modules/mu/providers/aws/user.rb +1 -1
  102. data/modules/mu/providers/aws/vpc.rb +106 -51
  103. data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
  104. data/modules/mu/providers/azure.rb +82 -16
  105. data/modules/mu/providers/azure/server.rb +18 -3
  106. data/modules/mu/providers/cloudformation/server.rb +1 -1
  107. data/modules/mu/providers/google.rb +20 -5
  108. data/modules/mu/providers/google/folder.rb +6 -2
  109. data/modules/mu/providers/google/function.rb +65 -30
  110. data/modules/mu/providers/google/role.rb +2 -1
  111. data/modules/mu/providers/google/vpc.rb +27 -2
  112. data/modules/tests/aws-servers-with-handrolled-iam.yaml +37 -0
  113. data/modules/tests/k8s.yaml +1 -1
  114. metadata +32 -15
@@ -29,7 +29,7 @@ module MU
29
29
  # @return [String]: The cloud provider's identifier for this storage pool.
30
30
  def create
31
31
  MU.log "Creating storage pool #{@mu_name}"
32
- resp = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).create_file_system(
32
+ resp = MU::Cloud::AWS.efs(region: @region, credentials: @credentials).create_file_system(
33
33
  creation_token: @mu_name,
34
34
  performance_mode: @config['storage_type']
35
35
  )
@@ -37,7 +37,7 @@ module MU
37
37
  attempts = 0
38
38
  loop do
39
39
  MU.log "Waiting for #{@mu_name}: #{resp.file_system_id} to become available" if attempts % 5 == 0
40
- storage_pool = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).describe_file_systems(
40
+ storage_pool = MU::Cloud::AWS.efs(region: @region, credentials: @credentials).describe_file_systems(
41
41
  creation_token: @mu_name
42
42
  ).file_systems.first
43
43
  break if storage_pool.life_cycle_state == "available"
@@ -47,7 +47,7 @@ module MU
47
47
  raise MuError, "timed out waiting for #{resp.mount_target_id }" if attempts >= 20
48
48
  end
49
49
 
50
- addStandardTags(cloud_id: resp.file_system_id, region: @config['region'], credentials: @config['credentials'])
50
+ addStandardTags(cloud_id: resp.file_system_id, region: @region, credentials: @credentials)
51
51
  @cloud_id = resp.file_system_id
52
52
 
53
53
  if @config['mount_points'] && !@config['mount_points'].empty?
@@ -82,8 +82,8 @@ module MU
82
82
  ip_address: target['ip_address'],
83
83
  subnet_id: target['vpc']['subnet_id'],
84
84
  security_groups: sgs,
85
- credentials: @config['credentials'],
86
- region: @config['region']
85
+ credentials: @credentials,
86
+ region: @region
87
87
  )
88
88
  target['cloud_id'] = mount_target.mount_target_id
89
89
  }
@@ -100,7 +100,7 @@ module MU
100
100
  # Canonical Amazon Resource Number for this resource
101
101
  # @return [String]
102
102
  def arn
103
- "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":elasticfilesystem:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@config['credentials'])+":file-system/"+@cloud_id
103
+ "arn:"+(MU::Cloud::AWS.isGovCloud?(@region) ? "aws-us-gov" : "aws")+":elasticfilesystem:"+@region+":"+MU::Cloud::AWS.credToAcct(@credentials)+":file-system/"+@cloud_id
104
104
  end
105
105
 
106
106
  # Locate an existing storage pool and return an array containing matching AWS resource descriptors for those that match.
@@ -254,14 +254,14 @@ module MU
254
254
 
255
255
  # Register a description of this storage pool with this deployment's metadata.
256
256
  def notify
257
- storage_pool = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).describe_file_systems(
257
+ storage_pool = MU::Cloud::AWS.efs(region: @region, credentials: @credentials).describe_file_systems(
258
258
  creation_token: @mu_name
259
259
  ).file_systems.first
260
260
 
261
261
  targets = {}
262
262
 
263
263
  if @config['mount_points'] && !@config['mount_points'].empty?
264
- mount_targets = MU::Cloud::AWS.efs(region: @config['region'], credentials: @config['credentials']).describe_mount_targets(
264
+ mount_targets = MU::Cloud::AWS.efs(region: @region, credentials: @credentials).describe_mount_targets(
265
265
  file_system_id: storage_pool.file_system_id
266
266
  ).mount_targets
267
267
 
@@ -274,6 +274,10 @@ module MU
274
274
  subnet_obj = mp_vpc.subnets.select { |s|
275
275
  s.name == mp["vpc"]["subnet_name"] or s.cloud_id == mp["vpc"]["subnet_id"]
276
276
  }.first
277
+ if !subnet_obj
278
+ MU.log "Failed to find live subnet matching configured mount_point", MU::WARN, details: mp["vpc"]
279
+ next
280
+ end
277
281
  mount_target = nil
278
282
  mount_targets.each { |t|
279
283
  subnet_cidr_obj = NetAddr::IPv4Net.parse(subnet_obj.ip_block)
@@ -283,6 +287,10 @@ module MU
283
287
  break
284
288
  end
285
289
  }
290
+ if !mount_target
291
+ MU.log "Failed to find live mount_target corresponding to configured mount_point", MU::WARN, details: mp
292
+ next
293
+ end
286
294
 
287
295
  targets[mp["name"]] = {
288
296
  "owner_id" => mount_target.owner_id,
@@ -294,7 +302,7 @@ module MU
294
302
  "availability_zone" => subnet.availability_zone,
295
303
  "state" => mount_target.life_cycle_state,
296
304
  "ip_address" => mount_target.ip_address,
297
- "endpoint" => "#{subnet.availability_zone}.#{mount_target.file_system_id}.efs.#{@config['region']}.amazonaws.com",
305
+ "endpoint" => "#{subnet.availability_zone}.#{mount_target.file_system_id}.efs.#{@region}.amazonaws.com",
298
306
  "network_interface_id" => mount_target.network_interface_id
299
307
  }
300
308
  }
@@ -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(URI.decode(pol.policy_document))
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: @config['region'], credentials: @config['credentials']).create_vpc(cidr_block: @config['ip_block']).vpc
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: @config['region'], credentials: @config['credentials']).describe_vpcs(vpc_ids: [@cloud_id]).vpcs.first
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: @config['region'], credentials: @config['credentials']).describe_route_tables(
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: @config['region'], credentials: @config['credentials']).create_internet_gateway
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: @config['region'], credentials: @config['credentials']).attach_internet_gateway(vpc_id: @cloud_id, internet_gateway_id: internet_gateway_id)
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: @config['region'], credentials: @config['credentials']).create_vpc_endpoint(config).vpc_endpoint
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: @config['region'], credentials: @config['credentials']).describe_vpc_endpoints(vpc_endpoint_ids: [endpoint_id]).vpc_endpoints.first
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: @config['region'], credentials: @config['credentials']).create_flow_logs(
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: @config['region'], credentials: @config['credentials']).create_route(route_config)
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: @config['region'], credentials: @config['credentials']).modify_vpc_attribute(
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: @config['region'], credentials: @config['credentials']).modify_vpc_attribute(
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: @config['region'], credentials: @config['credentials']).create_dhcp_options(
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: @config['region'], credentials: @config['credentials']).associate_dhcp_options(dhcp_options_id: dhcpopt_id, vpc_id: @cloud_id)
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?(@config['region'])
210
- mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu", credentials: @config['credentials']).values.first
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: @config['region'], credentials: @config['credentials'])
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?(@config["region"]) ? "aws-us-gov" : "aws")+":ec2:"+@config['region']+":"+MU::Cloud::AWS.credToAcct(@config['credentials'])+":vpc/"+@cloud_id
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: @config['region'], credentials: @config['credentials']).create_route(route_config)
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" => @config['credentials'],
330
+ "credentials" => @credentials,
331
331
  "cloud_id" => @cloud_id,
332
- "region" => @config['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: @config['region'], credentials: @credentials).describe_flow_logs(filter: [{ "name" => "resource-id", "values" => [@cloud_id] }])
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: @config['region'], credentials: @credentials).describe_nat_gateways(filter: [{ "name" => "vpc-id", "values" => [@cloud_id] }])
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: @config['region'], credentials: @credentials)
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: @config['region'], credentials: @config['credentials']).describe_subnets(
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'] = @config['region']
477
- subnet['credentials'] = @config['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' => @config['region'],
509
- 'credentials' => @config['credentials'],
521
+ 'region' => @region,
522
+ 'credentials' => @credentials,
510
523
  }
511
- subnet['name'] = subnet["ip_block"].gsub(/[\.\/]/, "_")
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: @config['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: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
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", no_create_wait: true)
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: @config['region'], credentials: @config['credentials']).describe_route_tables(
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: @config['region'],
1340
+ region: @region,
1323
1341
  type: "vpcs",
1324
1342
  subnet_pref: subnet_pref
1325
1343
  )
@@ -1330,6 +1348,9 @@ module MU
1330
1348
  def peerWith(peer)
1331
1349
  peer_ref = MU::Config::Ref.get(peer['vpc'])
1332
1350
  peer_obj = peer_ref.kitten
1351
+ if !peer_obj
1352
+ raise MuError.new "#{@mu_name}: Failed to locate my peer VPC", details: peer_ref.to_h
1353
+ end
1333
1354
  peer_id = peer_ref.kitten.cloud_id
1334
1355
  if peer_id == @cloud_id
1335
1356
  MU.log "#{@mu_name} attempted to peer with itself (#{@cloud_id})", MU::ERR, details: peer
@@ -1353,7 +1374,7 @@ module MU
1353
1374
 
1354
1375
  # See if the peering connection exists before we bother
1355
1376
  # creating it.
1356
- resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
1377
+ resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_vpc_peering_connections(
1357
1378
  filters: [
1358
1379
  {
1359
1380
  name: "requester-vpc-info.vpc-id",
@@ -1369,8 +1390,8 @@ module MU
1369
1390
  peering_id = if !resp or !resp.vpc_peering_connections or
1370
1391
  resp.vpc_peering_connections.empty?
1371
1392
 
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(
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(
1374
1395
  vpc_id: @cloud_id,
1375
1396
  peer_vpc_id: peer_id,
1376
1397
  peer_owner_id: peer['account'],
@@ -1386,13 +1407,13 @@ module MU
1386
1407
  tag_me(peering_id, peering_name)
1387
1408
 
1388
1409
  # Create routes to our new friend.
1389
- MU::Cloud::AWS::VPC.listAllSubnetRouteTables(@cloud_id, region: @config['region'], credentials: @config['credentials']).each { |rtb_id|
1410
+ MU::Cloud::AWS::VPC.listAllSubnetRouteTables(@cloud_id, region: @region, credentials: @credentials).each { |rtb_id|
1390
1411
  my_route_config = {
1391
1412
  :route_table_id => rtb_id,
1392
1413
  :destination_cidr_block => peer_obj.cloud_desc.cidr_block,
1393
1414
  :vpc_peering_connection_id => peering_id
1394
1415
  }
1395
- rtbdesc = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
1416
+ rtbdesc = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_route_tables(
1396
1417
  route_table_ids: [rtb_id]
1397
1418
  ).route_tables.first
1398
1419
  already_exists = false
@@ -1408,18 +1429,18 @@ module MU
1408
1429
  }
1409
1430
  next if already_exists
1410
1431
 
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)
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)
1413
1434
  } # MU::Cloud::AWS::VPC.listAllSubnetRouteTables
1414
1435
 
1415
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'])
1416
1437
 
1417
- cnxn = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
1438
+ cnxn = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_vpc_peering_connections(
1418
1439
  vpc_peering_connection_ids: [peering_id]
1419
1440
  ).vpc_peering_connections.first
1420
1441
 
1421
1442
  loop_if = Proc.new {
1422
- cnxn = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_vpc_peering_connections(
1443
+ cnxn = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).describe_vpc_peering_connections(
1423
1444
  vpc_peering_connection_ids: [peering_id]
1424
1445
  ).vpc_peering_connections.first
1425
1446
  ((can_auto_accept and cnxn.status.code == "pending-acceptance") or (cnxn.status.code != "active" and cnxn.status.code != "pending-acceptance"))
@@ -1448,9 +1469,9 @@ module MU
1448
1469
  end
1449
1470
 
1450
1471
  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
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
1452
1473
  begin
1453
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).delete_vpc_peering_connection(
1474
+ MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).delete_vpc_peering_connection(
1454
1475
  vpc_peering_connection_id: peering_id
1455
1476
  )
1456
1477
  rescue Aws::EC2::Errors::InvalidStateTransition
@@ -1466,8 +1487,8 @@ module MU
1466
1487
  def tag_me(resource_id = @cloud_id, name = @mu_name)
1467
1488
  MU::Cloud::AWS.createStandardTags(
1468
1489
  resource_id,
1469
- region: @config['region'],
1470
- credentials: @config['credentials'],
1490
+ region: @region,
1491
+ credentials: @credentials,
1471
1492
  optional: @config['optional_tags'],
1472
1493
  nametag: name,
1473
1494
  othertags: @config['tags']
@@ -1481,8 +1502,8 @@ module MU
1481
1502
  def createRouteTable(rtb)
1482
1503
  vpc_id = @cloud_id
1483
1504
  vpc_name = @config['name']
1484
- MU.setVar("curRegion", @config['region']) if !@config['region'].nil?
1485
- resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route_table(vpc_id: vpc_id).route_table
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
1486
1507
  route_table_id = rtb['route_table_id'] = resp.route_table_id
1487
1508
  sleep 5
1488
1509
 
@@ -1503,7 +1524,7 @@ module MU
1503
1524
  unless route['gateway'] == '#NAT'
1504
1525
  # Need to change the order of how things are created to create the route here
1505
1526
  MU.log "Creating route for #{route['destination_network']}", details: route_config
1506
- resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_route(route_config)
1527
+ resp = MU::Cloud::AWS.ec2(region: @region, credentials: @credentials).create_route(route_config)
1507
1528
  end
1508
1529
  end
1509
1530
  }
@@ -1611,6 +1632,40 @@ module MU
1611
1632
  end
1612
1633
  private_class_method :purge_nat_gateways
1613
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
+
1614
1669
  # Remove all VPC endpoints associated with the VPC of the currently loaded deployment.
1615
1670
  # @param noop [Boolean]: If true, will only print what would be done
1616
1671
  # @param vpc_id [String]: The cloud provider's unique VPC identifier