spec/beaker/hypervisor/aws_sdk_spec.rb in beaker-aws-0.4.0 vs spec/beaker/hypervisor/aws_sdk_spec.rb in beaker-aws-0.5.0
- old
+ new
@@ -5,21 +5,24 @@
let( :options ) { make_opts.merge({ 'logger' => double().as_null_object, 'timestamp' => Time.now }) }
let(:aws) {
# Mock out the call to load_fog_credentials
allow_any_instance_of( Beaker::AwsSdk ).
to receive(:load_fog_credentials).
- and_return({
- :access_key => fog_file_contents[:default][:aws_access_key_id],
- :secret_key => fog_file_contents[:default][:aws_secret_access_key],
- :session_token => fog_file_contents[:default][:aws_session_token],
- })
+ and_return(Aws::Credentials.new(
+ fog_file_contents[:default][:aws_access_key_id],
+ fog_file_contents[:default][:aws_secret_access_key],
+ fog_file_contents[:default][:aws_session_token],
+ ))
# This is needed because the EC2 api looks up a local endpoints.json file
FakeFS.deactivate!
aws = Beaker::AwsSdk.new(@hosts, options)
+ aws_partitions_dir = Gem::Specification.find_by_name('aws-partitions').gem_dir
FakeFS.activate!
+ allow(File).to receive(:exist?).with(File.join(aws_partitions_dir, 'partitions.json'))
+ FakeFS::FileSystem.clone(File.join(aws_partitions_dir, 'partitions.json'))
aws
}
let(:amispec) {{
"centos-5-x86-64-west" => {
@@ -57,47 +60,59 @@
context 'loading credentials' do
it 'from .fog file' do
creds = aws.load_fog_credentials
- expect( creds[:access_key] ).to eq("IMANACCESSKEY")
- expect( creds[:secret_key] ).to eq("supersekritkey")
- expect( creds[:session_token] ).to eq('somecrazylongsupersessiontoken!#%^^*(%$^&@$%#!!#$asd;fjapugfrejklvznb;jdgfjiadvij')
+ expect(creds).to have_attributes(
+ :access_key_id => 'IMANACCESSKEY',
+ :secret_access_key => 'supersekritkey',
+ :session_token =>'somecrazylongsupersessiontoken!#%^^*(%$^&@$%#!!#$asd;fjapugfrejklvznb;jdgfjiadvij',
+ )
end
it 'from environment variables' do
ENV['AWS_ACCESS_KEY_ID'] = "IMANACCESSKEY"
ENV['AWS_SECRET_ACCESS_KEY'] = "supersekritkey"
creds = aws.load_env_credentials
- expect( creds[:access_key] ).to eq("IMANACCESSKEY")
- expect( creds[:secret_key] ).to eq("supersekritkey")
- expect( creds[:session_token] ).to be_nil
+ expect(creds).to have_attributes(
+ :access_key_id => "IMANACCESSKEY",
+ :secret_access_key => "supersekritkey",
+ :session_token => nil,
+ )
end
it 'from environment variables with session_token' do
ENV['AWS_ACCESS_KEY_ID'] = "IMANACCESSKEY"
ENV['AWS_SECRET_ACCESS_KEY'] = "supersekritkey"
ENV['AWS_SESSION_TOKEN'] = 'somesuperlongsessiontokenspecialcharsblah!#%$#@$^!@qewpofudjsvjm'
creds = aws.load_env_credentials
- expect( creds[:access_key] ).to eq("IMANACCESSKEY")
- expect( creds[:secret_key] ).to eq("supersekritkey")
- expect( creds[:session_token] ).to eq('somesuperlongsessiontokenspecialcharsblah!#%$#@$^!@qewpofudjsvjm')
+ expect(creds).to have_attributes(
+ :access_key_id => "IMANACCESSKEY",
+ :secret_access_key => "supersekritkey",
+ :session_token => 'somesuperlongsessiontokenspecialcharsblah!#%$#@$^!@qewpofudjsvjm',
+ )
end
end
context 'dont read fog credentials' do
let(:options) { make_opts.merge({ 'use_fog_credentials' => false }) }
+ before(:each) do
+ ENV.delete('AWS_ACCESS_KEY_ID')
+ end
+
it 'not using fog' do
creds = aws.load_env_credentials
- expect( creds[:access_key] ).to eq(nil)
- expect( creds[:secret_key] ).to eq(nil)
- expect( options[:use_fog_credentials] ).to eq(false)
+ expect(creds).to have_attributes(
+ :access_key_id => nil,
+ :secret_access_key => nil,
+ )
+ expect(options[:use_fog_credentials]).to eq(false)
end
end
describe '#provision' do
before :each do
@@ -119,16 +134,34 @@
expect(aws.provision).to be_nil
end
end
describe '#kill_instances' do
- let( :ec2_instance ) { double('ec2_instance', :nil? => false, :exists? => true, :id => "ec2", :terminate => nil) }
- let( :vpc_instance ) { double('vpc_instance', :nil? => false, :exists? => true, :id => "vpc", :terminate => nil) }
- let( :nil_instance ) { double('vpc_instance', :nil? => true, :exists? => true, :id => "nil", :terminate => nil) }
- let( :unreal_instance ) { double('vpc_instance', :nil? => false, :exists? => false, :id => "unreal", :terminate => nil) }
+ def mock_instance(id, state)
+ instance_double(
+ Aws::EC2::Types::Instance,
+ :state => instance_double(Aws::EC2::Types::InstanceState, :name => state),
+ :instance_id => id,
+ )
+ end
+
+ let(:ec2_instance) { mock_instance('ec2', 'running') }
+ let(:vpc_instance) { mock_instance('vpc', 'running') }
+ let(:nil_instance) { nil }
+ let(:unreal_instance) { mock_instance('unreal', 'terminated') }
+
subject(:kill_instances) { aws.kill_instances(instance_set) }
+ let(:mock_client) { instance_double(Aws::EC2::Client, :terminate_instances => nil) }
+ before(:each) do
+ allow(aws).to receive(:client).and_return(mock_client)
+ allow(aws).to receive(:instance_by_id).with('ec2').and_return(ec2_instance)
+ allow(aws).to receive(:instance_by_id).with('vpc').and_return(vpc_instance)
+ allow(aws).to receive(:instance_by_id).with('nil').and_return(nil_instance)
+ allow(aws).to receive(:instance_by_id).with('unreal').and_return(unreal_instance)
+ end
+
it 'should return nil' do
instance_set = [ec2_instance, vpc_instance, nil_instance, unreal_instance]
expect(aws.kill_instances(instance_set)).to be_nil
end
@@ -136,115 +169,99 @@
instance_set = []
expect(aws.kill_instances(instance_set)).to be_nil
end
context 'in general use' do
- let( :instance_set ) { [ec2_instance, vpc_instance] }
+ let( :instance_set ) { [ec2_instance, nil_instance, vpc_instance] }
it 'terminates each running instance' do
- instance_set.each do |instance|
- expect(instance).to receive(:terminate).once
- end
- expect(kill_instances).to be_nil
- end
+ expect(mock_client).to receive(:terminate_instances).with(
+ :instance_ids => [ec2_instance.instance_id, vpc_instance.instance_id],
+ )
- it 'verifies instances are not nil' do
- instance_set.each do |instance|
- expect(instance).to receive(:nil?)
- allow(instance).to receive(:terminate).once
- end
expect(kill_instances).to be_nil
end
it 'verifies instances exist in AWS' do
- instance_set.each do |instance|
- expect(instance).to receive(:exists?)
- allow(instance).to receive(:terminate).once
+ instance_set.compact.each do |instance|
+ expect(aws).to receive(:instance_by_id).with(instance.instance_id)
end
+
expect(kill_instances).to be_nil
end
end
context 'for a single running instance' do
let( :instance_set ) { [ec2_instance] }
it 'terminates the running instance' do
- instance_set.each do |instance|
- expect(instance).to receive(:terminate).once
- end
- expect(kill_instances).to be_nil
- end
+ expect(mock_client).to receive(:terminate_instances).with(
+ :instance_ids => [ec2_instance.instance_id],
+ )
- it 'verifies instance is not nil' do
- instance_set.each do |instance|
- expect(instance).to receive(:nil?)
- allow(instance).to receive(:terminate).once
- end
expect(kill_instances).to be_nil
end
it 'verifies instance exists in AWS' do
instance_set.each do |instance|
- expect(instance).to receive(:exists?)
- allow(instance).to receive(:terminate).once
+ expected_state = instance_double(Aws::EC2::Types::InstanceState, :name => 'running')
+ expect(instance).to receive(:state).and_return(expected_state)
end
+
+ expect(mock_client).to receive(:terminate_instances).with(
+ :instance_ids => [ec2_instance.instance_id],
+ )
+
expect(kill_instances).to be_nil
end
end
context 'when an instance does not exist' do
let( :instance_set ) { [unreal_instance] }
it 'does not call terminate' do
- instance_set.each do |instance|
- expect(instance).to receive(:terminate).exactly(0).times
- end
+ expect(mock_client).not_to receive(:terminate_instances)
expect(kill_instances).to be_nil
end
it 'verifies instance does not exist' do
instance_set.each do |instance|
- expect(instance).to receive(:exists?).once
- allow(instance).to receive(:terminate).exactly(0).times
+ expected_state = instance_double(Aws::EC2::Types::InstanceState, :name => 'terminated')
+ expect(instance).to receive(:state).and_return(expected_state)
end
+
+ expect(mock_client).not_to receive(:terminate_instances)
expect(kill_instances).to be_nil
end
end
context 'when an instance is nil' do
- let( :instance_set ) { [nil_instance] }
+ let(:instance_set) { [nil_instance] }
it 'does not call terminate' do
- instance_set.each do |instance|
- expect(instance).to receive(:terminate).exactly(0).times
- end
- expect(kill_instances).to be_nil
- end
+ expect(mock_client).not_to receive(:terminate_instances)
- it 'verifies instance is nil' do
- instance_set.each do |instance|
- expect(instance).to receive(:nil?).once
- allow(instance).to receive(:terminate).exactly(0).times
- end
expect(kill_instances).to be_nil
end
end
-
end
describe '#cleanup' do
subject(:cleanup) { aws.cleanup }
- let( :ec2_instance ) { double('ec2_instance', :nil? => false, :exists? => true, :terminate => nil, :id => 'id') }
+ let(:ec2_instance) do
+ instance_double(Aws::EC2::Types::Instance,
+ :instance_id => 'id',
+ :state => instance_double(Aws::EC2::Types::InstanceState, :name => 'running'),
+ )
+ end
context 'with a list of hosts' do
before :each do
- @hosts.each {|host| host['instance'] = ec2_instance}
- expect(aws).to receive( :delete_key_pair_all_regions )
+ @hosts.each { |host| host['instance'] = ec2_instance }
+ expect(aws).to receive(:delete_key_pair_all_regions)
end
- it { is_expected.to be_nil }
-
it 'kills instances' do
expect(aws).to receive(:kill_instances).once
expect(cleanup).to be_nil
end
end
@@ -253,61 +270,46 @@
before :each do
@hosts = []
expect(aws).to receive( :delete_key_pair_all_regions )
end
- it { is_expected.to be_nil }
-
it 'kills instances' do
expect(aws).to receive(:kill_instances).once
expect(cleanup).to be_nil
end
end
end
describe '#log_instances', :wip do
end
- describe '#instance_by_id' do
- subject { aws.instance_by_id('my_id') }
- it { is_expected.to be_instance_of(AWS::EC2::Instance) }
+ describe '#instance_by_id', :wip do
end
- describe '#instances' do
- subject { aws.instances }
- it { is_expected.to be_instance_of(AWS::EC2::InstanceCollection) }
+ describe '#instances', :wip do
end
- describe '#vpc_by_id' do
- subject { aws.vpc_by_id('my_id') }
- it { is_expected.to be_instance_of(AWS::EC2::VPC) }
+ describe '#vpc_by_id', :wip do
end
- describe '#vpcs' do
- subject { aws.vpcs }
- it { is_expected.to be_instance_of(AWS::EC2::VPCCollection) }
+ describe '#vpcs', :wip do
end
- describe '#security_group_by_id' do
- subject { aws.security_group_by_id('my_id') }
- it { is_expected.to be_instance_of(AWS::EC2::SecurityGroup) }
+ describe '#security_group_by_id', :wip do
end
- describe '#security_groups' do
- subject { aws.security_groups }
- it { is_expected.to be_instance_of(AWS::EC2::SecurityGroupCollection) }
+ describe '#security_groups', :wip do
end
describe '#kill_zombies' do
it 'calls delete_key_pair_all_regions' do
- ec2_mock = Object.new
- allow(ec2_mock).to receive( :regions ).and_return( {} )
- aws.instance_variable_set( :@ec2, ec2_mock )
+ allow(aws).to receive(:regions).and_return([])
- expect( aws ).to receive( :delete_key_pair_all_regions ).once
+ expect(aws).to receive(:kill_instances).once
+ expect(aws).to receive(:delete_key_pair_all_regions).once
- aws.kill_zombies()
+ aws.kill_zombies
end
end
describe '#kill_zombie_volumes', :wip do
end
@@ -320,204 +322,290 @@
describe '#launch_all_nodes', :wip do
end
describe '#wait_for_status' do
- let( :aws_instance ) { double('aws_instance', :id => "ec2", :terminate => nil) }
- let( :instance_set ) { [{:instance => aws_instance}] }
+ let( :aws_instance ) { instance_double(Aws::EC2::Types::Instance, :instance_id => "ec2") }
+ let( :instance_set ) { [{:instance => aws_instance, :host => instance_double(Beaker::Host, :name => 'test')}] }
subject(:wait_for_status) { aws.wait_for_status(:running, instance_set) }
+ def mock_instance(state, other = {})
+ r = instance_double(
+ Aws::EC2::Types::Instance,
+ :instance_id => 'ec2',
+ :state => instance_double(Aws::EC2::Types::InstanceState, :name => state),
+ )
+
+ other.each do |k, v|
+ allow(r).to receive(:[]).with(k).and_return(v)
+ end
+
+ r
+ end
+
context 'single instance' do
it 'behaves correctly in typical case' do
- allow(aws_instance).to receive(:status).and_return(:waiting, :waiting, :running)
+ allow(aws).to receive(:instance_by_id).with('ec2').and_return(mock_instance(:waiting), mock_instance(:waiting), mock_instance(:running))
expect(aws).to receive(:backoff_sleep).exactly(3).times
expect(wait_for_status).to eq(instance_set)
end
it 'executes block correctly instead of status if given one' do
barn_value = 'did you grow up in a barn?'
- allow(aws_instance).to receive( :[] ).with( :barn ) { barn_value }
- expect(aws_instance).to receive(:status).exactly(0).times
+ expect(aws).to receive(:instance_by_id).and_return(mock_instance(:running, :barn => barn_value))
expect(aws).to receive(:backoff_sleep).exactly(1).times
aws.wait_for_status(:running, instance_set) do |instance|
expect( instance[:barn] ).to be === barn_value
true
end
end
end
context 'with multiple instances' do
- let( :instance_set ) { [{:instance => aws_instance}, {:instance => aws_instance}] }
+ let(:instance_set) do
+ [
+ { :instance => aws_instance, :host => instance_double(Beaker::Host, :name => 'test1') },
+ { :instance => aws_instance, :host => instance_double(Beaker::Host, :name => 'test2') },
+ ]
+ end
it 'returns the instance set passed to it' do
- allow(aws_instance).to receive(:status).and_return(:waiting, :waiting, :running, :waiting, :waiting, :running)
+ allow(aws).to receive(:instance_by_id).and_return(
+ mock_instance(:waiting),
+ mock_instance(:waiting),
+ mock_instance(:running),
+ mock_instance(:waiting),
+ mock_instance(:waiting),
+ mock_instance(:running)
+ )
allow(aws).to receive(:backoff_sleep).exactly(6).times
expect(wait_for_status).to eq(instance_set)
end
it 'calls backoff_sleep once per instance.status call' do
- allow(aws_instance).to receive(:status).and_return(:waiting, :waiting, :running, :waiting, :waiting, :running)
+ allow(aws).to receive(:instance_by_id).and_return(
+ mock_instance(:waiting),
+ mock_instance(:waiting),
+ mock_instance(:running),
+ mock_instance(:waiting),
+ mock_instance(:waiting),
+ mock_instance(:running),
+ )
expect(aws).to receive(:backoff_sleep).exactly(6).times
expect(wait_for_status).to eq(instance_set)
end
it 'executes block correctly instead of status if given one' do
barn_value = 'did you grow up in a barn?'
not_barn_value = 'notabarn'
allow(aws_instance).to receive( :[] ).with( :barn ).and_return(not_barn_value, barn_value, not_barn_value, barn_value)
- allow(aws_instance).to receive(:status).and_return(:waiting)
+ allow(aws).to receive(:instance_by_id).and_return(
+ mock_instance(:waiting, :barn => not_barn_value),
+ mock_instance(:waiting, :barn => barn_value),
+ mock_instance(:waiting, :barn => not_barn_value),
+ mock_instance(:waiting, :barn => barn_value),
+ )
expect(aws).to receive(:backoff_sleep).exactly(4).times
aws.wait_for_status(:running, instance_set) do |instance|
instance[:barn] == barn_value
end
end
end
context 'after 10 tries' do
it 'raises RuntimeError' do
- expect(aws_instance).to receive(:status).and_return(:waiting).exactly(10).times
+ expect(aws).to receive(:instance_by_id).and_return(mock_instance(:waiting)).exactly(10).times
expect(aws).to receive(:backoff_sleep).exactly(9).times
expect { wait_for_status }.to raise_error('Instance never reached state running')
end
it 'still raises RuntimeError if given a block' do
- expect(aws_instance).to receive(:status).and_return(:waiting).exactly(10).times
+ expect(aws).to receive(:instance_by_id).and_return(mock_instance(:waiting)).exactly(10).times
expect(aws).to receive(:backoff_sleep).exactly(9).times
expect { wait_for_status { false } }.to raise_error('Instance never reached state running')
end
end
-
- context 'with an invalid instance' do
- it 'raises AWS::EC2::Errors::InvalidInstanceID::NotFound' do
- expect(aws_instance).to receive(:status).and_raise(AWS::EC2::Errors::InvalidInstanceID::NotFound).exactly(10).times
- allow(aws).to receive(:backoff_sleep).at_most(10).times
- expect(wait_for_status).to eq(instance_set)
- end
- end
end
describe '#add_tags' do
- let( :aws_instance ) { double('aws_instance', :add_tag => nil) }
+ let(:aws_instance) { instance_double(Aws::EC2::Types::Instance, :instance_id => 'id-123') }
+ let(:mock_client) { instance_double(Aws::EC2::Client) }
+
subject(:add_tags) { aws.add_tags }
+ before(:each) do
+ allow(aws).to receive(:client).and_return(mock_client)
+ allow(mock_client).to receive(:create_tags)
+ end
+
it 'returns nil' do
@hosts.each {|host| host['instance'] = aws_instance}
expect(add_tags).to be_nil
end
- it 'handles a single host' do
- @hosts[0]['instance'] = aws_instance
- @hosts = [@hosts[0]]
- expect(add_tags).to be_nil
- end
-
context 'with multiple hosts' do
before :each do
- @hosts.each {|host| host['instance'] = aws_instance}
+ @hosts.each_with_index do |host, i|
+ host['instance'] = instance_double(Aws::EC2::Types::Instance, :instance_id => "id-#{i}")
+ end
end
it 'handles host_tags hash on host object' do
# set :host_tags on first host
- aws.instance_eval {
- @hosts[0][:host_tags] = {'test_tag' => 'test_value'}
- }
- expect(aws_instance).to receive(:add_tag).with('test_tag', hash_including(:value => 'test_value')).at_least(:once)
+ @hosts[0][:host_tags] = {'test_tag' => 'test_value'}
+
+ expect(mock_client).to receive(:create_tags).with(
+ :resources => [@hosts[0]['instance'].instance_id],
+ :tags => include(
+ {
+ :key => 'test_tag',
+ :value => 'test_value',
+ },
+ ),
+ ).once
+
expect(add_tags).to be_nil
end
it 'adds tag for jenkins_build_url' do
aws.instance_eval('@options[:jenkins_build_url] = "my_build_url"')
- expect(aws_instance).to receive(:add_tag).with('jenkins_build_url', hash_including(:value => 'my_build_url')).at_least(:once)
+
+ expect(mock_client).to receive(:create_tags).with(
+ :resources => anything,
+ :tags => include(
+ {
+ :key => 'jenkins_build_url',
+ :value => 'my_build_url',
+ },
+ ),
+ ).at_least(:once)
+
expect(add_tags).to be_nil
end
it 'adds tag for Name' do
- expect(aws_instance).to receive(:add_tag).with('Name', hash_including(:value => /vm/)).at_least(@hosts.size).times
+ expect(mock_client).to receive(:create_tags).with(
+ :resources => anything,
+ :tags => include(
+ {
+ :key => 'Name',
+ :value => a_string_matching(/vm/),
+ },
+ ),
+ ).at_least(:once)
+
expect(add_tags).to be_nil
end
it 'adds tag for department' do
aws.instance_eval('@options[:department] = "my_department"')
- expect(aws_instance).to receive(:add_tag).with('department', hash_including(:value => 'my_department')).at_least(:once)
+
+ expect(mock_client).to receive(:create_tags).with(
+ :resources => anything,
+ :tags => include(
+ {
+ :key => 'department',
+ :value => 'my_department',
+ },
+ ),
+ ).at_least(:once)
+
expect(add_tags).to be_nil
end
it 'adds tag for project' do
aws.instance_eval('@options[:project] = "my_project"')
- expect(aws_instance).to receive(:add_tag).with('project', hash_including(:value => 'my_project')).at_least(:once)
+
+ expect(mock_client).to receive(:create_tags).with(
+ :resources => anything,
+ :tags => include(
+ {
+ :key => 'project',
+ :value => 'my_project',
+ },
+ ),
+ ).at_least(:once)
+
expect(add_tags).to be_nil
end
it 'adds tag for created_by' do
aws.instance_eval('@options[:created_by] = "my_created_by"')
- expect(aws_instance).to receive(:add_tag).with('created_by', hash_including(:value => 'my_created_by')).at_least(:once)
+
+ expect(mock_client).to receive(:create_tags).with(
+ :resources => anything,
+ :tags => include(
+ {
+ :key => 'created_by',
+ :value => 'my_created_by',
+ },
+ ),
+ ).at_least(:once)
+
expect(add_tags).to be_nil
end
end
end
describe '#populate_dns' do
- let( :vpc_instance ) { {ip_address: nil, private_ip_address: "vpc_private_ip", dns_name: "vpc_dns_name"} }
- let( :ec2_instance ) { {ip_address: "ec2_public_ip", private_ip_address: "ec2_private_ip", dns_name: "ec2_dns_name"} }
+ let( :vpc_instance ) do
+ instance_double(Aws::EC2::Types::Instance, public_ip_address: nil, private_ip_address: "vpc_private_ip", public_dns_name: "vpc_dns_name")
+ end
+ let( :ec2_instance ) do
+ instance_double(Aws::EC2::Types::Instance, public_ip_address: "ec2_public_ip", private_ip_address: "ec2_private_ip", public_dns_name: "ec2_dns_name")
+ end
subject(:populate_dns) { aws.populate_dns }
+ subject(:hosts) { aws.instance_variable_get(:@hosts) }
context 'on a public EC2 instance' do
before :each do
- @hosts.each {|host| host['instance'] = make_instance ec2_instance}
- end
+ @hosts.each { |host| host['instance'] = ec2_instance }
- it 'sets host ip to instance.ip_address' do
populate_dns
- hosts = aws.instance_variable_get( :@hosts )
+ end
+
+ it 'sets host ip to instance.public_ip_address' do
hosts.each do |host|
- expect(host['ip']).to eql(ec2_instance[:ip_address])
+ expect(host['ip']).to eql(ec2_instance.public_ip_address)
end
end
it 'sets host private_ip to instance.private_ip_address' do
- populate_dns
- hosts = aws.instance_variable_get( :@hosts )
hosts.each do |host|
- expect(host['private_ip']).to eql(ec2_instance[:private_ip_address])
+ expect(host['private_ip']).to eql(ec2_instance.private_ip_address)
end
end
- it 'sets host dns_name to instance.dns_name' do
- populate_dns
- hosts = aws.instance_variable_get( :@hosts )
+ it 'sets host dns_name to instance.public_dns_name' do
hosts.each do |host|
- expect(host['dns_name']).to eql(ec2_instance[:dns_name])
+ expect(host['dns_name']).to eql(ec2_instance.public_dns_name)
end
end
end
context 'on a VPC based instance' do
before :each do
- @hosts.each {|host| host['instance'] = make_instance vpc_instance}
+ @hosts.each { |host| host['instance'] = vpc_instance }
+
+ populate_dns
end
it 'sets host ip to instance.private_ip_address' do
- populate_dns
- hosts = aws.instance_variable_get( :@hosts )
hosts.each do |host|
- expect(host['ip']).to eql(vpc_instance[:private_ip_address])
+ expect(host['ip']).to eql(vpc_instance.private_ip_address)
end
end
it 'sets host private_ip to instance.private_ip_address' do
- populate_dns
- hosts = aws.instance_variable_get( :@hosts )
hosts.each do |host|
- expect(host['private_ip']).to eql(vpc_instance[:private_ip_address])
+ expect(host['private_ip']).to eql(vpc_instance.private_ip_address)
end
end
- it 'sets host dns_name to instance.dns_name' do
- populate_dns
- hosts = aws.instance_variable_get( :@hosts )
+ it 'sets host dns_name to instance.public_dns_name' do
hosts.each do |host|
- expect(host['dns_name']).to eql(vpc_instance[:dns_name])
+ expect(host['dns_name']).to eql(vpc_instance.public_dns_name)
end
end
end
end
@@ -606,17 +694,15 @@
expect{ enable_root_f5 }.to raise_error( RuntimeError, /unable/ )
end
end
describe '#enable_root_netscaler' do
- let( :ns_host ) { @hosts[5] }
+ let(:ns_host) { @hosts[5] }
subject(:enable_root_netscaler) { aws.enable_root_netscaler(ns_host) }
it 'set password to instance id of the host' do
- instance_mock = Object.new
- allow( instance_mock ).to receive(:id).and_return("i-842018")
- ns_host["instance"]=instance_mock
+ ns_host["instance"] = instance_double(Aws::EC2::Types::Instance, :instance_id => 'i-842018')
enable_root_netscaler
expect(ns_host['ssh'][:password]).to eql("i-842018")
end
end
@@ -699,10 +785,12 @@
expect(public_key).to be === key_value
end
it "should return an error if the files do not exist" do
+ allow(File).to receive(:exist?).with(/id_[dr]sa.pub/) { false }
+ allow(File).to receive(:exist?).with(/id_[dr]sa/) { false }
expect { public_key }.to raise_error(RuntimeError, /Expected to find a public key/)
end
it "uses options-provided keys" do
opts = aws.instance_variable_get( :@options )
@@ -759,128 +847,137 @@
ensure_key_pair
end
end
describe '#delete_key_pair_all_regions' do
- it 'calls delete_key_pair over all regions' do
- key_name = 'kname_test1538'
- allow(aws).to receive( :key_name ).and_return(key_name)
- regions = []
- regions << double('region', :key_pairs => 'pair1', :name => 'name1')
- regions << double('region', :key_pairs => 'pair2', :name => 'name2')
- ec2_mock = Object.new
- allow(ec2_mock).to receive( :regions ).and_return(regions)
- aws.instance_variable_set( :@ec2, ec2_mock )
- region_keypairs_hash_mock = {}
- region_keypairs_hash_mock[double('region')] = ['key1', 'key2', 'key3']
- region_keypairs_hash_mock[double('region')] = ['key4', 'key5', 'key6']
- allow( aws ).to receive( :my_key_pairs ).and_return( region_keypairs_hash_mock )
+ before(:each) do
+ allow(aws).to receive(:my_key_pairs).and_return(region_keypairs)
+ end
- region_keypairs_hash_mock.each_pair do |region, keyname_array|
+ after(:each) do
+ aws.delete_key_pair_all_regions
+ end
+
+ let(:region_keypairs) do
+ {
+ 'test1' => ['key1', 'key2', 'key3'],
+ 'test2' => ['key4', 'key5', 'key6'],
+ }
+ end
+
+ it 'calls delete_key_pair over all regions' do
+ region_keypairs.each do |region, keyname_array|
keyname_array.each do |keyname|
- expect( aws ).to receive( :delete_key_pair ).with( region, keyname )
+ expect(aws).to receive(:delete_key_pair).with(region, keyname)
end
end
- aws.delete_key_pair_all_regions
end
end
describe '#my_key_pairs' do
- let( :region ) { double('region', :name => 'test_region_name') }
+ let(:regions) { ['name1', 'name2'] }
+ let(:mock_clients) { regions.map { |r| [r, instance_double(Aws::EC2::Client)] }.to_h }
+ let(:default_key_name) { 'test_pair_6193' }
- it 'uses the default keyname if no filter is given' do
- default_keyname_answer = 'test_pair_6193'
- allow( aws ).to receive( :key_name ).and_return( default_keyname_answer )
+ before(:each) do
+ allow(aws).to receive(:regions).and_return(regions)
+ allow(aws).to receive(:key_name).and_return(default_key_name)
- kp_mock_1 = double('keypair')
- kp_mock_2 = double('keypair')
- regions = []
- regions << double('region', :key_pairs => kp_mock_1, :name => 'name1')
- regions << double('region', :key_pairs => kp_mock_2, :name => 'name2')
- ec2_mock = Object.new
- allow( ec2_mock ).to receive( :regions ).and_return( regions )
- aws.instance_variable_set( :@ec2, ec2_mock )
+ regions.each do |region|
+ allow(aws).to receive(:client).with(region).and_return(mock_clients[region])
+ end
+ end
- kp_mock = double('keypair')
- allow( region ).to receive( :key_pairs ).and_return( kp_mock )
- expect( kp_mock_1 ).to receive( :filter ).with( 'key-name', default_keyname_answer ).and_return( [] )
- expect( kp_mock_2 ).to receive( :filter ).with( 'key-name', default_keyname_answer ).and_return( [] )
+ it 'uses the default keyname if no filter is given' do
+ regions.each do |region|
+ expect(mock_clients[region]).to receive(:describe_key_pairs).with(
+ :filters => [{ :name => 'key-name', :values => [default_key_name] }]
+ ).and_return(instance_double(Aws::EC2::Types::DescribeKeyPairsResult, :key_pairs => []))
+ end
aws.my_key_pairs()
end
it 'uses the filter passed if given' do
- default_keyname_answer = 'test_pair_6194'
- allow( aws ).to receive( :key_name ).and_return( default_keyname_answer )
name_filter = 'filter_pair_1597'
- filter_star = "#{name_filter}-*"
+ filter_pattern = "#{name_filter}-*"
- kp_mock_1 = double('keypair')
- kp_mock_2 = double('keypair')
- regions = []
- regions << double('region', :key_pairs => kp_mock_1, :name => 'name1')
- regions << double('region', :key_pairs => kp_mock_2, :name => 'name2')
- ec2_mock = Object.new
- allow( ec2_mock ).to receive( :regions ).and_return( regions )
- aws.instance_variable_set( :@ec2, ec2_mock )
+ regions.each do |region|
+ expect(mock_clients[region]).to receive(:describe_key_pairs).with(
+ :filters => [{ :name => 'key-name', :values => [filter_pattern] }]
+ ).and_return(instance_double(Aws::EC2::Types::DescribeKeyPairsResult, :key_pairs => []))
+ end
- kp_mock = double('keypair')
- allow( region ).to receive( :key_pairs ).and_return( kp_mock )
- expect( kp_mock_1 ).to receive( :filter ).with( 'key-name', filter_star ).and_return( [] )
- expect( kp_mock_2 ).to receive( :filter ).with( 'key-name', filter_star ).and_return( [] )
-
aws.my_key_pairs(name_filter)
end
end
describe '#delete_key_pair' do
- let( :region ) { double('region', :name => 'test_region_name') }
+ let(:region) { 'test_region_name' }
+ let(:mock_client) { instance_double(Aws::EC2::Client) }
+ let(:pair_name) { 'pair1' }
- it 'calls delete on a keypair if it exists' do
- pair_name = 'pair1'
- kp_mock = double('keypair', :exists? => true)
- expect( kp_mock ).to receive( :delete ).once
- pairs = { pair_name => kp_mock }
- allow( region ).to receive( :key_pairs ).and_return( pairs )
- aws.delete_key_pair(region, pair_name)
+ before(:each) do
+ allow(aws).to receive(:client).with(region).and_return(mock_client)
+ allow(mock_client).to receive(:describe_key_pairs).with(
+ :key_names => [pair_name]
+ ).and_return(instance_double(Aws::EC2::Types::DescribeKeyPairsResult, :key_pairs => result))
end
- it 'skips delete on a keypair if it does not exist' do
- pair_name = 'pair1'
- kp_mock = double('keypair', :exists? => false)
- expect( kp_mock ).to receive( :delete ).never
- pairs = { pair_name => kp_mock }
- allow( region ).to receive( :key_pairs ).and_return( pairs )
+ after(:each) do
aws.delete_key_pair(region, pair_name)
end
+
+ context 'when the keypair exists' do
+ let(:result) { [instance_double(Aws::EC2::Types::KeyPairInfo)] }
+
+ it 'deletes the keypair' do
+ expect(mock_client).to receive(:delete_key_pair).with(:key_name => pair_name)
+ end
+ end
+
+ context 'when the keypair does not exist' do
+ let(:result) { [] }
+
+ it 'does not try to delete the keypair' do
+ expect(mock_client).not_to receive(:delete_key_pair)
+ end
+ end
end
describe '#create_new_key_pair' do
- let(:region) { double('region', :name => 'test_region_name') }
+ let(:region) { 'test_region_name' }
let(:ssh_string) { 'ssh_string_test_0867' }
- let(:pairs) { double('keypairs') }
- let(:pair) { double('keypair') }
+ let(:pair) { instance_double(Aws::EC2::Types::KeyPairInfo) }
let(:pair_name) { 'pair_name_1555432' }
+ let(:mock_client) { instance_double(Aws::EC2::Client) }
before :each do
+ allow(aws).to receive(:client).with(region).and_return(mock_client)
allow(aws).to receive(:public_key).and_return(ssh_string)
- expect(pairs).to receive(:import).with(pair_name, ssh_string)
- expect(pairs).to receive(:[]).with(pair_name).and_return(pair)
- expect(region).to receive(:key_pairs).and_return(pairs).twice
+ allow(mock_client).to receive(:import_key_pair).with(
+ :key_name => pair_name,
+ :public_key_material => ssh_string,
+ )
+ allow(mock_client).to receive(:wait_until).with(:key_pair_exists, any_args)
end
it 'imports the key given from public_key' do
- expect(pair).to receive(:exists?).and_return(true)
+ expect(mock_client).to receive(:import_key_pair).with(
+ :key_name => pair_name,
+ :public_key_material => ssh_string,
+ )
+
aws.create_new_key_pair(region, pair_name)
end
it 'raises an exception if subsequent keypair check is false' do
- expect(pair).to receive(:exists?).and_return(false).exactly(5).times
- expect(aws).to receive(:backoff_sleep).exactly(5).times
- expect { aws.create_new_key_pair(region, pair_name) }.
- to raise_error(RuntimeError,
- "AWS key pair #{pair_name} can not be queried, even after import")
+ allow(mock_client).to receive(:wait_until).with(:key_pair_exists, any_args).and_raise(Aws::Waiters::Errors::WaiterFailed)
+ expect {
+ aws.create_new_key_pair(region, pair_name)
+ }.to raise_error(RuntimeError,
+ "AWS key pair #{pair_name} can not be queried, even after import")
end
end
describe '#group_id' do
it 'should return a predicatable group_id from a port list' do
@@ -891,109 +988,121 @@
expect { aws.group_id([]) }.to raise_error(ArgumentError, "Ports list cannot be nil or empty")
end
end
describe '#ensure_group' do
- let( :vpc ) { double('vpc') }
- let( :ports ) { [22, 80, 8080] }
+ let(:vpc) { instance_double(Aws::EC2::Types::Vpc, :vpc_id => 1) }
+ let(:ports) { [22, 80, 8080] }
subject(:ensure_group) { aws.ensure_group(vpc, ports) }
+ let(:mock_client) { instance_double(Aws::EC2::Client) }
+
+ before :each do
+ allow(aws).to receive(:client).and_return(mock_client)
+ end
+
+ let(:security_group_result) do
+ instance_double(Aws::EC2::Types::DescribeSecurityGroupsResult, :security_groups => [group])
+ end
+
context 'for an existing group' do
- before :each do
- @group = double(:nil? => false)
- end
+ let(:group) { instance_double(Aws::EC2::Types::SecurityGroup, :group_name => 'Beaker-1521896090') }
it 'returns group from vpc lookup' do
- expect(vpc).to receive_message_chain('security_groups.filter.first').and_return(@group)
- expect(ensure_group).to eq(@group)
+ allow(mock_client).to receive(:describe_security_groups).with(any_args).and_return(security_group_result)
+ expect(ensure_group).to eq(group)
end
context 'during group lookup' do
it 'performs group_id lookup for ports' do
expect(aws).to receive(:group_id).with(ports)
- expect(vpc).to receive_message_chain('security_groups.filter.first').and_return(@group)
- expect(ensure_group).to eq(@group)
+ allow(mock_client).to receive(:describe_security_groups).with(any_args).and_return(security_group_result)
+ expect(ensure_group).to eq(group)
end
it 'filters on group_id' do
- expect(vpc).to receive(:security_groups).and_return(vpc)
- expect(vpc).to receive(:filter).with('group-name', 'Beaker-1521896090').and_return(vpc)
- expect(vpc).to receive(:first).and_return(@group)
- expect(ensure_group).to eq(@group)
+ allow(mock_client).to receive(:describe_security_groups).with(:filters => include({:name => 'group-name', :values => ['Beaker-1521896090']})).and_return(security_group_result)
+ expect(ensure_group).to eq(group)
end
end
end
context 'when group does not exist' do
+ let(:group) { nil }
+
it 'creates group if group.nil?' do
- group = double(:nil? => true)
expect(aws).to receive(:create_group).with(vpc, ports).and_return(group)
- expect(vpc).to receive_message_chain('security_groups.filter.first').and_return(group)
+ allow(mock_client).to receive(:describe_security_groups).with(any_args).and_return(security_group_result)
expect(ensure_group).to eq(group)
end
end
end
describe '#create_group' do
- let( :rv ) { double('rv') }
- let( :ports ) { [22, 80, 8080] }
+ let(:rv) { double('rv') }
+ let(:ports) { [22, 80, 8080] }
subject(:create_group) { aws.create_group(rv, ports) }
- before :each do
- @group = double(:nil? => false)
+ let(:group) { instance_double(Aws::EC2::Types::SecurityGroup, :group_id => 1) }
+ let(:mock_client) { instance_double(Aws::EC2::Client) }
+
+ before(:each) do
+ allow(aws).to receive(:client).and_return(mock_client)
end
it 'returns a newly created group' do
- allow(rv).to receive_message_chain('security_groups.create').and_return(@group)
- allow(@group).to receive(:authorize_ingress).at_least(:once)
- expect(create_group).to eq(@group)
+ allow(mock_client).to receive(:create_security_group).with(any_args).and_return(group)
+ allow(mock_client).to receive(:authorize_security_group_ingress).with(include(:group_id => group.group_id)).at_least(:once)
+ expect(create_group).to eq(group)
end
it 'requests group_id for ports given' do
expect(aws).to receive(:group_id).with(ports)
- allow(rv).to receive_message_chain('security_groups.create').and_return(@group)
- allow(@group).to receive(:authorize_ingress).at_least(:once)
- expect(create_group).to eq(@group)
+ allow(mock_client).to receive(:create_security_group).with(any_args).and_return(group)
+ allow(mock_client).to receive(:authorize_security_group_ingress).with(include(:group_id => group.group_id)).at_least(:once)
+ expect(create_group).to eq(group)
end
it 'creates group with expected arguments' do
group_name = "Beaker-1521896090"
group_desc = "Custom Beaker security group for #{ports.to_a}"
- expect(rv).to receive_message_chain('security_groups.create')
- .with(group_name, :description => group_desc)
- .and_return(@group)
- allow(@group).to receive(:authorize_ingress).at_least(:once)
- expect(create_group).to eq(@group)
+ expect(mock_client).to receive(:create_security_group).with(
+ :group_name => group_name,
+ :description => group_desc,
+ ).and_return(group)
+ allow(mock_client).to receive(:authorize_security_group_ingress).with(include(:group_id => group.group_id)).at_least(:once)
+ expect(create_group).to eq(group)
end
it 'authorizes requested ports for group' do
- expect(rv).to receive_message_chain('security_groups.create').and_return(@group)
+ allow(mock_client).to receive(:create_security_group).with(any_args).and_return(group)
+
ports.each do |port|
- expect(@group).to receive(:authorize_ingress).with(:tcp, port).once
+ expect(mock_client).to receive(:authorize_security_group_ingress).with(include(:to_port => port)).once
end
- expect(create_group).to eq(@group)
+ expect(create_group).to eq(group)
end
end
describe '#load_fog_credentials' do
# Receive#and_call_original below allows us to test the core load_fog_credentials method
let(:dot_fog) { '.fog' }
subject(:load_fog_credentials) { aws.load_fog_credentials(dot_fog) }
it 'returns loaded fog credentials' do
- creds = {:access_key => 'awskey', :secret_key => 'awspass', :session_token => nil}
+ creds = {:access_key_id => 'awskey', :secret_access_key => 'awspass', :session_token => nil}
fog_hash = {:default => {:aws_access_key_id => 'awskey', :aws_secret_access_key => 'awspass'}}
expect(aws).to receive(:load_fog_credentials).and_call_original
expect(YAML).to receive(:load_file).and_return(fog_hash)
- expect(load_fog_credentials).to eq(creds)
+ expect(load_fog_credentials).to have_attributes(creds)
end
it 'returns loaded fog credentials with session token' do
- creds = {:access_key => 'awskey', :secret_key => 'awspass', :session_token => 'sometoken'}
+ creds = {:access_key_id => 'awskey', :secret_access_key => 'awspass', :session_token => 'sometoken'}
fog_hash = {:default => {:aws_access_key_id => 'awskey', :aws_secret_access_key => 'awspass', :aws_session_token => 'sometoken'}}
expect(aws).to receive(:load_fog_credentials).and_call_original
expect(YAML).to receive(:load_file).and_return(fog_hash)
- expect(load_fog_credentials).to eq(creds)
+ expect(load_fog_credentials).to have_attributes(creds)
end
context 'raises errors' do
it 'if missing access_key credential' do
fog_hash = {:default => {:aws_secret_access_key => 'awspass'}}