testlab 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/tl +80 -2
- data/lib/testlab/container/lifecycle.rb +2 -2
- data/lib/testlab/container/status.rb +1 -1
- data/lib/testlab/container.rb +3 -3
- data/lib/testlab/network/lifecycle.rb +12 -2
- data/lib/testlab/node/lifecycle.rb +5 -39
- data/lib/testlab/node/ssh.rb +2 -2
- data/lib/testlab/node.rb +7 -9
- data/lib/testlab/providers/local.rb +74 -2
- data/lib/testlab/provisioner.rb +4 -0
- data/lib/testlab/provisioners/apt.rb +39 -0
- data/lib/testlab/provisioners/apt_cacher_ng.rb +33 -35
- data/lib/testlab/{node → provisioners}/bind.rb +51 -24
- data/lib/testlab/provisioners/chef_gem.rb +3 -81
- data/lib/testlab/provisioners/raring.rb +37 -0
- data/lib/testlab/provisioners/resolv.rb +61 -0
- data/lib/testlab/provisioners/shell.rb +0 -11
- data/lib/testlab/provisioners/templates/apt/bootstrap.erb +11 -0
- data/lib/testlab/provisioners/templates/apt_cacher_ng/00proxy.erb +4 -0
- data/lib/testlab/provisioners/templates/apt_cacher_ng/bootstrap.erb +7 -0
- data/lib/testlab/{node/templates → provisioners/templates/bind}/bind-db.erb +0 -0
- data/lib/testlab/{node/templates → provisioners/templates/bind}/bind-zone.erb +0 -0
- data/lib/testlab/{node/templates → provisioners/templates/bind}/bind.erb +0 -0
- data/lib/testlab/provisioners/templates/chef/omnibus.erb +2 -0
- data/lib/testlab/provisioners/templates/chef/omnitruck.erb +1 -1
- data/lib/testlab/provisioners/templates/chef/rubygem.erb +0 -0
- data/lib/testlab/{node/templates/node-setup.erb → provisioners/templates/raring/bootstrap.erb} +2 -0
- data/lib/testlab/provisioners/templates/resolv/resolv.conf.erb +9 -0
- data/lib/testlab/version.rb +1 -1
- data/lib/testlab.rb +58 -2
- data/spec/node_spec.rb +4 -19
- data/spec/provisioners/shell_spec.rb +3 -9
- data/spec/support/Labfile +29 -10
- metadata +17 -11
- data/lib/testlab/node/resolv.rb +0 -29
- data/lib/testlab/node/templates/resolv.erb +0 -4
data/bin/tl
CHANGED
@@ -149,6 +149,82 @@ command :node do |c|
|
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
|
+
# NODE UP
|
153
|
+
##########
|
154
|
+
c.desc 'Up a node'
|
155
|
+
c.long_desc <<-EOF
|
156
|
+
Up a node. The node is started and brought online.
|
157
|
+
EOF
|
158
|
+
c.command :up do |up|
|
159
|
+
up.action do |global_options, options, args|
|
160
|
+
if options[:id].nil?
|
161
|
+
help_now!('id is required') if options[:id].nil?
|
162
|
+
else
|
163
|
+
node = @testlab.nodes.select{ |c| c.id.to_sym == options[:id].to_sym }.first
|
164
|
+
node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
|
165
|
+
|
166
|
+
node.up
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# NODE DOWN
|
172
|
+
############
|
173
|
+
c.desc 'Down a node'
|
174
|
+
c.long_desc <<-EOF
|
175
|
+
Down a node. The node is stopped taking it offline.
|
176
|
+
EOF
|
177
|
+
c.command :down do |down|
|
178
|
+
down.action do |global_options, options, args|
|
179
|
+
if options[:id].nil?
|
180
|
+
help_now!('id is required') if options[:id].nil?
|
181
|
+
else
|
182
|
+
node = @testlab.nodes.select{ |c| c.id.to_sym == options[:id].to_sym }.first
|
183
|
+
node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
|
184
|
+
|
185
|
+
node.down
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# NODE SETUP
|
191
|
+
#############
|
192
|
+
c.desc 'Setup a node'
|
193
|
+
c.long_desc <<-EOF
|
194
|
+
Setup a node. The node is created, started and provisioned.
|
195
|
+
EOF
|
196
|
+
c.command :setup do |setup|
|
197
|
+
setup.action do |global_options, options, args|
|
198
|
+
if options[:id].nil?
|
199
|
+
help_now!('id is required') if options[:id].nil?
|
200
|
+
else
|
201
|
+
node = @testlab.nodes.select{ |c| c.id.to_sym == options[:id].to_sym }.first
|
202
|
+
node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
|
203
|
+
|
204
|
+
node.setup
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# NODE TEARDOWN
|
210
|
+
################
|
211
|
+
c.desc 'Teardown a node'
|
212
|
+
c.long_desc <<-EOF
|
213
|
+
Teardown a node. The node is offlined and destroyed.
|
214
|
+
EOF
|
215
|
+
c.command :teardown do |teardown|
|
216
|
+
teardown.action do |global_options, options, args|
|
217
|
+
if options[:id].nil?
|
218
|
+
help_now!('id is required') if options[:id].nil?
|
219
|
+
else
|
220
|
+
node = @testlab.nodes.select{ |c| c.id.to_sym == options[:id].to_sym }.first
|
221
|
+
node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!"
|
222
|
+
|
223
|
+
node.teardown
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
152
228
|
end
|
153
229
|
|
154
230
|
# NETWORKS
|
@@ -377,8 +453,10 @@ EOF
|
|
377
453
|
if containers.count == 0
|
378
454
|
@testlab.ui.stderr.puts("You either have no containers defined or dead nodes!".yellow)
|
379
455
|
else
|
380
|
-
ZTK::Report.new(:ui => @testlab.ui).spreadsheet(containers, TestLab::Container::STATUS_KEYS.reject{|k| k == :fqdn}) do |container|
|
381
|
-
|
456
|
+
# ZTK::Report.new(:ui => @testlab.ui).spreadsheet(containers, TestLab::Container::STATUS_KEYS.reject{|k| k == :fqdn}) do |container|
|
457
|
+
ZTK::Report.new(:ui => @testlab.ui).list(containers, TestLab::Container::STATUS_KEYS) do |container|
|
458
|
+
# OpenStruct.new(container.status.reject{|k,v| k == :fqdn})
|
459
|
+
OpenStruct.new(container.status)
|
382
460
|
end
|
383
461
|
end
|
384
462
|
else
|
@@ -23,7 +23,7 @@ class TestLab
|
|
23
23
|
end
|
24
24
|
|
25
25
|
self.provisioners.each do |provisioner|
|
26
|
-
@ui.logger.info { ">>>>> PROVISIONER
|
26
|
+
@ui.logger.info { ">>>>> SETUP CONTAINER PROVISIONER: #{provisioner} <<<<<" }
|
27
27
|
p = provisioner.new(self.config, @ui)
|
28
28
|
p.respond_to?(:setup) and p.setup(self)
|
29
29
|
end
|
@@ -46,7 +46,7 @@ class TestLab
|
|
46
46
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
47
47
|
|
48
48
|
self.provisioners.each do |provisioner|
|
49
|
-
@ui.logger.info { ">>>>> PROVISIONER
|
49
|
+
@ui.logger.info { ">>>>> TEARDOWN CONTAINER PROVISIONER: #{provisioner} <<<<<" }
|
50
50
|
p = provisioner.new(self.config, @ui)
|
51
51
|
p.respond_to?(:teardown) and p.teardown(self)
|
52
52
|
end
|
@@ -59,7 +59,7 @@ class TestLab
|
|
59
59
|
:distro => self.distro,
|
60
60
|
:release => self.release,
|
61
61
|
:interfaces => interfaces,
|
62
|
-
:
|
62
|
+
:provisioners => self.provisioners.map(&:to_s).collect{ |p| p.split('::').last }.join('/'),
|
63
63
|
:node_id => self.node.id
|
64
64
|
}
|
65
65
|
end
|
data/lib/testlab/container.rb
CHANGED
@@ -15,9 +15,9 @@ class TestLab
|
|
15
15
|
# release "precise"
|
16
16
|
#
|
17
17
|
# user "deployer" do
|
18
|
+
# password "deployer"
|
18
19
|
# uid 2600
|
19
20
|
# gid 2600
|
20
|
-
# password "deployer"
|
21
21
|
# end
|
22
22
|
#
|
23
23
|
# interface do
|
@@ -34,9 +34,9 @@ class TestLab
|
|
34
34
|
# release "precise"
|
35
35
|
#
|
36
36
|
# user "deployer" do
|
37
|
+
# password "deployer"
|
37
38
|
# uid 2600
|
38
39
|
# gid 2600
|
39
|
-
# password "deployer"
|
40
40
|
# end
|
41
41
|
#
|
42
42
|
# interface do
|
@@ -70,7 +70,7 @@ class TestLab
|
|
70
70
|
# An array of symbols of the various keys in our status hash.
|
71
71
|
#
|
72
72
|
# @see TestLab::Container::Status
|
73
|
-
STATUS_KEYS = %w(node_id id clone fqdn state distro release interfaces
|
73
|
+
STATUS_KEYS = %w(node_id id clone fqdn state distro release interfaces provisioners).map(&:to_sym)
|
74
74
|
|
75
75
|
# Sub-Modules
|
76
76
|
autoload :Actions, 'testlab/container/actions'
|
@@ -9,16 +9,26 @@ class TestLab
|
|
9
9
|
|
10
10
|
self.create
|
11
11
|
self.up
|
12
|
-
|
12
|
+
|
13
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
14
|
+
self.route and manage_route(:add)
|
15
|
+
end
|
16
|
+
|
17
|
+
true
|
13
18
|
end
|
14
19
|
|
15
20
|
# Network Teardown
|
16
21
|
def teardown
|
17
22
|
@ui.logger.debug { "Network Teardown: #{self.id} " }
|
18
23
|
|
19
|
-
self
|
24
|
+
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
25
|
+
self.route and manage_route(:del)
|
26
|
+
end
|
27
|
+
|
20
28
|
self.down
|
21
29
|
self.destroy
|
30
|
+
|
31
|
+
true
|
22
32
|
end
|
23
33
|
|
24
34
|
def manage_route(action)
|
@@ -3,23 +3,6 @@ class TestLab
|
|
3
3
|
|
4
4
|
module Lifecycle
|
5
5
|
|
6
|
-
# Iterates an array of arrays calling the specified method on all the
|
7
|
-
# collections of objects
|
8
|
-
def call_collections(collections, method_name)
|
9
|
-
collections.each do |collection|
|
10
|
-
call_methods(collection, method_name)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# Calls the specified method on all the objects supplied
|
15
|
-
def call_methods(objects, method_name)
|
16
|
-
objects.each do |object|
|
17
|
-
if object.respond_to?(method_name)
|
18
|
-
object.send(method_name)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
6
|
# Bootstrap the node
|
24
7
|
def node_setup
|
25
8
|
node_setup_template = File.join(self.class.template_dir, 'node-setup.erb')
|
@@ -35,31 +18,16 @@ class TestLab
|
|
35
18
|
|
36
19
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Setup', :green)) do
|
37
20
|
|
38
|
-
|
21
|
+
global_provisioners = [self.provisioners, self.containers.map(&:provisioners)].flatten.compact.uniq
|
39
22
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
if self.components.include?('bind')
|
45
|
-
bind_setup
|
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
|
23
|
+
global_provisioners.each do |provisioner|
|
24
|
+
@ui.logger.info { ">>>>> NODE PROVISIONER: #{provisioner} <<<<<" }
|
25
|
+
p = provisioner.new(self.config, @ui)
|
26
|
+
p.respond_to?(:node) and p.node(self)
|
53
27
|
end
|
54
28
|
|
55
29
|
end
|
56
30
|
|
57
|
-
call_collections([self.networks, self.containers], :setup)
|
58
|
-
|
59
|
-
if self.components.include?('bind')
|
60
|
-
bind_reload
|
61
|
-
end
|
62
|
-
|
63
31
|
true
|
64
32
|
end
|
65
33
|
|
@@ -67,8 +35,6 @@ class TestLab
|
|
67
35
|
def teardown
|
68
36
|
@ui.logger.debug { "Node Teardown: #{self.id} " }
|
69
37
|
|
70
|
-
call_collections([self.containers.reverse, self.networks.reverse], :teardown)
|
71
|
-
|
72
38
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Teardown', :red)) do
|
73
39
|
# NOOP
|
74
40
|
end
|
data/lib/testlab/node/ssh.rb
CHANGED
@@ -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 =>
|
9
|
+
@ssh ||= ZTK::SSH.new({:ui => @ui, :timeout => 3600, :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 =>
|
25
|
+
@container_ssh[name] ||= ZTK::SSH.new({:ui => @ui, :timeout => 3600, :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
|
data/lib/testlab/node.rb
CHANGED
@@ -11,21 +11,17 @@ class TestLab
|
|
11
11
|
|
12
12
|
# Sub-Modules
|
13
13
|
autoload :Actions, 'testlab/node/actions'
|
14
|
-
autoload :Bind, 'testlab/node/bind'
|
15
14
|
autoload :ClassMethods, 'testlab/node/class_methods'
|
16
15
|
autoload :Lifecycle, 'testlab/node/lifecycle'
|
17
16
|
autoload :LXC, 'testlab/node/lxc'
|
18
17
|
autoload :MethodMissing, 'testlab/node/method_missing'
|
19
|
-
autoload :Resolv, 'testlab/node/resolv'
|
20
18
|
autoload :SSH, 'testlab/node/ssh'
|
21
19
|
autoload :Status, 'testlab/node/status'
|
22
20
|
|
23
21
|
include TestLab::Node::Actions
|
24
|
-
include TestLab::Node::Bind
|
25
22
|
include TestLab::Node::Lifecycle
|
26
23
|
include TestLab::Node::LXC
|
27
24
|
include TestLab::Node::MethodMissing
|
28
|
-
include TestLab::Node::Resolv
|
29
25
|
include TestLab::Node::SSH
|
30
26
|
include TestLab::Node::Status
|
31
27
|
|
@@ -34,19 +30,21 @@ class TestLab
|
|
34
30
|
include TestLab::Utility::Misc
|
35
31
|
|
36
32
|
# Associations and Attributes
|
37
|
-
belongs_to :labfile,
|
33
|
+
belongs_to :labfile, :class_name => 'TestLab::Labfile'
|
38
34
|
|
39
|
-
has_many :containers,
|
40
|
-
has_many :networks,
|
35
|
+
has_many :containers, :class_name => 'TestLab::Container'
|
36
|
+
has_many :networks, :class_name => 'TestLab::Network'
|
41
37
|
|
42
38
|
attribute :provider
|
43
|
-
attribute :
|
44
|
-
attribute :
|
39
|
+
attribute :provisioners, :default => Array.new
|
40
|
+
attribute :config, :default => Hash.new
|
45
41
|
|
46
42
|
|
47
43
|
def initialize(*args)
|
48
44
|
super(*args)
|
49
45
|
|
46
|
+
raise NodeError, "You must specify a provider class!" if self.provider.nil?
|
47
|
+
|
50
48
|
@ui = TestLab.ui
|
51
49
|
@provider = self.provider.new(self.config, @ui)
|
52
50
|
end
|
@@ -10,8 +10,80 @@ class TestLab
|
|
10
10
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
11
11
|
class Local
|
12
12
|
|
13
|
-
def initialize(ui=
|
14
|
-
@
|
13
|
+
def initialize(config={}, ui=nil)
|
14
|
+
@config = (config || Hash.new)
|
15
|
+
@ui = (ui || TestLab.ui)
|
16
|
+
|
17
|
+
# ensure our local key is there
|
18
|
+
@config[:local] ||= Hash.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# This is a NO-OP
|
22
|
+
def create
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
# This is a NO-OP
|
27
|
+
def destroy
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
# This is a NO-OP
|
32
|
+
def up
|
33
|
+
self.state
|
34
|
+
end
|
35
|
+
|
36
|
+
# This is a NO-OP
|
37
|
+
def down
|
38
|
+
self.state
|
39
|
+
end
|
40
|
+
|
41
|
+
# This is a NO-OP
|
42
|
+
def reload
|
43
|
+
self.down
|
44
|
+
self.up
|
45
|
+
|
46
|
+
self.state
|
47
|
+
end
|
48
|
+
|
49
|
+
# This is a NO-OP
|
50
|
+
def state
|
51
|
+
:running
|
52
|
+
end
|
53
|
+
|
54
|
+
# This is a NO-OP
|
55
|
+
def exists?
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
59
|
+
# This is a NO-OP
|
60
|
+
def alive?
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
# This is a NO-OP
|
65
|
+
def dead?
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
def instance_id
|
70
|
+
%x(hostname).strip
|
71
|
+
end
|
72
|
+
|
73
|
+
def user
|
74
|
+
ENV['USER']
|
75
|
+
end
|
76
|
+
|
77
|
+
def identity
|
78
|
+
File.join(ENV['HOME'], ".ssh", "id_rsa")
|
79
|
+
end
|
80
|
+
|
81
|
+
def ip
|
82
|
+
"127.0.0.1"
|
83
|
+
end
|
84
|
+
|
85
|
+
def port
|
86
|
+
(@config[:local][:port] || 22)
|
15
87
|
end
|
16
88
|
|
17
89
|
end
|
data/lib/testlab/provisioner.rb
CHANGED
@@ -7,10 +7,14 @@ class TestLab
|
|
7
7
|
#
|
8
8
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
9
9
|
class Provisioner
|
10
|
+
autoload :Apt, 'testlab/provisioners/apt'
|
10
11
|
autoload :AptCacherNG, 'testlab/provisioners/apt_cacher_ng'
|
12
|
+
autoload :Bind, 'testlab/provisioners/bind'
|
11
13
|
autoload :ChefGem, 'testlab/provisioners/chef_gem'
|
12
14
|
autoload :OmniBus, 'testlab/provisioners/omnibus'
|
13
15
|
autoload :OmniTruck, 'testlab/provisioners/omnitruck'
|
16
|
+
autoload :Resolv, 'testlab/provisioners/resolv'
|
17
|
+
autoload :Raring, 'testlab/provisioners/raring'
|
14
18
|
autoload :Shell, 'testlab/provisioners/shell'
|
15
19
|
|
16
20
|
class << self
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class TestLab
|
2
|
+
|
3
|
+
class Provisioner
|
4
|
+
|
5
|
+
# APT Provisioner Error Class
|
6
|
+
class AptError < ProvisionerError; end
|
7
|
+
|
8
|
+
# APT Provisioner Class
|
9
|
+
#
|
10
|
+
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
11
|
+
class Apt
|
12
|
+
|
13
|
+
def initialize(config={}, ui=nil)
|
14
|
+
@config = (config || Hash.new)
|
15
|
+
@ui = (ui || TestLab.ui)
|
16
|
+
|
17
|
+
@config[:apt] ||= Hash.new
|
18
|
+
@config[:apt][:install] ||= Array.new
|
19
|
+
@config[:apt][:remove] ||= Array.new
|
20
|
+
|
21
|
+
@ui.logger.debug { "config(#{@config.inspect})" }
|
22
|
+
end
|
23
|
+
|
24
|
+
# APT Provisioner Container Setup
|
25
|
+
#
|
26
|
+
# @param [TestLab::Container] container The container which we want to
|
27
|
+
# provision.
|
28
|
+
# @return [Boolean] True if successful.
|
29
|
+
def setup(container)
|
30
|
+
@ui.logger.debug { "APT Provisioner: Container #{container.id}" }
|
31
|
+
|
32
|
+
bootstrap_template = File.join(TestLab::Provisioner.template_dir, "apt", "bootstrap.erb")
|
33
|
+
container.ssh.bootstrap(ZTK::Template.render(bootstrap_template, @config))
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -14,65 +14,63 @@ class TestLab
|
|
14
14
|
@config = (config || Hash.new)
|
15
15
|
@ui = (ui || TestLab.ui)
|
16
16
|
|
17
|
+
@config[:apt] ||= Hash.new
|
18
|
+
@config[:apt][:cacher_ng] ||= Hash.new
|
19
|
+
@config[:apt][:cacher_ng][:exclude_hosts] ||= Array.new
|
20
|
+
|
21
|
+
@apt_conf_d_proxy_file_template = File.join(TestLab::Provisioner.template_dir, "apt_cacher_ng", "00proxy.erb")
|
22
|
+
|
17
23
|
@ui.logger.debug { "config(#{@config.inspect})" }
|
18
24
|
end
|
19
25
|
|
20
|
-
#
|
26
|
+
# APT-CacherNG Provisioner Node Setup
|
21
27
|
#
|
22
28
|
# @param [TestLab::Node] node The node which we want to provision.
|
23
29
|
# @return [Boolean] True if successful.
|
24
30
|
def node(node)
|
25
|
-
@ui.logger.debug { "
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
@ui.logger.debug { "APT-CacherNG Provisioner: Node #{node.id}" }
|
32
|
+
|
33
|
+
bootstrap_template = File.join(TestLab::Provisioner.template_dir, "apt_cacher_ng", "bootstrap.erb")
|
34
|
+
node.ssh.bootstrap(ZTK::Template.render(bootstrap_template, @config))
|
35
|
+
|
36
|
+
context = {
|
37
|
+
:apt => {
|
38
|
+
:cacher_ng => {
|
39
|
+
:proxy_url => "http://127.0.0.1:3142",
|
40
|
+
:exclude_hosts => Array.new
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
apt_conf_d_proxy_file = File.join("/etc", "apt", "apt.conf.d", "00proxy")
|
46
|
+
node.ssh.file(:target => apt_conf_d_proxy_file, :chown => "root:root", :chmod => "0644") do |file|
|
47
|
+
file.puts(ZTK::Template.render(@apt_conf_d_proxy_file_template, context))
|
48
|
+
end
|
35
49
|
|
36
50
|
true
|
37
51
|
end
|
38
52
|
|
39
|
-
#
|
53
|
+
# APT-CacherNG Provisioner Container Setup
|
40
54
|
#
|
41
55
|
# @param [TestLab::Container] container The container which we want to
|
42
56
|
# provision.
|
43
57
|
# @return [Boolean] True if successful.
|
44
58
|
def setup(container)
|
45
|
-
@ui.logger.debug { "
|
59
|
+
@ui.logger.debug { "APT-CacherNG Provisioner: Container #{container.id}" }
|
46
60
|
|
47
61
|
# Ensure the container APT calls use apt-cacher-ng on the node
|
48
|
-
gateway_ip
|
49
|
-
apt_conf_d_proxy_file
|
62
|
+
gateway_ip = container.primary_interface.network.ip
|
63
|
+
apt_conf_d_proxy_file = File.join(container.lxc.fs_root, "etc", "apt", "apt.conf.d", "00proxy")
|
50
64
|
|
51
|
-
|
52
|
-
mkdir -pv #{File.dirname(apt_conf_d_proxy_file)}
|
53
|
-
echo 'Acquire::HTTP { Proxy "http://#{gateway_ip}:3142"; };' | tee #{apt_conf_d_proxy_file}
|
54
|
-
EOF
|
65
|
+
@config[:apt][:cacher_ng] = { :proxy_url => "http://#{gateway_ip}:3142" }.merge(@config[:apt][:cacher_ng])
|
55
66
|
|
56
|
-
container.
|
57
|
-
|
67
|
+
container.node.ssh.file(:target => apt_conf_d_proxy_file, :chown => "root:root", :chmod => "0644") do |file|
|
68
|
+
file.puts(ZTK::Template.render(@apt_conf_d_proxy_file_template, @config))
|
58
69
|
end
|
59
70
|
|
60
71
|
# Fix the APT sources since LXC mudges them when using apt-cacher-ng
|
61
72
|
apt_conf_sources_file = File.join(container.lxc.fs_root, "etc", "apt", "sources.list")
|
62
|
-
|
63
|
-
|
64
|
-
container.node.ssh.bootstrap(script)
|
65
|
-
end
|
66
|
-
|
67
|
-
# AptCacherNG Provisioner Container Teardown
|
68
|
-
#
|
69
|
-
# This is a NO-OP currently.
|
70
|
-
#
|
71
|
-
# @return [Boolean] True if successful.
|
72
|
-
def teardown(container)
|
73
|
-
# NOOP
|
74
|
-
|
75
|
-
true
|
73
|
+
container.node.ssh.exec(%(sudo sed -i 's/127.0.0.1:3142\\///g' #{apt_conf_sources_file}))
|
76
74
|
end
|
77
75
|
|
78
76
|
end
|
@@ -1,12 +1,39 @@
|
|
1
1
|
class TestLab
|
2
|
-
class Node
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
class Provisioner
|
4
|
+
|
5
|
+
# Bind Provisioner Error Class
|
6
|
+
class BindError < ProvisionerError; end
|
7
|
+
|
8
|
+
# Bind Provisioner Class
|
9
|
+
#
|
10
|
+
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
11
|
+
class Bind
|
12
|
+
|
13
|
+
def initialize(config={}, ui=nil)
|
14
|
+
@config = (config || Hash.new)
|
15
|
+
@ui = (ui || TestLab.ui)
|
16
|
+
|
17
|
+
@config[:bind] ||= Hash.new
|
18
|
+
|
19
|
+
@ui.logger.debug { "config(#{@config.inspect})" }
|
20
|
+
end
|
21
|
+
|
22
|
+
# Bind Provisioner Node Setup
|
23
|
+
#
|
24
|
+
# @param [TestLab::Node] node The node which we want to provision.
|
25
|
+
# @return [Boolean] True if successful.
|
26
|
+
def node(node)
|
27
|
+
@ui.logger.debug { "BIND Provisioner: Node #{node.id}" }
|
28
|
+
|
29
|
+
bind_setup(node.ssh)
|
30
|
+
|
31
|
+
true
|
32
|
+
end
|
6
33
|
|
7
34
|
# Builds the main bind configuration sections
|
8
35
|
def build_bind_main_partial(file)
|
9
|
-
bind_conf_template = File.join(
|
36
|
+
bind_conf_template = File.join(TestLab::Provisioner.template_dir, "bind", "bind.erb")
|
10
37
|
|
11
38
|
file.puts(ZTK::Template.do_not_edit_notice(:message => "TestLab v#{TestLab::VERSION} BIND Configuration", :char => '//'))
|
12
39
|
file.puts(ZTK::Template.render(bind_conf_template, {}))
|
@@ -32,8 +59,8 @@ class TestLab
|
|
32
59
|
end
|
33
60
|
|
34
61
|
# Builds the bind configuration sections for our zones
|
35
|
-
def build_bind_zone_partial(file)
|
36
|
-
bind_zone_template = File.join(
|
62
|
+
def build_bind_zone_partial(ssh, file)
|
63
|
+
bind_zone_template = File.join(TestLab::Provisioner.template_dir, "bind", 'bind-zone.erb')
|
37
64
|
|
38
65
|
bind_records = build_bind_records
|
39
66
|
forward_records = bind_records[:forward]
|
@@ -47,7 +74,7 @@ class TestLab
|
|
47
74
|
file.puts
|
48
75
|
file.puts(ZTK::Template.render(bind_zone_template, context))
|
49
76
|
|
50
|
-
build_bind_db(network.arpa, reverse_records[network.id])
|
77
|
+
build_bind_db(ssh, network.arpa, reverse_records[network.id])
|
51
78
|
end
|
52
79
|
|
53
80
|
TestLab::Container.domains.each do |domain|
|
@@ -58,41 +85,41 @@ class TestLab
|
|
58
85
|
file.puts
|
59
86
|
file.puts(ZTK::Template.render(bind_zone_template, context))
|
60
87
|
|
61
|
-
build_bind_db(domain, forward_records[domain])
|
88
|
+
build_bind_db(ssh, domain, forward_records[domain])
|
62
89
|
end
|
63
90
|
end
|
64
91
|
|
65
|
-
def build_bind_db(zone, records)
|
66
|
-
bind_db_template = File.join(
|
92
|
+
def build_bind_db(ssh, zone, records)
|
93
|
+
bind_db_template = File.join(TestLab::Provisioner.template_dir, "bind", 'bind-db.erb')
|
67
94
|
|
68
|
-
|
95
|
+
ssh.file(:target => "/etc/bind/db.#{zone}", :chown => "bind:bind") do |file|
|
69
96
|
file.puts(ZTK::Template.do_not_edit_notice(:message => "TestLab v#{TestLab::VERSION} BIND DB: #{zone}", :char => ';'))
|
70
97
|
file.puts(ZTK::Template.render(bind_db_template, { :zone => zone, :records => records }))
|
71
98
|
end
|
72
99
|
end
|
73
100
|
|
74
101
|
# Builds the BIND configuration
|
75
|
-
def build_bind_conf
|
76
|
-
|
102
|
+
def build_bind_conf(ssh)
|
103
|
+
ssh.file(:target => File.join("/etc/bind/named.conf"), :chown => "bind:bind") do |file|
|
77
104
|
build_bind_main_partial(file)
|
78
|
-
build_bind_zone_partial(file)
|
105
|
+
build_bind_zone_partial(ssh, file)
|
79
106
|
end
|
80
107
|
end
|
81
108
|
|
82
|
-
def bind_install
|
83
|
-
|
84
|
-
|
109
|
+
def bind_install(ssh)
|
110
|
+
ssh.exec(%(sudo apt-get -y install bind9))
|
111
|
+
ssh.exec(%(sudo rm -fv /etc/bind/{*.arpa,*.zone,*.conf*}))
|
85
112
|
end
|
86
113
|
|
87
|
-
def bind_reload
|
88
|
-
|
89
|
-
|
114
|
+
def bind_reload(ssh)
|
115
|
+
ssh.exec(%(sudo chown -Rv bind:bind /etc/bind))
|
116
|
+
ssh.exec(%(sudo rndc reload))
|
90
117
|
end
|
91
118
|
|
92
|
-
def bind_setup
|
93
|
-
bind_install
|
94
|
-
build_bind_conf
|
95
|
-
bind_reload
|
119
|
+
def bind_setup(ssh)
|
120
|
+
bind_install(ssh)
|
121
|
+
build_bind_conf(ssh)
|
122
|
+
bind_reload(ssh)
|
96
123
|
end
|
97
124
|
|
98
125
|
end
|