bosh_cli_plugin_aws 1.5.0.pre.1113
Sign up to get free protection for your applications and to get access to all the features.
- 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
|