vmpooler-provider-ec2/spec/unit/providers/ec2_spec.rb
2022-07-27 10:19:22 -05:00

339 lines
9.7 KiB
Ruby

require 'spec_helper'
require 'mock_redis'
require 'ec2_helper'
require 'vmpooler/providers/ec2'
RSpec::Matchers.define :relocation_spec_with_host do |value|
match { |actual| actual[:spec].host == value }
end
describe 'Vmpooler::PoolManager::Provider::Ec2' do
let(:logger) { MockLogger.new }
let(:metrics) { Vmpooler::Metrics::DummyStatsd.new }
let(:poolname) { 'debian-9' }
let(:provider_options) { { 'param' => 'value' } }
let(:zone) { 'us-west-2b' }
let(:region) { 'us-west-2'}
let(:config) { YAML.load(<<~EOT
---
:config:
max_tries: 3
retry_factor: 10
:providers:
:ec2:
connection_pool_timeout: 1
zone: '#{zone}'
region: '#{region}'
:pools:
- name: '#{poolname}'
alias: [ 'mockpool' ]
amisize: 'a1.large'
template: 'ami-03c1b544a7566b3e5'
size: 5
timeout: 10
ready_ttl: 1440
provider: 'ec2'
EOT
)
}
let(:vmname) { 'vm17' }
let(:connection) { MockComputeServiceConnection.new }
let(:redis_connection_pool) do
Vmpooler::PoolManager::GenericConnectionPool.new(
metrics: metrics,
connpool_type: 'redis_connection_pool',
connpool_provider: 'testprovider',
size: 1,
timeout: 5
) { MockRedis.new }
end
subject { Vmpooler::PoolManager::Provider::Ec2.new(config, logger, metrics, redis_connection_pool, 'ec2', provider_options) }
describe '#manual tests live' do
context 'in itsysops' do
let(:vmname) { "instance-60" }
let(:poolname) { "amazon-7-x86_64-local" }
let(:amisize) { "c5.xlarge" }
let(:config) { YAML.load(<<~EOT
---
:config:
max_tries: 3
retry_factor: 10
site_name: 'vmpooler-local-dev'
:providers:
:ec2:
connection_pool_timeout: 1
zone: '#{zone}'
region: '#{region}'
project: 'vmpooler-test'
dns_zone_resource_name: 'vmpooler-test-puppet-net'
domain: 'vmpooler-test.puppet.net'
:pools:
- name: '#{poolname}'
alias: [ 'mockpool' ]
amisize: '#{amisize}'
template: 'ami-31394949'
size: 5
timeout: 10
ready_ttl: 1440
provider: 'ec2'
provision: 'true'
EOT
)
}
before(:each) {
allow(subject).to receive(:dns).and_call_original
}
skip 'gets a vm' do
result = subject.create_vm(poolname, vmname)
result = subject.destroy_vm(poolname, vmname)
#subject.vms_in_pool("amazon-6-x86_64-ec2")
#subject.provision_node_aws("ip-10-227-4-97.amz-dev.puppet.net", poolname)
# subject.create_snapshot(poolname, vmname, "foo")
#subject.create_disk(poolname, vmname, 10)
# a = subject.destroy_vm(poolname, vmname)
# b = subject.get_vm(poolname, vmname)
puts "done"
# subject.dns_teardown({'name' => vmname})
# subject.dns_setup({'name' => vmname, 'ip' => '1.2.3.5'})
end
end
end
describe '#vms_in_pool' do
let(:pool_config) { config[:pools][0] }
before(:each) do
allow(subject).to receive(:connect_to_aws).and_return(connection)
end
context 'Given an empty pool folder' do
it 'should return an empty array' do
allow(connection).to receive(:instances).and_return([nil])
result = subject.vms_in_pool(poolname)
expect(result).to eq([])
end
end
context 'Given a pool with many VMs' do
let(:expected_vm_list) do
[
{ 'name' => 'vm1' },
{ 'name' => 'vm2' },
{ 'name' => 'vm3' }
]
end
before(:each) do
instance_list = []
expected_vm_list.each do |vm_hash|
tags = [MockTag.new(key: "vm_name", value: vm_hash['name'])]
mock_vm = MockInstance.new(tags: tags)
instance_list << mock_vm
end
expect(connection).to receive(:instances).and_return(instance_list)
end
it 'should list all VMs in the VM folder for the pool' do
result = subject.vms_in_pool(poolname)
expect(result).to eq(expected_vm_list)
end
end
end
describe '#get_vm' do
before(:each) do
allow(subject).to receive(:connect_to_aws).and_return(connection)
end
context 'when VM does not exist' do
it 'should return nil' do
allow(connection).to receive(:instances).and_return([nil])
expect(subject.get_vm(poolname, vmname)).to be_nil
end
end
context 'when VM exists but is missing information' do
before(:each) do
tags = [MockTag.new(key: "vm_name", value: vmname)]
allow(connection).to receive(:instances).and_return([MockInstance.new(tags: tags)])
end
it 'should return a hash' do
expect(subject.get_vm(poolname, vmname)).to be_kind_of(Hash)
end
it 'should return the VM name' do
result = subject.get_vm(poolname, vmname)
expect(result['name']).to eq(vmname)
end
%w[boottime image_size status private_ip_address].each do |testcase|
it "should return nil for #{testcase}" do
result = subject.get_vm(poolname, vmname)
expect(result[testcase]).to be_nil
end
end
end
context 'when VM exists and contains all information' do
let(:vm_hostname) { "#{vmname}.demo.local" }
let(:boot_time) { Time.now }
let(:vm_object) do
state = Struct.new(:name)
runningstate = state.new "running"
MockInstance.new(
launch_time: boot_time,
state: runningstate,
instance_type: "a1.large",
private_ip_address: "1.1.1.1",
tags: [
MockTag.new(key: "vm_name", value: vmname),
MockTag.new(key: "pool", value: poolname)
]
)
end
let(:pool_info) { config[:pools][0] }
before(:each) do
allow(connection).to receive(:instances).and_return([vm_object])
end
it 'should return a hash' do
expect(subject.get_vm(poolname, vmname)).to be_kind_of(Hash)
end
it 'should return the VM name' do
result = subject.get_vm(poolname, vmname)
expect(result['name']).to eq(vmname)
end
it 'should return the template name' do
result = subject.get_vm(poolname, vmname)
expect(result['template']).to eq(pool_info['template'])
end
it 'should return the pool name' do
result = subject.get_vm(poolname, vmname)
expect(result['poolname']).to eq(pool_info['name'])
end
it 'should return the boot time' do
result = subject.get_vm(poolname, vmname)
expect(result['boottime']).to eq(boot_time)
end
it 'should return the status' do
result = subject.get_vm(poolname, vmname)
expect(result['status']).to eq("running")
end
it 'should return the status' do
result = subject.get_vm(poolname, vmname)
expect(result['image_size']).to eq("a1.large")
end
end
end
describe '#create_vm' do
before(:each) do
allow(subject).to receive(:connect_to_aws).and_return(connection)
end
context 'Given an invalid pool name' do
it 'should raise an error' do
expect { subject.create_vm('missing_pool', vmname) }.to raise_error(/missing_pool does not exist/)
end
end
context 'Given a vmname that already exists' do
before(:each) do
allow(subject).to receive(:get_vm).and_return({
'name' => "foobar",
'template' => "abc",
'status' => "running"
})
end
it 'should raise an error' do
expect { subject.create_vm(poolname, vmname) }.to raise_error(/Instance creation not attempted, .* already exists/)
end
end
context 'Given a successful creation' do
let(:client) { double }
before(:each) do
allow(subject).to receive(:get_vm).and_return(nil,{
'name' => vmname,
'template' => "abc",
'status' => "running"
})
result = Struct.new(:instance_id)
batch_instance = result.new(instance_id: "abcfoo")
allow(connection).to receive(:create_instances).and_return([batch_instance])
allow(connection).to receive(:client).and_return(client)
allow(client).to receive(:wait_until)
end
it 'should return a hash' do
result = subject.create_vm(poolname, vmname)
expect(result.is_a?(Hash)).to be true
end
it 'should have the new VM name' do
result = subject.create_vm(poolname, vmname)
expect(result['name']).to eq(vmname)
end
end
end
describe '#destroy_vm' do
before(:each) do
allow(subject).to receive(:connect_to_aws).and_return(connection)
end
context 'Given a missing VM name' do
let(:client) { double }
before(:each) do
allow(connection).to receive(:instances).and_return([nil])
allow(connection).to receive(:client).and_return(client)
allow(client).to receive(:wait_until)
end
it 'should return true' do
expect(subject.destroy_vm(poolname, 'missing_vm')).to be true
end
end
context 'Given a running VM' do
let(:instance) { double("instance") }
let(:client) { double }
before(:each) do
allow(connection).to receive(:instances).and_return([instance])
expect(instance).to receive(:terminate)
allow(connection).to receive(:client).and_return(client)
allow(client).to receive(:wait_until)
allow(instance).to receive(:id)
end
it 'should return true' do
expect(subject.destroy_vm(poolname, vmname)).to be true
end
end
end
end