vagrant-mos 0.8.39

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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/CHANGELOG.md +92 -0
  4. data/Gemfile +12 -0
  5. data/LICENSE +8 -0
  6. data/README.md +292 -0
  7. data/Rakefile +21 -0
  8. data/Vagrantfile +1 -0
  9. data/dummy.box +0 -0
  10. data/example_box/README.md +13 -0
  11. data/example_box/Vagrantfile +8 -0
  12. data/example_box/metadata.json +3 -0
  13. data/lib/vagrant-mos.rb +18 -0
  14. data/lib/vagrant-mos/action.rb +212 -0
  15. data/lib/vagrant-mos/action/connect_mos.rb +51 -0
  16. data/lib/vagrant-mos/action/elb_deregister_instance.rb +24 -0
  17. data/lib/vagrant-mos/action/elb_register_instance.rb +24 -0
  18. data/lib/vagrant-mos/action/is_created.rb +18 -0
  19. data/lib/vagrant-mos/action/is_stopped.rb +19 -0
  20. data/lib/vagrant-mos/action/message_already_created.rb +16 -0
  21. data/lib/vagrant-mos/action/message_not_created.rb +16 -0
  22. data/lib/vagrant-mos/action/message_will_not_destroy.rb +16 -0
  23. data/lib/vagrant-mos/action/package_instance.rb +192 -0
  24. data/lib/vagrant-mos/action/read_ssh_info.rb +64 -0
  25. data/lib/vagrant-mos/action/read_state.rb +46 -0
  26. data/lib/vagrant-mos/action/run_instance.rb +287 -0
  27. data/lib/vagrant-mos/action/start_instance.rb +82 -0
  28. data/lib/vagrant-mos/action/stop_instance.rb +29 -0
  29. data/lib/vagrant-mos/action/terminate_instance.rb +52 -0
  30. data/lib/vagrant-mos/action/timed_provision.rb +21 -0
  31. data/lib/vagrant-mos/action/wait_for_state.rb +41 -0
  32. data/lib/vagrant-mos/action/warn_networks.rb +19 -0
  33. data/lib/vagrant-mos/config.rb +405 -0
  34. data/lib/vagrant-mos/errors.rb +43 -0
  35. data/lib/vagrant-mos/plugin.rb +73 -0
  36. data/lib/vagrant-mos/provider.rb +53 -0
  37. data/lib/vagrant-mos/util/elb.rb +56 -0
  38. data/lib/vagrant-mos/util/timer.rb +17 -0
  39. data/lib/vagrant-mos/version.rb +5 -0
  40. data/locales/en.yml +153 -0
  41. data/mos.box +0 -0
  42. data/spec/spec_helper.rb +1 -0
  43. data/spec/vagrant-mos/config_spec.rb +225 -0
  44. data/templates/metadata.json.erb +3 -0
  45. data/templates/vagrant-aws_package_Vagrantfile.erb +5 -0
  46. data/vagrant-mos.gemspec +60 -0
  47. metadata +172 -0
@@ -0,0 +1,82 @@
1
+ require "log4r"
2
+
3
+ require 'vagrant/util/retryable'
4
+
5
+ require 'vagrant-mos/util/timer'
6
+
7
+ module VagrantPlugins
8
+ module MOS
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_mos::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[:mos_compute].servers.get(env[:machine].id)
24
+ server = (env[:mos_compute].describe_instances([env[:machine].id]))["Instance"]
25
+ env[:ui].info(I18n.t("vagrant_mos.starting"))
26
+
27
+ begin
28
+ #server.start
29
+ env[:mos_compute].start_instance(env[:machine].id)
30
+
31
+ region = env[:machine].provider_config.region
32
+ region_config = env[:machine].provider_config.get_region_config(region)
33
+
34
+ # Wait for the instance to be ready first
35
+ env[:metrics]["instance_ready_time"] = Util::Timer.time do
36
+ tries = region_config.instance_ready_timeout / 2
37
+
38
+ env[:ui].info(I18n.t("vagrant_mos.waiting_for_ready"))
39
+ #begin
40
+ # retryable(:on => Fog::Errors::TimeoutError, :tries => tries) do
41
+ # # If we're interrupted don't worry about waiting
42
+ # next if env[:interrupted]
43
+ #
44
+ # # Wait for the server to be ready
45
+ # #server.wait_for(2) { ready? }
46
+ # end
47
+ #rescue Fog::Errors::TimeoutError
48
+ # # Notify the user
49
+ # raise Errors::InstanceReadyTimeout,
50
+ # timeout: region_config.instance_ready_timeout
51
+ #end
52
+ end
53
+ rescue Fog::Compute::MOS::Error => e
54
+ raise Errors::FogError, :message => e.message
55
+ end
56
+
57
+ @logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
58
+
59
+ if !env[:interrupted]
60
+ env[:metrics]["instance_ssh_time"] = Util::Timer.time do
61
+ # Wait for SSH to be ready.
62
+ env[:ui].info(I18n.t("vagrant_mos.waiting_for_ssh"))
63
+ while true
64
+ # If we're interrupted then just back out
65
+ break if env[:interrupted]
66
+ break if env[:machine].communicate.ready?
67
+ sleep 2
68
+ end
69
+ end
70
+
71
+ @logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
72
+
73
+ # Ready and booted!
74
+ env[:ui].info(I18n.t("vagrant_mos.ready"))
75
+ end
76
+
77
+ @app.call(env)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,29 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module MOS
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_mos::action::stop_instance")
11
+ end
12
+
13
+ def call(env)
14
+ #server = env[:mos_compute].servers.get(env[:machine].id)
15
+ #server = (env[:mos_compute].describe_instances([env[:machine].id]))["Instance"]
16
+ if env[:machine].state.id == "ready"
17
+ env[:ui].info(I18n.t("vagrant_mos.already stopped"))
18
+ else
19
+ env[:ui].info(I18n.t("vagrant_mos.stopping"))
20
+ #server.stop(!!env[:force_halt])
21
+ env[:mos_compute].stop_instance(env[:machine].id)
22
+ end
23
+
24
+ @app.call(env)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,52 @@
1
+ require "log4r"
2
+ require "json"
3
+
4
+ module VagrantPlugins
5
+ module MOS
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_mos::action::terminate_instance")
12
+ end
13
+
14
+ def call(env)
15
+ server = env[:mos_compute].describe_instances(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_mos.terminating"))
30
+ #server.destroy
31
+ env[:mos_compute].terminate_instance(env[:machine].id)
32
+ env[:machine].id = nil
33
+
34
+ @app.call(env)
35
+ end
36
+
37
+ # Release an elastic IP address
38
+ def release_address(env,eip)
39
+ h = JSON.parse(eip)
40
+ # Use association_id and allocation_id for VPC, use public IP for EC2
41
+ if h['association_id']
42
+ env[:mos_compute].disassociate_address(nil,h['association_id'])
43
+ env[:mos_compute].release_address(h['allocation_id'])
44
+ else
45
+ env[:mos_compute].disassociate_address(h['public_ip'])
46
+ env[:mos_compute].release_address(h['public_ip'])
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,21 @@
1
+ require "vagrant-mos/util/timer"
2
+
3
+ module VagrantPlugins
4
+ module MOS
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 MOS
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_mos::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_mos.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 MOS
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_mos.warn_networks"))
12
+ end
13
+
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,405 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module MOS
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # The access key ID for accessing MOS.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :access_key_id
10
+
11
+ # The ID of the AMI to use.
12
+ #
13
+ # @return [String]
14
+ attr_accessor :ami
15
+
16
+ # The availability zone to launch the instance into. If nil, it will
17
+ # use the default for your account.
18
+ #
19
+ # @return [String]
20
+ attr_accessor :availability_zone
21
+
22
+ # The timeout to wait for an instance to become ready.
23
+ #
24
+ # @return [Fixnum]
25
+ attr_accessor :instance_ready_timeout
26
+
27
+ # The timeout to wait for an instance to successfully burn into an AMI.
28
+ #
29
+ # @return [Fixnum]
30
+ attr_accessor :instance_package_timeout
31
+
32
+ # The type of instance to launch, such as "m3.medium"
33
+ #
34
+ # @return [String]
35
+ attr_accessor :instance_type
36
+
37
+ # The name of the keypair to use.
38
+ #
39
+ # @return [String]
40
+ attr_accessor :keypair_name
41
+
42
+ # The private IP address to give this machine (VPC).
43
+ #
44
+ # @return [String]
45
+ attr_accessor :private_ip_address
46
+
47
+ # If true, acquire and attach an elastic IP address.
48
+ # If set to an IP address, assign to the instance.
49
+ #
50
+ # @return [String]
51
+ attr_accessor :elastic_ip
52
+
53
+ # The name of the MOS region in which to create the instance.
54
+ #
55
+ # @return [String]
56
+ attr_accessor :region
57
+
58
+ # The EC2 endpoint to connect to
59
+ #
60
+ # @return [String]
61
+ attr_accessor :endpoint
62
+
63
+ # The version of the MOS api to use
64
+ #
65
+ # @return [String]
66
+ attr_accessor :version
67
+
68
+ # The secret access key for accessing MOS.
69
+ #
70
+ # @return [String]
71
+ attr_accessor :secret_access_key
72
+
73
+ # The secret access url for accessing MOS.
74
+ #
75
+ # @return [String]
76
+ attr_accessor :secret_access_url
77
+
78
+ # The token associated with the key for accessing MOS.
79
+ #
80
+ # @return [String]
81
+ attr_accessor :session_token
82
+
83
+ # The security groups to set on the instance. For VPC this must
84
+ # be a list of IDs. For EC2, it can be either.
85
+ #
86
+ # @return [Array<String>]
87
+ attr_reader :security_groups
88
+
89
+ # The Amazon resource name (ARN) of the IAM Instance Profile
90
+ # to associate with the instance.
91
+ #
92
+ # @return [String]
93
+ attr_accessor :iam_instance_profile_arn
94
+
95
+ # The name of the IAM Instance Profile to associate with
96
+ # the instance.
97
+ #
98
+ # @return [String]
99
+ attr_accessor :iam_instance_profile_name
100
+
101
+ # The subnet ID to launch the machine into (VPC).
102
+ #
103
+ # @return [String]
104
+ attr_accessor :subnet_id
105
+
106
+ # The tags for the machine.
107
+ #
108
+ # @return [Hash<String, String>]
109
+ attr_accessor :tags
110
+
111
+ # Use IAM Instance Role for authentication to MOS instead of an
112
+ # explicit access_id and secret_access_key
113
+ #
114
+ # @return [Boolean]
115
+ attr_accessor :use_iam_profile
116
+
117
+ # The user data string
118
+ #
119
+ # @return [String]
120
+ attr_accessor :user_data
121
+
122
+ # Block device mappings
123
+ #
124
+ # @return [Array<Hash>]
125
+ attr_accessor :block_device_mapping
126
+
127
+ # Indicates whether an instance stops or terminates when you initiate shutdown from the instance
128
+ #
129
+ # @return [bool]
130
+ attr_accessor :terminate_on_shutdown
131
+
132
+ # Specifies which address to connect to with ssh
133
+ # Must be one of:
134
+ # - :public_ip_address
135
+ # - :dns_name
136
+ # - :private_ip_address
137
+ # This attribute also accepts an array of symbols
138
+ #
139
+ # @return [Symbol]
140
+ attr_accessor :ssh_host_attribute
141
+
142
+ # Enables Monitoring
143
+ #
144
+ # @return [Boolean]
145
+ attr_accessor :monitoring
146
+
147
+ # EBS optimized instance
148
+ #
149
+ # @return [Boolean]
150
+ attr_accessor :ebs_optimized
151
+
152
+ # Assigning a public IP address in a VPC
153
+ #
154
+ # @return [Boolean]
155
+ attr_accessor :associate_public_ip
156
+
157
+ # The name of ELB, which an instance should be
158
+ # attached to
159
+ #
160
+ # @return [String]
161
+ attr_accessor :elb
162
+
163
+ def initialize(region_specific=false)
164
+ @access_key_id = UNSET_VALUE
165
+ @ami = UNSET_VALUE
166
+ @availability_zone = UNSET_VALUE
167
+ @instance_ready_timeout = UNSET_VALUE
168
+ @instance_package_timeout = UNSET_VALUE
169
+ @instance_type = UNSET_VALUE
170
+ @keypair_name = UNSET_VALUE
171
+ @private_ip_address = UNSET_VALUE
172
+ @region = UNSET_VALUE
173
+ @endpoint = UNSET_VALUE
174
+ @version = UNSET_VALUE
175
+ @secret_access_key = UNSET_VALUE
176
+ @secret_access_url = UNSET_VALUE
177
+ @session_token = UNSET_VALUE
178
+ @security_groups = UNSET_VALUE
179
+ @subnet_id = UNSET_VALUE
180
+ @tags = {}
181
+ @user_data = UNSET_VALUE
182
+ @use_iam_profile = UNSET_VALUE
183
+ @block_device_mapping = []
184
+ @elastic_ip = UNSET_VALUE
185
+ @iam_instance_profile_arn = UNSET_VALUE
186
+ @iam_instance_profile_name = UNSET_VALUE
187
+ @terminate_on_shutdown = UNSET_VALUE
188
+ @ssh_host_attribute = UNSET_VALUE
189
+ @monitoring = UNSET_VALUE
190
+ @ebs_optimized = UNSET_VALUE
191
+ @associate_public_ip = UNSET_VALUE
192
+ @elb = UNSET_VALUE
193
+
194
+ # Internal state (prefix with __ so they aren't automatically
195
+ # merged)
196
+ @__compiled_region_configs = {}
197
+ @__finalized = false
198
+ @__region_config = {}
199
+ @__region_specific = region_specific
200
+ end
201
+
202
+ # set security_groups
203
+ def security_groups=(value)
204
+ # convert value to array if necessary
205
+ @security_groups = value.is_a?(Array) ? value : [value]
206
+ end
207
+
208
+ # Allows region-specific overrides of any of the settings on this
209
+ # configuration object. This allows the user to override things like
210
+ # AMI and keypair name for regions. Example:
211
+ #
212
+ # mos.region_config "us-east-1" do |region|
213
+ # region.ami = "ami-12345678"
214
+ # region.keypair_name = "company-east"
215
+ # end
216
+ #
217
+ # @param [String] region The region name to configure.
218
+ # @param [Hash] attributes Direct attributes to set on the configuration
219
+ # as a shortcut instead of specifying a full block.
220
+ # @yield [config] Yields a new MOS configuration.
221
+ def region_config(region, attributes=nil, &block)
222
+ # Append the block to the list of region configs for that region.
223
+ # We'll evaluate these upon finalization.
224
+ @__region_config[region] ||= []
225
+
226
+ # Append a block that sets attributes if we got one
227
+ if attributes
228
+ attr_block = lambda do |config|
229
+ config.set_options(attributes)
230
+ end
231
+
232
+ @__region_config[region] << attr_block
233
+ end
234
+
235
+ # Append a block if we got one
236
+ @__region_config[region] << block if block_given?
237
+ end
238
+
239
+ #-------------------------------------------------------------------
240
+ # Internal methods.
241
+ #-------------------------------------------------------------------
242
+
243
+ def merge(other)
244
+ super.tap do |result|
245
+ # Copy over the region specific flag. "True" is retained if either
246
+ # has it.
247
+ new_region_specific = other.instance_variable_get(:@__region_specific)
248
+ result.instance_variable_set(
249
+ :@__region_specific, new_region_specific || @__region_specific)
250
+
251
+ # Go through all the region configs and prepend ours onto
252
+ # theirs.
253
+ new_region_config = other.instance_variable_get(:@__region_config)
254
+ @__region_config.each do |key, value|
255
+ new_region_config[key] ||= []
256
+ new_region_config[key] = value + new_region_config[key]
257
+ end
258
+
259
+ # Set it
260
+ result.instance_variable_set(:@__region_config, new_region_config)
261
+
262
+ # Merge in the tags
263
+ result.tags.merge!(self.tags)
264
+ result.tags.merge!(other.tags)
265
+
266
+ # Merge block_device_mapping
267
+ result.block_device_mapping |= self.block_device_mapping
268
+ result.block_device_mapping |= other.block_device_mapping
269
+ end
270
+ end
271
+
272
+ def finalize!
273
+ # Try to get access keys from standard MOS environment variables; they
274
+ # will default to nil if the environment variables are not present.
275
+ @access_key_id = ENV['MOS_ACCESS_KEY'] if @access_key_id == UNSET_VALUE
276
+ @secret_access_key = ENV['MOS_SECRET_KEY'] if @secret_access_key == UNSET_VALUE
277
+ @session_token = ENV['MOS_SESSION_TOKEN'] if @session_token == UNSET_VALUE
278
+
279
+ # AMI must be nil, since we can't default that
280
+ @ami = nil if @ami == UNSET_VALUE
281
+
282
+ # Set the default timeout for waiting for an instance to be ready
283
+ @instance_ready_timeout = 120 if @instance_ready_timeout == UNSET_VALUE
284
+
285
+ # Set the default timeout for waiting for an instance to burn into and ami
286
+ @instance_package_timeout = 600 if @instance_package_timeout == UNSET_VALUE
287
+
288
+ # Default instance type is an m3.medium
289
+ #@instance_type = "m3.medium" if @instance_type == UNSET_VALUE
290
+ @instance_type = "C1_M2" if @instance_type == UNSET_VALUE
291
+ # Keypair defaults to nil
292
+ @keypair_name = nil if @keypair_name == UNSET_VALUE
293
+
294
+ # Default the private IP to nil since VPC is not default
295
+ @private_ip_address = nil if @private_ip_address == UNSET_VALUE
296
+
297
+ # Acquire an elastic IP if requested
298
+ @elastic_ip = nil if @elastic_ip == UNSET_VALUE
299
+
300
+ # Default region is us-east-1. This is sensible because MOS
301
+ # generally defaults to this as well.
302
+ @region = "us-east-1" if @region == UNSET_VALUE
303
+ @availability_zone = nil if @availability_zone == UNSET_VALUE
304
+ @endpoint = nil if @endpoint == UNSET_VALUE
305
+ @version = nil if @version == UNSET_VALUE
306
+
307
+ # The security groups are empty by default.
308
+ @security_groups = [] if @security_groups == UNSET_VALUE
309
+
310
+ # Subnet is nil by default otherwise we'd launch into VPC.
311
+ @subnet_id = nil if @subnet_id == UNSET_VALUE
312
+
313
+ # IAM Instance profile arn/name is nil by default.
314
+ @iam_instance_profile_arn = nil if @iam_instance_profile_arn == UNSET_VALUE
315
+ @iam_instance_profile_name = nil if @iam_instance_profile_name == UNSET_VALUE
316
+
317
+ # By default we don't use an IAM profile
318
+ @use_iam_profile = false if @use_iam_profile == UNSET_VALUE
319
+
320
+ # User Data is nil by default
321
+ @user_data = nil if @user_data == UNSET_VALUE
322
+
323
+ # default false
324
+ @terminate_on_shutdown = false if @terminate_on_shutdown == UNSET_VALUE
325
+
326
+ # default to nil
327
+ @ssh_host_attribute = nil if @ssh_host_attribute == UNSET_VALUE
328
+
329
+ # default false
330
+ @monitoring = false if @monitoring == UNSET_VALUE
331
+
332
+ # default false
333
+ @ebs_optimized = false if @ebs_optimized == UNSET_VALUE
334
+
335
+ # default false
336
+ @associate_public_ip = false if @associate_public_ip == UNSET_VALUE
337
+
338
+ # Don't attach instance to any ELB by default
339
+ @elb = nil if @elb == UNSET_VALUE
340
+
341
+ # Compile our region specific configurations only within
342
+ # NON-REGION-SPECIFIC configurations.
343
+ if !@__region_specific
344
+ @__region_config.each do |region, blocks|
345
+ config = self.class.new(true).merge(self)
346
+
347
+ # Execute the configuration for each block
348
+ blocks.each { |b| b.call(config) }
349
+
350
+ # The region name of the configuration always equals the
351
+ # region config name:
352
+ config.region = region
353
+
354
+ # Finalize the configuration
355
+ config.finalize!
356
+
357
+ # Store it for retrieval
358
+ @__compiled_region_configs[region] = config
359
+ end
360
+ end
361
+
362
+ # Mark that we finalized
363
+ @__finalized = true
364
+ end
365
+
366
+ def validate(machine)
367
+ errors = _detected_errors
368
+
369
+ errors << I18n.t("vagrant_mos.config.region_required") if @region.nil?
370
+
371
+ if @region
372
+ # Get the configuration for the region we're using and validate only
373
+ # that region.
374
+ config = get_region_config(@region)
375
+
376
+ if !config.use_iam_profile
377
+ errors << I18n.t("vagrant_mos.config.access_key_id_required") if \
378
+ config.access_key_id.nil?
379
+ errors << I18n.t("vagrant_mos.config.secret_access_key_required") if \
380
+ config.secret_access_key.nil?
381
+ end
382
+
383
+ if config.associate_public_ip && !config.subnet_id
384
+ errors << I18n.t("vagrant_mos.config.subnet_id_required_with_public_ip")
385
+ end
386
+
387
+ errors << I18n.interpolate("vagrant_mos.config.ami_required", :region => @region) if config.ami.nil?
388
+ end
389
+
390
+ { "MOS Provider" => errors }
391
+ end
392
+
393
+ # This gets the configuration for a specific region. It shouldn't
394
+ # be called by the general public and is only used internally.
395
+ def get_region_config(name)
396
+ if !@__finalized
397
+ raise "Configuration must be finalized before calling this method."
398
+ end
399
+
400
+ # Return the compiled region config
401
+ @__compiled_region_configs[name] || self
402
+ end
403
+ end
404
+ end
405
+ end