testlab 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -2,13 +2,10 @@ language: ruby
2
2
 
3
3
  rvm:
4
4
  - ree
5
+ - 1.8.7
5
6
  - 1.9.2
6
7
  - 1.9.3
7
8
  - 2.0.0
8
9
 
9
10
  notifications:
10
11
  irc: "irc.freenode.net#jovelabs"
11
-
12
- matrix:
13
- allow_failures:
14
- - rvm: ree
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem "json" if (RUBY_VERSION == "1.8.7")
4
+
3
5
  gemspec
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
- self.node.ssh.file(:target => File.join(self.lxc.fs_root, tempfile.path), :chmod => '0777', :chown => 'root:root') do |file|
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), tempfile.path)
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
@@ -31,6 +31,7 @@ class TestLab
31
31
 
32
32
  attribute :address
33
33
  attribute :bridge
34
+ attribute :route, :default => false
34
35
 
35
36
  attribute :config
36
37
 
@@ -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
@@ -12,6 +12,7 @@ class TestLab
12
12
  :instance_id => @provider.instance_id,
13
13
  :state => @provider.state,
14
14
  :user => @provider.user,
15
+ :identity => @provider.identity,
15
16
  :ip => @provider.ip,
16
17
  :port => @provider.port,
17
18
  :provider => @provider.class,
@@ -15,4 +15,3 @@ sysctl net.ipv4.ip_forward | grep "net.ipv4.ip_forward = 1" || sysctl -w net.ipv
15
15
 
16
16
  # Install an iptable NAT rule
17
17
  iptables -t nat --list -v | grep "MASQUERADE all -- any eth0 anywhere anywhere" || iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
18
-
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::Lab'
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)
@@ -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).exec(command, :silence => true)
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[:repo], "Vagrantfile")
194
+ vagrantfile = File.join(@config[:vagrant][:file], "Vagrantfile")
195
195
 
196
- # UGLY; but it makes it run under 1.9.2
197
- if RUBY_VERSION < "1.9.3"
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
- "chef-server" => {
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 /tmp/chef-solo/
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
- curl -L https://www.opscode.com/chef/install.sh | bash
29
- # bash install.sh -v <%= @version %>
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
@@ -1,6 +1,6 @@
1
1
  class TestLab
2
2
  unless const_defined?(:VERSION)
3
3
  # TestLab Gem Version
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.1"
5
5
  end
6
6
  end
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 ClassMethods
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::ClassMethods
276
- extend TestLab::ClassMethods
287
+ include TestLab::DualMethods
288
+ extend TestLab::DualMethods
277
289
 
278
290
  end
@@ -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
- :repo => File.dirname(__FILE__)
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.0
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-06 00:00:00.000000000 Z
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: 2598342112570301025
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: 2598342112570301025
293
+ hash: 3337879606359400445
294
294
  requirements: []
295
295
  rubyforge_project:
296
296
  rubygems_version: 1.8.25