testlab 0.4.0 → 0.4.1
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/.travis.yml +1 -4
- data/Gemfile +2 -0
- data/README.md +8 -0
- data/lib/testlab/container/actions.rb +17 -2
- data/lib/testlab/container/lxc.rb +3 -2
- data/lib/testlab/network/lifecycle.rb +15 -0
- data/lib/testlab/network.rb +1 -0
- data/lib/testlab/node/lifecycle.rb +1 -15
- data/lib/testlab/node/status.rb +1 -0
- data/lib/testlab/node/templates/node-setup.erb +0 -1
- data/lib/testlab/node.rb +2 -3
- data/lib/testlab/provider.rb +1 -1
- data/lib/testlab/providers/vagrant.rb +4 -9
- data/lib/testlab/provisioners/omnitruck.rb +12 -2
- data/lib/testlab/provisioners/templates/chef/omnitruck.erb +5 -6
- data/lib/testlab/version.rb +1 -1
- data/lib/testlab.rb +19 -7
- data/spec/container_spec.rb +2 -0
- data/spec/support/Labfile +8 -5
- metadata +4 -4
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -34,6 +34,14 @@ For more information see the TestLab Documentation, `testlab-repo`, command-line
|
|
34
34
|
|
35
35
|
* See the `testlab-repo` - https://github.com/zpatten/testlab-repo
|
36
36
|
|
37
|
+
# RUBIES TESTED AGAINST
|
38
|
+
|
39
|
+
* Ruby 1.8.7 (REE)
|
40
|
+
* Ruby 1.8.7 (MBARI)
|
41
|
+
* Ruby 1.9.2
|
42
|
+
* Ruby 1.9.3
|
43
|
+
* Ruby 2.0.0
|
44
|
+
|
37
45
|
# RESOURCES
|
38
46
|
|
39
47
|
IRC:
|
@@ -26,6 +26,18 @@ class TestLab
|
|
26
26
|
self.lxc.config.save
|
27
27
|
|
28
28
|
self.lxc.create(*create_args)
|
29
|
+
|
30
|
+
# TODO: This needs to really go somewhere else:
|
31
|
+
home_dir = ((self.node.user == "root") ? %(/root) : %(/home/#{self.node.user}))
|
32
|
+
container_home_dir = File.join(self.lxc.fs_root, "/home/ubuntu")
|
33
|
+
|
34
|
+
home_authkeys = File.join(home_dir, %(.ssh), %(authorized_keys))
|
35
|
+
container_authkeys = File.join(container_home_dir, %(.ssh), %(authorized_keys))
|
36
|
+
|
37
|
+
self.node.ssh.exec(%(mkdir -pv #{File.join(container_home_dir, %(.ssh))}))
|
38
|
+
self.node.ssh.exec(%(sudo cp -v #{home_authkeys} #{container_authkeys}))
|
39
|
+
self.node.ssh.exec(%(sudo chown -v 1000:1000 #{container_authkeys}))
|
40
|
+
self.node.ssh.exec(%(sudo chmod -v 644 #{container_authkeys}))
|
29
41
|
end
|
30
42
|
|
31
43
|
true
|
@@ -54,13 +66,16 @@ class TestLab
|
|
54
66
|
def up
|
55
67
|
@ui.logger.debug { "Container Up: #{self.id} " }
|
56
68
|
|
57
|
-
(self.lxc.state == :not_created) and raise ContainerError, "We can not online a non-existant container!"
|
69
|
+
(self.lxc.state == :not_created) and return false #raise ContainerError, "We can not online a non-existant container!"
|
58
70
|
|
59
71
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
60
72
|
self.lxc.start
|
61
73
|
self.lxc.wait(:running)
|
62
74
|
|
63
75
|
(self.lxc.state != :running) and raise ContainerError, "The container failed to online!"
|
76
|
+
|
77
|
+
# TODO: This needs to really go somewhere else:
|
78
|
+
self.lxc.attach(%(/bin/bash -c 'grep "sudo\tALL=\(ALL:ALL\) ALL" /etc/sudoers && sed -i "s/sudo\tALL=\(ALL:ALL\) ALL/sudo\tALL=\(ALL:ALL\) NOPASSWD: ALL/" /etc/sudoers'))
|
64
79
|
end
|
65
80
|
|
66
81
|
true
|
@@ -74,7 +89,7 @@ class TestLab
|
|
74
89
|
def down
|
75
90
|
@ui.logger.debug { "Container Down: #{self.id} " }
|
76
91
|
|
77
|
-
(self.lxc.state == :not_created) and raise ContainerError, "We can not offline a non-existant container!"
|
92
|
+
(self.lxc.state == :not_created) and return false # raise ContainerError, "We can not offline a non-existant container!"
|
78
93
|
|
79
94
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Down', :red)) do
|
80
95
|
self.lxc.stop
|
@@ -16,10 +16,11 @@ class TestLab
|
|
16
16
|
|
17
17
|
ZTK::RescueRetry.try(:tries => 3, :on => ContainerError) do
|
18
18
|
tempfile = Tempfile.new("bootstrap")
|
19
|
-
|
19
|
+
remote_tempfile = File.join("/tmp", File.basename(tempfile.path))
|
20
|
+
self.node.ssh.file(:target => File.join(self.lxc.fs_root, remote_tempfile), :chmod => '0777', :chown => 'root:root') do |file|
|
20
21
|
file.puts(content)
|
21
22
|
end
|
22
|
-
output = self.lxc.attach(%(/bin/bash),
|
23
|
+
output = self.lxc.attach(%(/bin/bash), remote_tempfile)
|
23
24
|
if output =~ /No such file or directory/
|
24
25
|
raise ContainerError, "We could not find the bootstrap file!"
|
25
26
|
end
|
@@ -9,16 +9,31 @@ class TestLab
|
|
9
9
|
|
10
10
|
self.create
|
11
11
|
self.up
|
12
|
+
self.route and route(:add)
|
12
13
|
end
|
13
14
|
|
14
15
|
# Network Teardown
|
15
16
|
def teardown
|
16
17
|
@ui.logger.debug { "Network Teardown: #{self.id} " }
|
17
18
|
|
19
|
+
self.route and route(:del)
|
18
20
|
self.down
|
19
21
|
self.destroy
|
20
22
|
end
|
21
23
|
|
24
|
+
def route(action)
|
25
|
+
self.networks.each do |network|
|
26
|
+
command = ZTK::Command.new(:ui => @ui, :silence => true, :ignore_exit_status => true)
|
27
|
+
|
28
|
+
case RUBY_PLATFORM
|
29
|
+
when /darwin/ then
|
30
|
+
command.exec(%(sudo route #{action} -net #{TestLab::Utility.network(network.address)} #{network.node.ip} #{TestLab::Utility.netmask(network.address)}))
|
31
|
+
when /linux/ then
|
32
|
+
command.exec(%(sudo route #{action} -net #{TestLab::Utility.network(network.address)} netmask #{TestLab::Utility.netmask(network.address)} gw #{network.node.ip}))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
22
37
|
end
|
23
38
|
|
24
39
|
end
|
data/lib/testlab/network.rb
CHANGED
@@ -26,23 +26,12 @@ class TestLab
|
|
26
26
|
self.ssh.bootstrap(ZTK::Template.render(node_setup_template))
|
27
27
|
end
|
28
28
|
|
29
|
-
def route_setup(action)
|
30
|
-
self.networks.each do |network|
|
31
|
-
command = ZTK::Command.new(:silence => true, :ignore_exit_status => true)
|
32
|
-
command.exec(%(sudo route #{action} -net #{TestLab::Utility.network(network.address)} netmask #{TestLab::Utility.netmask(network.address)} gw #{network.node.ip}))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
29
|
# Setup the node.
|
37
30
|
def setup
|
38
31
|
@ui.logger.debug { "Node Setup: #{self.id} " }
|
39
32
|
|
40
33
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
41
34
|
|
42
|
-
if (self.route == true)
|
43
|
-
route_setup(:add)
|
44
|
-
end
|
45
|
-
|
46
35
|
node_setup
|
47
36
|
|
48
37
|
if self.components.include?('resolv')
|
@@ -70,10 +59,7 @@ class TestLab
|
|
70
59
|
call_collections([self.containers, self.networks], :teardown)
|
71
60
|
|
72
61
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
73
|
-
|
74
|
-
if (self.route == true)
|
75
|
-
route_setup(:del)
|
76
|
-
end
|
62
|
+
# NOOP
|
77
63
|
end
|
78
64
|
|
79
65
|
true
|
data/lib/testlab/node/status.rb
CHANGED
data/lib/testlab/node.rb
CHANGED
@@ -34,15 +34,14 @@ class TestLab
|
|
34
34
|
include TestLab::Utility::Misc
|
35
35
|
|
36
36
|
# Associations and Attributes
|
37
|
-
belongs_to :labfile, :class_name => 'TestLab::
|
37
|
+
belongs_to :labfile, :class_name => 'TestLab::Labfile'
|
38
38
|
|
39
39
|
has_many :containers, :class_name => 'TestLab::Container'
|
40
40
|
has_many :networks, :class_name => 'TestLab::Network'
|
41
41
|
|
42
42
|
attribute :provider
|
43
|
-
attribute :config
|
43
|
+
attribute :config, :default => Hash.new
|
44
44
|
attribute :components, :default => Array.new
|
45
|
-
attribute :route, :default => false
|
46
45
|
|
47
46
|
|
48
47
|
def initialize(*args)
|
data/lib/testlab/provider.rb
CHANGED
@@ -7,7 +7,7 @@ class TestLab
|
|
7
7
|
#
|
8
8
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
9
9
|
class Provider
|
10
|
-
PROXY_METHODS = %w(instance_id state user ip port create destroy up down reload status alive? dead? exists?).map(&:to_sym)
|
10
|
+
PROXY_METHODS = %w(instance_id state user identity ip port create destroy up down reload status alive? dead? exists?).map(&:to_sym)
|
11
11
|
|
12
12
|
autoload :AWS, 'testlab/providers/aws'
|
13
13
|
autoload :Local, 'testlab/providers/local'
|
@@ -174,7 +174,7 @@ class TestLab
|
|
174
174
|
command = TestLab.build_command_line("vagrant", *args)
|
175
175
|
@ui.logger.debug { "command == #{command.inspect}" }
|
176
176
|
|
177
|
-
ZTK::Command.new(:ui => @ui
|
177
|
+
ZTK::Command.new(:ui => @ui, :silence => true).exec(command)
|
178
178
|
end
|
179
179
|
|
180
180
|
def render_vagrantfile
|
@@ -191,15 +191,10 @@ class TestLab
|
|
191
191
|
}
|
192
192
|
|
193
193
|
vagrantfile_template = File.join(TestLab::Provider.template_dir, "vagrant", "Vagrantfile.erb")
|
194
|
-
vagrantfile = File.join(@config[:
|
194
|
+
vagrantfile = File.join(@config[:vagrant][:file], "Vagrantfile")
|
195
195
|
|
196
|
-
|
197
|
-
|
198
|
-
File.open(vagrantfile, 'w') do |file|
|
199
|
-
file.puts(ZTK::Template.render(vagrantfile_template, context))
|
200
|
-
end
|
201
|
-
else
|
202
|
-
IO.write(vagrantfile, ZTK::Template.render(vagrantfile_template, context))
|
196
|
+
File.open(vagrantfile, 'w') do |file|
|
197
|
+
file.puts(ZTK::Template.render(vagrantfile_template, context))
|
203
198
|
end
|
204
199
|
end
|
205
200
|
|
@@ -40,7 +40,8 @@ class TestLab
|
|
40
40
|
:default_password => "p@ssw01d",
|
41
41
|
:user => ENV['USER'],
|
42
42
|
:hostname_short => container.id,
|
43
|
-
:hostname_full => container.fqdn
|
43
|
+
:hostname_full => container.fqdn,
|
44
|
+
:omnibus_version => omnibus_version
|
44
45
|
}).merge!(@config)
|
45
46
|
container.bootstrap(ZTK::Template.render(omnibus_template, config))
|
46
47
|
end
|
@@ -60,7 +61,8 @@ class TestLab
|
|
60
61
|
|
61
62
|
def build_chef_solo_10_attributes(container)
|
62
63
|
{
|
63
|
-
"
|
64
|
+
"chef_server" => {
|
65
|
+
"url" => "https://#{container.fqdn}",
|
64
66
|
"webui_enabled" => true
|
65
67
|
},
|
66
68
|
"run_list" => %w(recipe[chef-server::rubygems-install] recipe[chef-server::apache-proxy])
|
@@ -109,6 +111,14 @@ class TestLab
|
|
109
111
|
end
|
110
112
|
end
|
111
113
|
|
114
|
+
def omnibus_version
|
115
|
+
if (@config[:version].to_f == 0.1)
|
116
|
+
"10.12.0"
|
117
|
+
else
|
118
|
+
@config[:version]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
112
122
|
end
|
113
123
|
|
114
124
|
end
|
@@ -7,11 +7,11 @@ CHEF_SOLO_ROOT="/tmp/chef-solo"
|
|
7
7
|
KNIFE_CONFIG_EXP_FILE="/tmp/knife-config.exp"
|
8
8
|
export DEBIAN_FRONTEND CHEF_SOLO_ROOT KNIFE_CONFIG_EXP_FILE
|
9
9
|
|
10
|
-
mkdir -p
|
10
|
+
mkdir -p ${CHEF_SOLO_ROOT}
|
11
11
|
cd ${CHEF_SOLO_ROOT}
|
12
12
|
|
13
13
|
apt-get -y --force-yes update
|
14
|
-
apt-get -y --force-yes install build-essential expect wget curl
|
14
|
+
apt-get -y --force-yes install build-essential expect wget curl libgecode-dev
|
15
15
|
|
16
16
|
mkdir -pv /etc/chef /var/log/chef ${HOME}/.chef
|
17
17
|
|
@@ -25,8 +25,8 @@ cat <<EOF | tee ${CHEF_SOLO_ROOT}/attributes.json
|
|
25
25
|
<%= @chef_solo_attributes.to_json %>
|
26
26
|
EOF
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
wget -v https://www.opscode.com/chef/install.sh
|
29
|
+
bash install.sh -v <%= @omnibus_version %>
|
30
30
|
<% if (@chef_pre_11 == false) -%>
|
31
31
|
|
32
32
|
mkdir -pv /var/chef/cache ${CHEF_SOLO_ROOT}/cookbooks/chef-server
|
@@ -49,11 +49,10 @@ EOF
|
|
49
49
|
|
50
50
|
gem install bundler --no-ri --no-rdoc
|
51
51
|
bundle install --standalone --path vendor/bundle --binstubs
|
52
|
-
mv -v ${CHEF_SOLO_ROOT}/cookbooks ${CHEF_SOLO_ROOT}/site-cookbooks
|
53
52
|
bin/berks install --path ${CHEF_SOLO_ROOT}/cookbooks/
|
54
53
|
<% end -%>
|
55
54
|
|
56
|
-
chef-solo --config /etc/chef/solo.rb --json-attributes ${CHEF_SOLO_ROOT}/attributes.json --logfile /var/log/chef/chef-solo.log --log_level debug
|
55
|
+
PATH=./bin/:$PATH chef-solo --config /etc/chef/solo.rb --json-attributes ${CHEF_SOLO_ROOT}/attributes.json --logfile /var/log/chef/chef-solo.log --log_level debug
|
57
56
|
<% if (@chef_pre_11 == false) -%>
|
58
57
|
|
59
58
|
cat << EOF | tee /etc/chef-server/chef-server.rb
|
data/lib/testlab/version.rb
CHANGED
data/lib/testlab.rb
CHANGED
@@ -22,7 +22,8 @@ require 'testlab/monkeys'
|
|
22
22
|
# EOF
|
23
23
|
#
|
24
24
|
# config Hash[
|
25
|
-
# :domain => "default.zone"
|
25
|
+
# :domain => "default.zone",
|
26
|
+
# :repo => File.join(ENV['HOME'], "code", "personal", "testlab-repo")
|
26
27
|
# ]
|
27
28
|
#
|
28
29
|
# node :localhost do
|
@@ -39,8 +40,7 @@ require 'testlab/monkeys'
|
|
39
40
|
# :cpus => 8,
|
40
41
|
# :memory => 16384,
|
41
42
|
# :box => 'raring64'
|
42
|
-
# }
|
43
|
-
# :repo => File.join(ENV['HOME'], "code", "personal", "testlab-repo")
|
43
|
+
# }
|
44
44
|
# ]
|
45
45
|
#
|
46
46
|
# network :east do
|
@@ -103,6 +103,7 @@ class TestLab
|
|
103
103
|
labfile = (options[:labfile] || 'Labfile')
|
104
104
|
labfile_path = ZTK::Locator.find(labfile)
|
105
105
|
@labfile = TestLab::Labfile.load(labfile_path)
|
106
|
+
@labfile.config.merge!(:testlab => self)
|
106
107
|
end
|
107
108
|
|
108
109
|
# Test Lab Nodes
|
@@ -202,6 +203,17 @@ class TestLab
|
|
202
203
|
true
|
203
204
|
end
|
204
205
|
|
206
|
+
# TestLab Configuration Directory
|
207
|
+
#
|
208
|
+
# Returns the path to the test lab configuration directory which is located
|
209
|
+
# off the repo directory under '.testlab'.
|
210
|
+
#
|
211
|
+
# @return [String] The path to the TestLab configuration directory.
|
212
|
+
def config_dir
|
213
|
+
directory = File.join(self.config[:repo], '.testlab')
|
214
|
+
File.expand_path(directory, File.dirname(__FILE__))
|
215
|
+
end
|
216
|
+
|
205
217
|
# Provider Method Handler
|
206
218
|
#
|
207
219
|
# Proxies missing provider method calls to all nodes.
|
@@ -221,7 +233,7 @@ class TestLab
|
|
221
233
|
#
|
222
234
|
# These are special methods that we both include and extend on the parent
|
223
235
|
# class.
|
224
|
-
module
|
236
|
+
module DualMethods
|
225
237
|
|
226
238
|
@@ui ||= nil
|
227
239
|
|
@@ -266,13 +278,13 @@ class TestLab
|
|
266
278
|
#
|
267
279
|
# @return [String] Constructed command line with arguments.
|
268
280
|
def build_command_line(name, *args)
|
269
|
-
executable = (ZTK::Locator.find('bin', name) rescue "/bin/env #{name}")
|
281
|
+
executable = (ZTK::Locator.find('bin', name) rescue "/usr/bin/env #{name}")
|
270
282
|
[executable, args].flatten.compact.join(' ')
|
271
283
|
end
|
272
284
|
|
273
285
|
end
|
274
286
|
|
275
|
-
include TestLab::
|
276
|
-
extend TestLab::
|
287
|
+
include TestLab::DualMethods
|
288
|
+
extend TestLab::DualMethods
|
277
289
|
|
278
290
|
end
|
data/spec/container_spec.rb
CHANGED
@@ -147,6 +147,7 @@ describe TestLab::Container do
|
|
147
147
|
subject.lxc.config.stub(:save) { true }
|
148
148
|
subject.stub(:detect_arch) { "amd64" }
|
149
149
|
subject.lxc.stub(:create) { true }
|
150
|
+
subject.node.ssh.stub(:exec)
|
150
151
|
subject.create
|
151
152
|
end
|
152
153
|
end
|
@@ -163,6 +164,7 @@ describe TestLab::Container do
|
|
163
164
|
subject.lxc.stub(:start) { true }
|
164
165
|
subject.lxc.stub(:wait) { true }
|
165
166
|
subject.lxc.stub(:state) { :running }
|
167
|
+
subject.lxc.stub(:attach)
|
166
168
|
subject.up
|
167
169
|
end
|
168
170
|
end
|
data/spec/support/Labfile
CHANGED
@@ -7,14 +7,16 @@ apt-get -y update
|
|
7
7
|
apt-get -y install dnsutils
|
8
8
|
EOF
|
9
9
|
|
10
|
+
REPO = File.dirname(__FILE__)
|
11
|
+
|
10
12
|
config Hash[
|
11
|
-
:domain => "default.zone"
|
13
|
+
:domain => "default.zone",
|
14
|
+
:repo => REPO
|
12
15
|
]
|
13
16
|
|
14
17
|
node :localhost do
|
15
18
|
|
16
19
|
components %w(resolv bind)
|
17
|
-
route true
|
18
20
|
|
19
21
|
provider TestLab::Provider::Vagrant
|
20
22
|
config Hash[
|
@@ -24,14 +26,15 @@ node :localhost do
|
|
24
26
|
:user => "vagrant",
|
25
27
|
:port => 22,
|
26
28
|
:cpus => 1,
|
27
|
-
:memory => 512
|
28
|
-
|
29
|
-
|
29
|
+
:memory => 512,
|
30
|
+
:file => REPO
|
31
|
+
}
|
30
32
|
]
|
31
33
|
|
32
34
|
network :testnet do
|
33
35
|
address '192.168.255.254/16'
|
34
36
|
bridge :br0
|
37
|
+
route true
|
35
38
|
end
|
36
39
|
|
37
40
|
# DUAL NICs
|
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.4.
|
4
|
+
version: 0.4.1
|
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-05-
|
12
|
+
date: 2013-05-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gli
|
@@ -281,7 +281,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
281
281
|
version: '0'
|
282
282
|
segments:
|
283
283
|
- 0
|
284
|
-
hash:
|
284
|
+
hash: 3337879606359400445
|
285
285
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
286
286
|
none: false
|
287
287
|
requirements:
|
@@ -290,7 +290,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
290
290
|
version: '0'
|
291
291
|
segments:
|
292
292
|
- 0
|
293
|
-
hash:
|
293
|
+
hash: 3337879606359400445
|
294
294
|
requirements: []
|
295
295
|
rubyforge_project:
|
296
296
|
rubygems_version: 1.8.25
|