testlab 0.7.4 → 0.7.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Rakefile +12 -0
- data/bin/tl +10 -10
- data/features/step_definitions/container_steps.rb +35 -0
- data/features/step_definitions/network_steps.rb +7 -0
- data/features/step_definitions/node_steps.rb +19 -0
- data/features/step_definitions/testlab_steps.rb +28 -0
- data/features/support/Labfile +85 -0
- data/features/support/env.rb +18 -0
- data/features/testlab.feature +64 -0
- data/lib/commands/container.rb +118 -73
- data/lib/commands/network.rb +17 -13
- data/lib/testlab/container/actions.rb +4 -0
- data/lib/testlab/container/lxc.rb +5 -1
- data/lib/testlab/network/actions.rb +4 -0
- data/lib/testlab/utility/logger.rb +2 -1
- data/lib/testlab/version.rb +1 -1
- data/lib/testlab.rb +9 -4
- data/spec/container_spec.rb +5 -1
- data/spec/network_spec.rb +5 -1
- data/spec/node_spec.rb +1 -1
- data/spec/provisioners/shell_spec.rb +5 -1
- data/spec/testlab_spec.rb +1 -1
- data/testlab.gemspec +1 -0
- metadata +34 -4
data/.gitignore
CHANGED
data/Rakefile
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
#
|
19
19
|
################################################################################
|
20
20
|
|
21
|
+
require 'rake/clean'
|
21
22
|
require 'bundler/gem_tasks'
|
22
23
|
|
23
24
|
################################################################################
|
@@ -29,6 +30,17 @@ task :test => [:spec]
|
|
29
30
|
|
30
31
|
################################################################################
|
31
32
|
|
33
|
+
require 'cucumber/rake/task'
|
34
|
+
desc 'Run features'
|
35
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
36
|
+
opts = "features --format pretty -x"
|
37
|
+
opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
|
38
|
+
t.cucumber_opts = opts
|
39
|
+
t.fork = false
|
40
|
+
end
|
41
|
+
|
42
|
+
################################################################################
|
43
|
+
|
32
44
|
require 'coveralls/rake/task'
|
33
45
|
Coveralls::RakeTask.new
|
34
46
|
task :coveralls => [:spec, 'coveralls:push']
|
data/bin/tl
CHANGED
@@ -18,8 +18,6 @@
|
|
18
18
|
# limitations under the License.
|
19
19
|
#
|
20
20
|
################################################################################
|
21
|
-
require 'socket'
|
22
|
-
|
23
21
|
require 'gli'
|
24
22
|
require 'testlab'
|
25
23
|
|
@@ -34,6 +32,8 @@ program_desc %(TestLab - A toolkit for building virtual computer labs)
|
|
34
32
|
sort_help :manually
|
35
33
|
default_command :help
|
36
34
|
|
35
|
+
preserve_argv true
|
36
|
+
|
37
37
|
commands_from 'commands'
|
38
38
|
|
39
39
|
desc 'Show verbose output'
|
@@ -44,9 +44,9 @@ desc 'Quiet mode'
|
|
44
44
|
default_value false
|
45
45
|
switch [:q, :quiet]
|
46
46
|
|
47
|
-
desc 'Path to Labfile: ${
|
47
|
+
desc 'Path to Labfile: ${REPO}/Labfile'
|
48
48
|
arg_name 'path/to/file'
|
49
|
-
default_value File.join(Dir.pwd, 'Labfile')
|
49
|
+
# default_value File.join(Dir.pwd, 'Labfile')
|
50
50
|
flag [:l, :labfile]
|
51
51
|
|
52
52
|
desc 'Path to Repository directory: ${PWD}'
|
@@ -54,15 +54,15 @@ arg_name 'path/to/directory'
|
|
54
54
|
default_value Dir.pwd
|
55
55
|
flag [:r, :repo]
|
56
56
|
|
57
|
-
desc 'Path to Configuration directory: ${
|
57
|
+
desc 'Path to Configuration directory: ${REPO}/.testlab-$(hostname -s)'
|
58
58
|
arg_name 'path/to/directory'
|
59
|
-
default_value File.join(Dir.pwd, ".testlab-#{TestLab.hostname}")
|
59
|
+
# default_value File.join(Dir.pwd, ".testlab-#{TestLab.hostname}")
|
60
60
|
flag [:c, :config]
|
61
61
|
|
62
62
|
pre do |global,command,options,args|
|
63
63
|
(global[:verbose] == true) and (ENV['LOG_LEVEL'] = 'DEBUG')
|
64
64
|
|
65
|
-
log_file = File.join(
|
65
|
+
log_file = File.join(global[:repo], "testlab-#{TestLab.hostname}.log")
|
66
66
|
@logger = ZTK::Logger.new(log_file)
|
67
67
|
|
68
68
|
@ui = ZTK::UI.new(
|
@@ -73,9 +73,9 @@ pre do |global,command,options,args|
|
|
73
73
|
|
74
74
|
@testlab = TestLab.new(
|
75
75
|
:ui => @ui,
|
76
|
-
:
|
77
|
-
:config_dir
|
78
|
-
:repo_dir
|
76
|
+
:labfile_path => global[:labfile],
|
77
|
+
:config_dir => global[:config],
|
78
|
+
:repo_dir => global[:repo]
|
79
79
|
)
|
80
80
|
|
81
81
|
@ui.logger.debug { "global(#{global.inspect})" }
|
@@ -0,0 +1,35 @@
|
|
1
|
+
When /^I get the containers status with "([^"]*)"$/ do |app_name|
|
2
|
+
container_cmd(app_name, %W(status -n test-server))
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I get the containers ssh-config with "([^"]*)"$/ do |app_name|
|
6
|
+
container_cmd(app_name, %W(ssh-config -n test-server))
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I up the containers with "([^"]*)"$/ do |app_name|
|
10
|
+
container_cmd(app_name, %W(up -n test-server))
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I down the containers with "([^"]*)"$/ do |app_name|
|
14
|
+
container_cmd(app_name, %W(down -n test-server))
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^I clone the containers with "([^"]*)"$/ do |app_name|
|
18
|
+
container_cmd(app_name, %W(clone -n test-server))
|
19
|
+
end
|
20
|
+
|
21
|
+
When /^I build the containers with "([^"]*)"$/ do |app_name|
|
22
|
+
container_cmd(app_name, %W(build -n test-server))
|
23
|
+
end
|
24
|
+
|
25
|
+
When /^I export the containers with "([^"]*)"$/ do |app_name|
|
26
|
+
container_cmd(app_name, %W(export -n test-server --output=/tmp/test-server.sc))
|
27
|
+
end
|
28
|
+
|
29
|
+
When /^I import the containers with "([^"]*)"$/ do |app_name|
|
30
|
+
container_cmd(app_name, %W(import -n test-server --input=/tmp/test-server.sc))
|
31
|
+
end
|
32
|
+
|
33
|
+
def container_cmd(app_name, *args)
|
34
|
+
testlab_cmd(app_name, [%(container), args].flatten)
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
When /^I get the nodes status with "([^"]*)"$/ do |app_name|
|
2
|
+
node_cmd(app_name, %W(status -n vagrant))
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I up the nodes with "([^"]*)"$/ do |app_name|
|
6
|
+
node_cmd(app_name, %W(up -n vagrant))
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I down the nodes with "([^"]*)"$/ do |app_name|
|
10
|
+
node_cmd(app_name, %W(down -n vagrant))
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I build the nodes with "([^"]*)"$/ do |app_name|
|
14
|
+
node_cmd(app_name, %W(build -n vagrant))
|
15
|
+
end
|
16
|
+
|
17
|
+
def node_cmd(app_name, *args)
|
18
|
+
testlab_cmd(app_name, [%(node), args].flatten)
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
When /^I get help for "([^"]*)"$/ do |app_name|
|
2
|
+
testlab_cmd(app_name, %W(help))
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I get the status with "([^"]*)"$/ do |app_name|
|
6
|
+
testlab_cmd(app_name, %W(status))
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I build the lab with "([^"]*)"$/ do |app_name|
|
10
|
+
testlab_cmd(app_name, %W(build))
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I up the lab with "([^"]*)"$/ do |app_name|
|
14
|
+
testlab_cmd(app_name, %W(up))
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^I down the lab with "([^"]*)"$/ do |app_name|
|
18
|
+
testlab_cmd(app_name, %W(down))
|
19
|
+
end
|
20
|
+
|
21
|
+
When /^I destroy the lab with "([^"]*)"$/ do |app_name|
|
22
|
+
testlab_cmd(app_name, %W(destroy))
|
23
|
+
end
|
24
|
+
|
25
|
+
def testlab_cmd(app_name, *args)
|
26
|
+
args = args.join(' ')
|
27
|
+
step %(I run `#{app_name} --repo=#{TEST_REPO} #{args}`)
|
28
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#^syntax detection
|
3
|
+
|
4
|
+
# Labfile Simple Example
|
5
|
+
#########################
|
6
|
+
# This is a simple example that builds a lab with a chef-server and chef-client.
|
7
|
+
|
8
|
+
# Here we define our node; in this case we are using the localhost. We've
|
9
|
+
# selected the Vagrant provider so the Vagrant VM will be our target LXC node.
|
10
|
+
node :vagrant do
|
11
|
+
|
12
|
+
# This sets the provider for our node. This could be many things, from
|
13
|
+
# Vagrant, to AWS, to Local, to custom internal providers. Any class can be
|
14
|
+
# supplied assuming it's interface honors our contract.
|
15
|
+
provider TestLab::Provider::Vagrant
|
16
|
+
|
17
|
+
# These are provisioners that only need to run against the node (i.e. they
|
18
|
+
# do not have any container components). Provisioner classes applied to
|
19
|
+
# containers only are automatically interogated and executed during runtime
|
20
|
+
# if they have a node component.
|
21
|
+
provisioners [
|
22
|
+
TestLab::Provisioner::Raring,
|
23
|
+
TestLab::Provisioner::Bind
|
24
|
+
]
|
25
|
+
|
26
|
+
# this is a generic configuration object (hash) which is supplied to
|
27
|
+
# the provider
|
28
|
+
config ({
|
29
|
+
:vagrant => {
|
30
|
+
:id => "test-cucumber-#{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"
|
39
|
+
}
|
40
|
+
})
|
41
|
+
|
42
|
+
# Here we define our network segments; these will manifest into network
|
43
|
+
# bridges on the target LXC node.
|
44
|
+
network 'labnet' do
|
45
|
+
# provisioners [TestLab::Provisioner::Route]
|
46
|
+
address '10.128.0.1/16'
|
47
|
+
bridge :br0
|
48
|
+
end
|
49
|
+
|
50
|
+
# test-server.default.zone
|
51
|
+
###########################
|
52
|
+
container "test-server" do
|
53
|
+
distro "ubuntu"
|
54
|
+
release "precise"
|
55
|
+
|
56
|
+
provisioners [
|
57
|
+
TestLab::Provisioner::Resolv,
|
58
|
+
TestLab::Provisioner::AptCacherNG,
|
59
|
+
TestLab::Provisioner::Apt
|
60
|
+
]
|
61
|
+
|
62
|
+
# Here we define a default user to seed onto the box. This user will be
|
63
|
+
# given passwordless sudo access as well.
|
64
|
+
user 'deployer' do
|
65
|
+
password 'deployer'
|
66
|
+
identity File.join(ENV['HOME'], '.ssh', 'id_rsa')
|
67
|
+
public_identity File.join(ENV['HOME'], '.ssh', 'id_rsa.pub')
|
68
|
+
uid 2600
|
69
|
+
gid 2600
|
70
|
+
end
|
71
|
+
|
72
|
+
# Interfaces define what networks this container is linked to and what our
|
73
|
+
# configuration on that network should be. In the event we have more than
|
74
|
+
# one interface we should define one as the "primary". When multiple
|
75
|
+
# interfaces are at play, the default route for the container will be off
|
76
|
+
# the primary interface.
|
77
|
+
interface do
|
78
|
+
network_id 'labnet'
|
79
|
+
name :eth0
|
80
|
+
address '10.128.0.254/16'
|
81
|
+
mac '00:00:5e:63:b5:9f'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'aruba/cucumber'
|
2
|
+
|
3
|
+
ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
4
|
+
LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
|
5
|
+
TEST_REPO = File.dirname(__FILE__)
|
6
|
+
|
7
|
+
Before do
|
8
|
+
# Using "announce" causes massive warnings on 1.9.2
|
9
|
+
@aruba_timeout_seconds = 3600
|
10
|
+
@puts = true
|
11
|
+
@original_rubylib = ENV['RUBYLIB']
|
12
|
+
ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
13
|
+
# ENV['VAGRANT_HOME'] = File.join("", "tmp", ".vagrant.d")
|
14
|
+
end
|
15
|
+
|
16
|
+
After do
|
17
|
+
ENV['RUBYLIB'] = @original_rubylib
|
18
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
Feature: TestLab command-line
|
2
|
+
|
3
|
+
Background: TestLab status
|
4
|
+
When I get the status with "tl"
|
5
|
+
Then the exit status should be 0
|
6
|
+
When I get the nodes status with "tl"
|
7
|
+
Then the exit status should be 0
|
8
|
+
When I get the networks status with "tl"
|
9
|
+
Then the exit status should be 0
|
10
|
+
When I get the containers status with "tl"
|
11
|
+
Then the exit status should be 0
|
12
|
+
When I get the containers ssh-config with "tl"
|
13
|
+
Then the exit status should be 0
|
14
|
+
|
15
|
+
|
16
|
+
Scenario: TestLab help
|
17
|
+
When I get help for "tl"
|
18
|
+
Then the exit status should be 0
|
19
|
+
|
20
|
+
|
21
|
+
Scenario: TestLab export
|
22
|
+
When I build the lab with "tl"
|
23
|
+
Then the exit status should be 0
|
24
|
+
When I export the containers with "tl"
|
25
|
+
Then the exit status should be 0
|
26
|
+
|
27
|
+
|
28
|
+
Scenario: TestLab import
|
29
|
+
When I down the lab with "tl"
|
30
|
+
Then the exit status should be 0
|
31
|
+
When I build the nodes with "tl"
|
32
|
+
Then the exit status should be 0
|
33
|
+
When I import the containers with "tl"
|
34
|
+
Then the exit status should be 0
|
35
|
+
When I build the lab with "tl"
|
36
|
+
Then the exit status should be 0
|
37
|
+
|
38
|
+
|
39
|
+
Scenario: TestLab clone
|
40
|
+
When I down the lab with "tl"
|
41
|
+
Then the exit status should be 0
|
42
|
+
When I build the lab with "tl"
|
43
|
+
Then the exit status should be 0
|
44
|
+
When I clone the containers with "tl"
|
45
|
+
Then the exit status should be 0
|
46
|
+
When I build the containers with "tl"
|
47
|
+
Then the exit status should be 0
|
48
|
+
When I clone the containers with "tl"
|
49
|
+
Then the exit status should be 0
|
50
|
+
When I build the containers with "tl"
|
51
|
+
Then the exit status should be 0
|
52
|
+
When I down the containers with "tl"
|
53
|
+
Then the exit status should be 0
|
54
|
+
When I up the containers with "tl"
|
55
|
+
Then the exit status should be 0
|
56
|
+
When I build the containers with "tl"
|
57
|
+
Then the exit status should be 0
|
58
|
+
|
59
|
+
|
60
|
+
Scenario: TestLab destroy
|
61
|
+
When I down the lab with "tl"
|
62
|
+
Then the exit status should be 0
|
63
|
+
When I destroy the lab with "tl"
|
64
|
+
Then the exit status should be 0
|
data/lib/commands/container.rb
CHANGED
@@ -24,25 +24,28 @@ desc 'Manage containers'
|
|
24
24
|
arg_name 'Describe arguments to container here'
|
25
25
|
command :container do |c|
|
26
26
|
|
27
|
-
c.desc '
|
28
|
-
c.arg_name 'container'
|
27
|
+
c.desc 'Single or comma separated list of container IDs'
|
28
|
+
c.arg_name 'container[,container,...]'
|
29
29
|
c.flag [:n, :name]
|
30
30
|
|
31
31
|
# CONTAINER CREATE
|
32
32
|
###################
|
33
33
|
c.desc 'Create a container'
|
34
34
|
c.long_desc <<-EOF
|
35
|
-
|
35
|
+
Creates a container on the node the container belongs to.
|
36
36
|
EOF
|
37
37
|
c.command :create do |create|
|
38
38
|
create.action do |global_options, options, args|
|
39
39
|
if options[:name].nil?
|
40
40
|
help_now!('a name is required') if options[:name].nil?
|
41
41
|
else
|
42
|
-
|
43
|
-
|
42
|
+
names = options[:name].split(',')
|
43
|
+
containers = TestLab::Container.find(names)
|
44
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
44
45
|
|
45
|
-
container
|
46
|
+
containers.each do |container|
|
47
|
+
container.create
|
48
|
+
end
|
46
49
|
end
|
47
50
|
end
|
48
51
|
end
|
@@ -51,17 +54,20 @@ EOF
|
|
51
54
|
####################
|
52
55
|
c.desc 'Destroy a container'
|
53
56
|
c.long_desc <<-EOF
|
54
|
-
|
57
|
+
Destroys the container, force stopping it if necessary. The containers file system is purged from disk. This is a destructive operation, there is no way to recover from it.
|
55
58
|
EOF
|
56
59
|
c.command :destroy do |destroy|
|
57
60
|
destroy.action do |global_options, options, args|
|
58
61
|
if options[:name].nil?
|
59
62
|
help_now!('a name is required') if options[:name].nil?
|
60
63
|
else
|
61
|
-
|
62
|
-
|
64
|
+
names = options[:name].split(',')
|
65
|
+
containers = TestLab::Container.find(names)
|
66
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
63
67
|
|
64
|
-
container
|
68
|
+
containers.each do |container|
|
69
|
+
container.destroy
|
70
|
+
end
|
65
71
|
end
|
66
72
|
end
|
67
73
|
end
|
@@ -70,17 +76,20 @@ EOF
|
|
70
76
|
###############
|
71
77
|
c.desc 'Up a container'
|
72
78
|
c.long_desc <<-EOF
|
73
|
-
|
79
|
+
The container is started and brought online.
|
74
80
|
EOF
|
75
81
|
c.command :up do |up|
|
76
82
|
up.action do |global_options, options, args|
|
77
83
|
if options[:name].nil?
|
78
84
|
help_now!('a name is required') if options[:name].nil?
|
79
85
|
else
|
80
|
-
|
81
|
-
|
86
|
+
names = options[:name].split(',')
|
87
|
+
containers = TestLab::Container.find(names)
|
88
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
82
89
|
|
83
|
-
container
|
90
|
+
containers.each do |container|
|
91
|
+
container.up
|
92
|
+
end
|
84
93
|
end
|
85
94
|
end
|
86
95
|
end
|
@@ -89,17 +98,20 @@ EOF
|
|
89
98
|
#################
|
90
99
|
c.desc 'Down a container'
|
91
100
|
c.long_desc <<-EOF
|
92
|
-
|
101
|
+
The container is stopped taking it offline.
|
93
102
|
EOF
|
94
103
|
c.command :down do |down|
|
95
104
|
down.action do |global_options, options, args|
|
96
105
|
if options[:name].nil?
|
97
106
|
help_now!('a name is required') if options[:name].nil?
|
98
107
|
else
|
99
|
-
|
100
|
-
|
108
|
+
names = options[:name].split(',')
|
109
|
+
containers = TestLab::Container.find(names)
|
110
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
101
111
|
|
102
|
-
container
|
112
|
+
containers.each do |container|
|
113
|
+
container.down
|
114
|
+
end
|
103
115
|
end
|
104
116
|
end
|
105
117
|
end
|
@@ -108,17 +120,20 @@ EOF
|
|
108
120
|
####################
|
109
121
|
c.desc 'Setup a container'
|
110
122
|
c.long_desc <<-EOF
|
111
|
-
|
123
|
+
The container is provisioned.
|
112
124
|
EOF
|
113
125
|
c.command :setup do |setup|
|
114
126
|
setup.action do |global_options, options, args|
|
115
127
|
if options[:name].nil?
|
116
128
|
help_now!('a name is required') if options[:name].nil?
|
117
129
|
else
|
118
|
-
|
119
|
-
|
130
|
+
names = options[:name].split(',')
|
131
|
+
containers = TestLab::Container.find(names)
|
132
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
120
133
|
|
121
|
-
container
|
134
|
+
containers.each do |container|
|
135
|
+
container.setup
|
136
|
+
end
|
122
137
|
end
|
123
138
|
end
|
124
139
|
end
|
@@ -127,17 +142,20 @@ EOF
|
|
127
142
|
####################
|
128
143
|
c.desc 'Teardown a container'
|
129
144
|
c.long_desc <<-EOF
|
130
|
-
|
145
|
+
The container is deprovisioned.
|
131
146
|
EOF
|
132
147
|
c.command :teardown do |teardown|
|
133
148
|
teardown.action do |global_options, options, args|
|
134
149
|
if options[:name].nil?
|
135
150
|
help_now!('a name is required') if options[:name].nil?
|
136
151
|
else
|
137
|
-
|
138
|
-
|
152
|
+
names = options[:name].split(',')
|
153
|
+
containers = TestLab::Container.find(names)
|
154
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
139
155
|
|
140
|
-
container
|
156
|
+
containers.each do |container|
|
157
|
+
container.teardown
|
158
|
+
end
|
141
159
|
end
|
142
160
|
end
|
143
161
|
end
|
@@ -157,41 +175,47 @@ EOF
|
|
157
175
|
if options[:name].nil?
|
158
176
|
help_now!('a name is required') if options[:name].nil?
|
159
177
|
else
|
160
|
-
|
161
|
-
|
178
|
+
names = options[:name].split(',')
|
179
|
+
containers = TestLab::Container.find(names)
|
180
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
162
181
|
|
163
|
-
container
|
182
|
+
containers.each do |container|
|
183
|
+
container.build
|
184
|
+
end
|
164
185
|
end
|
165
186
|
end
|
166
187
|
end
|
167
188
|
|
168
189
|
# CONTAINER STATUS
|
169
190
|
###################
|
170
|
-
c.desc 'Display the status of
|
191
|
+
c.desc 'Display the status of containers'
|
171
192
|
c.long_desc <<-EOF
|
172
|
-
Displays the status of all containers or
|
193
|
+
Displays the status of all containers or single/multiple containers if supplied via the ID parameter.
|
173
194
|
EOF
|
174
195
|
c.command :status do |status|
|
175
196
|
status.action do |global_options, options, args|
|
197
|
+
containers = Array.new
|
198
|
+
|
176
199
|
if options[:name].nil?
|
177
200
|
# No ID supplied; show everything
|
178
|
-
containers =
|
179
|
-
if containers.count == 0
|
180
|
-
@testlab.ui.stderr.puts("You either have no containers defined or dead nodes!".yellow)
|
181
|
-
else
|
182
|
-
ZTK::Report.new(:ui => @testlab.ui).list(containers, TestLab::Container::STATUS_KEYS) do |container|
|
183
|
-
OpenStruct.new(container.status)
|
184
|
-
end
|
185
|
-
end
|
201
|
+
containers = TestLab::Container.all
|
186
202
|
else
|
187
|
-
# ID supplied; show just
|
188
|
-
|
189
|
-
|
203
|
+
# ID supplied; show just those items
|
204
|
+
names = options[:name].split(',')
|
205
|
+
containers = TestLab::Container.find(names)
|
206
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
207
|
+
end
|
208
|
+
|
209
|
+
containers = containers.delete_if{ |container| container.node.dead? }
|
190
210
|
|
191
|
-
|
211
|
+
if (containers.count == 0)
|
212
|
+
@testlab.ui.stderr.puts("You either have no containers defined or dead nodes!".yellow)
|
213
|
+
else
|
214
|
+
ZTK::Report.new(:ui => @testlab.ui).list(containers, TestLab::Container::STATUS_KEYS) do |container|
|
192
215
|
OpenStruct.new(container.status)
|
193
216
|
end
|
194
217
|
end
|
218
|
+
|
195
219
|
end
|
196
220
|
end
|
197
221
|
|
@@ -231,12 +255,17 @@ EOF
|
|
231
255
|
c.command :'ssh-config' do |ssh_config|
|
232
256
|
|
233
257
|
ssh_config.action do |global_options, options, args|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
258
|
+
if options[:name].nil?
|
259
|
+
help_now!('a name is required') if options[:name].nil?
|
260
|
+
else
|
261
|
+
names = options[:name].split(',')
|
262
|
+
containers = TestLab::Container.find(names)
|
263
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
238
264
|
|
239
|
-
|
265
|
+
containers.each do |container|
|
266
|
+
puts(container.ssh_config)
|
267
|
+
end
|
268
|
+
end
|
240
269
|
end
|
241
270
|
end
|
242
271
|
|
@@ -255,16 +284,19 @@ EOF
|
|
255
284
|
if options[:name].nil?
|
256
285
|
help_now!('a name is required') if options[:name].nil?
|
257
286
|
else
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
container
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
287
|
+
names = options[:name].split(',')
|
288
|
+
containers = TestLab::Container.find(names)
|
289
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
290
|
+
|
291
|
+
containers.each do |container|
|
292
|
+
container.teardown
|
293
|
+
container.down
|
294
|
+
container.destroy
|
295
|
+
|
296
|
+
container.create
|
297
|
+
container.up
|
298
|
+
container.setup
|
299
|
+
end
|
268
300
|
end
|
269
301
|
end
|
270
302
|
end
|
@@ -273,17 +305,20 @@ EOF
|
|
273
305
|
##################
|
274
306
|
c.desc 'Clone a container'
|
275
307
|
c.long_desc <<-EOF
|
276
|
-
|
308
|
+
An ephemeral copy of the container is started. There is a small delay incured during the first clone operation.
|
277
309
|
EOF
|
278
310
|
c.command :clone do |clone|
|
279
311
|
clone.action do |global_options, options, args|
|
280
312
|
if options[:name].nil?
|
281
313
|
help_now!('a name is required') if options[:name].nil?
|
282
314
|
else
|
283
|
-
|
284
|
-
|
315
|
+
names = options[:name].split(',')
|
316
|
+
containers = TestLab::Container.find(names)
|
317
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
285
318
|
|
286
|
-
container
|
319
|
+
containers.each do |container|
|
320
|
+
container.clone
|
321
|
+
end
|
287
322
|
end
|
288
323
|
end
|
289
324
|
end
|
@@ -304,12 +339,17 @@ EOF
|
|
304
339
|
export.flag [:output]
|
305
340
|
|
306
341
|
export.action do |global_options, options, args|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
342
|
+
if options[:name].nil?
|
343
|
+
help_now!('a name is required') if options[:name].nil?
|
344
|
+
else
|
345
|
+
names = options[:name].split(',')
|
346
|
+
containers = TestLab::Container.find(names)
|
347
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
311
348
|
|
312
|
-
|
349
|
+
containers.each do |container|
|
350
|
+
container.export(options[:compression], options[:output])
|
351
|
+
end
|
352
|
+
end
|
313
353
|
end
|
314
354
|
end
|
315
355
|
|
@@ -323,13 +363,18 @@ EOF
|
|
323
363
|
import.flag [:input]
|
324
364
|
|
325
365
|
import.action do |global_options, options, args|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
366
|
+
if (options[:name].nil? || options[:input].nil?)
|
367
|
+
help_now!('a name is required') if options[:name].nil?
|
368
|
+
help_now!('a filename is required') if options[:input].nil?
|
369
|
+
else
|
370
|
+
names = options[:name].split(',')
|
371
|
+
containers = TestLab::Container.find(names)
|
372
|
+
(containers.nil? || (containers.count == 0)) and raise TestLab::TestLabError, "We could not find any of the containers you supplied!"
|
331
373
|
|
332
|
-
|
374
|
+
containers.each do |container|
|
375
|
+
container.import(options[:input])
|
376
|
+
end
|
377
|
+
end
|
333
378
|
end
|
334
379
|
end
|
335
380
|
|
data/lib/commands/network.rb
CHANGED
@@ -167,30 +167,34 @@ EOF
|
|
167
167
|
|
168
168
|
# NETWORK STATUS
|
169
169
|
#################
|
170
|
-
c.desc 'Display the status of
|
170
|
+
c.desc 'Display the status of networks'
|
171
171
|
c.long_desc <<-EOF
|
172
|
-
Displays the status of all networks or
|
172
|
+
Displays the status of all networks or single/multiple networks if supplied via the ID parameter.
|
173
173
|
EOF
|
174
174
|
c.command :status do |status|
|
175
175
|
status.action do |global_options, options, args|
|
176
176
|
if options[:name].nil?
|
177
|
-
|
178
|
-
|
179
|
-
if
|
177
|
+
networks = Array.new
|
178
|
+
|
179
|
+
if options[:name].nil?
|
180
|
+
# No ID supplied; show everything
|
181
|
+
networks = TestLab::Network.all
|
182
|
+
else
|
183
|
+
# ID supplied; show just those items
|
184
|
+
names = options[:name].split(',')
|
185
|
+
networks = TestLab::Network.find(names)
|
186
|
+
(networks.nil? || (networks.count == 0)) and raise TestLab::TestLabError, "We could not find any of the networks you supplied!"
|
187
|
+
end
|
188
|
+
|
189
|
+
networks = networks.delete_if{ |network| network.node.dead? }
|
190
|
+
|
191
|
+
if (networks.count == 0)
|
180
192
|
@testlab.ui.stderr.puts("You either have no networks defined or dead nodes!".yellow)
|
181
193
|
else
|
182
194
|
ZTK::Report.new(:ui => @testlab.ui).list(networks, TestLab::Network::STATUS_KEYS) do |network|
|
183
195
|
OpenStruct.new(network.status)
|
184
196
|
end
|
185
197
|
end
|
186
|
-
else
|
187
|
-
# ID supplied; show just that item
|
188
|
-
network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first
|
189
|
-
network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!"
|
190
|
-
|
191
|
-
ZTK::Report.new(:ui => @testlab.ui).list(network, TestLab::Network::STATUS_KEYS) do |network|
|
192
|
-
OpenStruct.new(network.status)
|
193
|
-
end
|
194
198
|
end
|
195
199
|
end
|
196
200
|
end
|
@@ -12,6 +12,7 @@ class TestLab
|
|
12
12
|
def create
|
13
13
|
@ui.logger.debug { "Container Create: #{self.id} " }
|
14
14
|
|
15
|
+
(self.node.state == :not_created) and return false
|
15
16
|
(self.lxc.state != :not_created) and return false
|
16
17
|
|
17
18
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Create', :green)) do
|
@@ -31,6 +32,7 @@ class TestLab
|
|
31
32
|
def destroy
|
32
33
|
@ui.logger.debug { "Container Destroy: #{self.id} " }
|
33
34
|
|
35
|
+
(self.node.state == :not_created) and return false
|
34
36
|
(self.lxc.state == :not_created) and return false
|
35
37
|
|
36
38
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Destroy', :red)) do
|
@@ -49,6 +51,7 @@ class TestLab
|
|
49
51
|
def up
|
50
52
|
@ui.logger.debug { "Container Up: #{self.id} " }
|
51
53
|
|
54
|
+
(self.node.state != :running) and return false
|
52
55
|
(self.lxc.state == :running) and return false
|
53
56
|
|
54
57
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
@@ -79,6 +82,7 @@ class TestLab
|
|
79
82
|
def down
|
80
83
|
@ui.logger.debug { "Container Down: #{self.id} " }
|
81
84
|
|
85
|
+
(self.node.state != :running) and return false
|
82
86
|
(self.lxc.state != :running) and return false
|
83
87
|
|
84
88
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Down', :red)) do
|
@@ -18,7 +18,11 @@ class TestLab
|
|
18
18
|
# execute. This is generally a bash script of some sort for example.
|
19
19
|
# @return [String] The output of *lxc-attach*.
|
20
20
|
def bootstrap(content)
|
21
|
-
self.
|
21
|
+
if self.lxc_clone.exists?
|
22
|
+
self.ssh.bootstrap(content)
|
23
|
+
else
|
24
|
+
self.lxc.bootstrap(content)
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
# LXC::Container object
|
@@ -7,6 +7,7 @@ class TestLab
|
|
7
7
|
def create
|
8
8
|
@ui.logger.debug { "Network Create: #{self.id} " }
|
9
9
|
|
10
|
+
(self.node.state == :not_created) and return false
|
10
11
|
(self.state != :not_created) and return false
|
11
12
|
|
12
13
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Create', :green)) do
|
@@ -20,6 +21,7 @@ class TestLab
|
|
20
21
|
def destroy
|
21
22
|
@ui.logger.debug { "Network Destroy: #{self.id} " }
|
22
23
|
|
24
|
+
(self.node.state == :not_created) and return false
|
23
25
|
(self.state == :not_created) and return false
|
24
26
|
|
25
27
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Destroy', :red)) do
|
@@ -33,6 +35,7 @@ class TestLab
|
|
33
35
|
def up
|
34
36
|
@ui.logger.debug { "Network Up: #{self.id} " }
|
35
37
|
|
38
|
+
(self.node.state != :running) and return false
|
36
39
|
(self.state == :running) and return false
|
37
40
|
|
38
41
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
@@ -46,6 +49,7 @@ class TestLab
|
|
46
49
|
def down
|
47
50
|
@ui.logger.debug { "Network Down: #{self.id} " }
|
48
51
|
|
52
|
+
(self.node.state != :running) and return false
|
49
53
|
(self.state != :running) and return false
|
50
54
|
|
51
55
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Down', :red)) do
|
@@ -27,7 +27,8 @@ class TestLab
|
|
27
27
|
"repo_dir" => testlab.repo_dir.inspect,
|
28
28
|
"labfile_path" => testlab.labfile_path.inspect,
|
29
29
|
"logdev" => testlab.ui.logger.logdev.inspect,
|
30
|
-
"version" => TestLab::VERSION
|
30
|
+
"version" => TestLab::VERSION.inspect,
|
31
|
+
"argv" => ARGV.inspect
|
31
32
|
}
|
32
33
|
end
|
33
34
|
|
data/lib/testlab/version.rb
CHANGED
data/lib/testlab.rb
CHANGED
@@ -108,13 +108,18 @@ class TestLab
|
|
108
108
|
self.ui = (options[:ui] || ZTK::UI.new)
|
109
109
|
self.class.ui = self.ui
|
110
110
|
|
111
|
-
@
|
112
|
-
|
111
|
+
@repo_dir = File.expand_path(options[:repo_dir] || Dir.pwd)
|
112
|
+
|
113
|
+
@config_dir = File.expand_path(options[:config_dir] || File.join(@repo_dir, ".testlab-#{TestLab.hostname}"))
|
114
|
+
File.exists?(@config_dir) or FileUtils.mkdir_p(@config_dir)
|
115
|
+
|
116
|
+
labfile_path = (options[:labfile_path] || File.join(@repo_dir, 'Labfile'))
|
117
|
+
@labfile_path = File.expand_path(ZTK::Locator.find(labfile_path))
|
113
118
|
|
114
|
-
labfile = (options[:labfile] || File.join(Dir.pwd, 'Labfile'))
|
115
|
-
@labfile_path = ZTK::Locator.find(labfile)
|
116
119
|
@labfile = TestLab::Labfile.load(labfile_path)
|
117
120
|
@labfile.testlab = self
|
121
|
+
|
122
|
+
Dir.chdir(@repo_dir)
|
118
123
|
end
|
119
124
|
|
120
125
|
# Test Lab Nodes
|
data/spec/container_spec.rb
CHANGED
@@ -23,7 +23,7 @@ describe TestLab::Container do
|
|
23
23
|
|
24
24
|
subject {
|
25
25
|
@ui = ZTK::UI.new(:stdout => StringIO.new, :stderr => StringIO.new)
|
26
|
-
@testlab = TestLab.new(:
|
26
|
+
@testlab = TestLab.new(:labfile_path => LABFILE, :ui => @ui)
|
27
27
|
@testlab.containers.first
|
28
28
|
}
|
29
29
|
|
@@ -145,6 +145,7 @@ describe TestLab::Container do
|
|
145
145
|
|
146
146
|
describe "#create" do
|
147
147
|
it "should create the container" do
|
148
|
+
subject.node.stub(:state) { :running }
|
148
149
|
subject.lxc.config.stub(:save) { true }
|
149
150
|
subject.stub(:detect_arch) { "amd64" }
|
150
151
|
subject.lxc.stub(:create) { true }
|
@@ -156,6 +157,7 @@ describe TestLab::Container do
|
|
156
157
|
|
157
158
|
describe "#destroy" do
|
158
159
|
it "should destroy the container" do
|
160
|
+
subject.node.stub(:state) { :running }
|
159
161
|
subject.lxc.stub(:exists?) { true }
|
160
162
|
subject.lxc.stub(:state) { :stopped }
|
161
163
|
subject.lxc.stub(:destroy) { true }
|
@@ -166,6 +168,7 @@ describe TestLab::Container do
|
|
166
168
|
|
167
169
|
describe "#up" do
|
168
170
|
it "should up the container" do
|
171
|
+
subject.node.stub(:state) { :running }
|
169
172
|
subject.lxc.stub(:exists?) { true }
|
170
173
|
subject.lxc.stub(:start) { true }
|
171
174
|
subject.lxc.stub(:wait) { true }
|
@@ -180,6 +183,7 @@ describe TestLab::Container do
|
|
180
183
|
|
181
184
|
describe "#down" do
|
182
185
|
it "should down the container" do
|
186
|
+
subject.node.stub(:state) { :running }
|
183
187
|
subject.lxc.stub(:exists?) { true }
|
184
188
|
subject.lxc.stub(:stop) { true }
|
185
189
|
subject.lxc.stub(:wait) { true }
|
data/spec/network_spec.rb
CHANGED
@@ -23,7 +23,7 @@ describe TestLab::Network do
|
|
23
23
|
|
24
24
|
subject {
|
25
25
|
@ui = ZTK::UI.new(:stdout => StringIO.new, :stderr => StringIO.new)
|
26
|
-
@testlab = TestLab.new(:
|
26
|
+
@testlab = TestLab.new(:labfile_path => LABFILE, :ui => @ui)
|
27
27
|
@testlab.networks.first
|
28
28
|
}
|
29
29
|
|
@@ -108,6 +108,7 @@ describe TestLab::Network do
|
|
108
108
|
|
109
109
|
describe "#create" do
|
110
110
|
it "should create the network bridge" do
|
111
|
+
subject.node.stub(:state) { :running }
|
111
112
|
subject.stub(:state) { :not_created }
|
112
113
|
subject.node.ssh.stub(:exec) { true }
|
113
114
|
subject.create
|
@@ -116,6 +117,7 @@ describe TestLab::Network do
|
|
116
117
|
|
117
118
|
describe "#destroy" do
|
118
119
|
it "should destroy the network bridge" do
|
120
|
+
subject.node.stub(:state) { :running }
|
119
121
|
subject.stub(:state) { :stopped }
|
120
122
|
subject.node.ssh.stub(:exec) { true }
|
121
123
|
subject.destroy
|
@@ -124,6 +126,7 @@ describe TestLab::Network do
|
|
124
126
|
|
125
127
|
describe "#up" do
|
126
128
|
it "should online the network bridge" do
|
129
|
+
subject.node.stub(:state) { :running }
|
127
130
|
subject.stub(:state) { :stopped }
|
128
131
|
subject.node.ssh.stub(:exec) { true }
|
129
132
|
subject.up
|
@@ -132,6 +135,7 @@ describe TestLab::Network do
|
|
132
135
|
|
133
136
|
describe "#down" do
|
134
137
|
it "should offline the network bridge" do
|
138
|
+
subject.node.stub(:state) { :running }
|
135
139
|
subject.stub(:state) { :running }
|
136
140
|
subject.node.ssh.stub(:exec) { true }
|
137
141
|
subject.down
|
data/spec/node_spec.rb
CHANGED
@@ -23,7 +23,7 @@ describe TestLab::Node do
|
|
23
23
|
|
24
24
|
subject {
|
25
25
|
@ui = ZTK::UI.new(:stdout => StringIO.new, :stderr => StringIO.new)
|
26
|
-
@testlab = TestLab.new(:
|
26
|
+
@testlab = TestLab.new(:labfile_path => LABFILE, :ui => @ui)
|
27
27
|
@testlab.nodes.first
|
28
28
|
}
|
29
29
|
|
@@ -23,7 +23,7 @@ describe TestLab::Provisioner::Shell do
|
|
23
23
|
|
24
24
|
subject {
|
25
25
|
@ui = ZTK::UI.new(:stdout => StringIO.new, :stderr => StringIO.new)
|
26
|
-
@testlab = TestLab.new(:
|
26
|
+
@testlab = TestLab.new(:labfile_path => LABFILE, :ui => @ui)
|
27
27
|
TestLab::Container.first('server-shell')
|
28
28
|
}
|
29
29
|
|
@@ -42,7 +42,9 @@ describe TestLab::Provisioner::Shell do
|
|
42
42
|
it "should provision the container" do
|
43
43
|
subject.node.ssh.stub(:file).and_yield(StringIO.new)
|
44
44
|
subject.stub(:fs_root) { "/var/lib/lxc/#{subject.id}/rootfs" }
|
45
|
+
subject.ssh.stub(:bootstrap) { "" }
|
45
46
|
subject.lxc.stub(:bootstrap) { "" }
|
47
|
+
subject.lxc_clone.stub(:exists?) { false }
|
46
48
|
|
47
49
|
p = TestLab::Provisioner::Shell.new(subject.config, @ui)
|
48
50
|
p.on_container_setup(subject)
|
@@ -53,7 +55,9 @@ describe TestLab::Provisioner::Shell do
|
|
53
55
|
it "should raise an exception" do
|
54
56
|
subject.node.ssh.stub(:file).and_yield(StringIO.new)
|
55
57
|
subject.stub(:fs_root) { "/var/lib/lxc/#{subject.id}/rootfs" }
|
58
|
+
subject.ssh.stub(:bootstrap) { "" }
|
56
59
|
subject.lxc.stub(:bootstrap) { "" }
|
60
|
+
subject.lxc_clone.stub(:exists?) { false }
|
57
61
|
|
58
62
|
p = TestLab::Provisioner::Shell.new(Hash.new, @ui)
|
59
63
|
lambda{ p.on_container_setup(subject) }.should raise_error TestLab::Provisioner::ShellError
|
data/spec/testlab_spec.rb
CHANGED
@@ -23,7 +23,7 @@ describe TestLab do
|
|
23
23
|
|
24
24
|
subject {
|
25
25
|
@ui = ZTK::UI.new(:stdout => StringIO.new, :stderr => StringIO.new)
|
26
|
-
@testlab = TestLab.new(:
|
26
|
+
@testlab = TestLab.new(:labfile_path => LABFILE, :ui => @ui)
|
27
27
|
}
|
28
28
|
|
29
29
|
describe "class" do
|
data/testlab.gemspec
CHANGED
@@ -45,6 +45,7 @@ Gem::Specification.new do |spec|
|
|
45
45
|
spec.add_development_dependency("pry")
|
46
46
|
spec.add_development_dependency("rake")
|
47
47
|
spec.add_development_dependency("redcarpet")
|
48
|
+
spec.add_development_dependency("aruba")
|
48
49
|
spec.add_development_dependency("rspec")
|
49
50
|
spec.add_development_dependency("yard")
|
50
51
|
spec.add_development_dependency("coveralls")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: testlab
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gli
|
@@ -139,6 +139,22 @@ dependencies:
|
|
139
139
|
- - ! '>='
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: aruba
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
142
158
|
- !ruby/object:Gem::Dependency
|
143
159
|
name: rspec
|
144
160
|
requirement: !ruby/object:Gem::Requirement
|
@@ -206,6 +222,13 @@ files:
|
|
206
222
|
- README.md
|
207
223
|
- Rakefile
|
208
224
|
- bin/tl
|
225
|
+
- features/step_definitions/container_steps.rb
|
226
|
+
- features/step_definitions/network_steps.rb
|
227
|
+
- features/step_definitions/node_steps.rb
|
228
|
+
- features/step_definitions/testlab_steps.rb
|
229
|
+
- features/support/Labfile
|
230
|
+
- features/support/env.rb
|
231
|
+
- features/testlab.feature
|
209
232
|
- lib/commands/container.rb
|
210
233
|
- lib/commands/network.rb
|
211
234
|
- lib/commands/node.rb
|
@@ -303,7 +326,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
303
326
|
version: '0'
|
304
327
|
segments:
|
305
328
|
- 0
|
306
|
-
hash: -
|
329
|
+
hash: -1054202206124374407
|
307
330
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
308
331
|
none: false
|
309
332
|
requirements:
|
@@ -312,7 +335,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
312
335
|
version: '0'
|
313
336
|
segments:
|
314
337
|
- 0
|
315
|
-
hash: -
|
338
|
+
hash: -1054202206124374407
|
316
339
|
requirements: []
|
317
340
|
rubyforge_project:
|
318
341
|
rubygems_version: 1.8.25
|
@@ -320,6 +343,13 @@ signing_key:
|
|
320
343
|
specification_version: 3
|
321
344
|
summary: A toolkit for building virtual computer labs
|
322
345
|
test_files:
|
346
|
+
- features/step_definitions/container_steps.rb
|
347
|
+
- features/step_definitions/network_steps.rb
|
348
|
+
- features/step_definitions/node_steps.rb
|
349
|
+
- features/step_definitions/testlab_steps.rb
|
350
|
+
- features/support/Labfile
|
351
|
+
- features/support/env.rb
|
352
|
+
- features/testlab.feature
|
323
353
|
- spec/container_spec.rb
|
324
354
|
- spec/network_spec.rb
|
325
355
|
- spec/node_spec.rb
|