vagrant-aws-mkubenka 0.7.2.pre.8

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