cucumber-chef 2.1.0.rc.11 → 2.1.0.rc.12
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/cucumber-chef +10 -24
- data/chef_repo/cookbooks/cucumber-chef/recipes/lxc.rb +1 -65
- data/chef_repo/cookbooks/cucumber-chef/recipes/test_lab.rb +1 -41
- data/cucumber-chef.gemspec +1 -2
- data/lib/cucumber/chef/client.rb +50 -60
- data/lib/cucumber/chef/containers.rb +519 -0
- data/lib/cucumber/chef/providers/aws.rb +0 -2
- data/lib/cucumber/chef/providers/vagrant.rb +1 -1
- data/lib/cucumber/chef/steps/provision_steps.rb +11 -13
- data/lib/cucumber/chef/test_lab.rb +15 -40
- data/lib/cucumber/chef/version.rb +1 -1
- data/lib/cucumber/chef.rb +1 -4
- metadata +4 -17
- data/bin/cc-push +0 -49
- data/bin/cc-server +0 -84
- data/chef_repo/cookbooks/cucumber-chef/templates/default/gemrc.erb +0 -10
- data/lib/cucumber/chef/helpers/chef_client.rb +0 -167
- data/lib/cucumber/chef/helpers/chef_server.rb +0 -42
- data/lib/cucumber/chef/helpers/command.rb +0 -60
- data/lib/cucumber/chef/helpers/container.rb +0 -187
- data/lib/cucumber/chef/helpers/minitest.rb +0 -35
- data/lib/cucumber/chef/helpers/server.rb +0 -115
- data/lib/cucumber/chef/helpers/test_lab.rb +0 -52
- data/lib/cucumber/chef/helpers/utility.rb +0 -71
- data/lib/cucumber/chef/helpers.rb +0 -50
@@ -0,0 +1,519 @@
|
|
1
|
+
################################################################################
|
2
|
+
#
|
3
|
+
# Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
|
4
|
+
# Author: Zachary Patten <zachary@jovelabs.com>
|
5
|
+
# Copyright: Copyright (c) 2011-2013 Atalanta Systems Ltd
|
6
|
+
# License: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
################################################################################
|
21
|
+
|
22
|
+
module Cucumber
|
23
|
+
module Chef
|
24
|
+
|
25
|
+
class ContainersError < Error; end
|
26
|
+
|
27
|
+
class Containers
|
28
|
+
################################################################################
|
29
|
+
|
30
|
+
def initialize(ui=ZTK::UI.new, test_lab=nil)
|
31
|
+
@ui, @test_lab = ui, test_lab
|
32
|
+
end
|
33
|
+
|
34
|
+
################################################################################
|
35
|
+
|
36
|
+
def count
|
37
|
+
@containers.count
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_a
|
41
|
+
@containers
|
42
|
+
end
|
43
|
+
|
44
|
+
################################################################################
|
45
|
+
|
46
|
+
def load
|
47
|
+
@ui.logger.debug { "Reading '#{Cucumber::Chef.containers_bin}'." }
|
48
|
+
@containers = ((Marshal.load(IO.read(Cucumber::Chef.containers_bin)) rescue Hash.new) || Hash.new)
|
49
|
+
|
50
|
+
@ui.logger.info { "-" * 8 }
|
51
|
+
@containers.each do |key, value|
|
52
|
+
@ui.logger.info { "LOAD CONTAINER: #{key.inspect} => #{value.inspect}" }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
################################################################################
|
57
|
+
|
58
|
+
def save
|
59
|
+
@ui.logger.debug { "Writing '#{Cucumber::Chef.containers_bin}'." }
|
60
|
+
@ui.logger.info { "-" * 8 }
|
61
|
+
@containers.each do |key, value|
|
62
|
+
@ui.logger.info { "SAVE CONTAINER: #{key.inspect} => #{value.inspect}" }
|
63
|
+
end
|
64
|
+
|
65
|
+
File.open(Cucumber::Chef.containers_bin, 'w') do |f|
|
66
|
+
f.puts(Marshal.dump(@containers))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
################################################################################
|
71
|
+
|
72
|
+
def init(name)
|
73
|
+
@containers[name] ||= Hash.new
|
74
|
+
@containers[name][:chef_client] = nil
|
75
|
+
end
|
76
|
+
|
77
|
+
################################################################################
|
78
|
+
|
79
|
+
def create(name)
|
80
|
+
init(name)
|
81
|
+
|
82
|
+
# if this is a new or non-persistent container destroy it
|
83
|
+
destroy(name) if !@containers[name][:persist]
|
84
|
+
|
85
|
+
attributes = @containers[name]
|
86
|
+
@containers[name] = {
|
87
|
+
:ip => generate_ip,
|
88
|
+
:mac => generate_mac,
|
89
|
+
:persist => true,
|
90
|
+
:distro => "ubuntu",
|
91
|
+
:release => "lucid",
|
92
|
+
:arch => detect_arch(attributes[:distro] || "ubuntu")
|
93
|
+
}.merge(attributes)
|
94
|
+
|
95
|
+
if running?(name)
|
96
|
+
@ui.logger.info { "Container '#{name}' is already running." }
|
97
|
+
else
|
98
|
+
@ui.logger.info { "Please wait, creating container {#{name.inspect} => #{tag(name)}}." }
|
99
|
+
bm = ::Benchmark.realtime do
|
100
|
+
test_lab_config_dhcpd
|
101
|
+
config_network(name)
|
102
|
+
_create(name, @containers[name][:distro], @containers[name][:release], @containers[name][:arch])
|
103
|
+
end
|
104
|
+
@ui.logger.info { "Container '#{name}' creation took %0.4f seconds." % bm }
|
105
|
+
|
106
|
+
# bm = ::Benchmark.realtime do
|
107
|
+
# ZTK::TCPSocketCheck.new(:host => @containers[name][:ip], :port => 22).wait
|
108
|
+
# end
|
109
|
+
# @ui.logger.info { "Container '#{name}' SSHD responded after %0.4f seconds." % bm }
|
110
|
+
end
|
111
|
+
|
112
|
+
save
|
113
|
+
end
|
114
|
+
|
115
|
+
################################################################################
|
116
|
+
|
117
|
+
def destroy(name)
|
118
|
+
if exists?(name)
|
119
|
+
@test_lab.knife_cli("node delete #{name} --yes", :ignore_exit_status => true)
|
120
|
+
@test_lab.knife_cli("client delete #{name} --yes", :ignore_exit_status => true)
|
121
|
+
stop(name)
|
122
|
+
@test_lab.bootstrap_ssh.exec("sudo lxc-destroy -n #{name}", :silence => true)
|
123
|
+
@ui.logger.info { "Destroyed container '#{name}'." }
|
124
|
+
test_lab_config_dhcpd
|
125
|
+
@containers.delete(name)
|
126
|
+
save
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
################################################################################
|
131
|
+
|
132
|
+
def set_attributes(name, attributes={})
|
133
|
+
@containers[name].merge!(attributes)
|
134
|
+
end
|
135
|
+
|
136
|
+
################################################################################
|
137
|
+
|
138
|
+
def chef_set_client_config(config={})
|
139
|
+
@chef_client_config = (@chef_client_config || {
|
140
|
+
:log_level => :info,
|
141
|
+
:log_location => "/var/log/chef/client.log",
|
142
|
+
:chef_server_url => "https://api.opscode.com/organizations/#{config[:orgname]}",
|
143
|
+
:validation_client_name => "#{config[:orgname]}-validator",
|
144
|
+
:ssl_verify_mode => :verify_none,
|
145
|
+
:environment => nil # use default; i.e. set no value
|
146
|
+
}).merge(config)
|
147
|
+
|
148
|
+
@ui.logger.info { "Setting chef client config '#{@chef_client_config.inspect}'." }
|
149
|
+
|
150
|
+
true
|
151
|
+
end
|
152
|
+
|
153
|
+
################################################################################
|
154
|
+
|
155
|
+
def chef_set_client_attributes(name, attributes={})
|
156
|
+
@containers[name] ||= Hash.new
|
157
|
+
@containers[name][:chef_client] = (@containers[name][:chef_client] || {}).merge(attributes) { |k,o,n| (k = (o + n).uniq) }
|
158
|
+
|
159
|
+
@ui.logger.info { "Setting chef client attributes to '#{@containers[name][:chef_client].inspect}' for container '#{name}'." }
|
160
|
+
|
161
|
+
true
|
162
|
+
end
|
163
|
+
|
164
|
+
################################################################################
|
165
|
+
|
166
|
+
def chef_run_client(name, *args)
|
167
|
+
chef_config_client(name)
|
168
|
+
|
169
|
+
@ui.logger.info { "Removing artifacts #{Cucumber::Chef::Config[:artifacts].values.collect{|z| "'#{z}'" }.join(' ')}." }
|
170
|
+
(@test_lab.proxy_ssh(name).exec("/bin/rm -fv #{Cucumber::Chef::Config[:artifacts].values.join(' ')}", :silence => true) rescue nil)
|
171
|
+
|
172
|
+
@ui.logger.info { "Running chef client on container '#{name}'." }
|
173
|
+
|
174
|
+
arguments = {
|
175
|
+
"--node-name" => name,
|
176
|
+
"--json-attributes" => File.join("/etc", "chef", "attributes.json").to_s,
|
177
|
+
"--log_level" => @chef_client_config[:log_level],
|
178
|
+
"--logfile" => @chef_client_config[:log_location],
|
179
|
+
"--server" => @chef_client_config[:chef_server_url],
|
180
|
+
"--environment" => @chef_client_config[:environment]
|
181
|
+
}.reject{ |k,v| v.nil? }.sort
|
182
|
+
|
183
|
+
output = nil
|
184
|
+
bm = ::Benchmark.realtime do
|
185
|
+
output = @test_lab.proxy_ssh(name).exec(["/usr/bin/chef-client", arguments, args, "--once"].flatten.join(" "), :silence => true)
|
186
|
+
end
|
187
|
+
@ui.logger.info { "Chef client run on container '#{name}' took %0.4f seconds." % bm }
|
188
|
+
|
189
|
+
chef_client_artifacts(name)
|
190
|
+
|
191
|
+
output
|
192
|
+
end
|
193
|
+
|
194
|
+
################################################################################
|
195
|
+
|
196
|
+
def enable_minitest(name)
|
197
|
+
@chef_client_attributes[:run_list].unshift("recipe[minitest-handler]")
|
198
|
+
end
|
199
|
+
|
200
|
+
def run_minitests(name)
|
201
|
+
chef_run = chef_run_client(name, "-l info")
|
202
|
+
test_result = chef_run.drop_while {|e| e !~ /^# Running tests/}.take_while {|e| e !~ /^[.*] INFO/}
|
203
|
+
puts test_result
|
204
|
+
test_result
|
205
|
+
end
|
206
|
+
|
207
|
+
################################################################################
|
208
|
+
private
|
209
|
+
################################################################################
|
210
|
+
|
211
|
+
def _create(name, distro, release, arch)
|
212
|
+
unless exists?(name)
|
213
|
+
cache_rootfs = cache_root(name, distro, release, arch)
|
214
|
+
if !File.exists?(cache_rootfs)
|
215
|
+
@ui.logger.warn { "'#{name}' has triggered building the lxc file cache for '#{distro}'." }
|
216
|
+
@ui.logger.warn { "This one time process per distro can take up to 10 minutes or longer depending on the test lab." }
|
217
|
+
end
|
218
|
+
|
219
|
+
@test_lab.bootstrap_ssh.exec(create_command(name, distro, release, arch), :silence => true)
|
220
|
+
|
221
|
+
commands = Array.new
|
222
|
+
|
223
|
+
# install omnibus into the distro/release file cache if it's not already there
|
224
|
+
omnibus_chef_client = File.join("/", "opt", "chef", "bin", "chef-client")
|
225
|
+
omnibus_cache = File.join(cache_rootfs, omnibus_chef_client)
|
226
|
+
@ui.logger.info { "looking for omnibus cache in #{omnibus_cache}" }
|
227
|
+
if @test_lab.bootstrap_ssh.exec(%Q{sudo /bin/bash -c '[[ -f #{omnibus_cache} ]] ; echo $? ; true'}, :silence => true).output.chomp =~ /1/
|
228
|
+
case distro.downcase
|
229
|
+
when "ubuntu" then
|
230
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo chroot #{cache_rootfs} /bin/bash -c 'DEBIAN_FRONTEND=noninteractive apt-get -y --force-yes install wget'}, :silence => true)
|
231
|
+
when "fedora" then
|
232
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo yum --nogpgcheck --installroot=#{cache_rootfs} -y install wget openssh-server}, :silence => true)
|
233
|
+
end
|
234
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo chroot #{cache_rootfs} /bin/bash -c 'locale-gen'}, :silence => true)
|
235
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo chroot #{cache_rootfs} /bin/bash -c 'locale-gen en_US'}, :silence => true)
|
236
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo chroot #{cache_rootfs} /bin/bash -c 'wget http://www.opscode.com/chef/install.sh'}, :silence => true)
|
237
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo chroot #{cache_rootfs} /bin/bash -c 'bash install.sh -v #{Cucumber::Chef::Config.chef[:version]}'}, :silence => true)
|
238
|
+
if distro.downcase == "fedora"
|
239
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo chroot #{cache_rootfs} /bin/bash -c 'rpm -Uvh --nodeps /tmp/*rpm'}, :silence => true)
|
240
|
+
end
|
241
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo lxc-destroy -n #{name}}, :silence => true)
|
242
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo #{create_command(name, distro, release, arch)}}, :silence => true)
|
243
|
+
end
|
244
|
+
|
245
|
+
lab_ssh_path = File.join(Cucumber::Chef.lab_user_home_dir, ".ssh")
|
246
|
+
ssh_path = File.join(root(name), Cucumber::Chef.lxc_user_home_dir, ".ssh")
|
247
|
+
motd_path = File.join(root(name), "etc", "motd")
|
248
|
+
|
249
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo mkdir -vp #{ssh_path}}, :silence => true)
|
250
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo chmod 0700 #{ssh_path}}, :silence => true)
|
251
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo cat #{File.join(lab_ssh_path, "id_rsa.pub")} | sudo tee -a #{File.join(ssh_path, "authorized_keys")}}, :silence => true)
|
252
|
+
|
253
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo rm -vf #{motd_path}}, :silence => true)
|
254
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo cp -v /etc/motd #{motd_path}}, :silence => true)
|
255
|
+
@test_lab.bootstrap_ssh.exec(%Q{echo " You are now logged in to the "#{name}" container!\n" | sudo tee -a #{motd_path}}, :silence => true)
|
256
|
+
@test_lab.bootstrap_ssh.exec(%Q{echo "127.0.0.1 #{name}.#{Cucumber::Chef::Config.test_lab[:tld]} #{name}" | sudo tee -a #{File.join(root(name), "etc", "hosts")}}, :silence => true)
|
257
|
+
@test_lab.bootstrap_ssh.exec(%Q{echo "#{name}.test-lab" | sudo tee #{File.join(root(name), "etc", "hostname")}}, :silence => true)
|
258
|
+
end
|
259
|
+
start(name)
|
260
|
+
end
|
261
|
+
|
262
|
+
################################################################################
|
263
|
+
|
264
|
+
def start(name)
|
265
|
+
status = @test_lab.bootstrap_ssh.exec("sudo lxc-info -n #{name}", :silence => true).output
|
266
|
+
if status.include?("STOPPED")
|
267
|
+
@test_lab.bootstrap_ssh.exec("sudo lxc-start -d -n #{name}", :silence => true)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def stop(name)
|
272
|
+
status = @test_lab.bootstrap_ssh.exec("sudo lxc-info -n #{name}", :silence => true).output
|
273
|
+
if status.include?("RUNNING")
|
274
|
+
@test_lab.bootstrap_ssh.exec("sudo lxc-stop -n #{name}", :silence => true)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
################################################################################
|
279
|
+
|
280
|
+
def chef_config_client(name)
|
281
|
+
tempfile = Tempfile.new(name)
|
282
|
+
client_rb = File.join("/", root(name), "etc/chef/client.rb")
|
283
|
+
|
284
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo mkdir -pv #{File.dirname(client_rb)}}, :silence => true)
|
285
|
+
|
286
|
+
if Cucumber::Chef::Config.chef[:render_client_rb]
|
287
|
+
max_key_size = @chef_client_config.keys.collect{ |z| z.to_s.size }.max
|
288
|
+
|
289
|
+
File.open(tempfile, 'w') do |f|
|
290
|
+
f.puts(Cucumber::Chef.generate_do_not_edit_warning("Chef Client Configuration"))
|
291
|
+
f.puts
|
292
|
+
@chef_client_config.merge(:node_name => name).each do |(key,value)|
|
293
|
+
next if value.nil?
|
294
|
+
f.puts("%-#{max_key_size}s %s" % [key, value.inspect])
|
295
|
+
end
|
296
|
+
f.puts
|
297
|
+
f.puts("Mixlib::Log::Formatter.show_time = true")
|
298
|
+
end
|
299
|
+
@test_lab.bootstrap_ssh.upload(tempfile.path, File.basename(tempfile.path))
|
300
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo mv -v #{File.basename(tempfile.path)} #{client_rb}}, :silence => true)
|
301
|
+
else
|
302
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo /bin/bash -c '[[ -f #{client_rb} ]] && rm -fv #{client_rb}'}, :silence => true, :ignore_exit_status => true)
|
303
|
+
end
|
304
|
+
|
305
|
+
tempfile = Tempfile.new(name)
|
306
|
+
attributes_json = File.join("/", root(name), "etc", "chef", "attributes.json")
|
307
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo mkdir -pv #{File.dirname(attributes_json)}}, :silence => true)
|
308
|
+
File.open(tempfile, 'w') do |f|
|
309
|
+
f.puts((@containers[name][:chef_client] || {}).to_json)
|
310
|
+
end
|
311
|
+
@test_lab.bootstrap_ssh.upload(tempfile.path, File.basename(tempfile.path))
|
312
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo mv -v #{File.basename(tempfile.path)} #{attributes_json}}, :silence => true)
|
313
|
+
|
314
|
+
# make sure our log location is there
|
315
|
+
log_location = File.join("/", root(name), @chef_client_config[:log_location])
|
316
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo mkdir -pv #{File.dirname(log_location)}}, :silence => true)
|
317
|
+
|
318
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo cp /etc/chef/validation.pem #{root(name)}/etc/chef/}, :silence => true)
|
319
|
+
|
320
|
+
true
|
321
|
+
end
|
322
|
+
|
323
|
+
################################################################################
|
324
|
+
|
325
|
+
def chef_client_artifacts(name)
|
326
|
+
# this is messy and needs to be refactored into a more configurable
|
327
|
+
# solution; but for now this should do the trick
|
328
|
+
|
329
|
+
ssh = @test_lab.proxy_ssh(name)
|
330
|
+
|
331
|
+
feature_file = $scenario.file_colon_line.split(":").first
|
332
|
+
feature_line = $scenario.file_colon_line.split(":").last
|
333
|
+
scenario_tag = $scenario.name.gsub(" ", "_")
|
334
|
+
|
335
|
+
feature_name = File.basename(feature_file, ".feature")
|
336
|
+
feature_dir = feature_file.split("/")[-2]
|
337
|
+
|
338
|
+
Cucumber::Chef::Config[:artifacts].each do |label, remote_path|
|
339
|
+
result = ssh.exec("sudo /bin/bash -c '[[ -f #{remote_path} ]] ; echo $? ; true'", :silence => true)
|
340
|
+
if (result.output =~ /0/)
|
341
|
+
@ui.logger.info { "Retrieving artifact '#{remote_path}' from container '#{name}'." }
|
342
|
+
|
343
|
+
local_path = File.join(Cucumber::Chef.artifacts_dir, feature_dir, "#{feature_name}.txt")
|
344
|
+
tmp_path = File.join("/tmp", label)
|
345
|
+
|
346
|
+
FileUtils.mkdir_p(File.dirname(local_path))
|
347
|
+
ssh.download(remote_path, tmp_path)
|
348
|
+
data = IO.read(tmp_path).chomp
|
349
|
+
|
350
|
+
message = "#{$scenario.name} (#{File.basename(feature_file)}:#{feature_line}:#{label})"
|
351
|
+
header = ("-" * message.length)
|
352
|
+
|
353
|
+
f = File.open(local_path, "a")
|
354
|
+
f.write("#{header}\n")
|
355
|
+
f.write("#{message}\n")
|
356
|
+
f.write("#{header}\n")
|
357
|
+
f.write("#{data}\n")
|
358
|
+
|
359
|
+
File.chmod(0644, local_path)
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
true
|
364
|
+
end
|
365
|
+
|
366
|
+
################################################################################
|
367
|
+
|
368
|
+
def config_network(name)
|
369
|
+
tempfile = Tempfile.new(name)
|
370
|
+
lxc_network_config = File.join("/etc/lxc", name)
|
371
|
+
File.open(tempfile, 'w') do |f|
|
372
|
+
f.puts(Cucumber::Chef.generate_do_not_edit_warning("LXC Container Configuration"))
|
373
|
+
f.puts("")
|
374
|
+
f.puts("lxc.network.type = veth")
|
375
|
+
f.puts("lxc.network.flags = up")
|
376
|
+
f.puts("lxc.network.link = br0")
|
377
|
+
f.puts("lxc.network.name = eth0")
|
378
|
+
f.puts("lxc.network.hwaddr = #{@containers[name][:mac]}")
|
379
|
+
f.puts("lxc.network.ipv4 = 0.0.0.0")
|
380
|
+
end
|
381
|
+
@test_lab.bootstrap_ssh.upload(tempfile.path, File.basename(tempfile.path))
|
382
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo mv -v #{File.basename(tempfile.path)} #{lxc_network_config}}, :silence => true)
|
383
|
+
end
|
384
|
+
|
385
|
+
################################################################################
|
386
|
+
|
387
|
+
def test_lab_config_dhcpd
|
388
|
+
tempfile = Tempfile.new("dhcpd")
|
389
|
+
dhcpd_config = File.join("/etc/dhcp/test-lab.conf")
|
390
|
+
File.open(tempfile, 'w') do |f|
|
391
|
+
f.puts(Cucumber::Chef.generate_do_not_edit_warning("DHCPD Configuration"))
|
392
|
+
@containers.each do |key, value|
|
393
|
+
next if [:mac, :ip].any?{ |z| value[z].nil? }
|
394
|
+
|
395
|
+
f.puts
|
396
|
+
f.puts("host #{key} {")
|
397
|
+
f.puts(" hardware ethernet #{value[:mac]};")
|
398
|
+
f.puts(" fixed-address #{value[:ip]};")
|
399
|
+
f.puts(" ddns-hostname \"#{key}\";")
|
400
|
+
f.puts("}")
|
401
|
+
end
|
402
|
+
f.flush
|
403
|
+
f.close
|
404
|
+
end
|
405
|
+
@test_lab.bootstrap_ssh.upload(tempfile.path, File.basename(tempfile.path))
|
406
|
+
@test_lab.bootstrap_ssh.exec(%Q{sudo mv -v #{File.basename(tempfile.path)} #{dhcpd_config}}, :silence => true)
|
407
|
+
|
408
|
+
@test_lab.bootstrap_ssh.exec("sudo service isc-dhcp-server restart", :silence => true)
|
409
|
+
@test_lab.bootstrap_ssh.exec("sudo service bind9 restart", :silence => true)
|
410
|
+
end
|
411
|
+
|
412
|
+
################################################################################
|
413
|
+
|
414
|
+
def tag(name)
|
415
|
+
@containers[name].inspect.to_s
|
416
|
+
end
|
417
|
+
|
418
|
+
def detect_arch(distro)
|
419
|
+
@arch ||= @test_lab.bootstrap_ssh.exec("uname -m", :silence => true).output.chomp
|
420
|
+
case distro.downcase
|
421
|
+
when "ubuntu" then
|
422
|
+
((@arch =~ /x86_64/) ? "amd64" : "i386")
|
423
|
+
when "fedora" then
|
424
|
+
((@arch =~ /x86_64/) ? "amd64" : "i686")
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
################################################################################
|
429
|
+
|
430
|
+
def containers
|
431
|
+
@test_lab.bootstrap_ssh.exec("sudo lxc-ls 2>&1", :silence => true).output.split("\n").uniq
|
432
|
+
end
|
433
|
+
|
434
|
+
################################################################################
|
435
|
+
|
436
|
+
def running?(name)
|
437
|
+
status = @test_lab.bootstrap_ssh.exec("sudo lxc-info -n #{name}", :silence => true).output.chomp
|
438
|
+
status.include?("RUNNING")
|
439
|
+
end
|
440
|
+
|
441
|
+
################################################################################
|
442
|
+
|
443
|
+
def exists?(name)
|
444
|
+
(@test_lab.bootstrap_ssh.exec("sudo /bin/bash -c '[[ -d #{root(name)} ]] ; echo $? ; true'", :silence => true).output.chomp =~ /0/)
|
445
|
+
end
|
446
|
+
|
447
|
+
################################################################################
|
448
|
+
|
449
|
+
def root(name)
|
450
|
+
File.join("/", "var", "lib", "lxc", name, "rootfs")
|
451
|
+
end
|
452
|
+
|
453
|
+
################################################################################
|
454
|
+
|
455
|
+
def cache_root(name, distro, release, arch)
|
456
|
+
case distro.downcase
|
457
|
+
when "ubuntu" then
|
458
|
+
cache_root = File.join("/", "var", "cache", "lxc", release, "rootfs-#{arch}")
|
459
|
+
when "fedora" then
|
460
|
+
cache_root = File.join("/", "var", "cache", "lxc", distro, arch, release, "rootfs")
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
################################################################################
|
465
|
+
|
466
|
+
def create_command(name, distro, release, arch)
|
467
|
+
case distro.downcase
|
468
|
+
when "ubuntu" then
|
469
|
+
"sudo DEBIAN_FRONTEND=noninteractive lxc-create -n #{name} -f /etc/lxc/#{name} -t #{distro} -- --release #{release} --arch #{arch}"
|
470
|
+
when "fedora" then
|
471
|
+
"sudo lxc-create -n #{name} -f /etc/lxc/#{name} -t #{distro} -- --release #{release}"
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
################################################################################
|
476
|
+
|
477
|
+
def generate_ip
|
478
|
+
octets = [ 192..192,
|
479
|
+
168..168,
|
480
|
+
0..254,
|
481
|
+
1..254 ]
|
482
|
+
ip = Array.new
|
483
|
+
for x in 1..4 do
|
484
|
+
ip << octets[x-1].to_a[rand(octets[x-1].count)].to_s
|
485
|
+
end
|
486
|
+
ip.join(".")
|
487
|
+
end
|
488
|
+
|
489
|
+
################################################################################
|
490
|
+
|
491
|
+
def generate_mac
|
492
|
+
digits = [ %w(0),
|
493
|
+
%w(0),
|
494
|
+
%w(0),
|
495
|
+
%w(0),
|
496
|
+
%w(5),
|
497
|
+
%w(e),
|
498
|
+
%w(0 1 2 3 4 5 6 7 8 9 a b c d e f),
|
499
|
+
%w(0 1 2 3 4 5 6 7 8 9 a b c d e f),
|
500
|
+
%w(5 6 7 8 9 a b c d e f),
|
501
|
+
%w(3 4 5 6 7 8 9 a b c d e f),
|
502
|
+
%w(0 1 2 3 4 5 6 7 8 9 a b c d e f),
|
503
|
+
%w(0 1 2 3 4 5 6 7 8 9 a b c d e f) ]
|
504
|
+
mac = ""
|
505
|
+
for x in 1..12 do
|
506
|
+
mac += digits[x-1][rand(digits[x-1].count)]
|
507
|
+
mac += ":" if (x.modulo(2) == 0) && (x != 12)
|
508
|
+
end
|
509
|
+
mac
|
510
|
+
end
|
511
|
+
|
512
|
+
################################################################################
|
513
|
+
|
514
|
+
end
|
515
|
+
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
################################################################################
|
@@ -240,12 +240,10 @@ module Cucumber
|
|
240
240
|
security_group.authorize_port_range(22..22) if port_ranges.none?{ |port_range| port_range === 22 }
|
241
241
|
security_group.authorize_port_range(4000..4000) if port_ranges.none?{ |port_range| port_range === 4000 }
|
242
242
|
security_group.authorize_port_range(4040..4040) if port_ranges.none?{ |port_range| port_range === 4040 }
|
243
|
-
security_group.authorize_port_range(8787..8787) if port_ranges.none?{ |port_range| port_range === 8787 }
|
244
243
|
elsif (security_group = @connection.security_groups.new(:name => security_group_name, :description => "cucumber-chef test lab")).save
|
245
244
|
security_group.authorize_port_range(22..22)
|
246
245
|
security_group.authorize_port_range(4000..4000)
|
247
246
|
security_group.authorize_port_range(4040..4040)
|
248
|
-
security_group.authorize_port_range(8787..8787)
|
249
247
|
else
|
250
248
|
raise AWSError, "Could not find an existing or create a new AWS security group."
|
251
249
|
end
|
@@ -20,47 +20,45 @@
|
|
20
20
|
################################################################################
|
21
21
|
|
22
22
|
Given /^I have a server called "([^\"]*)"$/ do |name|
|
23
|
-
$test_lab.
|
23
|
+
$test_lab.containers.init(name)
|
24
24
|
end
|
25
25
|
|
26
26
|
And /^"([^\"]*)" is running "([^\"]*)" "([^\"]*)"$/ do |name, distro, release|
|
27
|
-
$test_lab.
|
27
|
+
$test_lab.containers.set_attributes(name, :distro => distro, :release => release)
|
28
28
|
end
|
29
29
|
|
30
30
|
And /^"([^\"]*)" has "([^\"]*)" architecture$/ do |name, arch|
|
31
|
-
$test_lab.
|
31
|
+
$test_lab.containers.set_attributes(name, :arch => arch)
|
32
32
|
end
|
33
33
|
|
34
34
|
And /^"([^\"]*)" should( not)? be persist[ae]nt$/ do |name, boolean|
|
35
|
-
$test_lab.
|
35
|
+
$test_lab.containers.set_attributes(name, :persist => (!boolean ? true : false))
|
36
36
|
end
|
37
37
|
|
38
38
|
And /^"([^\"]*)" has an IP address of "([^\"]*)"$/ do |name, ip|
|
39
|
-
$test_lab.
|
39
|
+
$test_lab.containers.set_attributes(name, :ip => ip)
|
40
40
|
end
|
41
41
|
|
42
42
|
And /^"([^\"]*)" has a MAC address of "([^\"]*)"$/ do |name, mac|
|
43
|
-
$test_lab.
|
43
|
+
$test_lab.containers.set_attributes(name, :mac => mac)
|
44
44
|
end
|
45
45
|
|
46
46
|
And /^"([^\"]*)" has been provisioned$/ do |name|
|
47
|
-
$test_lab.
|
47
|
+
$test_lab.containers.create(name)
|
48
48
|
end
|
49
49
|
|
50
50
|
And /^the "([^\"]*)" role has been added to the "([^\"]*)" run list$/ do |role, name|
|
51
|
-
$test_lab.
|
51
|
+
$test_lab.containers.chef_set_client_attributes(name, :run_list => ["role[#{role}]"])
|
52
52
|
end
|
53
53
|
|
54
54
|
And /^the "([^\"]*)" recipe has been added to the "([^\"]*)" run list$/ do |recipe, name|
|
55
|
-
$test_lab.
|
55
|
+
$test_lab.containers.chef_set_client_attributes(name, :run_list => ["recipe[#{recipe}]"])
|
56
56
|
end
|
57
57
|
|
58
58
|
And /^"([^\"]*)" is in the "([^\"]*)" environment$/ do |name, environment|
|
59
|
-
$test_lab.
|
59
|
+
$test_lab.containers.chef_set_client_config(:environment => environment)
|
60
60
|
end
|
61
61
|
|
62
62
|
And /^the chef-client has been run on "([^\"]*)"$/ do |name|
|
63
|
-
$test_lab.
|
64
|
-
$test_lab.drb.chef_run_client(name)
|
65
|
-
chef_client_artifacts(name)
|
63
|
+
$test_lab.containers.chef_run_client(name)
|
66
64
|
end
|