testlab 1.9.2 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +6 -2
- data/Gemfile +4 -0
- data/README.md +24 -14
- data/bin/tl +8 -3
- data/lib/commands/support.rb +85 -0
- data/lib/testlab/container.rb +0 -2
- data/lib/testlab/labfile.rb +28 -8
- data/lib/testlab/provisioners/apt.rb +5 -3
- data/lib/testlab/provisioners/templates/apt/provision.erb +13 -0
- data/lib/testlab/utility.rb +0 -2
- data/lib/testlab/version.rb +1 -1
- data/spec/container_spec.rb +156 -47
- data/spec/interface_spec.rb +34 -4
- data/spec/labfile_spec.rb +57 -0
- data/spec/network_spec.rb +46 -8
- data/spec/node_spec.rb +38 -0
- data/spec/providers/vagrant_spec.rb +79 -0
- data/spec/provisioners/generic_spec.rb +93 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/Labfile +125 -30
- data/spec/support/test +27 -0
- data/spec/support/test.pub +1 -0
- data/spec/testlab_spec.rb +106 -50
- data/spec/utility/logger_spec.rb +100 -0
- metadata +17 -8
- data/lib/testlab/container/method_missing.rb +0 -22
- data/lib/testlab/utility/gli.rb +0 -97
- data/spec/provisioners/shell_spec.rb +0 -71
data/.travis.yml
CHANGED
@@ -11,5 +11,9 @@ before_install: sudo ./spec/support/install-lxc.sh
|
|
11
11
|
|
12
12
|
notifications:
|
13
13
|
email:
|
14
|
-
|
15
|
-
|
14
|
+
recipients:
|
15
|
+
- testlab-ci@lookout.com
|
16
|
+
on_success: always
|
17
|
+
on_failure: always
|
18
|
+
irc:
|
19
|
+
- "irc.freenode.net#jovelabs"
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
[![Gem Version](https://badge.fury.io/rb/testlab.png)](http://badge.fury.io/rb/testlab)
|
2
2
|
[![Dependency Status](https://gemnasium.com/zpatten/testlab.png)](https://gemnasium.com/zpatten/testlab)
|
3
3
|
[![Build Status](https://secure.travis-ci.org/lookout/testlab.png)](http://travis-ci.org/lookout/testlab)
|
4
|
-
[![Coverage Status](https://coveralls.io/repos/
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/lookout/testlab/badge.png?branch=master)](https://coveralls.io/r/lookout/testlab)
|
5
5
|
[![Code Climate](https://codeclimate.com/github/zpatten/testlab.png)](https://codeclimate.com/github/zpatten/testlab)
|
6
6
|
|
7
7
|
# A Quick Note on Versioning
|
@@ -10,25 +10,31 @@ I attempt to keep TestLab in line with Semantic Versioning when incrementing ver
|
|
10
10
|
|
11
11
|
* http://semver.org/
|
12
12
|
|
13
|
-
# TestLab
|
13
|
+
# What is TestLab?
|
14
14
|
|
15
|
-
|
15
|
+
Simply put; a toolkit for building virtual computer labs.
|
16
16
|
|
17
|
-
|
17
|
+
TestLab lets you iterate virtual infrastructure quickly. Using a `Labfile` you can define how you want your virtual infrastructure laid out. You can define multiple network segments and containers (i.e. boxen). TestLab will then build and demolish this virtual infrastructure as you have dictated in the `Labfile`.
|
18
|
+
|
19
|
+
TestLab also allows you to template objects, meaning less congestion in your `Labfile`.
|
18
20
|
|
19
21
|
TestLab can also import and export containers, making it easy to share them. TestLab supports the latest LXC versions, allowing for ephemeral cloning operations, furthering your ability to iterate quickly. TestLab can be used for many other applications, including infrastructure unit and integration testing, allowing for vastly more complex configurations and more effective resource sharing than traditional VM solutions.
|
20
22
|
|
21
23
|
TestLab can be run via the command-line or can be interfaced with directly via Ruby code.
|
22
24
|
|
25
|
+
# What is a Labfile?
|
26
|
+
|
27
|
+
A `Labfile` defines what your lab will look like using the TestLab DSL.
|
28
|
+
|
23
29
|
# Using TestLab Interactively
|
24
30
|
|
25
|
-
$ tl
|
31
|
+
$ tl help
|
26
32
|
NAME
|
27
33
|
tl - TestLab - A toolkit for building virtual computer labs
|
28
34
|
|
29
35
|
TestLab is based around the abstraction of three main components: nodes, networks and containers. Nodes represent a system
|
30
|
-
(bare-metal or virtualized) that hosts containers. Networks
|
31
|
-
|
36
|
+
(bare-metal or virtualized) that hosts containers. Networks represent a Linux bridge on a node. Containers simply represent a Linux
|
37
|
+
Container (LXC) running on its parent node which is typically connected to a network on the node.
|
32
38
|
|
33
39
|
In addition to the core component abstractions, TestLab shares a series of core tasks that are universal across all of the
|
34
40
|
components. These are create and destroy, up and down, provision and deprovision. Several other core tasks, such as build,
|
@@ -36,11 +42,11 @@ TestLab can be run via the command-line or can be interfaced with directly via R
|
|
36
42
|
|
37
43
|
You can execute almost all of the tasks against the entire lab, or individual lab components.
|
38
44
|
|
39
|
-
When building a lab from scratch, you will typically run 'tl build'. To breakdown your lab, destroying all the components, you
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
45
|
+
When building a lab from scratch, you will typically run 'tl build'. To breakdown your lab, destroying all the components, you will
|
46
|
+
typically run 'tl demolish'. If you want to re-build the lab you can run 'tl recycle' which will run the demolish task followed by
|
47
|
+
the build task against all the lab components. If you want to power-cycle the entire lab you can run 'tl bounce' which will run the
|
48
|
+
down task followed by the up task against all the lab components. Again these tasks can be run against the lab as a whole or
|
49
|
+
individual components.
|
44
50
|
|
45
51
|
You can view the status of the entire lab using 'tl status', or view the status of individual components using 'tl node status',
|
46
52
|
'tl network status' or 'tl container status'.
|
@@ -52,11 +58,11 @@ TestLab can be run via the command-line or can be interfaced with directly via R
|
|
52
58
|
tl [global options] command [command options] [arguments...]
|
53
59
|
|
54
60
|
VERSION
|
55
|
-
1.
|
61
|
+
1.9.2
|
56
62
|
|
57
63
|
GLOBAL OPTIONS
|
58
64
|
-l, --labfile=path/to/file - Path to Labfile: ${REPO}/Labfile (default: none)
|
59
|
-
-r, --repo=path/to/directory - Path to Repository directory: ${PWD} (default: /home/zpatten/code/chef-repo)
|
65
|
+
-r, --repo=path/to/directory - Path to Repository directory: ${PWD} (default: /home/zpatten/Dropbox/code/lookout/chef-repo)
|
60
66
|
-c, --config=path/to/directory - Path to Configuration directory: ${REPO}/.testlab-$(hostname -s) (default: none)
|
61
67
|
--version - Display the program version
|
62
68
|
-v, --[no-]verbose - Show verbose output
|
@@ -270,6 +276,10 @@ You can access all the nodes for example:
|
|
270
276
|
|
271
277
|
For more information see the TestLab Documentation, `testlab-repo`, command-line binary and it never hurts to look at the TestLab source itself.
|
272
278
|
|
279
|
+
You can also check out the `tl-knife` command-line binary for another example of using TestLab in a programmatic fashion:
|
280
|
+
|
281
|
+
* https://github.com/zpatten/testlab/blob/master/bin/tl-knife
|
282
|
+
|
273
283
|
# REQUIREMENTS
|
274
284
|
|
275
285
|
* Latest VirtualBox Package
|
data/bin/tl
CHANGED
@@ -22,7 +22,6 @@ require 'gli'
|
|
22
22
|
require 'testlab'
|
23
23
|
|
24
24
|
include GLI::App
|
25
|
-
include TestLab::Utility::GLI
|
26
25
|
include TestLab::Utility::Misc
|
27
26
|
|
28
27
|
version TestLab::VERSION
|
@@ -31,7 +30,7 @@ program_desc %(TestLab - A toolkit for building virtual computer labs)
|
|
31
30
|
program_long_desc <<-EOF
|
32
31
|
TestLab is based around the abstraction of three main components: nodes,
|
33
32
|
networks and containers. Nodes represent a system (bare-metal or virtualized)
|
34
|
-
that hosts containers. Networks
|
33
|
+
that hosts containers. Networks represent a Linux bridge on a node. Containers
|
35
34
|
simply represent a Linux Container (LXC) running on its parent node which is
|
36
35
|
typically connected to a network on the node.
|
37
36
|
|
@@ -67,7 +66,13 @@ default_command :help
|
|
67
66
|
|
68
67
|
preserve_argv true
|
69
68
|
|
70
|
-
|
69
|
+
require 'commands/support'
|
70
|
+
require 'commands/testlab'
|
71
|
+
require 'commands/node'
|
72
|
+
require 'commands/network'
|
73
|
+
require 'commands/container'
|
74
|
+
|
75
|
+
# commands_from 'commands'
|
71
76
|
|
72
77
|
desc 'Show verbose output'
|
73
78
|
default_value false
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'ztk'
|
2
|
+
|
3
|
+
LAB_ACTION_ORDER = %W(build demolish recycle bounce create destroy up down provision deprovision).map(&:to_sym)
|
4
|
+
|
5
|
+
LAB_ACTIONS = {
|
6
|
+
:create => ["Initialize %s", "Attempts to create the <%= @component %>."],
|
7
|
+
:destroy => ["Terminate %s", "Attempts to destroy the <%= @component %>."],
|
8
|
+
:up => ["On-line %s", "Attempts to online the <%= @component %>."],
|
9
|
+
:down => ["Off-line %s", "Attempts to offline the <%= @component %>."],
|
10
|
+
:provision => ["Provision %s", "Attempts to provision the <%= @component %>."],
|
11
|
+
:deprovision => ["De-provision %s", "Attempts to deprovision the <%= @component %>."],
|
12
|
+
:bounce => ["Bounce %s (down->up)", <<-EOF],
|
13
|
+
Attempts to bounce the <%= @component %>. TestLab will attempt to offline, then online the <%= @component %>.
|
14
|
+
|
15
|
+
The <%= @component %> are taken through the following states:
|
16
|
+
|
17
|
+
Current -> Down -> Up
|
18
|
+
EOF
|
19
|
+
:recycle => ["Recycle %s (demolish->build)", <<-EOF],
|
20
|
+
Attempts to recycle the <%= @component %>. TestLab will attempt to demolish, then build the <%= @component %>.
|
21
|
+
|
22
|
+
The <%= @component %> are taken through the following states:
|
23
|
+
|
24
|
+
Current -> Demolish -> Build
|
25
|
+
EOF
|
26
|
+
:build => ["Build %s (create->up->provision)", <<-EOF],
|
27
|
+
Attempts to build the <%= @component %>. TestLab will attempt to create, online and provision the <%= @component %>.
|
28
|
+
|
29
|
+
The <%= @component %> are taken through the following states:
|
30
|
+
|
31
|
+
Current -> Create -> Up -> Provision
|
32
|
+
EOF
|
33
|
+
:demolish => ["Demolish %s (deprovision->down->destroy)", <<-EOF]
|
34
|
+
Attempts to demolish the <%= @component %>. TestLab will attempt to deprovision, offline and destroy the <%= @component %>.
|
35
|
+
|
36
|
+
The <%= @component %> are taken through the following states:
|
37
|
+
|
38
|
+
Current -> Deprovision -> Down -> Destroy
|
39
|
+
EOF
|
40
|
+
}
|
41
|
+
|
42
|
+
def build_lab_commands(component, klass, &block)
|
43
|
+
desc %(Manage lab #{component}s)
|
44
|
+
command component do |c|
|
45
|
+
c.desc %(Optional #{component} ID or comma separated list of #{component} IDs)
|
46
|
+
c.arg_name %(#{component}[,#{component},...])
|
47
|
+
c.flag [:n, :name]
|
48
|
+
|
49
|
+
LAB_ACTION_ORDER.each do |lab_action|
|
50
|
+
action_desc = LAB_ACTIONS[lab_action]
|
51
|
+
c.desc(action_desc.first % "#{component}s")
|
52
|
+
c.long_desc(ZTK::Template.string(action_desc.last, {:component => "#{component}s"}))
|
53
|
+
|
54
|
+
c.command lab_action do |la|
|
55
|
+
la.action do |global_options, options, args|
|
56
|
+
iterate_objects_by_name(options[:name], klass) do |object|
|
57
|
+
object.send(lab_action)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
!block.nil? and block.call(c)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def iterate_objects_by_name(name, klass, &block)
|
68
|
+
objects = Array.new
|
69
|
+
klass_name = klass.to_s.split('::').last.downcase
|
70
|
+
|
71
|
+
if name.nil?
|
72
|
+
objects = klass.all.select{ |object| (!object.template rescue true) }
|
73
|
+
else
|
74
|
+
names = name.split(',')
|
75
|
+
objects = klass.find(names).select{ |object| (!object.template rescue true) }
|
76
|
+
end
|
77
|
+
|
78
|
+
(objects.nil? || (objects.count == 0)) and raise TestLab::TestLabError, "We could not find any of the #{klass_name}s you supplied!"
|
79
|
+
|
80
|
+
objects.each do |object|
|
81
|
+
!block.nil? and block.call(object)
|
82
|
+
end
|
83
|
+
|
84
|
+
objects
|
85
|
+
end
|
data/lib/testlab/container.rb
CHANGED
@@ -82,7 +82,6 @@ class TestLab
|
|
82
82
|
autoload :Interface, 'testlab/container/interface'
|
83
83
|
autoload :IO, 'testlab/container/io'
|
84
84
|
autoload :LXC, 'testlab/container/lxc'
|
85
|
-
autoload :MethodMissing, 'testlab/container/method_missing'
|
86
85
|
autoload :Provision, 'testlab/container/provision'
|
87
86
|
autoload :SSH, 'testlab/container/ssh'
|
88
87
|
autoload :Status, 'testlab/container/status'
|
@@ -95,7 +94,6 @@ class TestLab
|
|
95
94
|
include TestLab::Container::Interface
|
96
95
|
include TestLab::Container::IO
|
97
96
|
include TestLab::Container::LXC
|
98
|
-
include TestLab::Container::MethodMissing
|
99
97
|
include TestLab::Container::Provision
|
100
98
|
include TestLab::Container::SSH
|
101
99
|
include TestLab::Container::Status
|
data/lib/testlab/labfile.rb
CHANGED
@@ -27,22 +27,42 @@ class TestLab
|
|
27
27
|
else
|
28
28
|
@ui.logger.debug { "Labfile Version: #{version}" }
|
29
29
|
version_arguments = version.split
|
30
|
-
@ui.logger.debug { version_arguments.inspect }
|
30
|
+
@ui.logger.debug { "version_arguments=#{version_arguments.inspect}" }
|
31
31
|
|
32
32
|
if version_arguments.count == 1
|
33
|
-
|
34
|
-
raise LabfileError, "This Labfile is not compatible with this version of TestLab! (#{version})"
|
35
|
-
end
|
33
|
+
compare_versions(TestLab::VERSION, version_arguments.first)
|
36
34
|
elsif version_arguments.count == 2
|
37
|
-
|
38
|
-
raise LabfileError, "This Labfile is not compatible with this version of TestLab! (#{version})"
|
39
|
-
end
|
35
|
+
compare_versions(TestLab::VERSION, version_arguments.last, version_arguments.first)
|
40
36
|
else
|
41
|
-
raise LabfileError, 'Invalid version!'
|
37
|
+
raise LabfileError, 'Invalid Labfile version attribute!'
|
42
38
|
end
|
43
39
|
end
|
44
40
|
end
|
45
41
|
|
42
|
+
def compare_versions(version_one, version_two, comparison_operator=nil)
|
43
|
+
v1_splat = version_one.split('.')
|
44
|
+
v2_splat = version_two.split('.')
|
45
|
+
|
46
|
+
max_length = [v1_splat.map(&:length).max, v2_splat.map(&:length).max].max
|
47
|
+
|
48
|
+
v1 = v1_splat.collect{ |element| "%0#{max_length}d" % element.to_i }.join('.')
|
49
|
+
v2 = v2_splat.collect{ |element| "%0#{max_length}d" % element.to_i }.join('.')
|
50
|
+
|
51
|
+
@ui.logger.debug { "v1=#{v1.inspect}" }
|
52
|
+
@ui.logger.debug { "v2=#{v2.inspect}" }
|
53
|
+
@ui.logger.debug { "max_length=#{max_length.inspect}" }
|
54
|
+
|
55
|
+
if comparison_operator.nil?
|
56
|
+
invalid_version if v1 != v2
|
57
|
+
else
|
58
|
+
invalid_version if !v1.send(comparison_operator.to_sym, v2)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def invalid_version
|
63
|
+
raise LabfileError, "This Labfile is not compatible with this version of TestLab! (#{self.version})"
|
64
|
+
end
|
65
|
+
|
46
66
|
def config_dir
|
47
67
|
self.testlab.config_dir
|
48
68
|
end
|
@@ -15,9 +15,11 @@ class TestLab
|
|
15
15
|
@ui = (ui || TestLab.ui)
|
16
16
|
|
17
17
|
@config[:apt] ||= Hash.new
|
18
|
-
@config[:apt][:install]
|
19
|
-
@config[:apt][:remove]
|
20
|
-
@config[:apt][:purge]
|
18
|
+
@config[:apt][:install] ||= Array.new
|
19
|
+
@config[:apt][:remove] ||= Array.new
|
20
|
+
@config[:apt][:purge] ||= Array.new
|
21
|
+
@config[:apt][:sources] ||= Array.new
|
22
|
+
@config[:apt][:multiarch] ||= true
|
21
23
|
|
22
24
|
@ui.logger.debug { "config(#{@config.inspect})" }
|
23
25
|
end
|
@@ -3,7 +3,20 @@ set -e
|
|
3
3
|
|
4
4
|
export DEBIAN_FRONTEND="noninteractive"
|
5
5
|
|
6
|
+
<% if !@apt[:multiarch].nil? && (@apt[:multiarch] == false) -%>
|
7
|
+
rm -fv /etc/dpkg/dpkg.cfg.d/multiarch || true
|
8
|
+
<% end -%>
|
9
|
+
|
10
|
+
apt-get -y update
|
11
|
+
apt-get -y install apt-transport-https
|
12
|
+
|
13
|
+
<% if !@apt[:sources].nil? && @apt[:sources].count > 0 -%>
|
14
|
+
rm -fv /etc/apt/sources.list || true
|
15
|
+
<% @apt[:sources].flatten.compact.each do |source| -%>
|
16
|
+
echo '<%= source %>' | tee -a /etc/apt/sources.list
|
17
|
+
<% end -%>
|
6
18
|
apt-get -y update
|
19
|
+
<% end -%>
|
7
20
|
|
8
21
|
<% if !@apt[:install].nil? -%>
|
9
22
|
<% @apt[:install].flatten.compact.each do |package| -%>
|
data/lib/testlab/utility.rb
CHANGED
@@ -11,12 +11,10 @@ class TestLab
|
|
11
11
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
12
12
|
module Utility
|
13
13
|
autoload :CIDR, 'testlab/utility/cidr'
|
14
|
-
autoload :GLI, 'testlab/utility/gli'
|
15
14
|
autoload :Logger, 'testlab/utility/logger'
|
16
15
|
autoload :Misc, 'testlab/utility/misc'
|
17
16
|
|
18
17
|
extend TestLab::Utility::CIDR
|
19
|
-
extend TestLab::Utility::GLI
|
20
18
|
extend TestLab::Utility::Logger
|
21
19
|
extend TestLab::Utility::Misc
|
22
20
|
|
data/lib/testlab/version.rb
CHANGED
data/spec/container_spec.rb
CHANGED
@@ -23,10 +23,11 @@ describe TestLab::Container do
|
|
23
23
|
|
24
24
|
subject {
|
25
25
|
@logger = ZTK::Logger.new('/tmp/test.log')
|
26
|
-
@ui =
|
27
|
-
@testlab =
|
26
|
+
@ui = ui_helper(:logger => @logger)
|
27
|
+
@testlab = testlab_helper(:ui => @ui)
|
28
28
|
@testlab.boot
|
29
|
-
|
29
|
+
|
30
|
+
TestLab::Container.first('master')
|
30
31
|
}
|
31
32
|
|
32
33
|
describe "class" do
|
@@ -51,44 +52,123 @@ describe TestLab::Container do
|
|
51
52
|
|
52
53
|
describe "methods" do
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
subject.node.stub(:dead?) { false }
|
57
|
-
subject.node.stub(:state) { :running }
|
58
|
-
subject.lxc.stub(:state) { :not_created }
|
59
|
-
subject.lxc.stub(:memory_usage) { 0 }
|
60
|
-
subject.lxc.stub(:cpu_usage) { 0 }
|
61
|
-
subject.lxc_clone.stub(:exists?) { false }
|
55
|
+
{ :ephemeral => true, :persistent => false }.each do |tag, mode|
|
56
|
+
context tag do
|
62
57
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
58
|
+
before(:each) do
|
59
|
+
subject.node.stub(:dead?) { false }
|
60
|
+
subject.node.stub(:alive?) { true }
|
61
|
+
subject.node.stub(:state) { :running }
|
62
|
+
|
63
|
+
subject.lxc_clone.stub(:exists?) { mode }
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#status" do
|
67
|
+
it "should return a hash of status information about the container" do
|
68
|
+
subject.lxc.stub(:state) { :not_created }
|
69
|
+
subject.lxc.stub(:memory_usage) { 0 }
|
70
|
+
subject.lxc.stub(:cpu_usage) { 0 }
|
71
|
+
|
72
|
+
subject.status.should be_kind_of(Hash)
|
73
|
+
subject.status.should_not be_empty
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#state" do
|
78
|
+
it "should return the state of the container" do
|
79
|
+
subject.node.stub(:dead?) { false }
|
80
|
+
subject.node.stub(:alive?) { true }
|
81
|
+
subject.node.stub(:state) { :running }
|
82
|
+
|
83
|
+
subject.state.should == :not_created
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#ephemeral" do
|
88
|
+
it "should attempt to convert to a ephemeral container" do
|
89
|
+
subject.ephemeral
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#persistent" do
|
94
|
+
it "should attempt to convert to a persistent container" do
|
95
|
+
subject.persistent
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# describe "#export" do
|
100
|
+
# it "should attempt to export the container" do
|
101
|
+
# case tag
|
102
|
+
# when :ephemeral
|
103
|
+
# lambda { subject.export }.should raise_error TestLab::ContainerError
|
104
|
+
# when :persistent
|
105
|
+
# subject.stub(:down) { true }
|
106
|
+
# # subject.stub(:destroy) { true }
|
107
|
+
# # subject.stub(:create) { true }
|
108
|
+
# # subject.stub(:up) { true }
|
109
|
+
|
110
|
+
# subject.lxc.config.stub(:save) { true }
|
111
|
+
# subject.lxc.stub(:state) { :running }
|
112
|
+
|
113
|
+
# subject.lxc.stub(:start) { true }
|
114
|
+
# subject.lxc.stub(:stop) { true }
|
115
|
+
# subject.lxc.stub(:create) { true }
|
116
|
+
# subject.lxc.stub(:destroy) { true }
|
117
|
+
|
118
|
+
# subject.lxc.stub(:attach) { "" }
|
119
|
+
# subject.lxc.stub(:exec) { OpenStruct.new(:exit_code => 0) }
|
120
|
+
|
121
|
+
# subject.export
|
122
|
+
# end
|
123
|
+
# end
|
124
|
+
# end
|
125
|
+
|
126
|
+
describe "#copy" do
|
127
|
+
it "should attempt to copy the container" do
|
128
|
+
case tag
|
129
|
+
when :ephemeral
|
130
|
+
lambda { subject.copy("master") }.should raise_error TestLab::ContainerError
|
131
|
+
when :persistent
|
132
|
+
subject.copy("master")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#up" do
|
138
|
+
it "should up the container" do
|
139
|
+
subject.lxc.config.stub(:save) { true }
|
140
|
+
subject.lxc.stub(:state) { :running }
|
141
|
+
subject.lxc.stub(:start) { true }
|
142
|
+
subject.lxc.stub(:attach) { "" }
|
143
|
+
subject.lxc.stub(:exec) { OpenStruct.new(:exit_code => 0) }
|
144
|
+
|
145
|
+
subject.node.stub(:arch) { "x86_64" }
|
146
|
+
subject.node.stub(:exec) { OpenStruct.new(:exit_code => 1) }
|
147
|
+
|
148
|
+
subject.stub(:provisioners) { Array.new }
|
149
|
+
|
150
|
+
subject.up
|
151
|
+
end
|
152
|
+
end
|
67
153
|
|
68
|
-
describe "#state" do
|
69
|
-
it "should return the state of the container" do
|
70
|
-
subject.node.stub(:dead?) { false }
|
71
|
-
subject.lxc.stub(:state) { :not_created }
|
72
|
-
subject.lxc_clone.stub(:exists?) { false }
|
73
|
-
subject.state.should == :not_created
|
74
154
|
end
|
75
155
|
end
|
76
156
|
|
77
157
|
describe "#fqdn" do
|
78
158
|
it "should return the FQDN for the container" do
|
79
|
-
subject.fqdn.should == "
|
159
|
+
subject.fqdn.should == "master.default.zone"
|
80
160
|
end
|
81
161
|
end
|
82
162
|
|
83
163
|
describe "#ip" do
|
84
164
|
it "should return the IP address of the containers primary interface" do
|
85
|
-
subject.ip.should == "
|
165
|
+
subject.ip.should == "100.64.0.10"
|
86
166
|
end
|
87
167
|
end
|
88
168
|
|
89
169
|
describe "#cidr" do
|
90
170
|
it "should return the CIDR of the containers primary interface" do
|
91
|
-
subject.cidr.should ==
|
171
|
+
subject.cidr.should == 24
|
92
172
|
end
|
93
173
|
end
|
94
174
|
|
@@ -96,7 +176,7 @@ describe TestLab::Container do
|
|
96
176
|
it "should return a BIND PTR record for the containers primary interface" do
|
97
177
|
subject.ptr.should be_kind_of(String)
|
98
178
|
subject.ptr.should_not be_empty
|
99
|
-
subject.ptr.should == "
|
179
|
+
subject.ptr.should == "10"
|
100
180
|
end
|
101
181
|
end
|
102
182
|
|
@@ -114,6 +194,22 @@ describe TestLab::Container do
|
|
114
194
|
end
|
115
195
|
end
|
116
196
|
|
197
|
+
describe "#console" do
|
198
|
+
it "should attempt to open an LXC console via a node SSH console" do
|
199
|
+
subject.node.ssh.stub(:console)
|
200
|
+
|
201
|
+
subject.console
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "#ssh_config" do
|
206
|
+
it "should return a text blob with our SSH configuration" do
|
207
|
+
subject.ssh_config.should_not be_nil
|
208
|
+
subject.ssh_config.should_not be_empty
|
209
|
+
subject.ssh_config.should be_kind_of(String)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
117
213
|
describe "#exists?" do
|
118
214
|
it "should return false for a non-existant container" do
|
119
215
|
subject.lxc.stub(:exists?) { false }
|
@@ -175,47 +271,60 @@ describe TestLab::Container do
|
|
175
271
|
end
|
176
272
|
end
|
177
273
|
|
178
|
-
describe "#
|
179
|
-
it "should
|
274
|
+
describe "#down" do
|
275
|
+
it "should down the container" do
|
180
276
|
subject.node.stub(:dead?) { false }
|
181
277
|
subject.node.stub(:alive?) { true }
|
182
278
|
subject.node.stub(:state) { :running }
|
183
|
-
subject.node.stub(:arch) { "x86_64" }
|
184
|
-
subject.node.stub(:exec) { }
|
185
279
|
|
186
280
|
subject.lxc.stub(:exists?) { true }
|
187
|
-
subject.lxc.stub(:
|
281
|
+
subject.lxc.stub(:stop) { true }
|
188
282
|
subject.lxc.stub(:wait) { true }
|
189
|
-
subject.lxc.stub(:state) { :
|
283
|
+
subject.lxc.stub(:state) { :stopped }
|
190
284
|
|
191
285
|
subject.lxc_clone.stub(:exists?) { false }
|
192
286
|
|
193
|
-
subject.stub(:exec) { }
|
194
|
-
subject.stub(:configure) { }
|
195
287
|
subject.stub(:provisioners) { Array.new }
|
196
288
|
|
197
|
-
|
289
|
+
subject.down
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
describe "#build" do
|
294
|
+
it "should build the container" do
|
295
|
+
subject.stub(:create) { true }
|
296
|
+
subject.stub(:up) { true }
|
297
|
+
subject.stub(:provision) { true }
|
198
298
|
|
199
|
-
subject.
|
299
|
+
subject.build.should == true
|
200
300
|
end
|
201
301
|
end
|
202
302
|
|
203
|
-
describe "#
|
204
|
-
it "should
|
205
|
-
subject.
|
206
|
-
subject.
|
207
|
-
subject.
|
303
|
+
describe "#demolish" do
|
304
|
+
it "should demolish the container" do
|
305
|
+
subject.stub(:destroy) { true }
|
306
|
+
subject.stub(:down) { true }
|
307
|
+
subject.stub(:deprovision) { true }
|
208
308
|
|
209
|
-
subject.
|
210
|
-
|
211
|
-
|
212
|
-
subject.lxc.stub(:state) { :stopped }
|
309
|
+
subject.demolish.should == true
|
310
|
+
end
|
311
|
+
end
|
213
312
|
|
214
|
-
|
313
|
+
describe "#recycle" do
|
314
|
+
it "should recycle the container" do
|
315
|
+
subject.stub(:demolish) { true }
|
316
|
+
subject.stub(:build) { true }
|
215
317
|
|
216
|
-
subject.
|
318
|
+
subject.recycle.should == true
|
319
|
+
end
|
320
|
+
end
|
217
321
|
|
218
|
-
|
322
|
+
describe "#bounce" do
|
323
|
+
it "should bounce the container" do
|
324
|
+
subject.stub(:down) { true }
|
325
|
+
subject.stub(:up) { true }
|
326
|
+
|
327
|
+
subject.bounce.should == true
|
219
328
|
end
|
220
329
|
end
|
221
330
|
|