testlab 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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