2013-03-10 22:15:31 +00:00
|
|
|
require 'unit_helper'
|
|
|
|
|
2014-03-11 22:50:28 +00:00
|
|
|
require 'vagrant-lxc/sudo_wrapper'
|
2013-04-05 05:17:19 +00:00
|
|
|
require 'vagrant-lxc/driver/cli'
|
2013-03-10 22:15:31 +00:00
|
|
|
|
2013-04-05 05:17:19 +00:00
|
|
|
describe Vagrant::LXC::Driver::CLI do
|
2014-07-25 00:57:35 +00:00
|
|
|
let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true, wrapper_path: nil) }
|
2013-07-28 05:17:05 +00:00
|
|
|
|
|
|
|
subject { described_class.new(sudo_wrapper) }
|
|
|
|
|
2013-03-10 22:15:31 +00:00
|
|
|
describe 'list' do
|
|
|
|
let(:lxc_ls_out) { "dup-container\na-container dup-container" }
|
2013-03-10 23:31:32 +00:00
|
|
|
let(:result) { @result }
|
2013-03-10 22:15:31 +00:00
|
|
|
|
|
|
|
before do
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:run).with(:ls).and_return(lxc_ls_out)
|
2013-03-10 23:31:32 +00:00
|
|
|
@result = subject.list
|
2013-03-10 22:15:31 +00:00
|
|
|
end
|
|
|
|
|
2013-03-10 23:31:32 +00:00
|
|
|
it 'grabs previously created containers from lxc-ls output' do
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(result).to be_an Enumerable
|
|
|
|
expect(result).to include 'a-container'
|
|
|
|
expect(result).to include 'dup-container'
|
2013-03-10 22:15:31 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'removes duplicates from lxc-ls output' do
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(result.uniq).to eq(result)
|
2013-03-10 22:15:31 +00:00
|
|
|
end
|
|
|
|
end
|
2013-03-10 23:31:32 +00:00
|
|
|
|
2013-04-09 01:27:29 +00:00
|
|
|
describe 'version' do
|
2014-09-23 12:07:03 +00:00
|
|
|
before do
|
2014-10-15 04:14:52 +00:00
|
|
|
allow(subject).to receive(:support_version_command?).and_return(true)
|
2014-09-23 12:07:03 +00:00
|
|
|
allow(subject).to receive(:run).with(:version).and_return(lxc_version_out)
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'lxc version before 1.x.x' do
|
|
|
|
let(:lxc_version_out) { "lxc version: 0.x.y-rc1\n" }
|
|
|
|
|
|
|
|
it 'parses the version from the output' do
|
|
|
|
expect(subject.version).to eq('0.x.y-rc1')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'lxc version after 1.x.x' do
|
|
|
|
let(:lxc_version_out) { "1.0.0\n" }
|
2013-04-09 01:27:29 +00:00
|
|
|
|
2014-09-23 12:07:03 +00:00
|
|
|
it 'parses the version from the output' do
|
|
|
|
expect(subject.version).to eq('1.0.0')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'config' do
|
2013-04-09 01:27:29 +00:00
|
|
|
before do
|
2014-10-15 04:14:52 +00:00
|
|
|
allow(subject).to receive(:support_version_command?).and_return(support_version_command?)
|
2014-09-23 12:07:03 +00:00
|
|
|
allow(subject).to receive(:run).with(:config, 'lxc.lxcpath').and_return(lxc_config_out)
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:run).with(:version).and_return(lxc_version_out)
|
2014-09-23 12:07:03 +00:00
|
|
|
allow(subject).to receive(:run).with(:create, '--version').and_return(lxc_version_out)
|
2013-04-09 01:27:29 +00:00
|
|
|
end
|
|
|
|
|
2014-09-23 12:07:03 +00:00
|
|
|
describe 'lxc version before 1.x.x' do
|
|
|
|
let(:support_version_command?) { true }
|
|
|
|
let(:lxc_config_out) { "/var/lib/lxc\n" }
|
|
|
|
let(:lxc_version_out) { "lxc version: 0.x.y-rc1\n" }
|
|
|
|
|
|
|
|
it 'not supported' do
|
|
|
|
expect{subject.config('lxc.lxcpath')}.to raise_error(Vagrant::LXC::Errors::CommandNotSupported)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'lxc version before after 1.x.x'do
|
|
|
|
let(:support_version_command?) { false }
|
|
|
|
let(:lxc_config_out) { "/var/lib/lxc\n" }
|
|
|
|
let(:lxc_version_out) { "1.0.0\n" }
|
|
|
|
|
|
|
|
it 'parser the lxc.lxcpath value' do
|
|
|
|
expect(subject.config('lxc.lxcpath')).not_to end_with("\n")
|
|
|
|
end
|
2013-04-09 01:27:29 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-03-10 23:31:32 +00:00
|
|
|
describe 'create' do
|
2014-05-04 23:50:04 +00:00
|
|
|
let(:template) { 'quantal-64' }
|
|
|
|
let(:name) { 'quantal-container' }
|
|
|
|
let(:backingstore) { 'btrfs' }
|
|
|
|
let(:backingstore_opts) { [['--dir', '/tmp/foo'], ['--foo', 'bar']] }
|
|
|
|
let(:config_file) { 'config' }
|
|
|
|
let(:template_args) { { '--extra-param' => 'param', '--other' => 'value' } }
|
2013-03-10 23:31:32 +00:00
|
|
|
|
2013-07-28 05:17:05 +00:00
|
|
|
subject { described_class.new(sudo_wrapper, name) }
|
2013-03-10 23:31:32 +00:00
|
|
|
|
|
|
|
before do
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:run) { |*args| @run_args = args }
|
2014-02-02 21:27:08 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'issues a lxc-create with provided template, container name and hash of arguments' do
|
2014-05-04 23:50:04 +00:00
|
|
|
subject.create(template, backingstore, backingstore_opts, config_file, template_args)
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(subject).to have_received(:run).with(
|
2014-02-02 21:27:08 +00:00
|
|
|
:create,
|
2014-05-04 23:50:04 +00:00
|
|
|
'-B', backingstore,
|
2014-02-02 21:27:08 +00:00
|
|
|
'--template', template,
|
|
|
|
'--name', name,
|
2015-01-14 23:07:35 +00:00
|
|
|
*(backingstore_opts.flatten),
|
2014-02-02 21:27:08 +00:00
|
|
|
'-f', config_file,
|
|
|
|
'--',
|
|
|
|
'--extra-param', 'param',
|
|
|
|
'--other', 'value'
|
|
|
|
)
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
|
|
|
|
2014-02-02 21:27:08 +00:00
|
|
|
it 'wraps a low level error into something more meaningful in case the container already exists' do
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:run) { raise Vagrant::LXC::Errors::ExecuteError, stderr: 'alreAdy Exists' }
|
2014-02-02 21:27:08 +00:00
|
|
|
expect {
|
2014-05-04 23:50:04 +00:00
|
|
|
subject.create(template, backingstore, backingstore_opts, config_file, template_args)
|
2014-02-02 21:27:08 +00:00
|
|
|
}.to raise_error(Vagrant::LXC::Errors::ContainerAlreadyExists)
|
|
|
|
end
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
describe 'destroy' do
|
|
|
|
let(:name) { 'a-container-for-destruction' }
|
|
|
|
|
2013-07-28 05:17:05 +00:00
|
|
|
subject { described_class.new(sudo_wrapper, name) }
|
2013-03-10 23:31:32 +00:00
|
|
|
|
|
|
|
before do
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:run)
|
2013-03-10 23:31:32 +00:00
|
|
|
subject.destroy
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'issues a lxc-destroy with container name' do
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(subject).to have_received(:run).with(:destroy, '--name', name)
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'start' do
|
|
|
|
let(:name) { 'a-container' }
|
2013-07-28 05:17:05 +00:00
|
|
|
subject { described_class.new(sudo_wrapper, name) }
|
2013-03-10 23:31:32 +00:00
|
|
|
|
|
|
|
before do
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:run)
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'starts container on the background' do
|
|
|
|
subject.start
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(subject).to have_received(:run).with(
|
2013-03-10 23:31:32 +00:00
|
|
|
:start,
|
|
|
|
'-d',
|
|
|
|
'--name', name
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-06-09 01:50:30 +00:00
|
|
|
describe 'stop' do
|
|
|
|
let(:name) { 'a-running-container' }
|
|
|
|
subject { described_class.new(sudo_wrapper, name) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
allow(subject).to receive(:run)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'lxc-attach is supported' do
|
|
|
|
before do
|
|
|
|
subject.stub(attach: true, supports_attach?: true)
|
|
|
|
subject.stop
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'runs a /sbin/halt within the container' do
|
|
|
|
expect(subject).to have_received(:attach).with('/sbin/halt')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'issues a lxc-stop with provided container name' do
|
|
|
|
expect(subject).to have_received(:run).with(:stop, '--name', name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'lxc-attach is not supported' do
|
|
|
|
before do
|
|
|
|
subject.stub(attach: false, supports_attach?: false)
|
|
|
|
subject.stop
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'runs a /sbin/halt within the container' do
|
|
|
|
expect(subject).to_not have_received(:attach)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'issues a lxc-stop with provided container name' do
|
|
|
|
expect(subject).to have_received(:run).with(:stop, '--name', name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-03-10 23:31:32 +00:00
|
|
|
describe 'state' do
|
|
|
|
let(:name) { 'a-container' }
|
2013-07-28 05:17:05 +00:00
|
|
|
subject { described_class.new(sudo_wrapper, name) }
|
2013-03-10 23:31:32 +00:00
|
|
|
|
|
|
|
before do
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:run).and_return("state: STOPPED\npid: 2")
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'calls lxc-info with the right arguments' do
|
|
|
|
subject.state
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(subject).to have_received(:run).with(:info, '--name', name, retryable: true)
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'maps the output of lxc-info status out to a symbol' do
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(subject.state).to eq(:stopped)
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
2014-02-12 03:47:12 +00:00
|
|
|
|
|
|
|
it 'is not case sensitive' do
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:run).and_return("StatE: STarTED\npid: 2")
|
|
|
|
expect(subject.state).to eq(:started)
|
2014-02-12 03:47:12 +00:00
|
|
|
end
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
|
|
|
|
2013-03-19 04:25:27 +00:00
|
|
|
describe 'attach' do
|
|
|
|
let(:name) { 'a-running-container' }
|
|
|
|
let(:command) { ['ls', 'cat /tmp/file'] }
|
|
|
|
let(:command_output) { 'folders list' }
|
2013-07-28 05:17:05 +00:00
|
|
|
subject { described_class.new(sudo_wrapper, name) }
|
2013-03-19 04:25:27 +00:00
|
|
|
|
|
|
|
before do
|
|
|
|
subject.stub(run: command_output)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'calls lxc-attach with specified command' do
|
|
|
|
subject.attach(*command)
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(subject).to have_received(:run).with(:attach, '--name', name, '--', *command)
|
2013-03-19 04:25:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'supports a "namespaces" parameter' do
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:run).with(:attach, '-h', :show_stderr => true).and_return({:stdout => '', :stderr => '--namespaces'})
|
2013-03-19 04:25:27 +00:00
|
|
|
subject.attach *(command + [{namespaces: ['network', 'mount']}])
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(subject).to have_received(:run).with(:attach, '--name', name, '--namespaces', 'NETWORK|MOUNT', '--', *command)
|
2013-03-19 04:25:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-03-10 23:31:32 +00:00
|
|
|
describe 'transition block' do
|
2013-05-07 14:07:35 +00:00
|
|
|
before do
|
|
|
|
subject.stub(run: true, sleep: true, state: :stopped)
|
|
|
|
end
|
2013-03-10 23:31:32 +00:00
|
|
|
|
2013-05-07 14:07:35 +00:00
|
|
|
it 'yields a cli object' do
|
2014-03-14 14:37:50 +00:00
|
|
|
allow(subject).to receive(:shutdown)
|
2013-03-10 23:31:32 +00:00
|
|
|
subject.transition_to(:stopped) { |c| c.shutdown }
|
2014-03-14 14:37:50 +00:00
|
|
|
expect(subject).to have_received(:shutdown)
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'throws an exception if block is not provided' do
|
|
|
|
expect {
|
|
|
|
subject.transition_to(:running)
|
|
|
|
}.to raise_error(described_class::TransitionBlockNotProvided)
|
|
|
|
end
|
|
|
|
|
2014-03-11 22:50:28 +00:00
|
|
|
skip 'waits for the expected container state'
|
2013-03-10 23:31:32 +00:00
|
|
|
end
|
2014-06-09 01:50:30 +00:00
|
|
|
|
|
|
|
describe 'check for whether lxc-attach is supported' do
|
|
|
|
let(:name) { 'a-running-container' }
|
|
|
|
subject { described_class.new(sudo_wrapper, name) }
|
|
|
|
|
|
|
|
context 'lxc-attach is present on system' do
|
|
|
|
before { subject.stub(run: true) }
|
|
|
|
|
|
|
|
it 'returns true if `lxc-attach --name CNAME -- /bin/true` works' do
|
|
|
|
expect(subject.supports_attach?).to be_truthy
|
|
|
|
expect(subject).to have_received(:run).with(
|
|
|
|
:attach, '--name', name, '--', '/bin/true'
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'lxc-attach is not present on system' do
|
|
|
|
before do
|
|
|
|
allow(subject).to receive(:run).and_raise(Vagrant::LXC::Errors::ExecuteError.new('msg'))
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns true if `lxc-attach --name CNAME -- /bin/true` works' do
|
|
|
|
expect(subject.supports_attach?).to be_falsy
|
|
|
|
expect(subject).to have_received(:run).with(
|
|
|
|
:attach, '--name', name, '--', '/bin/true'
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-03-10 22:15:31 +00:00
|
|
|
end
|