testlab 0.5.0 → 0.5.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.
@@ -19,21 +19,6 @@ class TestLab
19
19
  build_lxc_config(self.lxc.config)
20
20
 
21
21
  self.lxc.create(*create_args)
22
-
23
- # Ensure the container APT calls use apt-cacher-ng on the node
24
- gateway_ip = self.primary_interface.network.ip
25
- apt_conf_d_proxy_file = File.join(self.lxc.fs_root, "etc", "apt", "apt.conf.d", "02proxy")
26
- self.node.ssh.exec(%(sudo mkdir -pv #{File.dirname(apt_conf_d_proxy_file)}))
27
- self.node.ssh.exec(%(echo 'Acquire::http { Proxy "http://#{gateway_ip}:3142"; };' | sudo tee #{apt_conf_d_proxy_file}))
28
-
29
- # Fix the APT sources since LXC mudges them when using apt-cacher-ng
30
- apt_conf_sources_file = File.join(self.lxc.fs_root, "etc", "apt", "sources.list")
31
- self.node.ssh.exec(%(sudo sed -i 's/127.0.0.1:3142\\///g' #{apt_conf_sources_file}))
32
-
33
- self.users.each do |u|
34
- u.create
35
- end
36
-
37
22
  end
38
23
 
39
24
  true
@@ -75,10 +60,6 @@ class TestLab
75
60
 
76
61
  (self.lxc.state != :running) and raise ContainerError, "The container failed to online!"
77
62
 
78
- self.users.each do |u|
79
- u.up
80
- end
81
-
82
63
  end
83
64
 
84
65
  true
@@ -16,10 +16,18 @@ class TestLab
16
16
  self.create
17
17
  self.up
18
18
 
19
- if (!@provisioner.nil? && @provisioner.respond_to?(:setup))
20
- please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
21
- @provisioner.setup(self)
19
+ please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
20
+
21
+ self.users.each do |user|
22
+ user.setup
23
+ end
24
+
25
+ self.provisioners.each do |provisioner|
26
+ @ui.logger.info { ">>>>> PROVISIONER SETUP #{provisioner} <<<<<" }
27
+ p = provisioner.new(self.config, @ui)
28
+ p.respond_to?(:setup) and p.setup(self)
22
29
  end
30
+
23
31
  end
24
32
 
25
33
  true
@@ -35,10 +43,14 @@ class TestLab
35
43
  def teardown
36
44
  @ui.logger.debug { "Container Teardown: #{self.id} " }
37
45
 
38
- if (!@provisioner.nil? && @provisioner.respond_to?(:teardown))
39
- please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
40
- @provisioner.teardown(self)
46
+ please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
47
+
48
+ self.provisioners.each do |provisioner|
49
+ @ui.logger.info { ">>>>> PROVISIONER TEARDOWN #{provisioner} <<<<<" }
50
+ p = provisioner.new(self.config, @ui)
51
+ p.respond_to?(:teardown) and p.teardown(self)
41
52
  end
53
+
42
54
  end
43
55
 
44
56
  self.down
@@ -59,7 +59,7 @@ class TestLab
59
59
  :distro => self.distro,
60
60
  :release => self.release,
61
61
  :interfaces => interfaces,
62
- :provisioner => self.provisioner,
62
+ :provisioner => self.provisioners.map(&:to_s).join(','),
63
63
  :node_id => self.node.id
64
64
  }
65
65
  end
@@ -15,9 +15,10 @@ class TestLab
15
15
  if self.users.count == 0
16
16
  case self.distro.downcase
17
17
  when 'ubuntu' then
18
- TestLab::User.new "ubuntu" do
18
+ u = TestLab::User.new "ubuntu" do
19
19
  password 'ubuntu'
20
20
  end
21
+ u.container = self
21
22
  end
22
23
  elsif self.users.any?{ |u| u.primary == true }
23
24
  self.users.find{ |u| u.primary == true }
@@ -87,30 +87,29 @@ class TestLab
87
87
  include TestLab::Utility::Misc
88
88
 
89
89
  # Associations and Attributes
90
- belongs_to :node, :class_name => 'TestLab::Node'
91
- has_many :interfaces, :class_name => 'TestLab::Interface'
92
- has_many :users, :class_name => 'TestLab::User'
90
+ belongs_to :node, :class_name => 'TestLab::Node'
91
+ has_many :interfaces, :class_name => 'TestLab::Interface'
92
+ has_many :users, :class_name => 'TestLab::User'
93
93
 
94
- attribute :provisioner
95
- attribute :config, :default => Hash.new
94
+ attribute :provisioners, :default => Array.new
95
+ attribute :config, :default => Hash.new
96
96
 
97
97
  attribute :domain
98
98
 
99
- attribute :distro, :default => 'ubuntu'
100
- attribute :release, :default => 'precise'
99
+ attribute :distro, :default => 'ubuntu'
100
+ attribute :release, :default => 'precise'
101
101
  attribute :arch
102
102
 
103
103
  # Instructs ephemeral containers to persist; otherwise tmpfs will be used
104
104
  # as the backend store for ephemeral containers.
105
105
  # NOTE: tmpfs is very memory intensive and is disabled by default.
106
- attribute :persist, :default => true
106
+ attribute :persist, :default => true
107
107
 
108
108
 
109
109
  def initialize(*args)
110
110
  super(*args)
111
111
 
112
112
  @ui = TestLab.ui
113
- @provisioner = self.provisioner.new(self.config, @ui) if !self.provisioner.nil?
114
113
  end
115
114
 
116
115
  end
@@ -30,6 +30,9 @@ class TestLab
30
30
  def setup
31
31
  @ui.logger.debug { "Node Setup: #{self.id} " }
32
32
 
33
+ self.create
34
+ self.up
35
+
33
36
  please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
34
37
 
35
38
  node_setup
@@ -41,6 +44,14 @@ class TestLab
41
44
  if self.components.include?('bind')
42
45
  bind_setup
43
46
  end
47
+
48
+ self.containers.each do |container|
49
+ container.provisioners.each do |provisioner|
50
+ p = provisioner.new(container.config, @ui)
51
+ p.respond_to?(:node) and p.node(self)
52
+ end
53
+ end
54
+
44
55
  end
45
56
 
46
57
  call_collections([self.networks, self.containers], :setup)
@@ -62,6 +73,9 @@ class TestLab
62
73
  # NOOP
63
74
  end
64
75
 
76
+ self.down
77
+ self.destroy
78
+
65
79
  true
66
80
  end
67
81
 
@@ -6,7 +6,7 @@ class TestLab
6
6
  # SSH to the Node
7
7
  def ssh(options={})
8
8
  if (!defined?(@ssh) || @ssh.nil?)
9
- @ssh ||= ZTK::SSH.new({:ui => @ui, :timeout => 1200, :silence => true}.merge(options))
9
+ @ssh ||= ZTK::SSH.new({:ui => @ui, :timeout => 1800, :silence => true}.merge(options))
10
10
  @ssh.config do |c|
11
11
  c.host_name = @provider.ip
12
12
  c.port = @provider.port
@@ -22,7 +22,7 @@ class TestLab
22
22
  name = container.id
23
23
  @container_ssh ||= Hash.new
24
24
  if @container_ssh[name].nil?
25
- @container_ssh[name] ||= ZTK::SSH.new({:ui => @ui, :timeout => 1200, :silence => true}.merge(options))
25
+ @container_ssh[name] ||= ZTK::SSH.new({:ui => @ui, :timeout => 1800, :silence => true}.merge(options))
26
26
  @container_ssh[name].config do |c|
27
27
  c.proxy_host_name = @provider.ip
28
28
  c.proxy_port = @provider.port
@@ -33,7 +33,7 @@ class TestLab
33
33
 
34
34
  c.user = (options[:user] || container.primary_user.id)
35
35
  c.password = (options[:passwd] || container.primary_user.password)
36
- c.keys = (options[:keys] || container.primary_user.keys || @provider.identity)
36
+ c.keys = (options[:keys] || container.primary_user.identity || @provider.identity)
37
37
  end
38
38
  end
39
39
  @container_ssh[name]
@@ -2,21 +2,11 @@ set -x
2
2
 
3
3
  # Update APT and ensure our required packages are installed
4
4
  apt-get -y update
5
- apt-get -y install lxc bridge-utils debootstrap yum iptables ntpdate ntp apt-cacher-ng
6
-
7
- # Ensure APT Cache-NG is running
8
- service apt-cacher-ng restart || service apt-cacher-ng start
9
- cat <<EOF | tee /etc/apt/apt.conf.d/02proxy
10
- Acquire::http { Proxy "http://127.0.0.1:3142"; };
11
- EOF
5
+ apt-get -y install lxc bridge-utils debootstrap yum iptables ntpdate ntp
12
6
 
13
7
  # Ensure the default lxc networking services are off
14
8
  service lxc-net stop
15
9
 
16
- # Ensure that we use APT Cacher-NG for building containers
17
- grep "^MIRROR" /etc/default/lxc || echo "MIRROR=\"http://127.0.0.1:3142/archive.ubuntu.com/ubuntu\"" | tee -a /etc/default/lxc
18
- service lxc restart || service lxc start
19
-
20
10
  # Ensure NTP services are enabled and running
21
11
  service ntp restart || service ntp start
22
12
 
@@ -7,9 +7,10 @@ class TestLab
7
7
  #
8
8
  # @author Zachary Patten <zachary AT jovelabs DOT com>
9
9
  class Provisioner
10
- autoload :Shell, 'testlab/provisioners/shell'
11
- autoload :OmniBus, 'testlab/provisioners/omnibus'
12
- autoload :OmniTruck, 'testlab/provisioners/omnitruck'
10
+ autoload :Shell, 'testlab/provisioners/shell'
11
+ autoload :OmniBus, 'testlab/provisioners/omnibus'
12
+ autoload :OmniTruck, 'testlab/provisioners/omnitruck'
13
+ autoload :AptCacherNG, 'testlab/provisioners/apt_cacher_ng'
13
14
 
14
15
  class << self
15
16
 
@@ -0,0 +1,74 @@
1
+ class TestLab
2
+
3
+ class Provisioner
4
+
5
+ # AptCacherNG Provisioner Error Class
6
+ class AptCacherNGError < ProvisionerError; end
7
+
8
+ # AptCacherNG Provisioner Class
9
+ #
10
+ # @author Zachary Patten <zachary AT jovelabs DOT com>
11
+ class AptCacherNG
12
+
13
+ def initialize(config={}, ui=nil)
14
+ @config = (config || Hash.new)
15
+ @ui = (ui || TestLab.ui)
16
+
17
+ @ui.logger.debug { "config(#{@config.inspect})" }
18
+ end
19
+
20
+ # AptCacherNG Provisioner Node Setup
21
+ #
22
+ # @param [TestLab::Node] node The node which we want to provision.
23
+ # @return [Boolean] True if successful.
24
+ def node(node)
25
+ @ui.logger.debug { "AptCacherNG Provisioner: Node #{node.id}" }
26
+
27
+ node.ssh.exec(%(sudo apt-get -y install apt-cacher-ng))
28
+ node.ssh.exec(%(sudo service apt-cacher-ng restart || sudo service apt-cacher-ng start))
29
+ node.ssh.exec(%(echo 'Acquire::HTTP { Proxy "http://127.0.0.1:3142"; };' | sudo tee /etc/apt/apt.conf.d/00proxy))
30
+ node.ssh.exec(%(sudo grep "^MIRROR" /etc/default/lxc || echo 'MIRROR="http://127.0.0.1:3142/archive.ubuntu.com/ubuntu"' | sudo tee -a /etc/default/lxc))
31
+ node.ssh.exec(%(sudo service lxc restart || sudo service lxc start))
32
+
33
+ true
34
+ end
35
+
36
+ # AptCacherNG Provisioner Container Setup
37
+ #
38
+ # @param [TestLab::Container] container The container which we want to
39
+ # provision.
40
+ # @return [Boolean] True if successful.
41
+ def setup(container)
42
+ @ui.logger.debug { "AptCacherNG Provisioner: Container #{container.id}" }
43
+
44
+ # Ensure the container APT calls use apt-cacher-ng on the node
45
+ gateway_ip = container.primary_interface.network.ip
46
+ apt_conf_d_proxy_file = File.join(container.lxc.fs_root, "etc", "apt", "apt.conf.d", "00proxy")
47
+
48
+ container.node.ssh.exec(%(sudo mkdir -pv #{File.dirname(apt_conf_d_proxy_file)}))
49
+
50
+ container.node.ssh.exec(%(echo 'Acquire::HTTP { Proxy "http://#{gateway_ip}:3142"; };' | sudo tee #{apt_conf_d_proxy_file}))
51
+ container.config[:apt_cacher_exclude_hosts].each do |host|
52
+ container.node.ssh.exec(%(echo 'Acquire::HTTP::Proxy::#{host} "DIRECT";' | sudo tee -a #{apt_conf_d_proxy_file}))
53
+ end
54
+
55
+ # Fix the APT sources since LXC mudges them when using apt-cacher-ng
56
+ apt_conf_sources_file = File.join(container.lxc.fs_root, "etc", "apt", "sources.list")
57
+ container.node.ssh.exec(%(sudo sed -i 's/127.0.0.1:3142\\///g' #{apt_conf_sources_file}))
58
+ end
59
+
60
+ # AptCacherNG Provisioner Container Teardown
61
+ #
62
+ # This is a NO-OP currently.
63
+ #
64
+ # @return [Boolean] True if successful.
65
+ def teardown(container)
66
+ # NOOP
67
+
68
+ true
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+ end
@@ -25,8 +25,8 @@ class TestLab
25
25
  # provision.
26
26
  # @return [Boolean] True if successful.
27
27
  def setup(container)
28
- if !@config[:setup].nil?
29
- container.bootstrap(@config[:setup])
28
+ if !@config[:script].nil?
29
+ container.bootstrap(@config[:script])
30
30
  end
31
31
 
32
32
  true
@@ -1,12 +1,12 @@
1
1
  class TestLab
2
2
  class User
3
3
 
4
- module Actions
4
+ module Lifecycle
5
5
 
6
- # Create the user
6
+ # Setup the user
7
7
  #
8
8
  # @return [Boolean] True if successful.
9
- def create
9
+ def setup
10
10
  @ui.logger.debug { "User Create: #{self.id} " }
11
11
 
12
12
  node_home_dir = ((self.container.node.user == "root") ? %(/root) : %(/home/#{self.container.node.user}))
@@ -46,21 +46,14 @@ class TestLab
46
46
  self.container.node.ssh.exec(%(sudo chmod -v 644 #{destination}))
47
47
  end
48
48
 
49
- true
50
- end
51
-
52
- # Up the user
53
- #
54
- # @return [Boolean] True if successful.
55
- def up
56
- @ui.logger.debug { "User Up: #{self.id}" }
57
-
58
49
  # ensure the container user home directory is owned by them
59
50
  home_dir = self.container.lxc.attach(%(-- /bin/bash -c 'grep #{self.id} /etc/passwd | cut -d ":" -f6')).strip
60
51
  self.container.lxc.attach(%(-- /bin/bash -c 'sudo chown -Rv $(id -u #{self.id}):$(id -g #{self.id}) #{home_dir}'))
61
52
 
62
53
  # ensure the sudo user group can do passwordless sudo
63
54
  self.container.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'))
55
+
56
+ true
64
57
  end
65
58
 
66
59
  end
data/lib/testlab/user.rb CHANGED
@@ -9,16 +9,18 @@ class TestLab
9
9
  class User < ZTK::DSL::Base
10
10
 
11
11
  # Sub-Modules
12
- autoload :Actions, 'testlab/user/actions'
12
+ autoload :Lifecycle, 'testlab/user/lifecycle'
13
13
 
14
- include TestLab::User::Actions
14
+ include TestLab::User::Lifecycle
15
15
 
16
16
  # Associations and Attributes
17
17
  belongs_to :container, :class_name => 'TestLab::Container'
18
18
 
19
19
  attribute :user
20
20
  attribute :password
21
- attribute :keys
21
+
22
+ attribute :identity
23
+
22
24
  attribute :uid
23
25
  attribute :gid
24
26
 
@@ -1,6 +1,6 @@
1
1
  class TestLab
2
2
  unless const_defined?(:VERSION)
3
3
  # TestLab Gem Version
4
- VERSION = "0.5.0"
4
+ VERSION = "0.5.1"
5
5
  end
6
6
  end
@@ -188,7 +188,7 @@ describe TestLab::Container do
188
188
  it "should create and online the container" do
189
189
  subject.stub(:create) { true }
190
190
  subject.stub(:up) { true }
191
- subject.instance_variable_get(:@provisioner) and subject.instance_variable_get(:@provisioner).stub(:setup) { true }
191
+ subject.provisioners = Array.new
192
192
 
193
193
  subject.setup
194
194
  end
@@ -199,7 +199,7 @@ describe TestLab::Container do
199
199
  subject = TestLab::Container.first('server-shell')
200
200
  subject.stub(:create) { true }
201
201
  subject.stub(:up) { true }
202
- subject.instance_variable_get(:@provisioner) and subject.instance_variable_get(:@provisioner).stub(:setup) { true }
202
+ subject.provisioners = Array.new
203
203
 
204
204
  subject.setup
205
205
  end
@@ -211,7 +211,7 @@ describe TestLab::Container do
211
211
  it "should create and online the container" do
212
212
  subject.stub(:down) { true }
213
213
  subject.stub(:destroy) { true }
214
- subject.instance_variable_get(:@provisioner) and subject.instance_variable_get(:@provisioner).stub(:teardown) { true }
214
+ subject.provisioners = Array.new
215
215
 
216
216
  subject.teardown
217
217
  end
@@ -222,7 +222,7 @@ describe TestLab::Container do
222
222
  subject = TestLab::Container.first('server-shell')
223
223
  subject.stub(:down) { true }
224
224
  subject.stub(:destroy) { true }
225
- subject.instance_variable_get(:@provisioner) and subject.instance_variable_get(:@provisioner).stub(:teardown) { true }
225
+ subject.provisioners = Array.new
226
226
 
227
227
  subject.teardown
228
228
  end
@@ -30,7 +30,7 @@ describe TestLab::Provisioner::Shell do
30
30
  describe "class" do
31
31
 
32
32
  it "should be an instance of TestLab::Provisioner::Shell" do
33
- subject.instance_variable_get(:@provisioner).should be_an_instance_of TestLab::Provisioner::Shell
33
+ subject.provisioners.first.new(subject.config, @ui).should be_an_instance_of TestLab::Provisioner::Shell
34
34
  end
35
35
 
36
36
  end
@@ -42,7 +42,7 @@ 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.lxc.stub(:attach) { "" }
45
- subject.instance_variable_get(:@provisioner).setup(subject)
45
+ subject.provisioners.first.new(subject.config, @ui).setup(subject)
46
46
  end
47
47
  end
48
48
 
@@ -50,14 +50,14 @@ describe TestLab::Provisioner::Shell do
50
50
  it "should raise an exception" do
51
51
  subject.node.ssh.stub(:file).and_yield(StringIO.new)
52
52
  subject.lxc.stub(:attach) { "No such file or directory" }
53
- lambda{ subject.instance_variable_get(:@provisioner).setup(subject) }.should raise_error TestLab::ContainerError
53
+ lambda{ subject.provisioners.first.new(subject.config, @ui).setup(subject) }.should raise_error TestLab::ContainerError
54
54
  end
55
55
  end
56
56
  end
57
57
 
58
58
  describe "teardown" do
59
59
  it "should decomission the container" do
60
- subject.instance_variable_get(:@provisioner).teardown(subject)
60
+ subject.provisioners.first.new(subject.config, @ui).teardown(subject)
61
61
  end
62
62
  end
63
63
 
data/spec/support/Labfile CHANGED
@@ -31,7 +31,7 @@ node :localhost do
31
31
  }
32
32
  ]
33
33
 
34
- network :testnet do
34
+ network 'testnet' do
35
35
  address '192.168.255.254/16'
36
36
  bridge :br0
37
37
  route true
@@ -44,14 +44,14 @@ node :localhost do
44
44
 
45
45
  interface do
46
46
  name :eth0
47
- network_id :testnet
47
+ network_id 'testnet'
48
48
  address '192.168.0.254/16'
49
49
  primary true
50
50
  end
51
51
 
52
52
  interface do
53
53
  name :eth1
54
- network_id :testnet
54
+ network_id 'testnet'
55
55
  address '192.168.0.253/16'
56
56
  end
57
57
  end
@@ -63,7 +63,7 @@ node :localhost do
63
63
 
64
64
  interface do
65
65
  name :eth0
66
- network_id :testnet
66
+ network_id 'testnet'
67
67
  address '192.168.0.200/16'
68
68
  end
69
69
  end
@@ -73,15 +73,15 @@ node :localhost do
73
73
  distro "ubuntu"
74
74
  release "precise"
75
75
 
76
- provisioner TestLab::Provisioner::Shell
76
+ provisioners [TestLab::Provisioner::Shell]
77
77
  config Hash[
78
78
  :shell => "/bin/bash",
79
- :setup => shell_provision_script
79
+ :script => shell_provision_script
80
80
  ]
81
81
 
82
82
  interface do
83
83
  name :eth0
84
- network_id :testnet
84
+ network_id 'testnet'
85
85
  address '192.168.0.200/16'
86
86
  end
87
87
  end
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.5.0
4
+ version: 0.5.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-06-10 00:00:00.000000000 Z
12
+ date: 2013-06-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gli
@@ -248,13 +248,14 @@ files:
248
248
  - lib/testlab/providers/templates/vagrant/Vagrantfile.erb
249
249
  - lib/testlab/providers/vagrant.rb
250
250
  - lib/testlab/provisioner.rb
251
+ - lib/testlab/provisioners/apt_cacher_ng.rb
251
252
  - lib/testlab/provisioners/omnibus.rb
252
253
  - lib/testlab/provisioners/omnitruck.rb
253
254
  - lib/testlab/provisioners/shell.rb
254
255
  - lib/testlab/provisioners/templates/chef/omnibus.erb
255
256
  - lib/testlab/provisioners/templates/chef/omnitruck.erb
256
257
  - lib/testlab/user.rb
257
- - lib/testlab/user/actions.rb
258
+ - lib/testlab/user/lifecycle.rb
258
259
  - lib/testlab/utility.rb
259
260
  - lib/testlab/utility/cidr.rb
260
261
  - lib/testlab/utility/misc.rb
@@ -285,7 +286,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
285
286
  version: '0'
286
287
  segments:
287
288
  - 0
288
- hash: -532232323948453701
289
+ hash: 4401719777665072340
289
290
  required_rubygems_version: !ruby/object:Gem::Requirement
290
291
  none: false
291
292
  requirements:
@@ -294,7 +295,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
294
295
  version: '0'
295
296
  segments:
296
297
  - 0
297
- hash: -532232323948453701
298
+ hash: 4401719777665072340
298
299
  requirements: []
299
300
  rubyforge_project:
300
301
  rubygems_version: 1.8.25