vagrant-mcs 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +1 -0
  4. data/CHANGELOG.md +92 -0
  5. data/Gemfile +12 -0
  6. data/LICENSE +8 -0
  7. data/README.md +292 -0
  8. data/Rakefile +21 -0
  9. data/dummy.box +0 -0
  10. data/example_box/README.md +13 -0
  11. data/example_box/mcs.box +0 -0
  12. data/example_box/metadata.json +3 -0
  13. data/lib/vagrant-mcs/action/connect_mcs.rb +51 -0
  14. data/lib/vagrant-mcs/action/elb_deregister_instance.rb +24 -0
  15. data/lib/vagrant-mcs/action/elb_register_instance.rb +24 -0
  16. data/lib/vagrant-mcs/action/is_created.rb +18 -0
  17. data/lib/vagrant-mcs/action/is_stopped.rb +18 -0
  18. data/lib/vagrant-mcs/action/message_already_created.rb +16 -0
  19. data/lib/vagrant-mcs/action/message_not_created.rb +16 -0
  20. data/lib/vagrant-mcs/action/message_will_not_destroy.rb +16 -0
  21. data/lib/vagrant-mcs/action/package_instance.rb +192 -0
  22. data/lib/vagrant-mcs/action/read_ssh_info.rb +53 -0
  23. data/lib/vagrant-mcs/action/read_state.rb +38 -0
  24. data/lib/vagrant-mcs/action/run_instance.rb +274 -0
  25. data/lib/vagrant-mcs/action/start_instance.rb +81 -0
  26. data/lib/vagrant-mcs/action/stop_instance.rb +28 -0
  27. data/lib/vagrant-mcs/action/terminate_instance.rb +51 -0
  28. data/lib/vagrant-mcs/action/timed_provision.rb +21 -0
  29. data/lib/vagrant-mcs/action/wait_for_state.rb +41 -0
  30. data/lib/vagrant-mcs/action/warn_networks.rb +19 -0
  31. data/lib/vagrant-mcs/action.rb +210 -0
  32. data/lib/vagrant-mcs/config.rb +405 -0
  33. data/lib/vagrant-mcs/errors.rb +43 -0
  34. data/lib/vagrant-mcs/plugin.rb +73 -0
  35. data/lib/vagrant-mcs/provider.rb +50 -0
  36. data/lib/vagrant-mcs/util/elb.rb +56 -0
  37. data/lib/vagrant-mcs/util/timer.rb +17 -0
  38. data/lib/vagrant-mcs/version.rb +5 -0
  39. data/lib/vagrant-mcs.rb +18 -0
  40. data/locales/en.yml +153 -0
  41. data/mcs.box +0 -0
  42. data/spec/spec_helper.rb +1 -0
  43. data/spec/vagrant-aws/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-mcs.gemspec +60 -0
  47. metadata +172 -0
@@ -0,0 +1,21 @@
1
+ require "vagrant-mcs/util/timer"
2
+
3
+ module VagrantPlugins
4
+ module MCS
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 MCS
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_mcs::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_mcs.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 MCS
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_mcs.warn_networks"))
12
+ end
13
+
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,210 @@
1
+ require "pathname"
2
+
3
+ require "vagrant/action/builder"
4
+
5
+ module VagrantPlugins
6
+ module MCS
7
+ module Action
8
+ # Include the built-in modules so we can use them as top-level things.
9
+ include Vagrant::Action::Builtin
10
+
11
+ def self.action_package
12
+ Vagrant::Action::Builder.new.tap do |b|
13
+ b.use Call, IsCreated do |env, b2|
14
+ if !env[:result]
15
+ b2.use MessageNotCreated
16
+ next
17
+ end
18
+
19
+ # Connect to MCS and then Create a package from the server instance
20
+ b2.use ConnectMCS
21
+ b2.use PackageInstance
22
+ end
23
+ end
24
+ end
25
+
26
+ # This action is called to halt the remote machine.
27
+ def self.action_halt
28
+ Vagrant::Action::Builder.new.tap do |b|
29
+ b.use ConfigValidate
30
+ b.use Call, IsCreated do |env, b2|
31
+ if !env[:result]
32
+ b2.use MessageNotCreated
33
+ next
34
+ end
35
+
36
+ b2.use ConnectMCS
37
+ b2.use StopInstance
38
+ end
39
+ end
40
+ end
41
+
42
+ # This action is called to terminate the remote machine.
43
+ def self.action_destroy
44
+ Vagrant::Action::Builder.new.tap do |b|
45
+ b.use Call, DestroyConfirm do |env, b2|
46
+ if env[:result]
47
+ b2.use ConfigValidate
48
+ b2.use Call, IsCreated do |env2, b3|
49
+ if !env2[:result]
50
+ b3.use MessageNotCreated
51
+ next
52
+ end
53
+ b3.use ConnectMCS
54
+ b3.use ElbDeregisterInstance
55
+ b3.use TerminateInstance
56
+ b3.use ProvisionerCleanup if defined?(ProvisionerCleanup)
57
+ end
58
+ else
59
+ b2.use MessageWillNotDestroy
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ # This action is called when `vagrant provision` is called.
66
+ def self.action_provision
67
+ Vagrant::Action::Builder.new.tap do |b|
68
+ b.use ConfigValidate
69
+ b.use Call, IsCreated do |env, b2|
70
+ if !env[:result]
71
+ b2.use MessageNotCreated
72
+ next
73
+ end
74
+
75
+ b2.use Provision
76
+ b2.use SyncedFolders
77
+ end
78
+ end
79
+ end
80
+
81
+ # This action is called to read the SSH info of the machine. The
82
+ # resulting state is expected to be put into the `:machine_ssh_info`
83
+ # key.
84
+ def self.action_read_ssh_info
85
+ Vagrant::Action::Builder.new.tap do |b|
86
+ b.use ConfigValidate
87
+ b.use ConnectMCS
88
+ b.use ReadSSHInfo
89
+ end
90
+ end
91
+
92
+ # This action is called to read the state of the machine. The
93
+ # resulting state is expected to be put into the `:machine_state_id`
94
+ # key.
95
+ def self.action_read_state
96
+ Vagrant::Action::Builder.new.tap do |b|
97
+ b.use ConfigValidate
98
+ b.use ConnectMCS
99
+ b.use ReadState
100
+ end
101
+ end
102
+
103
+ # This action is called to SSH into the machine.
104
+ def self.action_ssh
105
+ Vagrant::Action::Builder.new.tap do |b|
106
+ b.use ConfigValidate
107
+ b.use Call, IsCreated do |env, b2|
108
+ if !env[:result]
109
+ b2.use MessageNotCreated
110
+ next
111
+ end
112
+
113
+ b2.use SSHExec
114
+ end
115
+ end
116
+ end
117
+
118
+ def self.action_ssh_run
119
+ Vagrant::Action::Builder.new.tap do |b|
120
+ b.use ConfigValidate
121
+ b.use Call, IsCreated do |env, b2|
122
+ if !env[:result]
123
+ b2.use MessageNotCreated
124
+ next
125
+ end
126
+
127
+ b2.use SSHRun
128
+ end
129
+ end
130
+ end
131
+
132
+ def self.action_prepare_boot
133
+ Vagrant::Action::Builder.new.tap do |b|
134
+ b.use Provision
135
+ b.use SyncedFolders
136
+ b.use WarnNetworks
137
+ b.use ElbRegisterInstance
138
+ end
139
+ end
140
+
141
+ # This action is called to bring the box up from nothing.
142
+ def self.action_up
143
+ Vagrant::Action::Builder.new.tap do |b|
144
+ b.use HandleBox
145
+ b.use ConfigValidate
146
+ b.use BoxCheckOutdated
147
+ b.use ConnectMCS
148
+ b.use Call, IsCreated do |env1, b1|
149
+ if env1[:result]
150
+ b1.use Call, IsStopped do |env2, b2|
151
+ if env2[:result]
152
+ b2.use action_prepare_boot
153
+ b2.use StartInstance # restart this instance
154
+ else
155
+ b2.use MessageAlreadyCreated # TODO write a better message
156
+ end
157
+ end
158
+ else
159
+ b1.use action_prepare_boot
160
+ b1.use RunInstance # launch a new instance
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ def self.action_reload
167
+ Vagrant::Action::Builder.new.tap do |b|
168
+ b.use ConfigValidate
169
+ b.use ConnectMCS
170
+ b.use Call, IsCreated do |env, b2|
171
+ if !env[:result]
172
+ b2.use MessageNotCreated
173
+ next
174
+ end
175
+
176
+ b2.use action_halt
177
+ b2.use Call, WaitForState, :stopped, 120 do |env2, b3|
178
+ if env2[:result]
179
+ b3.use action_up
180
+ else
181
+ # TODO we couldn't reach :stopped, what now?
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ # The autoload farm
189
+ action_root = Pathname.new(File.expand_path("../action", __FILE__))
190
+ autoload :ConnectMCS, action_root.join("connect_mcs")
191
+ autoload :IsCreated, action_root.join("is_created")
192
+ autoload :IsStopped, action_root.join("is_stopped")
193
+ autoload :MessageAlreadyCreated, action_root.join("message_already_created")
194
+ autoload :MessageNotCreated, action_root.join("message_not_created")
195
+ autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy")
196
+ autoload :PackageInstance, action_root.join("package_instance")
197
+ autoload :ReadSSHInfo, action_root.join("read_ssh_info")
198
+ autoload :ReadState, action_root.join("read_state")
199
+ autoload :RunInstance, action_root.join("run_instance")
200
+ autoload :StartInstance, action_root.join("start_instance")
201
+ autoload :StopInstance, action_root.join("stop_instance")
202
+ autoload :TerminateInstance, action_root.join("terminate_instance")
203
+ autoload :TimedProvision, action_root.join("timed_provision") # some plugins now expect this action to exist
204
+ autoload :WaitForState, action_root.join("wait_for_state")
205
+ autoload :WarnNetworks, action_root.join("warn_networks")
206
+ autoload :ElbRegisterInstance, action_root.join("elb_register_instance")
207
+ autoload :ElbDeregisterInstance, action_root.join("elb_deregister_instance")
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,405 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module MCS
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # The access key ID for accessing MCS.
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 MCS 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 MCS api to use
64
+ #
65
+ # @return [String]
66
+ attr_accessor :version
67
+
68
+ # The secret access key for accessing MCS.
69
+ #
70
+ # @return [String]
71
+ attr_accessor :secret_access_key
72
+
73
+ # The secret access url for accessing MCS.
74
+ #
75
+ # @return [String]
76
+ attr_accessor :secret_access_url
77
+
78
+ # The token associated with the key for accessing MCS.
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 MCS 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
+ # mcs.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 MCS 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 MCS environment variables; they
274
+ # will default to nil if the environment variables are not present.
275
+ @access_key_id = ENV['MCS_ACCESS_KEY'] if @access_key_id == UNSET_VALUE
276
+ @secret_access_key = ENV['MCS_SECRET_KEY'] if @secret_access_key == UNSET_VALUE
277
+ @session_token = ENV['MCS_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 MCS
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_mcs.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_mcs.config.access_key_id_required") if \
378
+ config.access_key_id.nil?
379
+ errors << I18n.t("vagrant_mcs.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_mcs.config.subnet_id_required_with_public_ip")
385
+ end
386
+
387
+ errors << I18n.interpolate("vagrant_mcs.config.ami_required", :region => @region) if config.ami.nil?
388
+ end
389
+
390
+ { "MCS 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