vagrant-mos 0.8.39

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 +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,43 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module MOS
5
+ module Errors
6
+ class VagrantMOSError < Vagrant::Errors::VagrantError
7
+ error_namespace("vagrant_mos.errors")
8
+ end
9
+
10
+ class FogError < VagrantMOSError
11
+ error_key(:fog_error)
12
+ end
13
+
14
+ class InternalFogError < VagrantMOSError
15
+ error_key(:internal_fog_error)
16
+ end
17
+
18
+ class InstanceReadyTimeout < VagrantMOSError
19
+ error_key(:instance_ready_timeout)
20
+ end
21
+
22
+ class InstancePackageError < VagrantMOSError
23
+ error_key(:instance_package_error)
24
+ end
25
+
26
+ class InstancePackageTimeout < VagrantMOSError
27
+ error_key(:instance_package_timeout)
28
+ end
29
+
30
+ class RsyncError < VagrantMOSError
31
+ error_key(:rsync_error)
32
+ end
33
+
34
+ class MkdirError < VagrantMOSError
35
+ error_key(:mkdir_error)
36
+ end
37
+
38
+ class ElbDoesNotExistError < VagrantMOSError
39
+ error_key("elb_does_not_exist")
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,73 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant MOS 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 MOS plugin is only compatible with Vagrant 1.2+"
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module MOS
15
+ class Plugin < Vagrant.plugin("2")
16
+ name "MOS"
17
+ description <<-DESC
18
+ This plugin installs a provider that allows Vagrant to manage
19
+ machines in MOS.
20
+ DESC
21
+
22
+ config(:mos, :provider) do
23
+ require_relative "config"
24
+ Config
25
+ end
26
+
27
+ provider(:mos, 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
+ # This initializes the internationalization strings.
38
+ def self.setup_i18n
39
+ I18n.load_path << File.expand_path("locales/en.yml", MOS.source_root)
40
+ I18n.reload!
41
+ end
42
+
43
+ # This sets up our log level to be whatever VAGRANT_LOG is.
44
+ def self.setup_logging
45
+ require "log4r"
46
+
47
+ level = nil
48
+ begin
49
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
50
+ rescue NameError
51
+ # This means that the logging constant wasn't found,
52
+ # which is fine. We just keep `level` as `nil`. But
53
+ # we tell the user.
54
+ level = nil
55
+ end
56
+
57
+ # Some constants, such as "true" resolve to booleans, so the
58
+ # above error checking doesn't catch it. This will check to make
59
+ # sure that the log level is an integer, as Log4r requires.
60
+ level = nil if !level.is_a?(Integer)
61
+
62
+ # Set the logging level on all "vagrant" namespaced
63
+ # logs as long as we have a valid level.
64
+ if level
65
+ logger = Log4r::Logger.new("vagrant_mos")
66
+ logger.outputters = Log4r::Outputter.stderr
67
+ logger.level = level
68
+ logger = nil
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,53 @@
1
+ require "log4r"
2
+ require "vagrant"
3
+
4
+ module VagrantPlugins
5
+ module MOS
6
+ class Provider < Vagrant.plugin("2", :provider)
7
+ def initialize(machine)
8
+ @machine = machine
9
+ end
10
+
11
+ def action(name)
12
+ # Attempt to get the action method from the Action class if it
13
+ # exists, otherwise return nil to show that we don't support the
14
+ # given action.
15
+ action_method = "action_#{name}"
16
+ return Action.send(action_method) if Action.respond_to?(action_method)
17
+ nil
18
+ end
19
+
20
+ def ssh_info
21
+ # Run a custom action called "read_ssh_info" which does what it
22
+ # says and puts the resulting SSH info into the `:machine_ssh_info`
23
+ # key in the environment.
24
+ env = @machine.action("read_ssh_info")
25
+ env[:machine_ssh_info]
26
+ end
27
+
28
+ def state
29
+ # Run a custom action we define called "read_state" which does
30
+ # what it says. It puts the state in the `:machine_state_id`
31
+ # key in the environment.
32
+ env = @machine.action("read_state")
33
+
34
+ state_id = env[:machine_state_id]
35
+ #if(state_id == "ready")
36
+ # state_id = "stopped"
37
+ #end
38
+
39
+ # Get the short and long description
40
+ short = I18n.t("vagrant_mos.states.short_#{state_id}")
41
+ long = I18n.t("vagrant_mos.states.long_#{state_id}")
42
+
43
+ # Return the MachineState object
44
+ Vagrant::MachineState.new(state_id, short, long)
45
+ end
46
+
47
+ def to_s
48
+ id = @machine.id.nil? ? "new" : @machine.id
49
+ "MOS (#{id})"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,56 @@
1
+ module VagrantPlugins
2
+ module MOS
3
+ module ElasticLoadBalancer
4
+
5
+ def register_instance(env, elb_name, instance_id)
6
+ env[:ui].info I18n.t("vagrant_mos.elb.registering", instance_id: instance_id, elb_name: elb_name), :new_line => false
7
+ elb = get_load_balancer(env[:mos_elb], elb_name)
8
+ unless elb.instances.include? instance_id
9
+ elb.register_instances([instance_id])
10
+ env[:ui].info I18n.t("vagrant_mos.elb.ok"), :prefix => false
11
+ adjust_availability_zones env, elb
12
+ else
13
+ env[:ui].info I18n.t("vagrant_mos.elb.skipped"), :prefix => false
14
+ end
15
+ end
16
+
17
+ def deregister_instance(env, elb_name, instance_id)
18
+ env[:ui].info I18n.t("vagrant_mos.elb.deregistering", instance_id: instance_id, elb_name: elb_name), :new_line => false
19
+ elb = get_load_balancer(env[:mos_elb], elb_name)
20
+ if elb.instances.include? instance_id
21
+ elb.deregister_instances([instance_id])
22
+ env[:ui].info I18n.t("vagrant_mos.elb.ok"), :prefix => false
23
+ adjust_availability_zones env, elb
24
+ else
25
+ env[:ui].info I18n.t("vagrant_mos.elb.skipped"), :prefix => false
26
+ end
27
+ end
28
+
29
+ def adjust_availability_zones(env, elb)
30
+ env[:ui].info I18n.t("vagrant_mos.elb.adjusting", elb_name: elb.id), :new_line => false
31
+
32
+ instances = env[:mos_compute].servers.all("instance-id" => elb.instances)
33
+
34
+ azs = if instances.empty?
35
+ ["#{env[:machine].provider_config.region}a"]
36
+ else
37
+ instances.map(&:availability_zone).uniq
38
+ end
39
+
40
+ az_to_disable = elb.availability_zones - azs
41
+ az_to_enable = azs - elb.availability_zones
42
+
43
+ elb.enable_availability_zones az_to_enable unless az_to_enable.empty?
44
+ elb.disable_availability_zones az_to_disable unless az_to_disable.empty?
45
+
46
+ env[:ui].info I18n.t("vagrant_mos.elb.ok"), :prefix => false
47
+ end
48
+
49
+ private
50
+
51
+ def get_load_balancer(mos, name)
52
+ mos.load_balancers.find { |lb| lb.id == name } or raise Errors::ElbDoesNotExistError
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,17 @@
1
+ module VagrantPlugins
2
+ module MOS
3
+ module Util
4
+ class Timer
5
+ # A basic utility method that times the execution of the given
6
+ # block and returns it.
7
+ def self.time
8
+ start_time = Time.now.to_f
9
+ yield
10
+ end_time = Time.now.to_f
11
+
12
+ end_time - start_time
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module MOS
3
+ VERSION = '0.8.39'
4
+ end
5
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,153 @@
1
+ en:
2
+ vagrant_mos:
3
+ already_status: |-
4
+ The machine is already %{status}.
5
+ burning_ami: |-
6
+ Waiting for the AMI '%{ami_id}' to burn...
7
+ elb:
8
+ adjusting: |-
9
+ Adjusting availability zones of ELB %{elb_name}...
10
+ registering: |-
11
+ Registering %{instance_id} at ELB %{elb_name}...
12
+ deregistering: |-
13
+ Deregistering %{instance_id} from ELB %{elb_name}...
14
+ ok: |-
15
+ ok
16
+ skipped: |-
17
+ skipped
18
+
19
+ launching_instance: |-
20
+ Launching an instance with the following settings...
21
+ launch_no_keypair: |-
22
+ Warning! You didn't specify a keypair to launch your instance with.
23
+ This can sometimes result in not being able to access your instance.
24
+ launch_vpc_warning: |-
25
+ Warning! You're launching this instance into a VPC without an
26
+ elastic IP. Please verify you're properly connected to a VPN so
27
+ you can access this machine, otherwise Vagrant will not be able
28
+ to SSH into it.
29
+ not_created: |-
30
+ Instance is not created. Please run `vagrant up` first.
31
+ packaging_instance: |-
32
+ Burning instance %{instance_id} into an ami
33
+ packaging_instance_complete: |-
34
+ Burn was successful in %{time_seconds}s
35
+ ready: |-
36
+ Machine is booted and ready for use!
37
+ rsync_not_found_warning: |-
38
+ Warning! Folder sync disabled because the rsync binary is missing in the %{side}.
39
+ Make sure rsync is installed and the binary can be found in the PATH.
40
+ rsync_folder: |-
41
+ Rsyncing folder: %{hostpath} => %{guestpath}
42
+ starting: |-
43
+ Starting the instance...
44
+ stopping: |-
45
+ Stopping the instance...
46
+ terminating: |-
47
+ Terminating the instance...
48
+ waiting_for_ready: |-
49
+ Waiting for instance to become "ready"...
50
+ waiting_for_ssh: |-
51
+ Waiting for SSH to become available...
52
+ warn_networks: |-
53
+ Warning! The MOS provider doesn't support any of the Vagrant
54
+ high-level network configurations (`config.vm.network`). They
55
+ will be silently ignored.
56
+ warn_ssh_access: |-
57
+ Warning! Vagrant might not be able to SSH into the instance.
58
+ Please check your security groups settings.
59
+ will_not_destroy: |-
60
+ The instance '%{name}' will not be destroyed, since the confirmation
61
+ was declined.
62
+
63
+ config:
64
+ access_key_id_required: |-
65
+ An access key ID must be specified via "access_key_id"
66
+ ami_required: |-
67
+ An AMI must be configured via "ami" (region: #{region})
68
+ private_key_missing: |-
69
+ The specified private key for MOS could not be found
70
+ region_required: |-
71
+ A region must be specified via "region"
72
+ secret_access_key_required: |-
73
+ A secret access key is required via "secret_access_key"
74
+ subnet_id_required_with_public_ip: |-
75
+ If you assign a public IP address to an instance in a VPC, a subnet must be specifed via "subnet_id"
76
+
77
+ errors:
78
+ fog_error: |-
79
+ There was an error talking to MOS. The error message is shown
80
+ below:
81
+
82
+ %{message}
83
+ internal_fog_error: |-
84
+ There was an error talking to MOS. The error message is shown
85
+ below:
86
+
87
+ Error: %{error}
88
+ Response: %{response}
89
+ instance_ready_timeout: |-
90
+ The instance never became "ready" in MOS. The timeout currently
91
+ set waiting for the instance to become ready is %{timeout} seconds.
92
+ Please verify that the machine properly boots. If you need more time
93
+ set the `instance_ready_timeout` configuration on the MOS provider.
94
+ instance_package_error: |-
95
+ There was an error packaging the instance. See details below for more info.
96
+
97
+ AMI Id: %{ami_id}
98
+ Error: %{err}
99
+ instance_package_timeout: |-
100
+ The AMI failed to become "ready" in MOS. The timeout currently
101
+ set waiting for the instance to become ready is %{timeout} seconds. For
102
+ larger instances AMI burning may take long periods of time. Please
103
+ ensure the timeout is set high enough, it can be changed by adjusting
104
+ the `instance_package_timeout` configuration on the MOS provider.
105
+ rsync_error: |-
106
+ There was an error when attempting to rsync a shared folder.
107
+ Please inspect the error message below for more info.
108
+
109
+ Host path: %{hostpath}
110
+ Guest path: %{guestpath}
111
+ Error: %{stderr}
112
+ mkdir_error: |-
113
+ There was an error when attempting to create a shared host folder.
114
+ Please inspect the error message below for more info.
115
+
116
+ Host path: %{hostpath}
117
+ Error: %{err}
118
+ elb_does_not_exist: |-
119
+ ELB configured for the instance does not exist
120
+
121
+ states:
122
+ short_not_created: |-
123
+ not created
124
+ long_not_created: |-
125
+ The MOS instance is not created. Run `vagrant up` to create it.
126
+
127
+ short_ready: |-
128
+ stopped
129
+ long_ready: |-
130
+ The MOS instance is stopped. Run `vagrant up` to start it.
131
+
132
+ short_stopping: |-
133
+ stopping
134
+ long_stopping: |-
135
+ The MOS instance is stopping. Wait until is completely stopped to
136
+ run `vagrant up` and start it.
137
+
138
+ short_pending: |-
139
+ pending
140
+ long_pending: |-
141
+ The MOS instance is pending a start (i.e. this is a transition state).
142
+
143
+ short_running: |-
144
+ running
145
+ long_running: |-
146
+ The MOS instance is running. To stop this machine, you can run
147
+ `vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
148
+
149
+ short_pending: |-
150
+ pending
151
+ long_pending: |-
152
+ The MOS instance is still being initialized. To destroy this machine,
153
+ you can run `vagrant destroy`.
data/mos.box ADDED
Binary file
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,225 @@
1
+ require "vagrant-mos/config"
2
+
3
+ describe VagrantPlugins::MOS::Config do
4
+ let(:instance) { described_class.new }
5
+
6
+ # Ensure tests are not affected by MOS credential environment variables
7
+ before :each do
8
+ ENV.stub(:[] => nil)
9
+ end
10
+
11
+ describe "defaults" do
12
+ subject do
13
+ instance.tap do |o|
14
+ o.finalize!
15
+ end
16
+ end
17
+
18
+ its("access_key_id") { should be_nil }
19
+ its("ami") { should be_nil }
20
+ its("availability_zone") { should be_nil }
21
+ its("instance_ready_timeout") { should == 120 }
22
+ its("instance_package_timeout") { should == 600 }
23
+ its("instance_type") { should == "m3.medium" }
24
+ its("keypair_name") { should be_nil }
25
+ its("private_ip_address") { should be_nil }
26
+ its("region") { should == "us-east-1" }
27
+ its("secret_access_key") { should be_nil }
28
+ its("session_token") { should be_nil }
29
+ its("security_groups") { should == [] }
30
+ its("subnet_id") { should be_nil }
31
+ its("iam_instance_profile_arn") { should be_nil }
32
+ its("iam_instance_profile_name") { should be_nil }
33
+ its("tags") { should == {} }
34
+ its("user_data") { should be_nil }
35
+ its("use_iam_profile") { should be_false }
36
+ its("block_device_mapping") {should == [] }
37
+ its("elastic_ip") { should be_nil }
38
+ its("terminate_on_shutdown") { should == false }
39
+ its("ssh_host_attribute") { should be_nil }
40
+ its("monitoring") { should == false }
41
+ its("ebs_optimized") { should == false }
42
+ its("associate_public_ip") { should == false }
43
+ end
44
+
45
+ describe "overriding defaults" do
46
+ # I typically don't meta-program in tests, but this is a very
47
+ # simple boilerplate test, so I cut corners here. It just sets
48
+ # each of these attributes to "foo" in isolation, and reads the value
49
+ # and asserts the proper result comes back out.
50
+ [:access_key_id, :ami, :availability_zone, :instance_ready_timeout,
51
+ :instance_package_timeout, :instance_type, :keypair_name, :ssh_host_attribute,
52
+ :ebs_optimized, :region, :secret_access_key, :session_token, :monitoring,
53
+ :associate_public_ip, :subnet_id, :tags, :elastic_ip, :terminate_on_shutdown,
54
+ :iam_instance_profile_arn, :iam_instance_profile_name,
55
+ :use_iam_profile, :user_data, :block_device_mapping].each do |attribute|
56
+
57
+ it "should not default #{attribute} if overridden" do
58
+ instance.send("#{attribute}=".to_sym, "foo")
59
+ instance.finalize!
60
+ instance.send(attribute).should == "foo"
61
+ end
62
+ end
63
+ it "should not default security_groups if overridden" do
64
+ instance.security_groups = "foo"
65
+ instance.finalize!
66
+ instance.security_groups.should == ["foo"]
67
+ end
68
+ end
69
+
70
+ describe "getting credentials from environment" do
71
+ context "without EC2 credential environment variables" do
72
+ subject do
73
+ instance.tap do |o|
74
+ o.finalize!
75
+ end
76
+ end
77
+
78
+ its("access_key_id") { should be_nil }
79
+ its("secret_access_key") { should be_nil }
80
+ its("session_token") { should be_nil }
81
+ end
82
+
83
+ context "with EC2 credential environment variables" do
84
+ before :each do
85
+ ENV.stub(:[]).with("MOS_ACCESS_KEY").and_return("access_key")
86
+ ENV.stub(:[]).with("MOS_SECRET_KEY").and_return("secret_key")
87
+ ENV.stub(:[]).with("MOS_SESSION_TOKEN").and_return("session_token")
88
+ end
89
+
90
+ subject do
91
+ instance.tap do |o|
92
+ o.finalize!
93
+ end
94
+ end
95
+
96
+ its("access_key_id") { should == "access_key" }
97
+ its("secret_access_key") { should == "secret_key" }
98
+ its("session_token") { should == "session_token" }
99
+ end
100
+ end
101
+
102
+ describe "region config" do
103
+ let(:config_access_key_id) { "foo" }
104
+ let(:config_ami) { "foo" }
105
+ let(:config_instance_type) { "foo" }
106
+ let(:config_keypair_name) { "foo" }
107
+ let(:config_region) { "foo" }
108
+ let(:config_secret_access_key) { "foo" }
109
+ let(:config_session_token) { "foo" }
110
+
111
+ def set_test_values(instance)
112
+ instance.access_key_id = config_access_key_id
113
+ instance.ami = config_ami
114
+ instance.instance_type = config_instance_type
115
+ instance.keypair_name = config_keypair_name
116
+ instance.region = config_region
117
+ instance.secret_access_key = config_secret_access_key
118
+ instance.session_token = config_session_token
119
+ end
120
+
121
+ it "should raise an exception if not finalized" do
122
+ expect { instance.get_region_config("us-east-1") }.
123
+ to raise_error
124
+ end
125
+
126
+ context "with no specific config set" do
127
+ subject do
128
+ # Set the values on the top-level object
129
+ set_test_values(instance)
130
+
131
+ # Finalize so we can get the region config
132
+ instance.finalize!
133
+
134
+ # Get a lower level region
135
+ instance.get_region_config("us-east-1")
136
+ end
137
+
138
+ its("access_key_id") { should == config_access_key_id }
139
+ its("ami") { should == config_ami }
140
+ its("instance_type") { should == config_instance_type }
141
+ its("keypair_name") { should == config_keypair_name }
142
+ its("region") { should == config_region }
143
+ its("secret_access_key") { should == config_secret_access_key }
144
+ its("session_token") { should == config_session_token }
145
+ end
146
+
147
+ context "with a specific config set" do
148
+ let(:region_name) { "hashi-region" }
149
+
150
+ subject do
151
+ # Set the values on a specific region
152
+ instance.region_config region_name do |config|
153
+ set_test_values(config)
154
+ end
155
+
156
+ # Finalize so we can get the region config
157
+ instance.finalize!
158
+
159
+ # Get the region
160
+ instance.get_region_config(region_name)
161
+ end
162
+
163
+ its("access_key_id") { should == config_access_key_id }
164
+ its("ami") { should == config_ami }
165
+ its("instance_type") { should == config_instance_type }
166
+ its("keypair_name") { should == config_keypair_name }
167
+ its("region") { should == region_name }
168
+ its("secret_access_key") { should == config_secret_access_key }
169
+ its("session_token") { should == config_session_token }
170
+ end
171
+
172
+ describe "inheritance of parent config" do
173
+ let(:region_name) { "hashi-region" }
174
+
175
+ subject do
176
+ # Set the values on a specific region
177
+ instance.region_config region_name do |config|
178
+ config.ami = "child"
179
+ end
180
+
181
+ # Set some top-level values
182
+ instance.access_key_id = "parent"
183
+ instance.ami = "parent"
184
+
185
+ # Finalize and get the region
186
+ instance.finalize!
187
+ instance.get_region_config(region_name)
188
+ end
189
+
190
+ its("access_key_id") { should == "parent" }
191
+ its("ami") { should == "child" }
192
+ end
193
+
194
+ describe "shortcut configuration" do
195
+ subject do
196
+ # Use the shortcut configuration to set some values
197
+ instance.region_config "us-east-1", :ami => "child"
198
+ instance.finalize!
199
+ instance.get_region_config("us-east-1")
200
+ end
201
+
202
+ its("ami") { should == "child" }
203
+ end
204
+
205
+ describe "merging" do
206
+ let(:first) { described_class.new }
207
+ let(:second) { described_class.new }
208
+
209
+ it "should merge the tags and block_device_mappings" do
210
+ first.tags["one"] = "one"
211
+ second.tags["two"] = "two"
212
+ first.block_device_mapping = [{:one => "one"}]
213
+ second.block_device_mapping = [{:two => "two"}]
214
+
215
+ third = first.merge(second)
216
+ third.tags.should == {
217
+ "one" => "one",
218
+ "two" => "two"
219
+ }
220
+ third.block_device_mapping.index({:one => "one"}).should_not be_nil
221
+ third.block_device_mapping.index({:two => "two"}).should_not be_nil
222
+ end
223
+ end
224
+ end
225
+ end