vagrant-aws-mscottford 0.8.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 +7 -0
- data/.gitignore +21 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +96 -0
- data/Gemfile +14 -0
- data/LICENSE +8 -0
- data/README.md +328 -0
- data/Rakefile +22 -0
- data/cortex.yaml +15 -0
- data/dummy.box +0 -0
- data/example_box/README.md +13 -0
- data/example_box/metadata.json +3 -0
- data/lib/vagrant-aws/action/connect_aws.rb +51 -0
- data/lib/vagrant-aws/action/elb_deregister_instance.rb +24 -0
- data/lib/vagrant-aws/action/elb_register_instance.rb +24 -0
- data/lib/vagrant-aws/action/is_created.rb +18 -0
- data/lib/vagrant-aws/action/is_stopped.rb +18 -0
- data/lib/vagrant-aws/action/message_already_created.rb +16 -0
- data/lib/vagrant-aws/action/message_not_created.rb +16 -0
- data/lib/vagrant-aws/action/message_will_not_destroy.rb +16 -0
- data/lib/vagrant-aws/action/package_instance.rb +192 -0
- data/lib/vagrant-aws/action/read_ssh_info.rb +53 -0
- data/lib/vagrant-aws/action/read_state.rb +38 -0
- data/lib/vagrant-aws/action/run_instance.rb +311 -0
- data/lib/vagrant-aws/action/start_instance.rb +81 -0
- data/lib/vagrant-aws/action/stop_instance.rb +28 -0
- data/lib/vagrant-aws/action/terminate_instance.rb +51 -0
- data/lib/vagrant-aws/action/timed_provision.rb +21 -0
- data/lib/vagrant-aws/action/wait_for_state.rb +41 -0
- data/lib/vagrant-aws/action/warn_networks.rb +19 -0
- data/lib/vagrant-aws/action.rb +209 -0
- data/lib/vagrant-aws/cap/winrm_info.rb +46 -0
- data/lib/vagrant-aws/config.rb +577 -0
- data/lib/vagrant-aws/errors.rb +43 -0
- data/lib/vagrant-aws/plugin.rb +78 -0
- data/lib/vagrant-aws/provider.rb +50 -0
- data/lib/vagrant-aws/util/elb.rb +58 -0
- data/lib/vagrant-aws/util/timer.rb +17 -0
- data/lib/vagrant-aws/version.rb +5 -0
- data/lib/vagrant-aws.rb +18 -0
- data/locales/en.yml +159 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/vagrant-aws/config_spec.rb +374 -0
- data/templates/metadata.json.erb +3 -0
- data/templates/vagrant-aws_package_Vagrantfile.erb +5 -0
- data/vagrant-aws-mscottford.gemspec +64 -0
- metadata +177 -0
@@ -0,0 +1,577 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
require "iniparse"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module AWS
|
6
|
+
class Config < Vagrant.plugin("2", :config)
|
7
|
+
# The access key ID for accessing AWS.
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
attr_accessor :access_key_id
|
11
|
+
|
12
|
+
# The ID of the AMI to use.
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
attr_accessor :ami
|
16
|
+
|
17
|
+
# The availability zone to launch the instance into. If nil, it will
|
18
|
+
# use the default for your account.
|
19
|
+
#
|
20
|
+
# @return [String]
|
21
|
+
attr_accessor :availability_zone
|
22
|
+
|
23
|
+
# The timeout to wait for an instance to become ready.
|
24
|
+
#
|
25
|
+
# @return [Fixnum]
|
26
|
+
attr_accessor :instance_ready_timeout
|
27
|
+
|
28
|
+
# The interval to wait for checking an instance's state.
|
29
|
+
#
|
30
|
+
# @return [Fixnum]
|
31
|
+
attr_accessor :instance_check_interval
|
32
|
+
|
33
|
+
# The timeout to wait for an instance to successfully burn into an AMI.
|
34
|
+
#
|
35
|
+
# @return [Fixnum]
|
36
|
+
attr_accessor :instance_package_timeout
|
37
|
+
|
38
|
+
# The type of instance to launch, such as "m3.medium"
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
attr_accessor :instance_type
|
42
|
+
|
43
|
+
# The name of the keypair to use.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
attr_accessor :keypair_name
|
47
|
+
|
48
|
+
# The path to the keypair to use.
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
attr_accessor :keypair_path
|
52
|
+
|
53
|
+
# The private IP address to give this machine (VPC).
|
54
|
+
#
|
55
|
+
# @return [String]
|
56
|
+
attr_accessor :private_ip_address
|
57
|
+
|
58
|
+
# If true, acquire and attach an elastic IP address.
|
59
|
+
# If set to an IP address, assign to the instance.
|
60
|
+
#
|
61
|
+
# @return [String]
|
62
|
+
attr_accessor :elastic_ip
|
63
|
+
|
64
|
+
# The name of the AWS region in which to create the instance.
|
65
|
+
#
|
66
|
+
# @return [String]
|
67
|
+
attr_accessor :region
|
68
|
+
|
69
|
+
# The EC2 endpoint to connect to
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
attr_accessor :endpoint
|
73
|
+
|
74
|
+
# The version of the AWS api to use
|
75
|
+
#
|
76
|
+
# @return [String]
|
77
|
+
attr_accessor :version
|
78
|
+
|
79
|
+
# The secret access key for accessing AWS.
|
80
|
+
#
|
81
|
+
# @return [String]
|
82
|
+
attr_accessor :secret_access_key
|
83
|
+
|
84
|
+
# The token associated with the key for accessing AWS.
|
85
|
+
#
|
86
|
+
# @return [String]
|
87
|
+
attr_accessor :session_token
|
88
|
+
|
89
|
+
# The security groups to set on the instance. For VPC this must
|
90
|
+
# be a list of IDs. For EC2, it can be either.
|
91
|
+
#
|
92
|
+
# @return [Array<String>]
|
93
|
+
attr_reader :security_groups
|
94
|
+
|
95
|
+
# The Amazon resource name (ARN) of the IAM Instance Profile
|
96
|
+
# to associate with the instance.
|
97
|
+
#
|
98
|
+
# @return [String]
|
99
|
+
attr_accessor :iam_instance_profile_arn
|
100
|
+
|
101
|
+
# The name of the IAM Instance Profile to associate with
|
102
|
+
# the instance.
|
103
|
+
#
|
104
|
+
# @return [String]
|
105
|
+
attr_accessor :iam_instance_profile_name
|
106
|
+
|
107
|
+
# The subnet ID to launch the machine into (VPC).
|
108
|
+
#
|
109
|
+
# @return [String]
|
110
|
+
attr_accessor :subnet_id
|
111
|
+
|
112
|
+
# The tags for the machine.
|
113
|
+
#
|
114
|
+
# @return [Hash<String, String>]
|
115
|
+
attr_accessor :tags
|
116
|
+
|
117
|
+
# The tags for the AMI generated with package.
|
118
|
+
#
|
119
|
+
# @return [Hash<String, String>]
|
120
|
+
attr_accessor :package_tags
|
121
|
+
|
122
|
+
# Use IAM Instance Role for authentication to AWS instead of an
|
123
|
+
# explicit access_id and secret_access_key
|
124
|
+
#
|
125
|
+
# @return [Boolean]
|
126
|
+
attr_accessor :use_iam_profile
|
127
|
+
|
128
|
+
# The user data string
|
129
|
+
#
|
130
|
+
# @return [String]
|
131
|
+
attr_accessor :user_data
|
132
|
+
|
133
|
+
# Block device mappings
|
134
|
+
#
|
135
|
+
# @return [Array<Hash>]
|
136
|
+
attr_accessor :block_device_mapping
|
137
|
+
|
138
|
+
# Indicates whether an instance stops or terminates when you initiate shutdown from the instance
|
139
|
+
#
|
140
|
+
# @return [bool]
|
141
|
+
attr_accessor :terminate_on_shutdown
|
142
|
+
|
143
|
+
# Specifies which address to connect to with ssh
|
144
|
+
# Must be one of:
|
145
|
+
# - :public_ip_address
|
146
|
+
# - :dns_name
|
147
|
+
# - :private_ip_address
|
148
|
+
# This attribute also accepts an array of symbols
|
149
|
+
#
|
150
|
+
# @return [Symbol]
|
151
|
+
attr_accessor :ssh_host_attribute
|
152
|
+
|
153
|
+
# Enables Monitoring
|
154
|
+
#
|
155
|
+
# @return [Boolean]
|
156
|
+
attr_accessor :monitoring
|
157
|
+
|
158
|
+
# EBS optimized instance
|
159
|
+
#
|
160
|
+
# @return [Boolean]
|
161
|
+
attr_accessor :ebs_optimized
|
162
|
+
|
163
|
+
# Source Destination check
|
164
|
+
#
|
165
|
+
# @return [Boolean]
|
166
|
+
attr_accessor :source_dest_check
|
167
|
+
|
168
|
+
# Assigning a public IP address in a VPC
|
169
|
+
#
|
170
|
+
# @return [Boolean]
|
171
|
+
attr_accessor :associate_public_ip
|
172
|
+
|
173
|
+
# The name of ELB, which an instance should be
|
174
|
+
# attached to
|
175
|
+
#
|
176
|
+
# @return [String]
|
177
|
+
attr_accessor :elb
|
178
|
+
|
179
|
+
# Disable unregisering ELB's from AZ - useful in case of not using default VPC
|
180
|
+
# @return [Boolean]
|
181
|
+
attr_accessor :unregister_elb_from_az
|
182
|
+
|
183
|
+
# Kernel Id
|
184
|
+
#
|
185
|
+
# @return [String]
|
186
|
+
attr_accessor :kernel_id
|
187
|
+
|
188
|
+
# The tenancy of the instance in a VPC.
|
189
|
+
# Defaults to 'default'.
|
190
|
+
#
|
191
|
+
# @return [String]
|
192
|
+
attr_accessor :tenancy
|
193
|
+
|
194
|
+
# The directory where AWS files are stored (usually $HOME/.aws)
|
195
|
+
#
|
196
|
+
# @return [String]
|
197
|
+
attr_accessor :aws_dir
|
198
|
+
|
199
|
+
# The selected AWS named profile (as defined in $HOME/.aws/* files)
|
200
|
+
#
|
201
|
+
# @return [String]
|
202
|
+
attr_accessor :aws_profile
|
203
|
+
|
204
|
+
def initialize(region_specific=false)
|
205
|
+
@access_key_id = UNSET_VALUE
|
206
|
+
@ami = UNSET_VALUE
|
207
|
+
@availability_zone = UNSET_VALUE
|
208
|
+
@instance_check_interval = UNSET_VALUE
|
209
|
+
@instance_ready_timeout = UNSET_VALUE
|
210
|
+
@instance_package_timeout = UNSET_VALUE
|
211
|
+
@instance_type = UNSET_VALUE
|
212
|
+
@keypair_name = UNSET_VALUE
|
213
|
+
@keypair_path = UNSET_VALUE
|
214
|
+
@private_ip_address = UNSET_VALUE
|
215
|
+
@region = UNSET_VALUE
|
216
|
+
@endpoint = UNSET_VALUE
|
217
|
+
@version = UNSET_VALUE
|
218
|
+
@secret_access_key = UNSET_VALUE
|
219
|
+
@session_token = UNSET_VALUE
|
220
|
+
@security_groups = UNSET_VALUE
|
221
|
+
@subnet_id = UNSET_VALUE
|
222
|
+
@tags = {}
|
223
|
+
@package_tags = {}
|
224
|
+
@user_data = UNSET_VALUE
|
225
|
+
@use_iam_profile = UNSET_VALUE
|
226
|
+
@block_device_mapping = []
|
227
|
+
@elastic_ip = UNSET_VALUE
|
228
|
+
@iam_instance_profile_arn = UNSET_VALUE
|
229
|
+
@iam_instance_profile_name = UNSET_VALUE
|
230
|
+
@terminate_on_shutdown = UNSET_VALUE
|
231
|
+
@ssh_host_attribute = UNSET_VALUE
|
232
|
+
@monitoring = UNSET_VALUE
|
233
|
+
@ebs_optimized = UNSET_VALUE
|
234
|
+
@source_dest_check = UNSET_VALUE
|
235
|
+
@associate_public_ip = UNSET_VALUE
|
236
|
+
@elb = UNSET_VALUE
|
237
|
+
@unregister_elb_from_az = UNSET_VALUE
|
238
|
+
@kernel_id = UNSET_VALUE
|
239
|
+
@tenancy = UNSET_VALUE
|
240
|
+
@aws_dir = UNSET_VALUE
|
241
|
+
@aws_profile = UNSET_VALUE
|
242
|
+
|
243
|
+
# Internal state (prefix with __ so they aren't automatically
|
244
|
+
# merged)
|
245
|
+
@__compiled_region_configs = {}
|
246
|
+
@__finalized = false
|
247
|
+
@__region_config = {}
|
248
|
+
@__region_specific = region_specific
|
249
|
+
end
|
250
|
+
|
251
|
+
# set security_groups
|
252
|
+
def security_groups=(value)
|
253
|
+
# convert value to array if necessary
|
254
|
+
@security_groups = value.is_a?(Array) ? value : [value]
|
255
|
+
end
|
256
|
+
|
257
|
+
# Allows region-specific overrides of any of the settings on this
|
258
|
+
# configuration object. This allows the user to override things like
|
259
|
+
# AMI and keypair name for regions. Example:
|
260
|
+
#
|
261
|
+
# aws.region_config "us-east-1" do |region|
|
262
|
+
# region.ami = "ami-12345678"
|
263
|
+
# region.keypair_name = "company-east"
|
264
|
+
# end
|
265
|
+
#
|
266
|
+
# @param [String] region The region name to configure.
|
267
|
+
# @param [Hash] attributes Direct attributes to set on the configuration
|
268
|
+
# as a shortcut instead of specifying a full block.
|
269
|
+
# @yield [config] Yields a new AWS configuration.
|
270
|
+
def region_config(region, attributes=nil, &block)
|
271
|
+
# Append the block to the list of region configs for that region.
|
272
|
+
# We'll evaluate these upon finalization.
|
273
|
+
@__region_config[region] ||= []
|
274
|
+
|
275
|
+
# Append a block that sets attributes if we got one
|
276
|
+
if attributes
|
277
|
+
attr_block = lambda do |config|
|
278
|
+
config.set_options(attributes)
|
279
|
+
end
|
280
|
+
|
281
|
+
@__region_config[region] << attr_block
|
282
|
+
end
|
283
|
+
|
284
|
+
# Append a block if we got one
|
285
|
+
@__region_config[region] << block if block_given?
|
286
|
+
end
|
287
|
+
|
288
|
+
#-------------------------------------------------------------------
|
289
|
+
# Internal methods.
|
290
|
+
#-------------------------------------------------------------------
|
291
|
+
|
292
|
+
def merge(other)
|
293
|
+
super.tap do |result|
|
294
|
+
# Copy over the region specific flag. "True" is retained if either
|
295
|
+
# has it.
|
296
|
+
new_region_specific = other.instance_variable_get(:@__region_specific)
|
297
|
+
result.instance_variable_set(
|
298
|
+
:@__region_specific, new_region_specific || @__region_specific)
|
299
|
+
|
300
|
+
# Go through all the region configs and prepend ours onto
|
301
|
+
# theirs.
|
302
|
+
new_region_config = other.instance_variable_get(:@__region_config)
|
303
|
+
@__region_config.each do |key, value|
|
304
|
+
new_region_config[key] ||= []
|
305
|
+
new_region_config[key] = value + new_region_config[key]
|
306
|
+
end
|
307
|
+
|
308
|
+
# Set it
|
309
|
+
result.instance_variable_set(:@__region_config, new_region_config)
|
310
|
+
|
311
|
+
# Merge in the tags
|
312
|
+
result.tags.merge!(self.tags)
|
313
|
+
result.tags.merge!(other.tags)
|
314
|
+
|
315
|
+
# Merge in the package tags
|
316
|
+
result.package_tags.merge!(self.package_tags)
|
317
|
+
result.package_tags.merge!(other.package_tags)
|
318
|
+
|
319
|
+
# Merge block_device_mapping
|
320
|
+
result.block_device_mapping |= self.block_device_mapping
|
321
|
+
result.block_device_mapping |= other.block_device_mapping
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def finalize!
|
326
|
+
# If access_key_id or secret_access_key were not specified in Vagrantfile
|
327
|
+
# then try to read from environment variables first, and if it fails from
|
328
|
+
# the AWS folder.
|
329
|
+
if @access_key_id == UNSET_VALUE or @secret_access_key == UNSET_VALUE
|
330
|
+
@aws_profile = 'default' if @aws_profile == UNSET_VALUE
|
331
|
+
@aws_dir = ENV['HOME'].to_s + '/.aws/' if @aws_dir == UNSET_VALUE
|
332
|
+
@region, @access_key_id, @secret_access_key, @session_token = Credentials.new.get_aws_info(@aws_profile, @aws_dir)
|
333
|
+
@region = UNSET_VALUE if @region.nil?
|
334
|
+
end
|
335
|
+
|
336
|
+
# session token must be set to nil, empty string isn't enough!
|
337
|
+
@session_token = nil if @session_token == UNSET_VALUE
|
338
|
+
|
339
|
+
# AMI must be nil, since we can't default that
|
340
|
+
@ami = nil if @ami == UNSET_VALUE
|
341
|
+
|
342
|
+
# Set the default timeout for waiting for an instance to be ready
|
343
|
+
@instance_ready_timeout = 120 if @instance_ready_timeout == UNSET_VALUE
|
344
|
+
|
345
|
+
# Set the default interval to check instance state
|
346
|
+
@instance_check_interval = 2 if @instance_check_interval == UNSET_VALUE
|
347
|
+
|
348
|
+
# Set the default timeout for waiting for an instance to burn into and ami
|
349
|
+
@instance_package_timeout = 600 if @instance_package_timeout == UNSET_VALUE
|
350
|
+
|
351
|
+
# Default instance type is an m3.medium
|
352
|
+
@instance_type = "m3.medium" if @instance_type == UNSET_VALUE
|
353
|
+
|
354
|
+
# Keypair defaults to nil
|
355
|
+
@keypair_name = nil if @keypair_name == UNSET_VALUE
|
356
|
+
|
357
|
+
# If 'keypair_name' is set, then keypair path defaults to similarly
|
358
|
+
# named file in user's .ssh directory. Otherwise it defaults to nil.
|
359
|
+
if @keypair_path == UNSET_VALUE
|
360
|
+
if keypair_name.nil?
|
361
|
+
@keypair_path = nil
|
362
|
+
else
|
363
|
+
@keypair_path = "#{Dir.home}/.ssh/#{@keypair_name}.pem"
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
# Default the private IP to nil since VPC is not default
|
368
|
+
@private_ip_address = nil if @private_ip_address == UNSET_VALUE
|
369
|
+
|
370
|
+
# Acquire an elastic IP if requested
|
371
|
+
@elastic_ip = nil if @elastic_ip == UNSET_VALUE
|
372
|
+
|
373
|
+
# Default region is us-east-1. This is sensible because AWS
|
374
|
+
# generally defaults to this as well.
|
375
|
+
@region = "us-east-1" if @region == UNSET_VALUE
|
376
|
+
@availability_zone = nil if @availability_zone == UNSET_VALUE
|
377
|
+
@endpoint = nil if @endpoint == UNSET_VALUE
|
378
|
+
@version = nil if @version == UNSET_VALUE
|
379
|
+
|
380
|
+
# The security groups are empty by default.
|
381
|
+
@security_groups = [] if @security_groups == UNSET_VALUE
|
382
|
+
|
383
|
+
# Subnet is nil by default otherwise we'd launch into VPC.
|
384
|
+
@subnet_id = nil if @subnet_id == UNSET_VALUE
|
385
|
+
|
386
|
+
# IAM Instance profile arn/name is nil by default.
|
387
|
+
@iam_instance_profile_arn = nil if @iam_instance_profile_arn == UNSET_VALUE
|
388
|
+
@iam_instance_profile_name = nil if @iam_instance_profile_name == UNSET_VALUE
|
389
|
+
|
390
|
+
# By default we don't use an IAM profile
|
391
|
+
@use_iam_profile = false if @use_iam_profile == UNSET_VALUE
|
392
|
+
|
393
|
+
# User Data is nil by default
|
394
|
+
@user_data = nil if @user_data == UNSET_VALUE
|
395
|
+
|
396
|
+
# default false
|
397
|
+
@terminate_on_shutdown = false if @terminate_on_shutdown == UNSET_VALUE
|
398
|
+
|
399
|
+
# default to nil
|
400
|
+
@ssh_host_attribute = nil if @ssh_host_attribute == UNSET_VALUE
|
401
|
+
|
402
|
+
# default false
|
403
|
+
@monitoring = false if @monitoring == UNSET_VALUE
|
404
|
+
|
405
|
+
# default false
|
406
|
+
@ebs_optimized = false if @ebs_optimized == UNSET_VALUE
|
407
|
+
|
408
|
+
# default to nil
|
409
|
+
@source_dest_check = nil if @source_dest_check == UNSET_VALUE
|
410
|
+
|
411
|
+
# default false
|
412
|
+
@associate_public_ip = false if @associate_public_ip == UNSET_VALUE
|
413
|
+
|
414
|
+
# default 'default'
|
415
|
+
@tenancy = "default" if @tenancy == UNSET_VALUE
|
416
|
+
|
417
|
+
# Don't attach instance to any ELB by default
|
418
|
+
@elb = nil if @elb == UNSET_VALUE
|
419
|
+
|
420
|
+
@unregister_elb_from_az = true if @unregister_elb_from_az == UNSET_VALUE
|
421
|
+
|
422
|
+
# default to nil
|
423
|
+
@kernel_id = nil if @kernel_id == UNSET_VALUE
|
424
|
+
|
425
|
+
# Compile our region specific configurations only within
|
426
|
+
# NON-REGION-SPECIFIC configurations.
|
427
|
+
if !@__region_specific
|
428
|
+
@__region_config.each do |region, blocks|
|
429
|
+
config = self.class.new(true).merge(self)
|
430
|
+
|
431
|
+
# Execute the configuration for each block
|
432
|
+
blocks.each { |b| b.call(config) }
|
433
|
+
|
434
|
+
# The region name of the configuration always equals the
|
435
|
+
# region config name:
|
436
|
+
config.region = region
|
437
|
+
|
438
|
+
# Finalize the configuration
|
439
|
+
config.finalize!
|
440
|
+
|
441
|
+
# Store it for retrieval
|
442
|
+
@__compiled_region_configs[region] = config
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
# Mark that we finalized
|
447
|
+
@__finalized = true
|
448
|
+
end
|
449
|
+
|
450
|
+
def validate(machine)
|
451
|
+
errors = _detected_errors
|
452
|
+
|
453
|
+
errors << I18n.t("vagrant_aws.config.aws_info_required",
|
454
|
+
:profile => @aws_profile, :location => @aws_dir) if \
|
455
|
+
@aws_profile and (@access_key_id.nil? or @secret_access_key.nil? or @region.nil?)
|
456
|
+
|
457
|
+
errors << I18n.t("vagrant_aws.config.region_required") if @region.nil?
|
458
|
+
|
459
|
+
if @region
|
460
|
+
# Get the configuration for the region we're using and validate only
|
461
|
+
# that region.
|
462
|
+
config = get_region_config(@region)
|
463
|
+
|
464
|
+
if !config.use_iam_profile
|
465
|
+
errors << I18n.t("vagrant_aws.config.access_key_id_required") if \
|
466
|
+
config.access_key_id.nil?
|
467
|
+
errors << I18n.t("vagrant_aws.config.secret_access_key_required") if \
|
468
|
+
config.secret_access_key.nil?
|
469
|
+
end
|
470
|
+
|
471
|
+
if config.associate_public_ip && !config.subnet_id
|
472
|
+
errors << I18n.t("vagrant_aws.config.subnet_id_required_with_public_ip")
|
473
|
+
end
|
474
|
+
|
475
|
+
errors << I18n.t("vagrant_aws.config.ami_required", :region => @region) if config.ami.nil?
|
476
|
+
end
|
477
|
+
|
478
|
+
{ "AWS Provider" => errors }
|
479
|
+
end
|
480
|
+
|
481
|
+
# This gets the configuration for a specific region. It shouldn't
|
482
|
+
# be called by the general public and is only used internally.
|
483
|
+
def get_region_config(name)
|
484
|
+
if !@__finalized
|
485
|
+
raise "Configuration must be finalized before calling this method."
|
486
|
+
end
|
487
|
+
|
488
|
+
# Return the compiled region config
|
489
|
+
@__compiled_region_configs[name] || self
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
|
494
|
+
class Credentials < Vagrant.plugin("2", :config)
|
495
|
+
# This module reads AWS config and credentials.
|
496
|
+
# Behaviour aims to mimic what is described in AWS documentation:
|
497
|
+
# http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html
|
498
|
+
# http://docs.aws.amazon.com/cli/latest/topic/config-vars.html
|
499
|
+
# Which is the following (stopping at the first successful case):
|
500
|
+
# 1) read config and credentials from environment variables
|
501
|
+
# 2) read config and credentials from files at location defined by environment variables
|
502
|
+
# 3) read config and credentials from files at default location
|
503
|
+
#
|
504
|
+
# The mandatory fields for a successful "get credentials" are the id and the secret keys.
|
505
|
+
# Region is not required since Config#finalize falls back to sensible defaults.
|
506
|
+
# The behaviour is all-or-nothing (ie: no mixing between vars and files).
|
507
|
+
#
|
508
|
+
# It also allows choosing a profile (by default it's [default]) and an "info"
|
509
|
+
# directory (by default $HOME/.aws), which can be specified in the Vagrantfile.
|
510
|
+
# Supported information: region, aws_access_key_id, aws_secret_access_key, and aws_session_token.
|
511
|
+
|
512
|
+
def get_aws_info(profile, location)
|
513
|
+
# read credentials from environment variables
|
514
|
+
aws_region, aws_id, aws_secret, aws_token = read_aws_environment()
|
515
|
+
# if nothing there, then read from files
|
516
|
+
# (the _if_ doesn't check aws_region since Config#finalize sets one by default)
|
517
|
+
if aws_id.to_s == '' or aws_secret.to_s == ''
|
518
|
+
# check if there are env variables for credential location, if so use then
|
519
|
+
aws_config = ENV['AWS_CONFIG_FILE'].to_s
|
520
|
+
aws_creds = ENV['AWS_SHARED_CREDENTIALS_FILE'].to_s
|
521
|
+
if aws_config == '' or aws_creds == ''
|
522
|
+
aws_config = location + 'config'
|
523
|
+
aws_creds = location + 'credentials'
|
524
|
+
end
|
525
|
+
if File.exist?(aws_config) and File.exist?(aws_creds)
|
526
|
+
aws_region, aws_id, aws_secret, aws_token = read_aws_files(profile, aws_config, aws_creds)
|
527
|
+
end
|
528
|
+
end
|
529
|
+
aws_region = nil if aws_region == ''
|
530
|
+
aws_id = nil if aws_id == ''
|
531
|
+
aws_secret = nil if aws_secret == ''
|
532
|
+
aws_token = nil if aws_token == ''
|
533
|
+
|
534
|
+
return aws_region, aws_id, aws_secret, aws_token
|
535
|
+
end
|
536
|
+
|
537
|
+
|
538
|
+
private
|
539
|
+
|
540
|
+
def read_aws_files(profile, aws_config, aws_creds)
|
541
|
+
# determine section in config ini file
|
542
|
+
if profile == 'default'
|
543
|
+
ini_profile = profile
|
544
|
+
else
|
545
|
+
ini_profile = 'profile ' + profile
|
546
|
+
end
|
547
|
+
# get info from config ini file for selected profile
|
548
|
+
data = File.read(aws_config)
|
549
|
+
doc_cfg = IniParse.parse(data)
|
550
|
+
aws_region = doc_cfg[ini_profile]['region']
|
551
|
+
|
552
|
+
# determine section in credentials ini file
|
553
|
+
ini_profile = profile
|
554
|
+
# get info from credentials ini file for selected profile
|
555
|
+
data = File.read(aws_creds)
|
556
|
+
doc_cfg = IniParse.parse(data)
|
557
|
+
aws_id = doc_cfg[ini_profile]['aws_access_key_id']
|
558
|
+
aws_secret = doc_cfg[ini_profile]['aws_secret_access_key']
|
559
|
+
aws_token = doc_cfg[ini_profile]['aws_session_token']
|
560
|
+
|
561
|
+
return aws_region, aws_id, aws_secret, aws_token
|
562
|
+
end
|
563
|
+
|
564
|
+
def read_aws_environment()
|
565
|
+
aws_region = ENV['AWS_DEFAULT_REGION']
|
566
|
+
aws_id = ENV['AWS_ACCESS_KEY_ID']
|
567
|
+
aws_secret = ENV['AWS_SECRET_ACCESS_KEY']
|
568
|
+
aws_token = ENV['AWS_SESSION_TOKEN']
|
569
|
+
|
570
|
+
return aws_region, aws_id, aws_secret, aws_token
|
571
|
+
end
|
572
|
+
|
573
|
+
end
|
574
|
+
|
575
|
+
|
576
|
+
end
|
577
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module AWS
|
5
|
+
module Errors
|
6
|
+
class VagrantAWSError < Vagrant::Errors::VagrantError
|
7
|
+
error_namespace("vagrant_aws.errors")
|
8
|
+
end
|
9
|
+
|
10
|
+
class FogError < VagrantAWSError
|
11
|
+
error_key(:fog_error)
|
12
|
+
end
|
13
|
+
|
14
|
+
class InternalFogError < VagrantAWSError
|
15
|
+
error_key(:internal_fog_error)
|
16
|
+
end
|
17
|
+
|
18
|
+
class InstanceReadyTimeout < VagrantAWSError
|
19
|
+
error_key(:instance_ready_timeout)
|
20
|
+
end
|
21
|
+
|
22
|
+
class InstancePackageError < VagrantAWSError
|
23
|
+
error_key(:instance_package_error)
|
24
|
+
end
|
25
|
+
|
26
|
+
class InstancePackageTimeout < VagrantAWSError
|
27
|
+
error_key(:instance_package_timeout)
|
28
|
+
end
|
29
|
+
|
30
|
+
class RsyncError < VagrantAWSError
|
31
|
+
error_key(:rsync_error)
|
32
|
+
end
|
33
|
+
|
34
|
+
class MkdirError < VagrantAWSError
|
35
|
+
error_key(:mkdir_error)
|
36
|
+
end
|
37
|
+
|
38
|
+
class ElbDoesNotExistError < VagrantAWSError
|
39
|
+
error_key("elb_does_not_exist")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
begin
|
2
|
+
require "vagrant"
|
3
|
+
rescue LoadError
|
4
|
+
raise "The Vagrant AWS plugin must be run within Vagrant."
|
5
|
+
end
|
6
|
+
|
7
|
+
# This is a sanity check to make sure no one is attempting to install
|
8
|
+
# this into an early Vagrant version.
|
9
|
+
if Vagrant::VERSION < "1.2.0"
|
10
|
+
raise "The Vagrant AWS plugin is only compatible with Vagrant 1.2+"
|
11
|
+
end
|
12
|
+
|
13
|
+
module VagrantPlugins
|
14
|
+
module AWS
|
15
|
+
class Plugin < Vagrant.plugin("2")
|
16
|
+
name "AWS"
|
17
|
+
description <<-DESC
|
18
|
+
This plugin installs a provider that allows Vagrant to manage
|
19
|
+
machines in AWS (EC2/VPC).
|
20
|
+
DESC
|
21
|
+
|
22
|
+
config(:aws, :provider) do
|
23
|
+
require_relative "config"
|
24
|
+
Config
|
25
|
+
end
|
26
|
+
|
27
|
+
provider(:aws, parallel: true) do
|
28
|
+
# Setup logging and i18n
|
29
|
+
setup_logging
|
30
|
+
setup_i18n
|
31
|
+
|
32
|
+
# Return the provider
|
33
|
+
require_relative "provider"
|
34
|
+
Provider
|
35
|
+
end
|
36
|
+
|
37
|
+
provider_capability(:aws, :winrm_info) do
|
38
|
+
require_relative "cap/winrm_info"
|
39
|
+
Cap::WinRMInfo
|
40
|
+
end
|
41
|
+
|
42
|
+
# This initializes the internationalization strings.
|
43
|
+
def self.setup_i18n
|
44
|
+
I18n.load_path << File.expand_path("locales/en.yml", AWS.source_root)
|
45
|
+
I18n.reload!
|
46
|
+
end
|
47
|
+
|
48
|
+
# This sets up our log level to be whatever VAGRANT_LOG is.
|
49
|
+
def self.setup_logging
|
50
|
+
require "log4r"
|
51
|
+
|
52
|
+
level = nil
|
53
|
+
begin
|
54
|
+
level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
|
55
|
+
rescue NameError
|
56
|
+
# This means that the logging constant wasn't found,
|
57
|
+
# which is fine. We just keep `level` as `nil`. But
|
58
|
+
# we tell the user.
|
59
|
+
level = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# Some constants, such as "true" resolve to booleans, so the
|
63
|
+
# above error checking doesn't catch it. This will check to make
|
64
|
+
# sure that the log level is an integer, as Log4r requires.
|
65
|
+
level = nil if !level.is_a?(Integer)
|
66
|
+
|
67
|
+
# Set the logging level on all "vagrant" namespaced
|
68
|
+
# logs as long as we have a valid level.
|
69
|
+
if level
|
70
|
+
logger = Log4r::Logger.new("vagrant_aws")
|
71
|
+
logger.outputters = Log4r::Outputter.stderr
|
72
|
+
logger.level = level
|
73
|
+
logger = nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|