Implement CLI object required functionality to refactor the Container object
This commit is contained in:
parent
567ede7db6
commit
228e03ecbe
2 changed files with 176 additions and 16 deletions
|
@ -1,5 +1,3 @@
|
||||||
require 'unit_helper'
|
|
||||||
|
|
||||||
require "vagrant/util/retryable"
|
require "vagrant/util/retryable"
|
||||||
require "vagrant/util/subprocess"
|
require "vagrant/util/subprocess"
|
||||||
|
|
||||||
|
@ -9,6 +7,10 @@ module Vagrant
|
||||||
module LXC
|
module LXC
|
||||||
class Container
|
class Container
|
||||||
class CLI
|
class CLI
|
||||||
|
attr_accessor :name
|
||||||
|
|
||||||
|
class TransitionBlockNotProvided < RuntimeError; end
|
||||||
|
|
||||||
# Include this so we can use `Subprocess` more easily.
|
# Include this so we can use `Subprocess` more easily.
|
||||||
include Vagrant::Util::Retryable
|
include Vagrant::Util::Retryable
|
||||||
|
|
||||||
|
@ -18,17 +20,57 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def list
|
def list
|
||||||
containers = lxc :ls
|
run(:ls).split(/\s+/).uniq
|
||||||
containers.split(/\s+/).uniq
|
end
|
||||||
|
|
||||||
|
def state
|
||||||
|
if @name && run(:info, '--name', @name) =~ /^state:[^A-Z]+([A-Z]+)$/
|
||||||
|
$1.downcase.to_sym
|
||||||
|
elsif @name
|
||||||
|
:unknown
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create(template, template_opts = {})
|
||||||
|
extra = template_opts.to_a.flatten
|
||||||
|
extra.unshift '--' unless extra.empty?
|
||||||
|
|
||||||
|
run :create,
|
||||||
|
# lxc-create options
|
||||||
|
'--template', template,
|
||||||
|
'--name', @name,
|
||||||
|
*extra
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
run :destroy, '--name', @name
|
||||||
|
end
|
||||||
|
|
||||||
|
def start(configs = {})
|
||||||
|
configs = configs.map { |key, value| ["-s", "#{key}=#{value}"] }.flatten
|
||||||
|
run :start, '-d', '--name', @name, *configs
|
||||||
|
end
|
||||||
|
|
||||||
|
def shutdown
|
||||||
|
run :shutdown, '--name', @name
|
||||||
|
end
|
||||||
|
|
||||||
|
def transition_to(state, &block)
|
||||||
|
raise TransitionBlockNotProvided unless block_given?
|
||||||
|
|
||||||
|
yield self
|
||||||
|
|
||||||
|
run :wait, '--name', @name, '--state', state.to_s.upcase
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def lxc(command, *args)
|
def run(command, *args)
|
||||||
execute('sudo', "lxc-#{command}", *args)
|
execute('sudo', "lxc-#{command}", *args)
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Review code below this line, it was pretty much a copy and paste from VirtualBox base driver
|
# TODO: Review code below this line, it was pretty much a copy and
|
||||||
|
# paste from VirtualBox base driver and has no tests
|
||||||
def execute(*command, &block)
|
def execute(*command, &block)
|
||||||
# Get the options hash if it exists
|
# Get the options hash if it exists
|
||||||
opts = {}
|
opts = {}
|
||||||
|
|
|
@ -7,24 +7,142 @@ describe Vagrant::LXC::Container::CLI do
|
||||||
describe 'list' do
|
describe 'list' do
|
||||||
let(:lxc_ls_out) { "dup-container\na-container dup-container" }
|
let(:lxc_ls_out) { "dup-container\na-container dup-container" }
|
||||||
let(:exec_args) { @exec_args }
|
let(:exec_args) { @exec_args }
|
||||||
let(:result) { subject.list }
|
let(:result) { @result }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
Vagrant::Util::Subprocess.stub(:execute) { |*args|
|
subject.stub(:run).with(:ls).and_return(lxc_ls_out)
|
||||||
@exec_args = args
|
@result = subject.list
|
||||||
stub(exit_code: 0, stdout: lxc_ls_out)
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'grabs previously created containers from lxc-ls' do
|
it 'grabs previously created containers from lxc-ls output' do
|
||||||
result.should be_an Enumerable
|
result.should be_an Enumerable
|
||||||
result.should include 'a-container'
|
result.should include 'a-container'
|
||||||
result.should include 'dup-container'
|
result.should include 'dup-container'
|
||||||
exec_args.should include 'lxc-ls'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'removes duplicates from lxc-ls output' do
|
it 'removes duplicates from lxc-ls output' do
|
||||||
result.uniq.should == result
|
result.uniq.should == result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'create' do
|
||||||
|
let(:template) { 'quantal-64' }
|
||||||
|
let(:name) { 'quantal-container' }
|
||||||
|
let(:template_args) { { '--extra-param' => 'param', '--other' => 'value' } }
|
||||||
|
|
||||||
|
subject { described_class.new(name) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject.stub(:run)
|
||||||
|
subject.create(template, template_args)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'issues a lxc-create with provided template, container name and hash of arguments' do
|
||||||
|
subject.should have_received(:run).with(
|
||||||
|
:create,
|
||||||
|
'--template', template,
|
||||||
|
'--name', name,
|
||||||
|
'--',
|
||||||
|
'--extra-param', 'param',
|
||||||
|
'--other', 'value'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'destroy' do
|
||||||
|
let(:name) { 'a-container-for-destruction' }
|
||||||
|
|
||||||
|
subject { described_class.new(name) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject.stub(:run)
|
||||||
|
subject.destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'issues a lxc-destroy with container name' do
|
||||||
|
subject.should have_received(:run).with(:destroy, '--name', name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'start' do
|
||||||
|
let(:name) { 'a-container' }
|
||||||
|
subject { described_class.new(name) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject.stub(:run)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'starts container on the background' do
|
||||||
|
subject.start
|
||||||
|
subject.should have_received(:run).with(
|
||||||
|
:start,
|
||||||
|
'-d',
|
||||||
|
'--name', name
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'uses provided hash to configure the container' do
|
||||||
|
subject.start('lxc.config' => 'value', 'lxc.other' => 'value')
|
||||||
|
subject.should have_received(:run).with(:start, '-d', '--name', name,
|
||||||
|
'-s', 'lxc.config=value',
|
||||||
|
'-s', 'lxc.other=value'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'shutdown' do
|
||||||
|
let(:name) { 'a-running-container' }
|
||||||
|
subject { described_class.new(name) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject.stub(:run)
|
||||||
|
subject.shutdown
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'issues a lxc-shutdown with provided container name' do
|
||||||
|
subject.should have_received(:run).with(:shutdown, '--name', name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'state' do
|
||||||
|
let(:name) { 'a-container' }
|
||||||
|
subject { described_class.new(name) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject.stub(:run).and_return("state: STOPPED\npid: 2")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls lxc-info with the right arguments' do
|
||||||
|
subject.state
|
||||||
|
subject.should have_received(:run).with(:info, '--name', name)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'maps the output of lxc-info status out to a symbol' do
|
||||||
|
subject.state.should == :stopped
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'transition block' do
|
||||||
|
let(:name) { 'a-running-container' }
|
||||||
|
subject { described_class.new(name) }
|
||||||
|
|
||||||
|
before { subject.stub(:run) }
|
||||||
|
|
||||||
|
it 'yields cli object' do
|
||||||
|
subject.stub(:shutdown)
|
||||||
|
subject.transition_to(:stopped) { |c| c.shutdown }
|
||||||
|
subject.should have_received(:shutdown)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'throws an exception if block is not provided' do
|
||||||
|
expect {
|
||||||
|
subject.transition_to(:running)
|
||||||
|
}.to raise_error(described_class::TransitionBlockNotProvided)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'waits for the expected container state using lxc-wait' do
|
||||||
|
subject.transition_to(:running) { }
|
||||||
|
subject.should have_received(:run).with(:wait, '--name', name, '--state', 'RUNNING')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue