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,43 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module AWS
5
+ module Errors
6
+ class VagrantAWSError < Vagrant::Errors::VagrantError
7
+ error_namespace("vagrant_aws.errors")
8
+ end
9
+
10
+ class FogError < VagrantAWSError
11
+ error_key(:fog_error)
12
+ end
13
+
14
+ class InternalFogError < VagrantAWSError
15
+ error_key(:internal_fog_error)
16
+ end
17
+
18
+ class InstanceReadyTimeout < VagrantAWSError
19
+ error_key(:instance_ready_timeout)
20
+ end
21
+
22
+ class InstancePackageError < VagrantAWSError
23
+ error_key(:instance_package_error)
24
+ end
25
+
26
+ class InstancePackageTimeout < VagrantAWSError
27
+ error_key(:instance_package_timeout)
28
+ end
29
+
30
+ class RsyncError < VagrantAWSError
31
+ error_key(:rsync_error)
32
+ end
33
+
34
+ class MkdirError < VagrantAWSError
35
+ error_key(:mkdir_error)
36
+ end
37
+
38
+ class ElbDoesNotExistError < VagrantAWSError
39
+ error_key("elb_does_not_exist")
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,73 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant AWS plugin must be run within Vagrant."
5
+ end
6
+
7
+ # This is a sanity check to make sure no one is attempting to install
8
+ # this into an early Vagrant version.
9
+ if Vagrant::VERSION < "1.2.0"
10
+ raise "The Vagrant AWS plugin is only compatible with Vagrant 1.2+"
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module AWS
15
+ class Plugin < Vagrant.plugin("2")
16
+ name "AWS"
17
+ description <<-DESC
18
+ This plugin installs a provider that allows Vagrant to manage
19
+ machines in AWS (EC2/VPC).
20
+ DESC
21
+
22
+ config(:aws, :provider) do
23
+ require_relative "config"
24
+ Config
25
+ end
26
+
27
+ provider(:aws, parallel: true) do
28
+ # Setup logging and i18n
29
+ setup_logging
30
+ setup_i18n
31
+
32
+ # Return the provider
33
+ require_relative "provider"
34
+ Provider
35
+ end
36
+
37
+ # This initializes the internationalization strings.
38
+ def self.setup_i18n
39
+ I18n.load_path << File.expand_path("locales/en.yml", AWS.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_aws")
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,50 @@
1
+ require "log4r"
2
+ require "vagrant"
3
+
4
+ module VagrantPlugins
5
+ module AWS
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", lock: false)
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", lock: false)
33
+
34
+ state_id = env[:machine_state_id]
35
+
36
+ # Get the short and long description
37
+ short = I18n.t("vagrant_aws.states.short_#{state_id}")
38
+ long = I18n.t("vagrant_aws.states.long_#{state_id}")
39
+
40
+ # Return the MachineState object
41
+ Vagrant::MachineState.new(state_id, short, long)
42
+ end
43
+
44
+ def to_s
45
+ id = @machine.id.nil? ? "new" : @machine.id
46
+ "AWS (#{id})"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ module VagrantPlugins
2
+ module AWS
3
+ module ElasticLoadBalancer
4
+
5
+ def register_instance(env, elb_name, instance_id)
6
+ env[:ui].info I18n.t("vagrant_aws.elb.registering", instance_id: instance_id, elb_name: elb_name), :new_line => false
7
+ elb = get_load_balancer(env[:aws_elb], elb_name)
8
+ unless elb.instances.include? instance_id
9
+ elb.register_instances([instance_id])
10
+ env[:ui].info I18n.t("vagrant_aws.elb.ok"), :prefix => false
11
+ adjust_availability_zones env, elb
12
+ else
13
+ env[:ui].info I18n.t("vagrant_aws.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_aws.elb.deregistering", instance_id: instance_id, elb_name: elb_name), :new_line => false
19
+ elb = get_load_balancer(env[:aws_elb], elb_name)
20
+ if elb.instances.include? instance_id
21
+ elb.deregister_instances([instance_id])
22
+ env[:ui].info I18n.t("vagrant_aws.elb.ok"), :prefix => false
23
+ if env[:machine].provider_config.unregister_elb_from_az
24
+ adjust_availability_zones env, elb
25
+ end
26
+ else
27
+ env[:ui].info I18n.t("vagrant_aws.elb.skipped"), :prefix => false
28
+ end
29
+ end
30
+
31
+ def adjust_availability_zones(env, elb)
32
+ env[:ui].info I18n.t("vagrant_aws.elb.adjusting", elb_name: elb.id), :new_line => false
33
+
34
+ instances = env[:aws_compute].servers.all("instance-id" => elb.instances)
35
+
36
+ azs = if instances.empty?
37
+ ["#{env[:machine].provider_config.region}a"]
38
+ else
39
+ instances.map(&:availability_zone).uniq
40
+ end
41
+
42
+ az_to_disable = elb.availability_zones - azs
43
+ az_to_enable = azs - elb.availability_zones
44
+
45
+ elb.enable_availability_zones az_to_enable unless az_to_enable.empty?
46
+ elb.disable_availability_zones az_to_disable unless az_to_disable.empty?
47
+
48
+ env[:ui].info I18n.t("vagrant_aws.elb.ok"), :prefix => false
49
+ end
50
+
51
+ private
52
+
53
+ def get_load_balancer(aws, name)
54
+ aws.load_balancers.find { |lb| lb.id == name } or raise Errors::ElbDoesNotExistError
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,17 @@
1
+ module VagrantPlugins
2
+ module AWS
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 AWS
3
+ VERSION = '0.7.2'
4
+ end
5
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,159 @@
1
+ en:
2
+ vagrant_aws:
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
+ source_dest_checks_no_vpc: |-
43
+ Warning! Ignoring source_dest_checks flag as it can only be configured on
44
+ a VPC instance.
45
+ starting: |-
46
+ Starting the instance...
47
+ stopping: |-
48
+ Stopping the instance...
49
+ terminating: |-
50
+ Terminating the instance...
51
+ waiting_for_ready: |-
52
+ Waiting for instance to become "ready"...
53
+ waiting_for_ssh: |-
54
+ Waiting for SSH to become available...
55
+ warn_networks: |-
56
+ Warning! The AWS provider doesn't support any of the Vagrant
57
+ high-level network configurations (`config.vm.network`). They
58
+ will be silently ignored.
59
+ warn_ssh_access: |-
60
+ Warning! Vagrant might not be able to SSH into the instance.
61
+ Please check your security groups settings.
62
+ will_not_destroy: |-
63
+ The instance '%{name}' will not be destroyed, since the confirmation
64
+ was declined.
65
+
66
+ config:
67
+ access_key_id_required: |-
68
+ An access key ID must be specified via "access_key_id"
69
+ ami_required: |-
70
+ An AMI must be configured via "ami" (region: #{region})
71
+ private_key_missing: |-
72
+ The specified private key for AWS could not be found
73
+ region_required: |-
74
+ A region must be specified via "region"
75
+ secret_access_key_required: |-
76
+ A secret access key is required via "secret_access_key"
77
+ subnet_id_required_with_public_ip: |-
78
+ If you assign a public IP address to an instance in a VPC, a subnet must be specifed via "subnet_id"
79
+ aws_info_required: |-
80
+ One or more of the needed AWS credentials are missing. No environment variables
81
+ are set nor profile '%{profile}' exists at '%{location}'
82
+
83
+ errors:
84
+ fog_error: |-
85
+ There was an error talking to AWS. The error message is shown
86
+ below:
87
+
88
+ %{message}
89
+ internal_fog_error: |-
90
+ There was an error talking to AWS. The error message is shown
91
+ below:
92
+
93
+ Error: %{error}
94
+ Response: %{response}
95
+ instance_ready_timeout: |-
96
+ The instance never became "ready" in AWS. The timeout currently
97
+ set waiting for the instance to become ready is %{timeout} seconds.
98
+ Please verify that the machine properly boots. If you need more time
99
+ set the `instance_ready_timeout` configuration on the AWS provider.
100
+ instance_package_error: |-
101
+ There was an error packaging the instance. See details below for more info.
102
+
103
+ AMI Id: %{ami_id}
104
+ Error: %{err}
105
+ instance_package_timeout: |-
106
+ The AMI failed to become "ready" in AWS. The timeout currently
107
+ set waiting for the instance to become ready is %{timeout} seconds. For
108
+ larger instances AMI burning may take long periods of time. Please
109
+ ensure the timeout is set high enough, it can be changed by adjusting
110
+ the `instance_package_timeout` configuration on the AWS provider.
111
+ rsync_error: |-
112
+ There was an error when attempting to rsync a shared folder.
113
+ Please inspect the error message below for more info.
114
+
115
+ Host path: %{hostpath}
116
+ Guest path: %{guestpath}
117
+ Error: %{stderr}
118
+ mkdir_error: |-
119
+ There was an error when attempting to create a shared host folder.
120
+ Please inspect the error message below for more info.
121
+
122
+ Host path: %{hostpath}
123
+ Error: %{err}
124
+ elb_does_not_exist: |-
125
+ ELB configured for the instance does not exist
126
+
127
+ states:
128
+ short_not_created: |-
129
+ not created
130
+ long_not_created: |-
131
+ The EC2 instance is not created. Run `vagrant up` to create it.
132
+
133
+ short_stopped: |-
134
+ stopped
135
+ long_stopped: |-
136
+ The EC2 instance is stopped. Run `vagrant up` to start it.
137
+
138
+ short_stopping: |-
139
+ stopping
140
+ long_stopping: |-
141
+ The EC2 instance is stopping. Wait until is completely stopped to
142
+ run `vagrant up` and start it.
143
+
144
+ short_pending: |-
145
+ pending
146
+ long_pending: |-
147
+ The EC2 instance is pending a start (i.e. this is a transition state).
148
+
149
+ short_running: |-
150
+ running
151
+ long_running: |-
152
+ The EC2 instance is running. To stop this machine, you can run
153
+ `vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
154
+
155
+ short_pending: |-
156
+ pending
157
+ long_pending: |-
158
+ The EC2 instance is still being initialized. To destroy this machine,
159
+ you can run `vagrant destroy`.
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,374 @@
1
+ require "vagrant-aws/config"
2
+ require 'rspec/its'
3
+
4
+ # remove deprecation warnings
5
+ # (until someone decides to update the whole spec file to rspec 3.4)
6
+ RSpec.configure do |config|
7
+ # ...
8
+ config.mock_with :rspec do |c|
9
+ c.syntax = [:should, :expect]
10
+ end
11
+ config.expect_with :rspec do |c|
12
+ c.syntax = [:should, :expect]
13
+ end
14
+ end
15
+
16
+ describe VagrantPlugins::AWS::Config do
17
+ let(:instance) { described_class.new }
18
+
19
+ # Ensure tests are not affected by AWS credential environment variables
20
+ before :each do
21
+ ENV.stub(:[] => nil)
22
+ end
23
+
24
+ describe "defaults" do
25
+ subject do
26
+ instance.tap do |o|
27
+ o.finalize!
28
+ end
29
+ end
30
+
31
+ its("access_key_id") { should be_nil }
32
+ its("ami") { should be_nil }
33
+ its("availability_zone") { should be_nil }
34
+ its("instance_ready_timeout") { should == 120 }
35
+ its("instance_check_interval") { should == 2 }
36
+ its("instance_package_timeout") { should == 600 }
37
+ its("instance_type") { should == "m3.medium" }
38
+ its("keypair_name") { should be_nil }
39
+ its("private_ip_address") { should be_nil }
40
+ its("region") { should == "us-east-1" }
41
+ its("secret_access_key") { should be_nil }
42
+ its("session_token") { should be_nil }
43
+ its("security_groups") { should == [] }
44
+ its("subnet_id") { should be_nil }
45
+ its("iam_instance_profile_arn") { should be_nil }
46
+ its("iam_instance_profile_name") { should be_nil }
47
+ its("tags") { should == {} }
48
+ its("package_tags") { should == {} }
49
+ its("user_data") { should be_nil }
50
+ its("use_iam_profile") { should be false }
51
+ its("block_device_mapping") {should == [] }
52
+ its("elastic_ip") { should be_nil }
53
+ its("terminate_on_shutdown") { should == false }
54
+ its("ssh_host_attribute") { should be_nil }
55
+ its("monitoring") { should == false }
56
+ its("ebs_optimized") { should == false }
57
+ its("source_dest_check") { should be_nil }
58
+ its("associate_public_ip") { should == false }
59
+ its("unregister_elb_from_az") { should == true }
60
+ its("tenancy") { should == "default" }
61
+ end
62
+
63
+ describe "overriding defaults" do
64
+ # I typically don't meta-program in tests, but this is a very
65
+ # simple boilerplate test, so I cut corners here. It just sets
66
+ # each of these attributes to "foo" in isolation, and reads the value
67
+ # and asserts the proper result comes back out.
68
+ [:access_key_id, :ami, :availability_zone, :instance_ready_timeout,
69
+ :instance_package_timeout, :instance_type, :keypair_name, :ssh_host_attribute,
70
+ :ebs_optimized, :region, :secret_access_key, :session_token, :monitoring,
71
+ :associate_public_ip, :subnet_id, :tags, :package_tags, :elastic_ip,
72
+ :terminate_on_shutdown, :iam_instance_profile_arn, :iam_instance_profile_name,
73
+ :use_iam_profile, :user_data, :block_device_mapping,
74
+ :source_dest_check].each do |attribute|
75
+
76
+ it "should not default #{attribute} if overridden" do
77
+ # but these should always come together, so you need to set them all or nothing
78
+ instance.send("access_key_id=".to_sym, "foo")
79
+ instance.send("secret_access_key=".to_sym, "foo")
80
+ instance.send("session_token=".to_sym, "foo")
81
+ instance.send("#{attribute}=".to_sym, "foo")
82
+ instance.finalize!
83
+ instance.send(attribute).should == "foo"
84
+ end
85
+ end
86
+ it "should not default security_groups if overridden" do
87
+ instance.security_groups = "foo"
88
+ instance.finalize!
89
+ instance.security_groups.should == ["foo"]
90
+ end
91
+ end
92
+
93
+ describe "getting credentials from environment" do
94
+ context "without EC2 credential environment variables" do
95
+ subject do
96
+ instance.tap do |o|
97
+ o.finalize!
98
+ end
99
+ end
100
+
101
+ its("access_key_id") { should be_nil }
102
+ its("secret_access_key") { should be_nil }
103
+ its("session_token") { should be_nil }
104
+ end
105
+
106
+ context "with EC2 credential environment variables" do
107
+ before :each do
108
+ ENV.stub(:[]).with("AWS_ACCESS_KEY_ID").and_return("access_key")
109
+ ENV.stub(:[]).with("AWS_SECRET_ACCESS_KEY").and_return("secret_key")
110
+ ENV.stub(:[]).with("AWS_SESSION_TOKEN").and_return("session_token")
111
+ end
112
+
113
+ subject do
114
+ instance.tap do |o|
115
+ o.finalize!
116
+ end
117
+ end
118
+
119
+ its("access_key_id") { should == "access_key" }
120
+ its("secret_access_key") { should == "secret_key" }
121
+ its("session_token") { should == "session_token" }
122
+ end
123
+ end
124
+
125
+
126
+ describe "getting credentials when there is an AWS profile" do
127
+ ## ENV has been nuked so ENV['HOME'] will be a empty string when Credentials#get_aws_info gets called
128
+ let(:filename_cfg) { "/.aws/config" }
129
+ let(:filename_keys) { "/.aws/credentials" }
130
+ let(:data_cfg) {
131
+ "[default]
132
+ region=eu-west-1
133
+ output=json
134
+
135
+ [profile user1]
136
+ region=us-east-1
137
+ output=text
138
+
139
+ [profile user2]
140
+ region=us-east-1
141
+ output=text
142
+
143
+ [profile user3]
144
+ region=us-west-2
145
+ output=text
146
+ " }
147
+ let(:data_keys) {
148
+ "[default]
149
+ aws_access_key_id=AKIdefault
150
+ aws_secret_access_key=PASSdefault
151
+
152
+ [user1]
153
+ aws_access_key_id=AKIuser1
154
+ aws_secret_access_key=PASSuser1
155
+
156
+ [user2]
157
+ aws_access_key_id=AKIuser2
158
+ aws_secret_access_key=PASSuser2
159
+ aws_session_token=TOKuser2
160
+
161
+ [user3]
162
+ aws_access_key_id=AKIuser3
163
+ aws_secret_access_key=PASSuser3
164
+ aws_session_token= TOKuser3
165
+ " }
166
+ # filenames and file data when using AWS_SHARED_CREDENTIALS_FILE and AWS_CONFIG_FILE
167
+ let(:sh_dir) { "/aws_shared/" }
168
+ let(:sh_filename_cfg) { sh_dir + "config" }
169
+ let(:sh_filename_keys) { sh_dir + "credentials" }
170
+ let(:sh_data_cfg) { "[default]\nregion=sh-region\noutput=text" }
171
+ let(:sh_data_keys) { "[default]\naws_access_key_id=AKI_set_shared\naws_secret_access_key=set_shared_foobar" }
172
+
173
+ context "with EC2 credential environment variables set" do
174
+ subject do
175
+ ENV.stub(:[]).with("AWS_ACCESS_KEY_ID").and_return("env_access_key")
176
+ ENV.stub(:[]).with("AWS_SECRET_ACCESS_KEY").and_return("env_secret_key")
177
+ ENV.stub(:[]).with("AWS_SESSION_TOKEN").and_return("env_session_token")
178
+ ENV.stub(:[]).with("AWS_DEFAULT_REGION").and_return("env_region")
179
+ allow(File).to receive(:read).with(filename_cfg).and_return(data_cfg)
180
+ allow(File).to receive(:read).with(filename_keys).and_return(data_keys)
181
+ instance.tap do |o|
182
+ o.finalize!
183
+ end
184
+ end
185
+ its("access_key_id") { should == "env_access_key" }
186
+ its("secret_access_key") { should == "env_secret_key" }
187
+ its("session_token") { should == "env_session_token" }
188
+ its("region") { should == "env_region" }
189
+ end
190
+
191
+ context "without EC2 credential environment variables but with AWS_CONFIG_FILE and AWS_SHARED_CREDENTIALS_FILE set" do
192
+ subject do
193
+ allow(File).to receive(:exist?).and_return(true)
194
+ allow(File).to receive(:read).with(filename_cfg).and_return(data_cfg)
195
+ allow(File).to receive(:read).with(filename_keys).and_return(data_keys)
196
+ ENV.stub(:[]).with("AWS_CONFIG_FILE").and_return(sh_filename_cfg)
197
+ ENV.stub(:[]).with("AWS_SHARED_CREDENTIALS_FILE").and_return(sh_filename_keys)
198
+ allow(File).to receive(:read).with(sh_filename_cfg).and_return(sh_data_cfg)
199
+ allow(File).to receive(:read).with(sh_filename_keys).and_return(sh_data_keys)
200
+ instance.tap do |o|
201
+ o.finalize!
202
+ end
203
+ end
204
+ its("access_key_id") { should == "AKI_set_shared" }
205
+ its("secret_access_key") { should == "set_shared_foobar" }
206
+ its("session_token") { should be_nil }
207
+ its("region") { should == "sh-region" }
208
+ end
209
+
210
+ context "without any credential environment variables and fallback to default profile at default location" do
211
+ subject do
212
+ allow(File).to receive(:exist?).and_return(true)
213
+ allow(File).to receive(:read).with(filename_cfg).and_return(data_cfg)
214
+ allow(File).to receive(:read).with(filename_keys).and_return(data_keys)
215
+ instance.tap do |o|
216
+ o.finalize!
217
+ end
218
+ end
219
+ its("access_key_id") { should == "AKIdefault" }
220
+ its("secret_access_key") { should == "PASSdefault" }
221
+ its("session_token") { should be_nil }
222
+ end
223
+
224
+ context "without any credential environment variables and chosing a profile" do
225
+ subject do
226
+ allow(File).to receive(:exist?).and_return(true)
227
+ allow(File).to receive(:read).with(filename_cfg).and_return(data_cfg)
228
+ allow(File).to receive(:read).with(filename_keys).and_return(data_keys)
229
+ instance.aws_profile = "user3"
230
+ instance.tap do |o|
231
+ o.finalize!
232
+ end
233
+ end
234
+ its("access_key_id") { should == "AKIuser3" }
235
+ its("secret_access_key") { should == "PASSuser3" }
236
+ its("session_token") { should == "TOKuser3" }
237
+ its("region") { should == "us-west-2" }
238
+ end
239
+ end
240
+
241
+
242
+
243
+ describe "region config" do
244
+ let(:config_access_key_id) { "foo" }
245
+ let(:config_ami) { "foo" }
246
+ let(:config_instance_type) { "foo" }
247
+ let(:config_keypair_name) { "foo" }
248
+ let(:config_region) { "foo" }
249
+ let(:config_secret_access_key) { "foo" }
250
+ let(:config_session_token) { "foo" }
251
+
252
+ def set_test_values(instance)
253
+ instance.access_key_id = config_access_key_id
254
+ instance.ami = config_ami
255
+ instance.instance_type = config_instance_type
256
+ instance.keypair_name = config_keypair_name
257
+ instance.region = config_region
258
+ instance.secret_access_key = config_secret_access_key
259
+ instance.session_token = config_session_token
260
+ end
261
+
262
+ it "should raise an exception if not finalized" do
263
+ expect { instance.get_region_config("us-east-1") }.
264
+ to raise_error
265
+ end
266
+
267
+ context "with no specific config set" do
268
+ subject do
269
+ # Set the values on the top-level object
270
+ set_test_values(instance)
271
+
272
+ # Finalize so we can get the region config
273
+ instance.finalize!
274
+
275
+ # Get a lower level region
276
+ instance.get_region_config("us-east-1")
277
+ end
278
+
279
+ its("access_key_id") { should == config_access_key_id }
280
+ its("ami") { should == config_ami }
281
+ its("instance_type") { should == config_instance_type }
282
+ its("keypair_name") { should == config_keypair_name }
283
+ its("region") { should == config_region }
284
+ its("secret_access_key") { should == config_secret_access_key }
285
+ its("session_token") { should == config_session_token }
286
+ end
287
+
288
+ context "with a specific config set" do
289
+ let(:region_name) { "hashi-region" }
290
+
291
+ subject do
292
+ # Set the values on a specific region
293
+ instance.region_config region_name do |config|
294
+ set_test_values(config)
295
+ end
296
+
297
+ # Finalize so we can get the region config
298
+ instance.finalize!
299
+
300
+ # Get the region
301
+ instance.get_region_config(region_name)
302
+ end
303
+
304
+ its("access_key_id") { should == config_access_key_id }
305
+ its("ami") { should == config_ami }
306
+ its("instance_type") { should == config_instance_type }
307
+ its("keypair_name") { should == config_keypair_name }
308
+ its("region") { should == region_name }
309
+ its("secret_access_key") { should == config_secret_access_key }
310
+ its("session_token") { should == config_session_token }
311
+ end
312
+
313
+ describe "inheritance of parent config" do
314
+ let(:region_name) { "hashi-region" }
315
+
316
+ subject do
317
+ # Set the values on a specific region
318
+ instance.region_config region_name do |config|
319
+ config.ami = "child"
320
+ end
321
+
322
+ # Set some top-level values
323
+ instance.access_key_id = "parent"
324
+ instance.secret_access_key = "parent"
325
+ instance.ami = "parent"
326
+
327
+ # Finalize and get the region
328
+ instance.finalize!
329
+ instance.get_region_config(region_name)
330
+ end
331
+
332
+ its("access_key_id") { should == "parent" }
333
+ its("secret_access_key") { should == "parent" }
334
+ its("ami") { should == "child" }
335
+ end
336
+
337
+ describe "shortcut configuration" do
338
+ subject do
339
+ # Use the shortcut configuration to set some values
340
+ instance.region_config "us-east-1", :ami => "child"
341
+ instance.finalize!
342
+ instance.get_region_config("us-east-1")
343
+ end
344
+
345
+ its("ami") { should == "child" }
346
+ end
347
+
348
+ describe "merging" do
349
+ let(:first) { described_class.new }
350
+ let(:second) { described_class.new }
351
+
352
+ it "should merge the tags and block_device_mappings" do
353
+ first.tags["one"] = "one"
354
+ second.tags["two"] = "two"
355
+ first.package_tags["three"] = "three"
356
+ second.package_tags["four"] = "four"
357
+ first.block_device_mapping = [{:one => "one"}]
358
+ second.block_device_mapping = [{:two => "two"}]
359
+
360
+ third = first.merge(second)
361
+ third.tags.should == {
362
+ "one" => "one",
363
+ "two" => "two"
364
+ }
365
+ third.package_tags.should == {
366
+ "three" => "three",
367
+ "four" => "four"
368
+ }
369
+ third.block_device_mapping.index({:one => "one"}).should_not be_nil
370
+ third.block_device_mapping.index({:two => "two"}).should_not be_nil
371
+ end
372
+ end
373
+ end
374
+ end