testlab 0.7.6 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -1
- data/bin/tl +8 -4
- data/features/step_definitions/testlab_steps.rb +5 -1
- data/features/support/Labfile.local +46 -0
- data/features/support/Labfile.vagrant +58 -0
- data/features/support/env.rb +8 -0
- data/features/testlab.feature +4 -8
- data/lib/commands/container.rb +28 -240
- data/lib/commands/network.rb +27 -193
- data/lib/commands/node.rb +9 -160
- data/lib/commands/testlab.rb +72 -10
- data/lib/testlab/container/actions.rb +2 -2
- data/lib/testlab/container/io.rb +21 -12
- data/lib/testlab/container/lifecycle.rb +13 -0
- data/lib/testlab/container/ssh.rb +2 -2
- data/lib/testlab/container.rb +3 -1
- data/lib/testlab/interface.rb +2 -0
- data/lib/testlab/network/actions.rb +2 -2
- data/lib/testlab/network/lifecycle.rb +15 -0
- data/lib/testlab/network/status.rb +1 -1
- data/lib/testlab/network.rb +3 -1
- data/lib/testlab/node/lifecycle.rb +9 -0
- data/lib/testlab/node.rb +2 -0
- data/lib/testlab/user.rb +2 -0
- data/lib/testlab/utility/gli.rb +83 -0
- data/lib/testlab/utility/logger.rb +35 -30
- data/lib/testlab/utility.rb +2 -0
- data/lib/testlab/version.rb +1 -1
- data/lib/testlab.rb +111 -38
- data/spec/container_spec.rb +4 -0
- data/spec/network_spec.rb +4 -0
- metadata +9 -6
- data/features/support/Labfile +0 -85
@@ -13,6 +13,9 @@ class TestLab
|
|
13
13
|
def setup
|
14
14
|
@ui.logger.debug { "Container Setup: #{self.id} " }
|
15
15
|
|
16
|
+
(self.node.state != :running) and return false
|
17
|
+
(self.lxc.state == :not_created) and return false
|
18
|
+
|
16
19
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
17
20
|
|
18
21
|
self.container_provisioners.each do |provisioner|
|
@@ -36,6 +39,7 @@ class TestLab
|
|
36
39
|
def teardown
|
37
40
|
@ui.logger.debug { "Container Teardown: #{self.id} " }
|
38
41
|
|
42
|
+
(self.node.state != :running) and return false
|
39
43
|
(self.lxc.state == :not_created) and return false
|
40
44
|
|
41
45
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
@@ -60,6 +64,15 @@ class TestLab
|
|
60
64
|
true
|
61
65
|
end
|
62
66
|
|
67
|
+
# Demolish the container
|
68
|
+
def demolish
|
69
|
+
self.teardown
|
70
|
+
self.down
|
71
|
+
self.destroy
|
72
|
+
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
63
76
|
# Returns all defined provisioners for this container's networks and the container iteself.
|
64
77
|
def container_provisioners
|
65
78
|
[self.interfaces.map(&:network).map(&:provisioners), self.provisioners].flatten.compact.uniq
|
@@ -20,14 +20,14 @@ class TestLab
|
|
20
20
|
identities = [self.users.map(&:identity), self.node.identity].flatten.compact.uniq
|
21
21
|
|
22
22
|
output = <<-EOF
|
23
|
-
#{ZTK::Template.do_not_edit_notice(:message => %(TestLab "#{self.
|
23
|
+
#{ZTK::Template.do_not_edit_notice(:message => %(TestLab "#{self.id}" SSH Configuration))}
|
24
24
|
Host #{self.id}
|
25
25
|
HostName #{self.ip}
|
26
26
|
Port 22
|
27
27
|
UserKnownHostsFile /dev/null
|
28
28
|
StrictHostKeyChecking no
|
29
29
|
PasswordAuthentication no
|
30
|
-
ForwardAgent
|
30
|
+
ForwardAgent yes
|
31
31
|
IdentitiesOnly yes
|
32
32
|
EOF
|
33
33
|
|
data/lib/testlab/container.rb
CHANGED
@@ -70,7 +70,7 @@ class TestLab
|
|
70
70
|
# An array of symbols of the various keys in our status hash.
|
71
71
|
#
|
72
72
|
# @see TestLab::Container::Status
|
73
|
-
STATUS_KEYS = %w(node_id
|
73
|
+
STATUS_KEYS = %w(id node_id clone fqdn state distro release interfaces provisioners).map(&:to_sym)
|
74
74
|
|
75
75
|
# Sub-Modules
|
76
76
|
autoload :Actions, 'testlab/container/actions'
|
@@ -124,6 +124,8 @@ class TestLab
|
|
124
124
|
@ui = TestLab.ui
|
125
125
|
|
126
126
|
super(*args)
|
127
|
+
|
128
|
+
@ui.logger.info { "Container '#{self.id}' Loaded" }
|
127
129
|
end
|
128
130
|
|
129
131
|
def config_dir
|
data/lib/testlab/interface.rb
CHANGED
@@ -7,7 +7,7 @@ class TestLab
|
|
7
7
|
def create
|
8
8
|
@ui.logger.debug { "Network Create: #{self.id} " }
|
9
9
|
|
10
|
-
(self.node.state
|
10
|
+
(self.node.state != :running) and return false
|
11
11
|
(self.state != :not_created) and return false
|
12
12
|
|
13
13
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Create', :green)) do
|
@@ -21,7 +21,7 @@ class TestLab
|
|
21
21
|
def destroy
|
22
22
|
@ui.logger.debug { "Network Destroy: #{self.id} " }
|
23
23
|
|
24
|
-
(self.node.state
|
24
|
+
(self.node.state != :running) and return false
|
25
25
|
(self.state == :not_created) and return false
|
26
26
|
|
27
27
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Destroy', :red)) do
|
@@ -7,6 +7,9 @@ class TestLab
|
|
7
7
|
def setup
|
8
8
|
@ui.logger.debug { "Network Setup: #{self.id} " }
|
9
9
|
|
10
|
+
(self.node.state != :running) and return false
|
11
|
+
(self.state == :not_created) and return false
|
12
|
+
|
10
13
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
11
14
|
|
12
15
|
self.network_provisioners.each do |provisioner|
|
@@ -24,6 +27,9 @@ class TestLab
|
|
24
27
|
def teardown
|
25
28
|
@ui.logger.debug { "Network Teardown: #{self.id} " }
|
26
29
|
|
30
|
+
(self.node.state != :running) and return false
|
31
|
+
(self.state == :not_created) and return false
|
32
|
+
|
27
33
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
28
34
|
|
29
35
|
self.network_provisioners.each do |provisioner|
|
@@ -46,6 +52,15 @@ class TestLab
|
|
46
52
|
true
|
47
53
|
end
|
48
54
|
|
55
|
+
# Demolish the network
|
56
|
+
def demolish
|
57
|
+
self.teardown
|
58
|
+
self.down
|
59
|
+
self.destroy
|
60
|
+
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
49
64
|
# Returns all defined provisioners for this network's containers and the network iteself.
|
50
65
|
def network_provisioners
|
51
66
|
[self.provisioners, self.interfaces.map(&:container).map(&:provisioners)].flatten.compact.uniq
|
@@ -48,7 +48,7 @@ class TestLab
|
|
48
48
|
:not_created
|
49
49
|
else
|
50
50
|
output = self.node.ssh.exec(%(sudo ifconfig #{self.bridge} 2>&1 | grep 'MTU'), :silence => true, :ignore_exit_status => true).output.strip
|
51
|
-
if ((output =~ /UP/)
|
51
|
+
if ((output =~ /UP/) || (output =~ /RUNNING/))
|
52
52
|
:running
|
53
53
|
else
|
54
54
|
:stopped
|
data/lib/testlab/network.rb
CHANGED
@@ -7,7 +7,7 @@ class TestLab
|
|
7
7
|
#
|
8
8
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
9
9
|
class Network < ZTK::DSL::Base
|
10
|
-
STATUS_KEYS = %w(node_id
|
10
|
+
STATUS_KEYS = %w(id node_id state interface network netmask broadcast provisioners).map(&:to_sym)
|
11
11
|
|
12
12
|
# Sub-Modules
|
13
13
|
autoload :Actions, 'testlab/network/actions'
|
@@ -40,6 +40,8 @@ class TestLab
|
|
40
40
|
@ui = TestLab.ui
|
41
41
|
|
42
42
|
super(*args)
|
43
|
+
|
44
|
+
@ui.logger.info { "Network '#{self.id}' Loaded" }
|
43
45
|
end
|
44
46
|
|
45
47
|
end
|
@@ -54,6 +54,15 @@ class TestLab
|
|
54
54
|
true
|
55
55
|
end
|
56
56
|
|
57
|
+
# Demolish the node
|
58
|
+
def demolish
|
59
|
+
self.teardown
|
60
|
+
self.down
|
61
|
+
self.destroy
|
62
|
+
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
57
66
|
# Returns all defined provisioners for this node and it's networks and containers.
|
58
67
|
def all_provisioners
|
59
68
|
[self.provisioners, self.networks.map(&:provisioners), self.containers.map(&:provisioners)].flatten.compact.uniq
|
data/lib/testlab/node.rb
CHANGED
data/lib/testlab/user.rb
CHANGED
@@ -0,0 +1,83 @@
|
|
1
|
+
class TestLab
|
2
|
+
module Utility
|
3
|
+
|
4
|
+
# GLI Module
|
5
|
+
#
|
6
|
+
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
7
|
+
module GLI
|
8
|
+
require 'ztk'
|
9
|
+
|
10
|
+
LAB_ACTION_ORDER = %W(create destroy up down setup teardown build demolish).map(&:to_sym)
|
11
|
+
|
12
|
+
LAB_ACTIONS = {
|
13
|
+
:create => ["Construct %s", "Attempts to create the <%= @component %>."],
|
14
|
+
:destroy => ["Destruct %s", "Attempts to destroy the <%= @component %>."],
|
15
|
+
:up => ["On-line %s", "Attempts to online the <%= @component %>."],
|
16
|
+
:down => ["Off-line %s", "Attempts to offline the <%= @component %>."],
|
17
|
+
:setup => ["Provision %s", "Attempts to provision the <%= @component %>."],
|
18
|
+
:teardown => ["De-provision %s", "Attempts to deprovision the <%= @component %>."],
|
19
|
+
:build => ["Build %s", <<-EOF],
|
20
|
+
Attempts to build the <%= @component %>. TestLab will attempt to create, online and provision the <%= @component %>.
|
21
|
+
|
22
|
+
The <%= @component %> are taken through the following states:
|
23
|
+
|
24
|
+
Create -> Up -> Setup
|
25
|
+
EOF
|
26
|
+
:demolish => ["Demolish %s", <<-EOF]
|
27
|
+
Attempts to demolish the <%= @component %>. TestLab will attempt to deprovision, offline and destroy the <%= @component %>.
|
28
|
+
|
29
|
+
The <%= @component %> are taken through the following states:
|
30
|
+
|
31
|
+
Teardown -> Down -> Destroy
|
32
|
+
EOF
|
33
|
+
}
|
34
|
+
|
35
|
+
def build_lab_commands(component, klass, &block)
|
36
|
+
desc %(Manage lab #{component}s)
|
37
|
+
command component do |c|
|
38
|
+
c.desc %(Optional #{component} ID or comma separated list of #{component} IDs)
|
39
|
+
c.arg_name %(#{component}[,#{component},...])
|
40
|
+
c.flag [:n, :name]
|
41
|
+
|
42
|
+
LAB_ACTION_ORDER.each do |lab_action|
|
43
|
+
action_desc = LAB_ACTIONS[lab_action]
|
44
|
+
c.desc(action_desc.first % "#{component}s")
|
45
|
+
c.long_desc(ZTK::Template.string(action_desc.last, {:component => "#{component}s"}))
|
46
|
+
|
47
|
+
c.command lab_action do |la|
|
48
|
+
la.action do |global_options, options, args|
|
49
|
+
iterate_objects_by_name(options[:name], klass) do |object|
|
50
|
+
object.send(lab_action)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
!block.nil? and block.call(c)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def iterate_objects_by_name(name, klass, &block)
|
61
|
+
objects = Array.new
|
62
|
+
klass_name = klass.to_s.split('::').last.downcase
|
63
|
+
|
64
|
+
if name.nil?
|
65
|
+
objects = klass.all
|
66
|
+
else
|
67
|
+
names = name.split(',')
|
68
|
+
objects = klass.find(names)
|
69
|
+
end
|
70
|
+
|
71
|
+
(objects.nil? || (objects.count == 0)) and raise TestLab::TestLabError, "We could not find any of the #{klass_name}s you supplied!"
|
72
|
+
|
73
|
+
objects.each do |object|
|
74
|
+
!block.nil? and block.call(object)
|
75
|
+
end
|
76
|
+
|
77
|
+
objects
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -16,76 +16,81 @@ class TestLab
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def log_page_break(max_key_length, char='-')
|
19
|
+
(max_key_length > 80) and (max_key_length = 80)
|
19
20
|
(char * max_key_length)
|
20
21
|
end
|
21
22
|
|
22
|
-
def
|
23
|
+
def log_config(testlab)
|
23
24
|
{
|
24
|
-
"hostname" => "%s (%s)" % [Socket.gethostname.inspect, TestLab.hostname.inspect],
|
25
|
-
"program" => $0.to_s.inspect,
|
26
25
|
"config_dir" => testlab.config_dir.inspect,
|
27
26
|
"repo_dir" => testlab.repo_dir.inspect,
|
28
27
|
"labfile_path" => testlab.labfile_path.inspect,
|
29
28
|
"logdev" => testlab.ui.logger.logdev.inspect,
|
30
29
|
"version" => TestLab::VERSION.inspect,
|
31
|
-
"argv" => ARGV.inspect
|
32
30
|
}
|
33
31
|
end
|
34
32
|
|
35
|
-
def
|
33
|
+
def log_details(testlab)
|
34
|
+
{
|
35
|
+
"hostname" => "%s (%s)" % [Socket.gethostname.inspect, TestLab.hostname.inspect],
|
36
|
+
"program" => $0.to_s.inspect,
|
37
|
+
"argv" => ARGV.join(' ').inspect,
|
38
|
+
"timezone" => Time.now.zone.inspect
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def log_ruby(testlab)
|
36
43
|
dependencies = {
|
37
44
|
"ruby_version" => RUBY_VERSION.inspect,
|
38
45
|
"ruby_patchlevel" => RUBY_PATCHLEVEL.inspect,
|
39
46
|
"ruby_platform" => RUBY_PLATFORM.inspect
|
40
47
|
}
|
41
48
|
|
42
|
-
defined?(RUBY_ENGINE)
|
49
|
+
defined?(RUBY_ENGINE) and dependencies.merge!("ruby_engine" => RUBY_ENGINE)
|
50
|
+
defined?(RUBY_DESCRIPTION) and dependencies.merge!("ruby_description" => RUBY_DESCRIPTION)
|
51
|
+
defined?(RUBY_RELEASE_DATE) and dependencies.merge!("ruby_release_date" => RUBY_RELEASE_DATE)
|
43
52
|
|
44
53
|
dependencies
|
45
54
|
end
|
46
55
|
|
47
|
-
def
|
48
|
-
@command = ZTK::Command.new(:silence => true, :ignore_exit_status => true)
|
49
|
-
|
56
|
+
def log_gem_dependencies(testlab)
|
50
57
|
{
|
51
58
|
"gli_version" => ::GLI::VERSION.inspect,
|
52
59
|
"lxc_version" => ::LXC::VERSION.inspect,
|
53
60
|
"ztk_version" => ::ZTK::VERSION.inspect,
|
54
|
-
"activesupport_version" => ::ActiveSupport::VERSION::STRING.inspect
|
61
|
+
"activesupport_version" => ::ActiveSupport::VERSION::STRING.inspect
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def log_external_dependencies(testlab)
|
66
|
+
@command = ZTK::Command.new(:silence => true, :ignore_exit_status => true)
|
67
|
+
|
68
|
+
{
|
55
69
|
"vagrant_version" => @command.exec(%(/usr/bin/env vagrant --version)).output.strip.inspect,
|
56
|
-
"virtualbox_version" => @command.exec(%(/usr/bin/env vboxmanage --version)).output.strip.inspect
|
70
|
+
"virtualbox_version" => @command.exec(%(/usr/bin/env vboxmanage --version)).output.strip.inspect,
|
71
|
+
"lxc_version" => @command.exec(%(/usr/bin/env lxc-version)).output.strip.inspect
|
57
72
|
}
|
58
73
|
end
|
59
74
|
|
60
75
|
def log_header(testlab)
|
61
76
|
log_lines = Array.new
|
62
77
|
|
63
|
-
|
64
|
-
|
65
|
-
dependencies_hash = log_dependencies
|
78
|
+
log_methods = [:log_details, :log_config, :log_ruby, :log_gem_dependencies, :log_external_dependencies]
|
79
|
+
log_hashes = log_methods.collect{ |log_method| self.send(log_method, testlab) }
|
66
80
|
|
67
|
-
max_key_length =
|
68
|
-
max_value_length =
|
81
|
+
max_key_length = log_hashes.collect{ |log_hash| log_hash.keys }.flatten.compact.map(&:length).max + 2
|
82
|
+
max_value_length = log_hashes.collect{ |log_hash| log_hash.values }.flatten.compact.map(&:length).max + 2
|
69
83
|
|
70
84
|
max_length = (max_key_length + max_value_length + 2)
|
71
85
|
|
72
86
|
log_lines << log_page_break(max_length, '=')
|
73
|
-
|
74
|
-
|
87
|
+
log_hashes.each do |log_hash|
|
88
|
+
log_hash.sort.each do |key, value|
|
89
|
+
log_lines << log_key_value(key, value, max_key_length)
|
90
|
+
end
|
91
|
+
log_lines << log_page_break(max_length, '=')
|
75
92
|
end
|
76
93
|
|
77
|
-
log_lines << log_page_break(max_length)
|
78
|
-
ruby_hash.sort.each do |key, value|
|
79
|
-
log_lines << log_key_value(key, value, max_key_length)
|
80
|
-
end
|
81
|
-
|
82
|
-
log_lines << log_page_break(max_length)
|
83
|
-
dependencies_hash.sort.each do |key, value|
|
84
|
-
log_lines << log_key_value(key, value, max_key_length)
|
85
|
-
end
|
86
|
-
|
87
|
-
log_lines << log_page_break(max_length, '=')
|
88
|
-
|
89
94
|
log_lines.flatten.compact
|
90
95
|
end
|
91
96
|
|
data/lib/testlab/utility.rb
CHANGED
@@ -11,10 +11,12 @@ 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'
|
14
15
|
autoload :Logger, 'testlab/utility/logger'
|
15
16
|
autoload :Misc, 'testlab/utility/misc'
|
16
17
|
|
17
18
|
extend TestLab::Utility::CIDR
|
19
|
+
extend TestLab::Utility::GLI
|
18
20
|
extend TestLab::Utility::Logger
|
19
21
|
extend TestLab::Utility::Misc
|
20
22
|
|
data/lib/testlab/version.rb
CHANGED
data/lib/testlab.rb
CHANGED
@@ -17,53 +17,85 @@ require 'testlab/monkeys'
|
|
17
17
|
# to accomplish this.
|
18
18
|
#
|
19
19
|
# @example Sample Labfile:
|
20
|
-
#
|
21
|
-
# set -x
|
22
|
-
# apt-get -y update
|
23
|
-
# apt-get -y install dnsutils
|
24
|
-
# EOF
|
20
|
+
# node 'vagrant' do
|
25
21
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# node :localhost do
|
32
|
-
# components %w(resolv bind)
|
33
|
-
# route true
|
22
|
+
# provider TestLab::Provider::Vagrant
|
23
|
+
# provisioners [
|
24
|
+
# TestLab::Provisioner::Raring,
|
25
|
+
# TestLab::Provisioner::Bind
|
26
|
+
# ]
|
34
27
|
#
|
35
|
-
#
|
36
|
-
# config Hash[
|
28
|
+
# config ({
|
37
29
|
# :vagrant => {
|
38
|
-
# :id => "
|
39
|
-
# :
|
40
|
-
# :
|
41
|
-
# :
|
42
|
-
# :
|
43
|
-
# :
|
44
|
-
#
|
30
|
+
# :id => "chef-rubygem-#{TestLab.hostname}".downcase,
|
31
|
+
# :cpus => ZTK::Parallel::MAX_FORKS.div(2), # use half of the available processors
|
32
|
+
# :memory => ZTK::Parallel::MAX_MEMORY.div(3).div(1024 * 1024), # use a third of available RAM
|
33
|
+
# :box => 'raring64',
|
34
|
+
# :box_url => 'https://dl.dropboxusercontent.com/u/22904185/boxes/raring64.box',
|
35
|
+
# :file => File.dirname(__FILE__)
|
36
|
+
# },
|
37
|
+
# :bind => {
|
38
|
+
# :domain => "default.zone"
|
45
39
|
# }
|
46
|
-
#
|
40
|
+
# })
|
47
41
|
#
|
48
|
-
# network
|
49
|
-
#
|
50
|
-
#
|
42
|
+
# network 'labnet' do
|
43
|
+
# provisioners [TestLab::Provisioner::Route]
|
44
|
+
# address '10.10.0.1/16'
|
45
|
+
# bridge :br0
|
51
46
|
# end
|
52
47
|
#
|
53
|
-
# container "server
|
54
|
-
#
|
48
|
+
# container "chef-server" do
|
49
|
+
# distro "ubuntu"
|
50
|
+
# release "precise"
|
51
|
+
#
|
52
|
+
# provisioners [
|
53
|
+
# TestLab::Provisioner::Resolv,
|
54
|
+
# TestLab::Provisioner::AptCacherNG,
|
55
|
+
# TestLab::Provisioner::Apt,
|
56
|
+
# TestLab::Provisioner::Chef::RubyGemServer
|
57
|
+
# ]
|
58
|
+
#
|
59
|
+
# user 'deployer' do
|
60
|
+
# password 'deployer'
|
61
|
+
# identity File.join(ENV['HOME'], '.ssh', 'id_rsa')
|
62
|
+
# public_identity File.join(ENV['HOME'], '.ssh', 'id_rsa.pub')
|
63
|
+
# uid 2600
|
64
|
+
# gid 2600
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# interface do
|
68
|
+
# network_id 'labnet'
|
69
|
+
# name :eth0
|
70
|
+
# address '10.10.0.254/16'
|
71
|
+
# mac '00:00:5e:63:b5:9f'
|
72
|
+
# end
|
73
|
+
# end
|
55
74
|
#
|
75
|
+
# container "chef-client" do
|
56
76
|
# distro "ubuntu"
|
57
77
|
# release "precise"
|
58
78
|
#
|
59
|
-
#
|
60
|
-
#
|
79
|
+
# provisioners [
|
80
|
+
# TestLab::Provisioner::Resolv,
|
81
|
+
# TestLab::Provisioner::AptCacherNG,
|
82
|
+
# TestLab::Provisioner::Apt,
|
83
|
+
# TestLab::Provisioner::Chef::RubyGemClient
|
84
|
+
# ]
|
85
|
+
#
|
86
|
+
# user 'deployer' do
|
87
|
+
# password 'deployer'
|
88
|
+
# identity File.join(ENV['HOME'], '.ssh', 'id_rsa')
|
89
|
+
# public_identity File.join(ENV['HOME'], '.ssh', 'id_rsa.pub')
|
90
|
+
# uid 2600
|
91
|
+
# gid 2600
|
92
|
+
# end
|
61
93
|
#
|
62
94
|
# interface do
|
63
|
-
#
|
64
|
-
#
|
65
|
-
# address
|
66
|
-
# mac
|
95
|
+
# network_id 'labnet'
|
96
|
+
# name :eth0
|
97
|
+
# address '10.10.0.20/16'
|
98
|
+
# mac '00:00:5e:b7:e5:15'
|
67
99
|
# end
|
68
100
|
# end
|
69
101
|
#
|
@@ -78,8 +110,8 @@ require 'testlab/monkeys'
|
|
78
110
|
# @example We can control things via code easily as well:
|
79
111
|
# testlab.create # creates the lab
|
80
112
|
# testlab.up # ensures the lab is up and running
|
81
|
-
# testlab.
|
82
|
-
# testlab.
|
113
|
+
# testlab.build # build the lab, creating all networks and containers
|
114
|
+
# testlab.demolish # demolish the lab, destroy all networks and containers
|
83
115
|
#
|
84
116
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
85
117
|
class TestLab
|
@@ -115,11 +147,16 @@ class TestLab
|
|
115
147
|
|
116
148
|
labfile_path = (options[:labfile_path] || File.join(@repo_dir, 'Labfile'))
|
117
149
|
@labfile_path = File.expand_path(ZTK::Locator.find(labfile_path))
|
150
|
+
end
|
118
151
|
|
152
|
+
# Boot TestLab
|
153
|
+
#
|
154
|
+
# Change to the defined repository directory and load the *Labfile*.
|
155
|
+
#
|
156
|
+
# @return [Boolean] True if successful.
|
157
|
+
def boot
|
119
158
|
@labfile = TestLab::Labfile.load(labfile_path)
|
120
159
|
@labfile.testlab = self
|
121
|
-
|
122
|
-
Dir.chdir(@repo_dir)
|
123
160
|
end
|
124
161
|
|
125
162
|
# Test Lab Nodes
|
@@ -186,6 +223,30 @@ class TestLab
|
|
186
223
|
!alive?
|
187
224
|
end
|
188
225
|
|
226
|
+
# Test Lab Create
|
227
|
+
#
|
228
|
+
# Attempts to create our lab topology. This calls the create method on all of
|
229
|
+
# our nodes.
|
230
|
+
#
|
231
|
+
# @return [Boolean] True if successful.
|
232
|
+
def create
|
233
|
+
method_proxy(:create)
|
234
|
+
|
235
|
+
true
|
236
|
+
end
|
237
|
+
|
238
|
+
# Test Lab Destroy
|
239
|
+
#
|
240
|
+
# Attempts to destroy our lab topology. This calls the destroy method on all of
|
241
|
+
# our nodes.
|
242
|
+
#
|
243
|
+
# @return [Boolean] True if successful.
|
244
|
+
def destroy
|
245
|
+
reverse_method_proxy(:destroy)
|
246
|
+
|
247
|
+
true
|
248
|
+
end
|
249
|
+
|
189
250
|
# Test Lab Up
|
190
251
|
#
|
191
252
|
# Attempts to up our lab topology. This calls the up method on all of
|
@@ -246,6 +307,18 @@ class TestLab
|
|
246
307
|
true
|
247
308
|
end
|
248
309
|
|
310
|
+
# Test Lab Demolish
|
311
|
+
#
|
312
|
+
# Attempts to demolish our lab topology. This calls various methods on
|
313
|
+
# all of our nodes, networks and containers.
|
314
|
+
#
|
315
|
+
# @return [Boolean] True if successful.
|
316
|
+
def demolish
|
317
|
+
reverse_method_proxy(:demolish)
|
318
|
+
|
319
|
+
true
|
320
|
+
end
|
321
|
+
|
249
322
|
# Node Method Proxy
|
250
323
|
#
|
251
324
|
# Iterates all of the lab nodes, sending the supplied method name and arguments
|
data/spec/container_spec.rb
CHANGED
@@ -195,6 +195,7 @@ describe TestLab::Container do
|
|
195
195
|
describe "#setup" do
|
196
196
|
context "with no provisioner" do
|
197
197
|
it "should setup the container" do
|
198
|
+
subject.node.stub(:state) { :running }
|
198
199
|
subject.lxc.stub(:exists?) { true }
|
199
200
|
subject.lxc.stub(:state) { :stopped }
|
200
201
|
subject.provisioners = Array.new
|
@@ -207,6 +208,7 @@ describe TestLab::Container do
|
|
207
208
|
it "should setup the container" do
|
208
209
|
subject = TestLab::Container.first('server-shell')
|
209
210
|
|
211
|
+
subject.node.stub(:state) { :running }
|
210
212
|
subject.lxc.stub(:exists?) { true }
|
211
213
|
subject.lxc.stub(:state) { :stopped }
|
212
214
|
subject.provisioners = Array.new
|
@@ -219,6 +221,7 @@ describe TestLab::Container do
|
|
219
221
|
describe "#teardown" do
|
220
222
|
context "with no provisioner" do
|
221
223
|
it "should teardown the container" do
|
224
|
+
subject.node.stub(:state) { :running }
|
222
225
|
subject.lxc.stub(:exists?) { true }
|
223
226
|
subject.lxc.stub(:state) { :stopped }
|
224
227
|
subject.provisioners = Array.new
|
@@ -231,6 +234,7 @@ describe TestLab::Container do
|
|
231
234
|
it "should teardown the container" do
|
232
235
|
subject = TestLab::Container.first('server-shell')
|
233
236
|
|
237
|
+
subject.node.stub(:state) { :running }
|
234
238
|
subject.lxc.stub(:exists?) { true }
|
235
239
|
subject.lxc.stub(:state) { :stopped }
|
236
240
|
subject.provisioners = Array.new
|
data/spec/network_spec.rb
CHANGED
@@ -144,6 +144,8 @@ describe TestLab::Network do
|
|
144
144
|
|
145
145
|
describe "#setup" do
|
146
146
|
it "should create and online the network" do
|
147
|
+
subject.node.stub(:state) { :running }
|
148
|
+
subject.stub(:state) { :running }
|
147
149
|
subject.stub(:create) { true }
|
148
150
|
subject.stub(:up) { true }
|
149
151
|
|
@@ -153,6 +155,8 @@ describe TestLab::Network do
|
|
153
155
|
|
154
156
|
describe "#teardown" do
|
155
157
|
it "should create and online the network" do
|
158
|
+
subject.node.stub(:state) { :running }
|
159
|
+
subject.stub(:state) { :running }
|
156
160
|
subject.stub(:down) { true }
|
157
161
|
subject.stub(:destroy) { true }
|
158
162
|
|