testlab 0.7.4 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|