bosh_cli_plugin_aws 1.5.0.pre.1113
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.
- data/lib/bosh/cli/commands/aws.rb +464 -0
- data/lib/bosh_cli_plugin_aws/aws_config.rb +141 -0
- data/lib/bosh_cli_plugin_aws/aws_provider.rb +53 -0
- data/lib/bosh_cli_plugin_aws/bat_manifest.rb +40 -0
- data/lib/bosh_cli_plugin_aws/bootstrap.rb +31 -0
- data/lib/bosh_cli_plugin_aws/bosh_bootstrap.rb +158 -0
- data/lib/bosh_cli_plugin_aws/bosh_manifest.rb +71 -0
- data/lib/bosh_cli_plugin_aws/ec2.rb +265 -0
- data/lib/bosh_cli_plugin_aws/elb.rb +132 -0
- data/lib/bosh_cli_plugin_aws/micro_bosh_bootstrap.rb +64 -0
- data/lib/bosh_cli_plugin_aws/microbosh_manifest.rb +117 -0
- data/lib/bosh_cli_plugin_aws/migration.rb +40 -0
- data/lib/bosh_cli_plugin_aws/migration_helper.rb +150 -0
- data/lib/bosh_cli_plugin_aws/migrator.rb +137 -0
- data/lib/bosh_cli_plugin_aws/rds.rb +182 -0
- data/lib/bosh_cli_plugin_aws/route53.rb +103 -0
- data/lib/bosh_cli_plugin_aws/s3.rb +93 -0
- data/lib/bosh_cli_plugin_aws/version.rb +5 -0
- data/lib/bosh_cli_plugin_aws/vpc.rb +181 -0
- data/lib/bosh_cli_plugin_aws.rb +31 -0
- data/migrations/20130412000811_create_key_pairs.rb +8 -0
- data/migrations/20130412004642_create_vpc.rb +65 -0
- data/migrations/20130412181302_create_route53_records.rb +37 -0
- data/migrations/20130412183544_create_rds_dbs.rb +35 -0
- data/migrations/20130412192351_create_s3.rb +4 -0
- data/migrations/20130529212130_create_more_unique_s3_buckets.rb +33 -0
- data/migrations/20130531180445_create_bosh_rds_db.rb +30 -0
- data/migrations/20130826150635_update_elb_for_websockets.rb +97 -0
- data/migrations/20130827000001_add_secondary_az_to_vpc.rb +34 -0
- data/templates/aws_configuration_template.yml.erb +187 -0
- data/templates/aws_migration.erb +5 -0
- data/templates/aws_migration_spec.erb +12 -0
- data/templates/bat.yml.erb +84 -0
- data/templates/bosh.yml.erb +198 -0
- data/templates/micro_bosh.yml.erb +82 -0
- metadata +163 -0
@@ -0,0 +1,464 @@
|
|
1
|
+
require "aws-sdk"
|
2
|
+
require "securerandom"
|
3
|
+
require_relative "../../../bosh_cli_plugin_aws"
|
4
|
+
|
5
|
+
module Bosh::Cli::Command
|
6
|
+
class AWS < Base
|
7
|
+
DEFAULT_CIDR = "10.0.0.0/16" # KILL
|
8
|
+
|
9
|
+
attr_reader :output_state, :config_dir, :ec2
|
10
|
+
attr_accessor :vpc
|
11
|
+
|
12
|
+
def initialize(runner = [])
|
13
|
+
super(runner)
|
14
|
+
@output_state = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
usage "aws"
|
18
|
+
desc "show bosh aws sub-commands"
|
19
|
+
def help
|
20
|
+
say "bosh aws sub-commands:\n"
|
21
|
+
commands = Bosh::Cli::Config.commands.values.find_all { |command| command.usage =~ /^aws/ }
|
22
|
+
Bosh::Cli::Command::Help.list_commands(commands)
|
23
|
+
end
|
24
|
+
|
25
|
+
usage "aws bootstrap micro"
|
26
|
+
desc "rm deployments dir, creates a deployments/micro/micro_bosh.yml and deploys the microbosh"
|
27
|
+
def bootstrap_micro
|
28
|
+
options[:hm_director_password] = SecureRandom.base64
|
29
|
+
options[:hm_director_user] ||= 'hm'
|
30
|
+
|
31
|
+
bootstrap = Bosh::Aws::MicroBoshBootstrap.new(runner, options)
|
32
|
+
bootstrap.start
|
33
|
+
|
34
|
+
bootstrap.create_user(options[:hm_director_user], options[:hm_director_password])
|
35
|
+
|
36
|
+
if interactive?
|
37
|
+
username = ask("Enter username: ")
|
38
|
+
password = ask("Enter password: ") { |q| q.echo = "*" }
|
39
|
+
|
40
|
+
if username.blank? || password.blank?
|
41
|
+
err("Please enter username and password")
|
42
|
+
end
|
43
|
+
|
44
|
+
bootstrap.create_user(username, password)
|
45
|
+
else
|
46
|
+
bootstrap.create_user("admin", SecureRandom.base64)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
usage "aws bootstrap bosh"
|
51
|
+
desc "bootstrap full bosh deployment"
|
52
|
+
def bootstrap_bosh(config_file = nil)
|
53
|
+
target_required
|
54
|
+
err "To bootstrap BOSH, first log in to `#{config.target}'" unless logged_in?
|
55
|
+
|
56
|
+
options[:hm_director_user] ||= 'hm'
|
57
|
+
options[:hm_director_password] = SecureRandom.base64
|
58
|
+
|
59
|
+
bootstrap = Bosh::Aws::BoshBootstrap.new(director, s3(config_file), self.options)
|
60
|
+
bootstrap.start
|
61
|
+
|
62
|
+
say "For security purposes, please provide a username and password for BOSH Director"
|
63
|
+
username = ask("Enter username: ")
|
64
|
+
password = ask("Enter password: ") { |q| q.echo = "*" }
|
65
|
+
|
66
|
+
bootstrap.create_user(username, password)
|
67
|
+
|
68
|
+
say "BOSH deployed successfully. You are logged in as #{username}."
|
69
|
+
|
70
|
+
bootstrap.create_user(options[:hm_director_user], options[:hm_director_password])
|
71
|
+
rescue Bosh::Aws::BootstrapError => e
|
72
|
+
err "Unable to bootstrap bosh: #{e.message}"
|
73
|
+
end
|
74
|
+
|
75
|
+
usage "aws generate micro_bosh"
|
76
|
+
desc "generate micro_bosh.yml"
|
77
|
+
def create_micro_bosh_manifest(vpc_receipt_file, route53_receipt_file)
|
78
|
+
vpc_config = load_yaml_file(vpc_receipt_file)
|
79
|
+
route53_config = load_yaml_file(route53_receipt_file)
|
80
|
+
|
81
|
+
options[:hm_director_user] ||= 'hm'
|
82
|
+
options[:hm_director_password] = SecureRandom.base64
|
83
|
+
|
84
|
+
manifest = Bosh::Aws::MicroboshManifest.new(vpc_config, route53_config, options)
|
85
|
+
|
86
|
+
write_yaml(manifest, manifest.file_name)
|
87
|
+
end
|
88
|
+
|
89
|
+
usage "aws generate bosh"
|
90
|
+
desc "generate bosh.yml deployment manifest"
|
91
|
+
def create_bosh_manifest(vpc_receipt_file, route53_receipt_file, bosh_rds_receipt_file)
|
92
|
+
target_required
|
93
|
+
|
94
|
+
options[:hm_director_user] ||= 'hm'
|
95
|
+
options[:hm_director_password] = SecureRandom.base64
|
96
|
+
|
97
|
+
vpc_config = load_yaml_file(vpc_receipt_file)
|
98
|
+
route53_config = load_yaml_file(route53_receipt_file)
|
99
|
+
bosh_rds_config = load_yaml_file(bosh_rds_receipt_file)
|
100
|
+
bosh_manifest = Bosh::Aws::BoshManifest.new(vpc_config, route53_config, director.uuid, bosh_rds_config, options)
|
101
|
+
|
102
|
+
write_yaml(bosh_manifest, bosh_manifest.file_name)
|
103
|
+
end
|
104
|
+
|
105
|
+
usage "aws generate bat"
|
106
|
+
desc "generate bat.yml"
|
107
|
+
def create_bat_manifest(vpc_receipt_file, route53_receipt_file, stemcell_version, stemcell_name)
|
108
|
+
target_required
|
109
|
+
|
110
|
+
vpc_config = load_yaml_file(vpc_receipt_file)
|
111
|
+
route53_config = load_yaml_file(route53_receipt_file)
|
112
|
+
manifest = Bosh::Aws::BatManifest.new(
|
113
|
+
vpc_config, route53_config, stemcell_version, director.uuid, stemcell_name)
|
114
|
+
|
115
|
+
write_yaml(manifest, manifest.file_name)
|
116
|
+
end
|
117
|
+
|
118
|
+
usage "aws create"
|
119
|
+
desc "create everything in migrations"
|
120
|
+
option "--trace", "print all HTTP traffic"
|
121
|
+
def create(config_file = nil)
|
122
|
+
if !!options[:trace]
|
123
|
+
require 'logger'
|
124
|
+
::AWS.config(:logger => Logger.new($stdout), :http_wire_trace => true)
|
125
|
+
end
|
126
|
+
|
127
|
+
Bosh::Aws::Migrator.new(load_config(config_file)).migrate
|
128
|
+
end
|
129
|
+
|
130
|
+
usage "aws create s3"
|
131
|
+
desc "create only the s3 buckets"
|
132
|
+
def create_s3(config_file = nil)
|
133
|
+
Bosh::Aws::Migrator.new(load_config(config_file)).migrate_version("20130412192351")
|
134
|
+
end
|
135
|
+
|
136
|
+
usage "aws create key_pairs"
|
137
|
+
desc "creates only the key pairs"
|
138
|
+
def create_key_pairs(config_file = nil)
|
139
|
+
Bosh::Aws::Migrator.new(load_config(config_file)).migrate_version("20130412000811")
|
140
|
+
end
|
141
|
+
|
142
|
+
usage "aws create route53 records"
|
143
|
+
desc "creates only the Route 53 records"
|
144
|
+
def create_route53_records(config_file = nil)
|
145
|
+
Bosh::Aws::Migrator.new(load_config(config_file)).migrate_version("20130412181302")
|
146
|
+
end
|
147
|
+
|
148
|
+
usage "aws create vpc"
|
149
|
+
desc "creates only the VPC"
|
150
|
+
def create_vpc(config_file = nil)
|
151
|
+
Bosh::Aws::Migrator.new(load_config(config_file)).migrate_version("20130412004642")
|
152
|
+
end
|
153
|
+
|
154
|
+
usage "aws destroy"
|
155
|
+
desc "destroy everything in an AWS account"
|
156
|
+
def destroy(config_file = nil)
|
157
|
+
delete_all_elbs(config_file)
|
158
|
+
delete_all_ec2(config_file)
|
159
|
+
delete_all_ebs(config_file)
|
160
|
+
delete_all_rds_dbs(config_file)
|
161
|
+
delete_all_s3(config_file)
|
162
|
+
delete_all_vpcs(config_file)
|
163
|
+
delete_all_key_pairs(config_file)
|
164
|
+
delete_all_elastic_ips(config_file)
|
165
|
+
delete_all_security_groups(config_file)
|
166
|
+
delete_all_route53_records(config_file)
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
def s3(config_file)
|
172
|
+
config = load_config(config_file)
|
173
|
+
Bosh::Aws::S3.new(config["aws"])
|
174
|
+
end
|
175
|
+
|
176
|
+
def delete_vpc(details_file)
|
177
|
+
details = load_yaml_file details_file
|
178
|
+
|
179
|
+
ec2 = Bosh::Aws::EC2.new(details["aws"])
|
180
|
+
vpc = Bosh::Aws::VPC.find(ec2, details["vpc"]["id"])
|
181
|
+
route53 = Bosh::Aws::Route53.new(details["aws"])
|
182
|
+
|
183
|
+
err("#{vpc.instances_count} instance(s) running in #{vpc.vpc_id} - delete them first") if vpc.instances_count > 0
|
184
|
+
|
185
|
+
dhcp_options = vpc.dhcp_options
|
186
|
+
|
187
|
+
Bosh::Common.retryable(sleep: aws_retry_wait_time,
|
188
|
+
tries: 120, on: [::AWS::Errors::Base]) do |tries, e|
|
189
|
+
say("unable to delete resource: #{e}") if tries > 0
|
190
|
+
vpc.delete_security_groups
|
191
|
+
vpc.delete_subnets
|
192
|
+
ec2.delete_internet_gateways(ec2.internet_gateway_ids)
|
193
|
+
vpc.delete_vpc
|
194
|
+
dhcp_options.delete
|
195
|
+
|
196
|
+
if details["key_pairs"]
|
197
|
+
details["key_pairs"].each do |name|
|
198
|
+
ec2.remove_key_pair name
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
if details["elastic_ips"]
|
203
|
+
details["elastic_ips"].values.each do |job|
|
204
|
+
ec2.release_elastic_ips(job["ips"])
|
205
|
+
if job["dns_record"]
|
206
|
+
route53.delete_record(job["dns_record"], details["vpc"]["domain"])
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
true # retryable block must yield true if we only want to retry on Exceptions
|
211
|
+
end
|
212
|
+
|
213
|
+
say "deleted VPC and all dependencies".make_green
|
214
|
+
end
|
215
|
+
|
216
|
+
def delete_all_vpcs(config_file)
|
217
|
+
config = load_config(config_file)
|
218
|
+
|
219
|
+
ec2 = Bosh::Aws::EC2.new(config["aws"])
|
220
|
+
vpc_ids = ec2.vpcs.map { |vpc| vpc.id }
|
221
|
+
dhcp_options = []
|
222
|
+
|
223
|
+
unless vpc_ids.empty?
|
224
|
+
say("THIS IS A VERY DESTRUCTIVE OPERATION AND IT CANNOT BE UNDONE!\n".make_red)
|
225
|
+
say("VPCs:\n\t#{vpc_ids.join("\n\t")}")
|
226
|
+
|
227
|
+
if confirmed?("Are you sure you want to delete all VPCs?")
|
228
|
+
vpc_ids.each do |vpc_id|
|
229
|
+
vpc = Bosh::Aws::VPC.find(ec2, vpc_id)
|
230
|
+
err("#{vpc.instances_count} instance(s) running in #{vpc.vpc_id} - delete them first") if vpc.instances_count > 0
|
231
|
+
|
232
|
+
dhcp_options << vpc.dhcp_options
|
233
|
+
|
234
|
+
vpc.delete_network_interfaces
|
235
|
+
vpc.delete_security_groups
|
236
|
+
ec2.delete_internet_gateways(ec2.internet_gateway_ids)
|
237
|
+
vpc.delete_subnets
|
238
|
+
vpc.delete_route_tables
|
239
|
+
vpc.delete_vpc
|
240
|
+
end
|
241
|
+
dhcp_options.uniq(&:id).map(&:delete)
|
242
|
+
end
|
243
|
+
else
|
244
|
+
say("No VPCs found")
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def delete_all_key_pairs(config_file)
|
249
|
+
config = load_config(config_file)
|
250
|
+
ec2 = Bosh::Aws::EC2.new(config["aws"])
|
251
|
+
|
252
|
+
if confirmed?("Are you sure you want to delete all SSH Keypairs?")
|
253
|
+
say "Deleting all key pairs..."
|
254
|
+
ec2.remove_all_key_pairs
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def delete_all_elastic_ips(config_file)
|
259
|
+
config = load_config(config_file)
|
260
|
+
ec2 = Bosh::Aws::EC2.new(config["aws"])
|
261
|
+
|
262
|
+
if confirmed?("Are you sure you want to delete all Elastic IPs?")
|
263
|
+
say "Releasing all elastic IPs..."
|
264
|
+
ec2.release_all_elastic_ips
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def delete_all_s3(config_file)
|
269
|
+
config = load_config(config_file)
|
270
|
+
|
271
|
+
check_instance_count(config)
|
272
|
+
|
273
|
+
s3 = Bosh::Aws::S3.new(config["aws"])
|
274
|
+
bucket_names = s3.bucket_names
|
275
|
+
|
276
|
+
unless bucket_names.empty?
|
277
|
+
say("THIS IS A VERY DESTRUCTIVE OPERATION AND IT CANNOT BE UNDONE!\n".make_red)
|
278
|
+
say("Buckets:\n\t#{bucket_names.join("\n\t")}")
|
279
|
+
|
280
|
+
s3.empty if confirmed?("Are you sure you want to empty and delete all buckets?")
|
281
|
+
else
|
282
|
+
say("No S3 buckets found")
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def delete_all_ec2(config_file)
|
287
|
+
config = load_config(config_file)
|
288
|
+
credentials = config["aws"]
|
289
|
+
check_instance_count(config)
|
290
|
+
ec2 = Bosh::Aws::EC2.new(credentials)
|
291
|
+
|
292
|
+
formatted_names = ec2.instance_names.map { |id, name| "#{name} (id: #{id})" }
|
293
|
+
unless formatted_names.empty?
|
294
|
+
say("THIS IS A VERY DESTRUCTIVE OPERATION AND IT CANNOT BE UNDONE!\n".make_red)
|
295
|
+
say("Instances:\n\t#{formatted_names.join("\n\t")}")
|
296
|
+
|
297
|
+
if confirmed?("Are you sure you want to terminate all terminatable EC2 instances and their associated non-persistent EBS volumes?")
|
298
|
+
say "Terminating instances and waiting for them to die..."
|
299
|
+
if !ec2.terminate_instances
|
300
|
+
say "Warning: instances did not terminate yet after 100 retries".make_red
|
301
|
+
end
|
302
|
+
end
|
303
|
+
else
|
304
|
+
say("No EC2 instances found")
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def delete_all_elbs(config_file)
|
309
|
+
config = load_config(config_file)
|
310
|
+
credentials = config["aws"]
|
311
|
+
elb = Bosh::Aws::ELB.new(credentials)
|
312
|
+
elb_names = elb.names
|
313
|
+
if elb_names.any? && confirmed?("Are you sure you want to delete all ELBs (#{elb_names.join(", ")})?")
|
314
|
+
elb.delete_elbs
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def delete_server_certificates(config_file)
|
319
|
+
config = load_config(config_file)
|
320
|
+
credentials = config["aws"]
|
321
|
+
elb = Bosh::Aws::ELB.new(credentials)
|
322
|
+
certificates = elb.server_certificate_names
|
323
|
+
|
324
|
+
if certificates.any? && confirmed?("Are you sure you want to delete all server certificates? (#{certificates.join(", ")})")
|
325
|
+
elb.delete_server_certificates
|
326
|
+
say "Server certificates deleted."
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def delete_all_rds_dbs(config_file)
|
331
|
+
config = load_config(config_file)
|
332
|
+
credentials = config["aws"]
|
333
|
+
check_instance_count(config)
|
334
|
+
rds = Bosh::Aws::RDS.new(credentials)
|
335
|
+
|
336
|
+
formatted_names = rds.database_names.map { |instance, db| "#{instance}\t(database_name: #{db})" }
|
337
|
+
|
338
|
+
say("THIS IS A VERY DESTRUCTIVE OPERATION AND IT CANNOT BE UNDONE!\n".make_red)
|
339
|
+
say("Database Instances:\n\t#{formatted_names.join("\n\t")}")
|
340
|
+
|
341
|
+
if confirmed?("Are you sure you want to delete all databases?")
|
342
|
+
rds.delete_databases unless formatted_names.empty?
|
343
|
+
err("not all rds instances could be deleted") unless all_rds_instances_deleted?(rds)
|
344
|
+
|
345
|
+
delete_all_rds_subnet_groups(config_file)
|
346
|
+
delete_all_rds_security_groups(config_file)
|
347
|
+
rds.delete_db_parameter_group('utf8')
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
def delete_all_rds_subnet_groups(config_file)
|
352
|
+
config = load_config(config_file)
|
353
|
+
credentials = config["aws"]
|
354
|
+
rds = Bosh::Aws::RDS.new(credentials)
|
355
|
+
rds.delete_subnet_groups
|
356
|
+
end
|
357
|
+
|
358
|
+
def delete_all_rds_security_groups(config_file)
|
359
|
+
config = load_config(config_file)
|
360
|
+
credentials = config["aws"]
|
361
|
+
rds = Bosh::Aws::RDS.new(credentials)
|
362
|
+
rds.delete_security_groups
|
363
|
+
end
|
364
|
+
|
365
|
+
def delete_all_ebs(config_file)
|
366
|
+
config = load_config(config_file)
|
367
|
+
credentials = config["aws"]
|
368
|
+
ec2 = Bosh::Aws::EC2.new(credentials)
|
369
|
+
check_volume_count(config)
|
370
|
+
|
371
|
+
if ec2.volume_count > 0
|
372
|
+
say("THIS IS A VERY DESTRUCTIVE OPERATION AND IT CANNOT BE UNDONE!\n".make_red)
|
373
|
+
say("It will delete #{ec2.volume_count} EBS volume(s)")
|
374
|
+
|
375
|
+
ec2.delete_volumes if confirmed?("Are you sure you want to delete all unattached EBS volumes?")
|
376
|
+
else
|
377
|
+
say("No EBS volumes found")
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
def delete_all_security_groups(config_file)
|
382
|
+
config = load_config(config_file)
|
383
|
+
ec2 = Bosh::Aws::EC2.new(config["aws"])
|
384
|
+
|
385
|
+
if confirmed?('Are you sure you want to delete all security groups?')
|
386
|
+
Bosh::Common.retryable(sleep: aws_retry_wait_time,
|
387
|
+
tries: 120, on: [::AWS::EC2::Errors::InvalidGroup::InUse]) do |tries, e|
|
388
|
+
say("unable to delete security groups: #{e}") if tries > 0
|
389
|
+
ec2.delete_all_security_groups
|
390
|
+
true # retryable block must yield true if we only want to retry on Exceptions
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
def delete_all_route53_records(config_file)
|
396
|
+
config = load_config(config_file)
|
397
|
+
route53 = Bosh::Aws::Route53.new(config["aws"])
|
398
|
+
|
399
|
+
say("THIS IS A VERY DESTRUCTIVE OPERATION AND IT CANNOT BE UNDONE!\n".make_red)
|
400
|
+
|
401
|
+
omit_types = options[:omit_types] || %w[NS SOA]
|
402
|
+
if omit_types.empty?
|
403
|
+
msg = "Are you sure you want to delete all records from Route 53?"
|
404
|
+
else
|
405
|
+
msg = "Are you sure you want to delete all but #{omit_types.join("/")} records from Route 53?"
|
406
|
+
end
|
407
|
+
|
408
|
+
route53.delete_all_records(omit_types: omit_types) if confirmed?(msg)
|
409
|
+
end
|
410
|
+
|
411
|
+
def all_rds_instances_deleted?(rds)
|
412
|
+
return true if rds.databases.count == 0
|
413
|
+
(1..120).any? do |attempt|
|
414
|
+
say "waiting for RDS deletion..."
|
415
|
+
sleep 10
|
416
|
+
rds.databases.each do |db_instance|
|
417
|
+
begin
|
418
|
+
say " #{db_instance.db_name} #{db_instance.db_instance_status}"
|
419
|
+
rescue ::AWS::RDS::Errors::DBInstanceNotFound
|
420
|
+
# it is possible for a db to be deleted between the time the
|
421
|
+
# each returns an instance and when we print out its info
|
422
|
+
end
|
423
|
+
end
|
424
|
+
rds.databases.count == 0
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
def deployment_manifest_state
|
429
|
+
@output_state["deployment_manifest"] ||= {}
|
430
|
+
end
|
431
|
+
|
432
|
+
def deployment_properties
|
433
|
+
deployment_manifest_state["properties"] ||= {}
|
434
|
+
end
|
435
|
+
|
436
|
+
def flush_output_state(file_path)
|
437
|
+
File.open(file_path, 'w') { |f| f.write output_state.to_yaml }
|
438
|
+
end
|
439
|
+
|
440
|
+
def check_instance_count(config)
|
441
|
+
ec2 = Bosh::Aws::EC2.new(config["aws"])
|
442
|
+
err("#{ec2.instances_count} instance(s) running. This isn't a dev account (more than 20) please make sure you want to do this, aborting.") if ec2.instances_count > 20
|
443
|
+
end
|
444
|
+
|
445
|
+
def check_volume_count(config)
|
446
|
+
ec2 = Bosh::Aws::EC2.new(config["aws"])
|
447
|
+
err("#{ec2.volume_count} volume(s) present. This isn't a dev account (more than 20) please make sure you want to do this, aborting.") if ec2.volume_count > 20
|
448
|
+
end
|
449
|
+
|
450
|
+
def default_config_file
|
451
|
+
File.expand_path(File.join(
|
452
|
+
File.dirname(__FILE__), "..", "..", "..", "..", "templates", "aws_configuration_template.yml.erb"
|
453
|
+
))
|
454
|
+
end
|
455
|
+
|
456
|
+
def load_config(config_file=nil)
|
457
|
+
config_file ||= default_config_file
|
458
|
+
|
459
|
+
Bosh::Aws::AwsConfig.new(config_file).configuration
|
460
|
+
end
|
461
|
+
|
462
|
+
def aws_retry_wait_time; 10; end
|
463
|
+
end
|
464
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Bosh
|
4
|
+
module Aws
|
5
|
+
class ConfigurationInvalid < RuntimeError; end
|
6
|
+
|
7
|
+
class AwsConfig
|
8
|
+
def initialize(filename, env = ENV)
|
9
|
+
@filename = filename
|
10
|
+
@env = env
|
11
|
+
end
|
12
|
+
|
13
|
+
def configuration
|
14
|
+
load_configuration(File.read(@filename))
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch_from_env(key, msg=nil)
|
18
|
+
@env.fetch(key) {
|
19
|
+
msg ||= "Missing ENV variable #{key}"
|
20
|
+
raise(ConfigurationInvalid, msg)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def aws_secret_access_key
|
25
|
+
fetch_from_env("BOSH_AWS_SECRET_ACCESS_KEY")
|
26
|
+
end
|
27
|
+
|
28
|
+
def aws_access_key_id
|
29
|
+
fetch_from_env("BOSH_AWS_ACCESS_KEY_ID")
|
30
|
+
end
|
31
|
+
|
32
|
+
def aws_region
|
33
|
+
@env.fetch('BOSH_AWS_REGION', 'us-east-1')
|
34
|
+
end
|
35
|
+
|
36
|
+
def vpc_domain
|
37
|
+
@env["BOSH_VPC_DOMAIN"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def vpc_subdomain
|
41
|
+
@env["BOSH_VPC_SUBDOMAIN"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def vpc_deployment_name
|
45
|
+
if has_vpc_subdomain?
|
46
|
+
vpc_subdomain
|
47
|
+
elsif has_vpc_domain?
|
48
|
+
vpc_domain.gsub('.', '-')
|
49
|
+
else
|
50
|
+
"deployment"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def vpc_generated_domain
|
55
|
+
if has_vpc_domain? && has_vpc_subdomain?
|
56
|
+
"#{vpc_subdomain}.#{vpc_domain}"
|
57
|
+
elsif has_vpc_subdomain?
|
58
|
+
"#{vpc_subdomain}.cf-app.com"
|
59
|
+
elsif has_vpc_domain?
|
60
|
+
vpc_domain
|
61
|
+
else
|
62
|
+
raise(ConfigurationInvalid, "No domain and subdomain are defined.")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def has_vpc_domain?
|
67
|
+
vpc_domain && vpc_domain != ""
|
68
|
+
end
|
69
|
+
|
70
|
+
def has_vpc_subdomain?
|
71
|
+
vpc_subdomain && vpc_subdomain != ""
|
72
|
+
end
|
73
|
+
|
74
|
+
def vpc_primary_az
|
75
|
+
fetch_from_env("BOSH_VPC_PRIMARY_AZ")
|
76
|
+
end
|
77
|
+
|
78
|
+
def vpc_secondary_az
|
79
|
+
fetch_from_env("BOSH_VPC_SECONDARY_AZ")
|
80
|
+
end
|
81
|
+
|
82
|
+
def key_pair_name
|
83
|
+
@env.fetch("BOSH_KEY_PAIR_NAME", "bosh")
|
84
|
+
end
|
85
|
+
|
86
|
+
def key_pair_path
|
87
|
+
@env.fetch("BOSH_KEY_PATH", "#{@env['HOME']}/.ssh/id_rsa_bosh")
|
88
|
+
end
|
89
|
+
|
90
|
+
def elb_ssl_key_file
|
91
|
+
@env.fetch("BOSH_AWS_ELB_SSL_KEY", "elb-cfrouter.key")
|
92
|
+
end
|
93
|
+
|
94
|
+
def elb_ssl_cert_file
|
95
|
+
@env.fetch("BOSH_AWS_ELB_SSL_CERT", "elb-cfrouter.pem")
|
96
|
+
end
|
97
|
+
|
98
|
+
def elb_ssl_cert_chain_file
|
99
|
+
@env["BOSH_AWS_ELB_SSL_CHAIN"]
|
100
|
+
end
|
101
|
+
|
102
|
+
def director_ssl_key_file
|
103
|
+
@env.fetch("BOSH_DIRECTOR_SSL_KEY", "director.key")
|
104
|
+
end
|
105
|
+
|
106
|
+
def director_ssl_cert_file
|
107
|
+
@env.fetch("BOSH_DIRECTOR_SSL_CERT", "director.pem")
|
108
|
+
end
|
109
|
+
|
110
|
+
def has_package_cache_configuration?
|
111
|
+
cache_access_key_id
|
112
|
+
end
|
113
|
+
|
114
|
+
def cache_access_key_id
|
115
|
+
@env["BOSH_CACHE_ACCESS_KEY_ID"]
|
116
|
+
end
|
117
|
+
|
118
|
+
def cache_secret_access_key
|
119
|
+
unless has_package_cache_configuration?
|
120
|
+
raise ConfigurationInvalid, "Missing ENV variable BOSH_CACHE_ACCESS_KEY_ID"
|
121
|
+
end
|
122
|
+
|
123
|
+
fetch_from_env("BOSH_CACHE_SECRET_ACCESS_KEY")
|
124
|
+
end
|
125
|
+
|
126
|
+
def cache_bucket_name
|
127
|
+
@env.fetch("BOSH_CACHE_BUCKET_NAME", "bosh-global-package-cache")
|
128
|
+
end
|
129
|
+
|
130
|
+
def production_resources?
|
131
|
+
@env['BOSH_PRODUCTION_RESOURCES']
|
132
|
+
end
|
133
|
+
|
134
|
+
def load_configuration(yaml)
|
135
|
+
renderer = ERB.new(yaml, 0, '<>%-')
|
136
|
+
|
137
|
+
YAML.load(renderer.result(binding))
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Bosh
|
2
|
+
module Aws
|
3
|
+
class AwsProvider
|
4
|
+
attr_reader :credentials
|
5
|
+
|
6
|
+
def initialize(credentials)
|
7
|
+
@credentials = credentials
|
8
|
+
end
|
9
|
+
|
10
|
+
def ec2
|
11
|
+
@ec2 ||= ::AWS::EC2.new(credentials)
|
12
|
+
end
|
13
|
+
|
14
|
+
def elb
|
15
|
+
@elb ||= ::AWS::ELB.new(credentials.merge('elb_endpoint' => elb_endpoint))
|
16
|
+
end
|
17
|
+
|
18
|
+
def iam
|
19
|
+
@iam ||= ::AWS::IAM.new(credentials)
|
20
|
+
end
|
21
|
+
|
22
|
+
def rds
|
23
|
+
@rds ||= ::AWS::RDS.new(credentials.merge('rds_endpoint' => rds_endpoint))
|
24
|
+
end
|
25
|
+
|
26
|
+
def rds_client
|
27
|
+
@rds_client ||= ::AWS::RDS::Client.new(credentials.merge('rds_endpoint' => rds_endpoint))
|
28
|
+
end
|
29
|
+
|
30
|
+
def route53
|
31
|
+
@aws_route53 ||= ::AWS::Route53.new(credentials)
|
32
|
+
end
|
33
|
+
|
34
|
+
def region
|
35
|
+
credentials['region']
|
36
|
+
end
|
37
|
+
|
38
|
+
def s3
|
39
|
+
@s3 ||= ::AWS::S3.new(credentials)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def elb_endpoint
|
45
|
+
"elasticloadbalancing.#{region}.amazonaws.com"
|
46
|
+
end
|
47
|
+
|
48
|
+
def rds_endpoint
|
49
|
+
"rds.#{region}.amazonaws.com"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Bosh
|
4
|
+
module Aws
|
5
|
+
class BatManifest < MicroboshManifest
|
6
|
+
attr_reader :stemcell_version, :director_uuid, :stemcell_name
|
7
|
+
|
8
|
+
def initialize(vpc_receipt, route53_receipt, stemcell_version, director_uuid, stemcell_name)
|
9
|
+
super(vpc_receipt, route53_receipt)
|
10
|
+
@stemcell_version = stemcell_version
|
11
|
+
@director_uuid = director_uuid
|
12
|
+
@stemcell_name = stemcell_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def file_name
|
16
|
+
"bat.yml"
|
17
|
+
end
|
18
|
+
|
19
|
+
def deployment_name
|
20
|
+
"bat"
|
21
|
+
end
|
22
|
+
|
23
|
+
def domain
|
24
|
+
vpc_receipt["vpc"]["domain"] || warning('Missing domain field')
|
25
|
+
end
|
26
|
+
|
27
|
+
def vip
|
28
|
+
route53_receipt['elastic_ips']['bat']['ips'][0] || warning('Missing vip field')
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_y
|
32
|
+
ERB.new(File.read(get_template("bat.yml.erb"))).result(binding)
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_template(template)
|
36
|
+
File.expand_path("../../../templates/#{template}", __FILE__)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|