testlab 0.6.11 → 0.6.12
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +36 -22
- data/lib/testlab/container/lifecycle.rb +7 -2
- data/lib/testlab/network/lifecycle.rb +7 -2
- data/lib/testlab/node/lifecycle.rb +5 -5
- data/lib/testlab/version.rb +1 -1
- metadata +4 -4
data/README.md
CHANGED
@@ -8,13 +8,15 @@
|
|
8
8
|
|
9
9
|
A toolkit for building virtual computer labs.
|
10
10
|
|
11
|
-
What is TestLab? TestLab lets you iterate virtual infrastructure quickly. Using a `Labfile` you can define how you want your virtual infrastructure laid out. You can define multiple network segments and containers (i.e. boxen). TestLab will then setup and
|
11
|
+
What is TestLab? TestLab lets you iterate virtual infrastructure quickly. Using a `Labfile` you can define how you want your virtual infrastructure laid out. You can define multiple network segments and containers (i.e. boxen). TestLab will then setup and tear down this virtual infrastructure as you have dictated in the `Labfile`.
|
12
12
|
|
13
|
-
TestLab can
|
13
|
+
TestLab can also import and export containers, making it easy to share them. TestLab supports the latest LXC versions, allowing for ephemeral cloning operations, furthering your ability to iterate quickly. TestLab can be used for many other applications, including infrastructure unit and integration testing, allowing for vastly more complex configurations and more effective resource sharing than traditional VM solutions.
|
14
|
+
|
15
|
+
TestLab can be run via the command-line or can be interfaced with directly via Ruby code.
|
14
16
|
|
15
17
|
# Using TestLab Interactively
|
16
18
|
|
17
|
-
The TestLab command-line program `tl` follows in the style of git
|
19
|
+
The TestLab command-line program `tl` follows in the style of git:
|
18
20
|
|
19
21
|
$ tl help
|
20
22
|
NAME
|
@@ -50,7 +52,7 @@ You stand up your lab with the following command:
|
|
50
52
|
|
51
53
|
tl build
|
52
54
|
|
53
|
-
You can down the entire lab:
|
55
|
+
You can down the entire lab (this would only down the containers on the Local provider for example):
|
54
56
|
|
55
57
|
tl down
|
56
58
|
|
@@ -58,18 +60,33 @@ You can also destroy it (only works for VM backed providers; this would be a NO-
|
|
58
60
|
|
59
61
|
tl destroy
|
60
62
|
|
63
|
+
## Getting Help
|
64
|
+
|
65
|
+
TestLab uses the GLI RubyGem, which gives us a command line pattern similar to that of Git. Therefore help is easy to get:
|
66
|
+
|
67
|
+
tl help
|
68
|
+
tl help node
|
69
|
+
tl help container
|
70
|
+
tl help network
|
71
|
+
|
61
72
|
## Interacting with Containers
|
62
73
|
|
63
|
-
|
74
|
+
Almost all commands dealing will containers will take this argument:
|
64
75
|
|
65
76
|
COMMAND OPTIONS
|
66
77
|
-n, --name=container - Container ID or Name (default: none)
|
67
78
|
|
68
79
|
You can interact with containers via SSH:
|
69
80
|
|
70
|
-
tl container ssh -n <
|
81
|
+
tl container ssh -n <name>
|
82
|
+
|
83
|
+
For example:
|
84
|
+
|
85
|
+
tl container ssh -n server-www-1
|
86
|
+
|
87
|
+
Would connect to the container defined as 'server-www-1' in our Labfile.
|
71
88
|
|
72
|
-
You can pass an optional
|
89
|
+
You can pass an optional username and/or identity to use. By default TestLab will attempt to SSH as the user defined in the `Labfile` for that container, otherwise the default user for the containers distro is used.
|
73
90
|
|
74
91
|
$ tl help container ssh
|
75
92
|
NAME
|
@@ -95,7 +112,7 @@ You can recycle a container, effectively destroying then creating it again, prov
|
|
95
112
|
|
96
113
|
## Ephemeral Container Cloning
|
97
114
|
|
98
|
-
As it stands attempting to iterate infrastructure
|
115
|
+
As it stands attempting to iterate infrastructure with Vagrant is a slow and painful process. Enter LXC and ephemeral cloning. The idea here is that you have a container that is provisioned to a "pristine" state according to the `Labfile`. You then clone this container and run actions against the container. After running your actions against the container you want to maybe tweak your Chef cookbook, for example, and re-run it against the container. Running an ever changing cookbook in development against the same system over and over again causes drift and problems. With the cloning you can instantly reinstate the container as it was when you first cloned it.
|
99
116
|
|
100
117
|
Here we are cloning the container for the first time. It takes a bit longer than normal because TestLab is actually shutting down the container so it can be retained as the "pristine" copy of it, and starting up a ephemeral container in its place. Subsequent calls to clone are very fast.
|
101
118
|
|
@@ -112,6 +129,8 @@ Here we are cloning the container for the first time. It takes a bit longer tha
|
|
112
129
|
[TL] TestLab v0.6.1 Loaded
|
113
130
|
[TL] container server-www-1 clone # Completed in 1.0281 seconds!
|
114
131
|
|
132
|
+
The idea in the above example is that you run the initial clone command to put your container into an ephemeral clone state. You would then modify the container in some fashion, test, etc. When you where done with that iteration you would run the clone command again, losing all the changes you did to the container, replacing it with a new clean cloned copy of your original container. RRP (Rinse, Repeat, Profit)
|
133
|
+
|
115
134
|
We can also see the containers status reflects that it is a clone currently:
|
116
135
|
|
117
136
|
$ tl container status -n server-www-1
|
@@ -128,7 +147,7 @@ We can also see the containers status reflects that it is a clone currently:
|
|
128
147
|
| PROVISIONERS: Resolv/AptCacherNG/Apt/Shell |
|
129
148
|
+----------------------------------------------+
|
130
149
|
|
131
|
-
We can easily revert it back to a full container if we want to make changes to it:
|
150
|
+
We can easily revert it back to a full container if we want to make "permanent" changes to it:
|
132
151
|
|
133
152
|
$ tl container up -n server-www-1
|
134
153
|
|
@@ -136,9 +155,13 @@ We can even recycle it while it is in a cloned state:
|
|
136
155
|
|
137
156
|
$ tl container recycle -n server-www-1
|
138
157
|
|
158
|
+
We can run setup against a clone as well (note: running `build`, calls `up`, which would revert us back to a non-cloned container and we would not want this to happen):
|
159
|
+
|
160
|
+
$ tl container setup -n server-www-1
|
161
|
+
|
139
162
|
## Network Routes
|
140
163
|
|
141
|
-
TestLab will add network routes for any networks defined in the `Labfile`
|
164
|
+
TestLab will add network routes for any networks defined in the `Labfile` witch have the `TestLab::Provisioner::Route` provisioner class specified for them. This will allow you to directly interact with containers over the network. Here is an example of the routes added with the multi-network `Labfile`.
|
142
165
|
|
143
166
|
$ tl network route show -n labnet
|
144
167
|
[TL] TestLab v0.6.1 Loaded
|
@@ -146,7 +169,7 @@ TestLab will add network routes for any networks defined in the `Labfile` with t
|
|
146
169
|
10.10.0.0 192.168.33.239 255.255.0.0 UG 0 0 0 vboxnet0
|
147
170
|
10.11.0.0 192.168.33.239 255.255.0.0 UG 0 0 0 vboxnet0
|
148
171
|
|
149
|
-
These routes can be manually manipulated as well:
|
172
|
+
These routes can be manually manipulated as well (regardless of if you have specified the `TestLab::Provisioner::Route` provisioner class for the networks via the `Labfile`):
|
150
173
|
|
151
174
|
$ tl help network route
|
152
175
|
NAME
|
@@ -162,15 +185,6 @@ These routes can be manually manipulated as well:
|
|
162
185
|
del - Delete routes to lab networks
|
163
186
|
show - Show routes to lab networks
|
164
187
|
|
165
|
-
## Getting Help
|
166
|
-
|
167
|
-
TestLab uses the GLI RubyGem, which gives us a command line pattern similar to that of Git. Therefore help is easy to get:
|
168
|
-
|
169
|
-
tl help
|
170
|
-
tl help node
|
171
|
-
tl help container
|
172
|
-
tl help network
|
173
|
-
|
174
188
|
# Using TestLab Programmatically
|
175
189
|
|
176
190
|
Accessing TestLab via code is meant to be fairly easy and straightforward. To get an instance of TestLab you only need about four lines of code:
|
@@ -180,9 +194,9 @@ Accessing TestLab via code is meant to be fairly easy and straightforward. To g
|
|
180
194
|
@ui = ZTK::UI.new(:logger => @logger)
|
181
195
|
@testlab = TestLab.new(:ui => @ui)
|
182
196
|
|
183
|
-
Calling `TestLab.new` without a `:labfile` option will, by default, attempt to read `Labfile` from the current directory. This
|
197
|
+
Calling `TestLab.new` without a `:labfile` option will, by default, attempt to read `Labfile` from the current directory. This behavior can be changed by passing the `:labfile` key with a path to your desired "Labfile" as the value to your `TestLab.new`.
|
184
198
|
|
185
|
-
There are several easy accessors available to grab the first container and
|
199
|
+
There are several easy accessors available to grab the first container and execute the command `uptime` on it via and SSH connection:
|
186
200
|
|
187
201
|
container = @testlab.containers.first
|
188
202
|
container.ssh.exec(%(uptime))
|
@@ -15,7 +15,7 @@ class TestLab
|
|
15
15
|
|
16
16
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
17
17
|
|
18
|
-
self.
|
18
|
+
self.container_provisioners.each do |provisioner|
|
19
19
|
@ui.logger.info { ">>>>> CONTAINER PROVISIONER SETUP: #{provisioner} <<<<<" }
|
20
20
|
p = provisioner.new(self.config, @ui)
|
21
21
|
p.respond_to?(:on_container_setup) and p.on_container_setup(self)
|
@@ -40,7 +40,7 @@ class TestLab
|
|
40
40
|
|
41
41
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
42
42
|
|
43
|
-
self.
|
43
|
+
self.container_provisioners.each do |provisioner|
|
44
44
|
@ui.logger.info { ">>>>> CONTAINER PROVISIONER TEARDOWN: #{provisioner} <<<<<" }
|
45
45
|
p = provisioner.new(self.config, @ui)
|
46
46
|
p.respond_to?(:on_container_teardown) and p.on_container_teardown(self)
|
@@ -60,6 +60,11 @@ class TestLab
|
|
60
60
|
true
|
61
61
|
end
|
62
62
|
|
63
|
+
# Returns all defined provisioners for this container's networks and the container iteself.
|
64
|
+
def container_provisioners
|
65
|
+
[self.interfaces.map(&:network).map(&:provisioners), self.provisioners].flatten.compact.uniq
|
66
|
+
end
|
67
|
+
|
63
68
|
end
|
64
69
|
|
65
70
|
end
|
@@ -9,7 +9,7 @@ class TestLab
|
|
9
9
|
|
10
10
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
11
11
|
|
12
|
-
self.
|
12
|
+
self.network_provisioners.each do |provisioner|
|
13
13
|
@ui.logger.info { ">>>>> NETWORK PROVISIONER SETUP: #{provisioner} <<<<<" }
|
14
14
|
p = provisioner.new(self.config, @ui)
|
15
15
|
p.respond_to?(:on_network_setup) and p.on_network_setup(self)
|
@@ -26,7 +26,7 @@ class TestLab
|
|
26
26
|
|
27
27
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
28
28
|
|
29
|
-
self.
|
29
|
+
self.network_provisioners.each do |provisioner|
|
30
30
|
@ui.logger.info { ">>>>> NETWORK PROVISIONER TEARDOWN: #{provisioner} <<<<<" }
|
31
31
|
p = provisioner.new(self.config, @ui)
|
32
32
|
p.respond_to?(:on_network_teardown) and p.on_network_teardown(self)
|
@@ -46,6 +46,11 @@ class TestLab
|
|
46
46
|
true
|
47
47
|
end
|
48
48
|
|
49
|
+
# Returns all defined provisioners for this network's containers and the network iteself.
|
50
|
+
def network_provisioners
|
51
|
+
[self.provisioners, self.interfaces.map(&:container).map(&:provisioners)].flatten.compact.uniq
|
52
|
+
end
|
53
|
+
|
49
54
|
end
|
50
55
|
|
51
56
|
end
|
@@ -15,7 +15,7 @@ class TestLab
|
|
15
15
|
|
16
16
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
17
17
|
|
18
|
-
|
18
|
+
self.all_provisioners.each do |provisioner|
|
19
19
|
@ui.logger.info { ">>>>> NODE PROVISIONER SETUP: #{provisioner} <<<<<" }
|
20
20
|
p = provisioner.new(self.config, @ui)
|
21
21
|
p.respond_to?(:on_node_setup) and p.on_node_setup(self)
|
@@ -34,7 +34,7 @@ class TestLab
|
|
34
34
|
|
35
35
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
36
36
|
|
37
|
-
|
37
|
+
self.all_provisioners.each do |provisioner|
|
38
38
|
@ui.logger.info { ">>>>> NODE PROVISIONER TEARDOWN: #{provisioner} <<<<<" }
|
39
39
|
p = provisioner.new(self.config, @ui)
|
40
40
|
p.respond_to?(:on_node_teardown) and p.on_node_teardown(self)
|
@@ -54,11 +54,11 @@ class TestLab
|
|
54
54
|
true
|
55
55
|
end
|
56
56
|
|
57
|
-
|
58
|
-
|
57
|
+
# Returns all defined provisioners for this node and it's networks and containers.
|
58
|
+
def all_provisioners
|
59
|
+
[self.provisioners, self.networks.map(&:provisioners), self.containers.map(&:provisioners)].flatten.compact.uniq
|
59
60
|
end
|
60
61
|
|
61
62
|
end
|
62
|
-
|
63
63
|
end
|
64
64
|
end
|
data/lib/testlab/version.rb
CHANGED
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.6.
|
4
|
+
version: 0.6.12
|
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-06-
|
12
|
+
date: 2013-06-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gli
|
@@ -300,7 +300,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
300
300
|
version: '0'
|
301
301
|
segments:
|
302
302
|
- 0
|
303
|
-
hash: -
|
303
|
+
hash: -3900495778607553131
|
304
304
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
305
305
|
none: false
|
306
306
|
requirements:
|
@@ -309,7 +309,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
309
309
|
version: '0'
|
310
310
|
segments:
|
311
311
|
- 0
|
312
|
-
hash: -
|
312
|
+
hash: -3900495778607553131
|
313
313
|
requirements: []
|
314
314
|
rubyforge_project:
|
315
315
|
rubygems_version: 1.8.25
|