beaker 1.8.1 → 1.8.2

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.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/bin/beaker +1 -1
  3. data/lib/beaker.rb +1 -1
  4. data/lib/beaker/cli.rb +15 -35
  5. data/lib/beaker/host_prebuilt_steps.rb +335 -0
  6. data/lib/beaker/hypervisor.rb +53 -4
  7. data/lib/beaker/hypervisor/aixer.rb +2 -2
  8. data/lib/beaker/hypervisor/blimper.rb +5 -5
  9. data/lib/beaker/hypervisor/fusion.rb +3 -3
  10. data/lib/beaker/hypervisor/solaris.rb +2 -2
  11. data/lib/beaker/hypervisor/vagrant.rb +6 -16
  12. data/lib/beaker/hypervisor/vcloud.rb +6 -6
  13. data/lib/beaker/hypervisor/vcloud_pooled.rb +4 -4
  14. data/lib/beaker/hypervisor/vsphere.rb +3 -3
  15. data/lib/beaker/network_manager.rb +51 -37
  16. data/lib/beaker/options/presets.rb +1 -0
  17. data/lib/beaker/shared.rb +2 -2
  18. data/lib/beaker/shared/host_role_parser.rb +36 -0
  19. data/lib/beaker/version.rb +1 -1
  20. data/spec/beaker/host_prebuilt_steps_spec.rb +421 -0
  21. data/spec/beaker/hypervisor/google_compute.rb +23 -0
  22. data/spec/beaker/hypervisor/vagrant_spec.rb +5 -4
  23. data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +2 -2
  24. data/spec/beaker/hypervisor/vcloud_spec.rb +2 -2
  25. data/spec/beaker/hypervisor/vsphere_spec.rb +2 -2
  26. data/spec/beaker/options/parser_spec.rb +1 -1
  27. data/spec/beaker/shared/host_role_parser_spec.rb +58 -0
  28. metadata +10 -18
  29. data/lib/beaker/shared/host_handler.rb +0 -51
  30. data/lib/beaker/utils.rb +0 -7
  31. data/lib/beaker/utils/ntp_control.rb +0 -57
  32. data/lib/beaker/utils/repo_control.rb +0 -90
  33. data/lib/beaker/utils/setup_helper.rb +0 -66
  34. data/lib/beaker/utils/validator.rb +0 -36
  35. data/spec/beaker/shared/host_handler_spec.rb +0 -104
  36. data/spec/beaker/utils/ntp_control_spec.rb +0 -70
  37. data/spec/beaker/utils/repo_control_spec.rb +0 -168
  38. data/spec/beaker/utils/setup_helper_spec.rb +0 -82
  39. data/spec/beaker/utils/validator_spec.rb +0 -91
@@ -47,6 +47,7 @@ module Beaker
47
47
  :timesync => false,
48
48
  :repo_proxy => false,
49
49
  :add_el_extras => false,
50
+ :add_master_entry => false,
50
51
  :consoleport => 443,
51
52
  :pe_dir => '/opt/enterprise/dists',
52
53
  :pe_version_file => 'LATEST',
data/lib/beaker/shared.rb CHANGED
@@ -1,4 +1,4 @@
1
- [ 'repetition', 'error_handler', 'host_handler', 'timed' ].each do |file|
1
+ [ 'repetition', 'error_handler', 'host_role_parser', 'timed' ].each do |file|
2
2
  begin
3
3
  require "beaker/shared/#{file}"
4
4
  rescue LoadError
@@ -8,7 +8,7 @@ end
8
8
  module Beaker
9
9
  module Shared
10
10
  include Beaker::Shared::ErrorHandler
11
- include Beaker::Shared::HostHandler
11
+ include Beaker::Shared::HostRoleParser
12
12
  include Beaker::Shared::Repetition
13
13
  include Beaker::Shared::Timed
14
14
  end
@@ -0,0 +1,36 @@
1
+ module Beaker
2
+ module Shared
3
+ #Methods for selecting host or hosts that match roles.
4
+ module HostRoleParser
5
+
6
+ #Find hosts from a given array of hosts that all have the desired role.
7
+ #@param [Array<Host>] hosts The hosts to examine
8
+ #@param [String] desired_role The hosts returned will have this role in their roles list
9
+ #@return [Array<Host>] The hosts that have the desired role in their roles list
10
+ def hosts_with_role(hosts, desired_role = nil)
11
+ hosts.select do |host|
12
+ desired_role.nil? or host['roles'].include?(desired_role.to_s)
13
+ end
14
+ end
15
+
16
+ #Find a single host with the role provided. Raise an error if more than one host is found to have the
17
+ #provided role.
18
+ #@param [Array<Host>] hosts The hosts to examine
19
+ #@param [String] role The host returned will have this role in its role list
20
+ #@return [Host] The single host with the desired role in its roles list
21
+ #@raise [ArgumentError] Raised if more than one host has the given role defined, or if no host has the
22
+ # role defined.
23
+ def only_host_with_role(hosts, role)
24
+ a_host = hosts_with_role(hosts, role)
25
+ case
26
+ when a_host.length == 0
27
+ raise ArgumentError, "There should be one host with #{role} defined!"
28
+ when a_host.length > 1
29
+ host_string = ( a_host.map { |host| host.name } ).join( ', ')
30
+ raise ArgumentError, "There should be only one host with #{role} defined, but I found #{a_host.length} (#{host_string})"
31
+ end
32
+ a_host.first
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,5 @@
1
1
  module Beaker
2
2
  module Version
3
- STRING = '1.8.1'
3
+ STRING = '1.8.2'
4
4
  end
5
5
  end
@@ -0,0 +1,421 @@
1
+ require 'spec_helper'
2
+
3
+ describe Beaker do
4
+ let( :options ) { make_opts.merge({ 'logger' => double().as_null_object }) }
5
+ let( :ntpserver ) { Beaker::HostPrebuiltSteps::NTPSERVER }
6
+ let( :apt_cfg ) { Beaker::HostPrebuiltSteps::APT_CFG }
7
+ let( :ips_pkg_repo ) { Beaker::HostPrebuiltSteps::IPS_PKG_REPO }
8
+ let( :sync_cmd ) { Beaker::HostPrebuiltSteps::ROOT_KEYS_SYNC_CMD }
9
+ let( :pkgs ) { Beaker::HostPrebuiltSteps::PACKAGES }
10
+ let( :unix_only_pkgs ) { Beaker::HostPrebuiltSteps::UNIX_PACKAGES }
11
+ let( :sles_only_pkgs ) { Beaker::HostPrebuiltSteps::SLES_PACKAGES }
12
+ let( :platform ) { @platform || 'unix' }
13
+ let( :ip ) { "ip.address.0.0" }
14
+ let( :stdout) { @stdout || ip }
15
+ let( :hosts ) { hosts = make_hosts( { :stdout => stdout, :platform => platform } )
16
+ hosts[0][:roles] = ['agent']
17
+ hosts[1][:roles] = ['master', 'dashboard', 'agent', 'database']
18
+ hosts[2][:roles] = ['agent']
19
+ hosts }
20
+ let( :dummy_class ) { Class.new { include Beaker::HostPrebuiltSteps } }
21
+
22
+ context 'timesync' do
23
+
24
+ subject { dummy_class.new }
25
+
26
+ it "can sync time on unix hosts" do
27
+ hosts = make_hosts( { :platform => 'unix' } )
28
+
29
+ Beaker::Command.should_receive( :new ).with("ntpdate -t 20 #{ntpserver}").exactly( 3 ).times
30
+
31
+ subject.timesync( hosts, options )
32
+ end
33
+
34
+ it "can retry on failure on unix hosts" do
35
+ hosts = make_hosts( { :platform => 'unix', :exit_code => [1, 0] } )
36
+ subject.stub( :sleep ).and_return(true)
37
+
38
+ Beaker::Command.should_receive( :new ).with("ntpdate -t 20 #{ntpserver}").exactly( 6 ).times
39
+
40
+ subject.timesync( hosts, options )
41
+ end
42
+
43
+ it "eventually gives up and raises an error when unix hosts can't be synched" do
44
+ hosts = make_hosts( { :platform => 'unix', :exit_code => 1 } )
45
+ subject.stub( :sleep ).and_return(true)
46
+
47
+ Beaker::Command.should_receive( :new ).with("ntpdate -t 20 #{ntpserver}").exactly( 5 ).times
48
+
49
+ expect{ subject.timesync( hosts, options ) }.to raise_error
50
+ end
51
+
52
+ it "can sync time on solaris-10 hosts" do
53
+ hosts = make_hosts( { :platform => 'solaris-10' } )
54
+
55
+ Beaker::Command.should_receive( :new ).with("sleep 10 && ntpdate -w #{ntpserver}").exactly( 3 ).times
56
+
57
+ subject.timesync( hosts, options )
58
+
59
+ end
60
+
61
+ it "can sync time on windows hosts" do
62
+ hosts = make_hosts( { :platform => 'windows' } )
63
+
64
+ Beaker::Command.should_receive( :new ).with("w32tm /register").exactly( 3 ).times
65
+ Beaker::Command.should_receive( :new ).with("net start w32time").exactly( 3 ).times
66
+ Beaker::Command.should_receive( :new ).with("w32tm /config /manualpeerlist:#{ntpserver} /syncfromflags:manual /update").exactly( 3 ).times
67
+ Beaker::Command.should_receive( :new ).with("w32tm /resync").exactly( 3 ).times
68
+
69
+ subject.timesync( hosts, options )
70
+
71
+ end
72
+
73
+ it "can sync time on Sles hosts" do
74
+ hosts = make_hosts( { :platform => 'sles-13.1-x64' } )
75
+
76
+ Beaker::Command.should_receive( :new ).with("sntp #{ntpserver}").exactly( 3 ).times
77
+
78
+ subject.timesync( hosts, options )
79
+
80
+ end
81
+ end
82
+
83
+ context "epel_info_for!" do
84
+ subject { dummy_class.new }
85
+
86
+ it "can return the correct url for an el-6 host" do
87
+ host = make_host( 'testhost', { :platform => 'el-6-platform' } )
88
+
89
+ expect( subject.epel_info_for!( host )).to be === "http://mirror.itc.virginia.edu/fedora-epel/6/i386/epel-release-6-8.noarch.rpm"
90
+ end
91
+
92
+ it "can return the correct url for an el-5 host" do
93
+ host = make_host( 'testhost', { :platform => 'el-5-platform' } )
94
+
95
+ expect( subject.epel_info_for!( host )).to be === "http://archive.linux.duke.edu/pub/epel/5/i386/epel-release-5-4.noarch.rpm"
96
+
97
+ end
98
+
99
+ it "raises an error on non el-5/6 host" do
100
+ host = make_host( 'testhost', { :platform => 'el-4-platform' } )
101
+
102
+ expect{ subject.epel_info_for!( host )}.to raise_error
103
+
104
+ end
105
+
106
+ end
107
+
108
+ context "apt_get_update" do
109
+ subject { dummy_class.new }
110
+
111
+ it "can perform apt-get on ubuntu hosts" do
112
+ host = make_host( 'testhost', { :platform => 'ubuntu' } )
113
+
114
+ Beaker::Command.should_receive( :new ).with("apt-get -y -f -m update").once
115
+
116
+ subject.apt_get_update( host )
117
+
118
+ end
119
+
120
+ it "can perform apt-get on debian hosts" do
121
+ host = make_host( 'testhost', { :platform => 'debian' } )
122
+
123
+ Beaker::Command.should_receive( :new ).with("apt-get -y -f -m update").once
124
+
125
+ subject.apt_get_update( host )
126
+
127
+ end
128
+
129
+ it "does nothing on non debian/ubuntu hosts" do
130
+ host = make_host( 'testhost', { :platform => 'windows' } )
131
+
132
+ Beaker::Command.should_receive( :new ).never
133
+
134
+ subject.apt_get_update( host )
135
+
136
+ end
137
+
138
+ end
139
+
140
+ context "copy_file_to_remote" do
141
+ subject { dummy_class.new }
142
+
143
+ it "can copy a file to a remote host" do
144
+ content = "this is the content"
145
+ tempfilepath = "/path/to/tempfile"
146
+ filepath = "/path/to/file"
147
+ host = make_host( 'testhost', { :platform => 'windows' })
148
+ tempfile = double( 'tempfile' )
149
+ tempfile.stub( :path ).and_return( tempfilepath )
150
+ Tempfile.stub( :open ).and_yield( tempfile )
151
+ file = double( 'file' )
152
+ File.stub( :open ).and_yield( file )
153
+
154
+ file.should_receive( :puts ).with( content ).once
155
+ host.should_receive( :do_scp_to ).with( tempfilepath, filepath, subject.instance_variable_get( :@options ) ).once
156
+
157
+ subject.copy_file_to_remote(host, filepath, content)
158
+
159
+ end
160
+
161
+ end
162
+
163
+ context "proxy_config" do
164
+ subject { dummy_class.new }
165
+
166
+ it "correctly configures ubuntu hosts" do
167
+ hosts = make_hosts( { :platform => 'ubuntu', :exit_code => 1 } )
168
+
169
+ Beaker::Command.should_receive( :new ).with( "if test -f /etc/apt/apt.conf; then mv /etc/apt/apt.conf /etc/apt/apt.conf.bk; fi" ).exactly( 3 )
170
+ hosts.each do |host|
171
+ subject.should_receive( :copy_file_to_remote ).with( host, '/etc/apt/apt.conf', apt_cfg ).once
172
+ subject.should_receive( :apt_get_update ).with( host ).once
173
+ end
174
+
175
+ subject.proxy_config( hosts, options )
176
+
177
+ end
178
+
179
+ it "correctly configures debian hosts" do
180
+ hosts = make_hosts( { :platform => 'debian' } )
181
+
182
+ Beaker::Command.should_receive( :new ).with( "if test -f /etc/apt/apt.conf; then mv /etc/apt/apt.conf /etc/apt/apt.conf.bk; fi" ).exactly( 3 ).times
183
+ hosts.each do |host|
184
+ subject.should_receive( :copy_file_to_remote ).with( host, '/etc/apt/apt.conf', apt_cfg ).once
185
+ subject.should_receive( :apt_get_update ).with( host ).once
186
+ end
187
+
188
+ subject.proxy_config( hosts, options )
189
+
190
+ end
191
+
192
+ it "correctly configures solaris-11 hosts" do
193
+ hosts = make_hosts( { :platform => 'solaris-11' } )
194
+
195
+ Beaker::Command.should_receive( :new ).with( "/usr/bin/pkg unset-publisher solaris || :" ).exactly( 3 ).times
196
+ hosts.each do |host|
197
+ Beaker::Command.should_receive( :new ).with( "/usr/bin/pkg set-publisher -g %s solaris" % ips_pkg_repo ).once
198
+ end
199
+
200
+ subject.proxy_config( hosts, options )
201
+
202
+ end
203
+
204
+ it "does nothing for non ubuntu/debian/solaris-11 hosts" do
205
+ hosts = make_hosts( { :platform => 'windows' } )
206
+
207
+ Beaker::Command.should_receive( :new ).never
208
+
209
+ subject.proxy_config( hosts, options )
210
+
211
+ end
212
+ end
213
+
214
+ context "add_el_extras" do
215
+ subject { dummy_class.new }
216
+
217
+ it "add extras for el-5/6 hosts" do
218
+ hosts = make_hosts( { :platform => 'el-5', :exit_code => 1 } )
219
+ hosts[0][:platform] = 'el-6'
220
+ url = "http://el_extras_url"
221
+
222
+ subject.stub( :epel_info_for! ).and_return( url )
223
+
224
+ Beaker::Command.should_receive( :new ).with("rpm -qa | grep epel-release").exactly( 3 ).times
225
+ Beaker::Command.should_receive( :new ).with("rpm -i #{url}").exactly( 3 ).times
226
+ Beaker::Command.should_receive( :new ).with("yum clean all && yum makecache").exactly( 3 ).times
227
+
228
+ subject.add_el_extras( hosts, options )
229
+
230
+ end
231
+
232
+ it "should do nothing for non el-5/6 hosts" do
233
+ hosts = make_hosts( { :platform => 'windows' } )
234
+
235
+ Beaker::Command.should_receive( :new ).never
236
+
237
+ subject.add_el_extras( hosts, options )
238
+
239
+ end
240
+ end
241
+
242
+ context "add_master_entry" do
243
+ subject { dummy_class.new }
244
+
245
+ it "can configure /etc/hosts on a unix master" do
246
+ path = Beaker::HostPrebuiltSteps::ETC_HOSTS_PATH
247
+ master = subject.only_host_with_role(hosts, :master)
248
+
249
+ Beaker::Command.should_receive( :new ).with( "ip a|awk '/global/{print$2}' | cut -d/ -f1 | head -1" ).once
250
+ Beaker::Command.should_receive( :new ).with( "cp %s %s.old" % [path, path] ).once
251
+ Beaker::Command.should_receive( :new ).with( "cp %s %s.new" % [path, path] ).once
252
+ Beaker::Command.should_receive( :new ).with( "grep -v '#{ip} #{master}' %s > %s.new" % [path, path] ).once
253
+ Beaker::Command.should_receive( :new ).with( "echo '#{ip} #{master}' >> %s.new" % path ).once
254
+ Beaker::Command.should_receive( :new ).with( "mv %s.new %s" % [path, path] ).once
255
+
256
+ subject.add_master_entry( hosts, options )
257
+ end
258
+
259
+ it "can configure /etc/hosts on a solaris master" do
260
+ @platform = 'solaris'
261
+ path = Beaker::HostPrebuiltSteps::ETC_HOSTS_PATH_SOLARIS
262
+ master = subject.only_host_with_role(hosts, :master)
263
+
264
+ Beaker::Command.should_receive( :new ).with( "ifconfig -a inet| awk '/broadcast/ {print $2}' | cut -d/ -f1 | head -1" ).once
265
+ Beaker::Command.should_receive( :new ).with( "cp %s %s.old" % [path, path] ).once
266
+ Beaker::Command.should_receive( :new ).with( "cp %s %s.new" % [path, path] ).once
267
+ Beaker::Command.should_receive( :new ).with( "grep -v '#{ip} #{master}' %s > %s.new" % [path, path] ).once
268
+ Beaker::Command.should_receive( :new ).with( "echo '#{ip} #{master}' >> %s.new" % path ).once
269
+ Beaker::Command.should_receive( :new ).with( "mv %s.new %s" % [path, path] ).once
270
+
271
+ subject.add_master_entry( hosts, options )
272
+ end
273
+
274
+ it "does nothing on a vagrant master" do
275
+ master = subject.only_host_with_role(hosts, :master)
276
+ master[:hypervisor] = 'vagrant'
277
+
278
+ Beaker::Command.should_receive( :new ).never
279
+
280
+ subject.add_master_entry( hosts, options )
281
+
282
+ end
283
+ end
284
+
285
+ context "sync_root_keys" do
286
+ subject { dummy_class.new }
287
+
288
+ it "can sync keys on a solaris host" do
289
+ @platform = 'solaris'
290
+
291
+ Beaker::Command.should_receive( :new ).with( sync_cmd % "bash" ).exactly( 3 ).times
292
+
293
+ subject.sync_root_keys( hosts, options )
294
+
295
+ end
296
+
297
+ it "can sync keys on a non-solaris host" do
298
+
299
+ Beaker::Command.should_receive( :new ).with( sync_cmd % "env PATH=/usr/gnu/bin:$PATH bash" ).exactly( 3 ).times
300
+
301
+ subject.sync_root_keys( hosts, options )
302
+
303
+ end
304
+
305
+ end
306
+
307
+ context "validate_host" do
308
+ subject { dummy_class.new }
309
+
310
+ it "can validate unix hosts" do
311
+
312
+ hosts.each do |host|
313
+ pkgs.each do |pkg|
314
+ host.should_receive( :check_for_package ).with( pkg ).once.and_return( false )
315
+ host.should_receive( :install_package ).with( pkg ).once
316
+ end
317
+ unix_only_pkgs.each do |pkg|
318
+ host.should_receive( :check_for_package ).with( pkg ).once.and_return( false )
319
+ host.should_receive( :install_package ).with( pkg ).once
320
+ end
321
+
322
+ end
323
+
324
+ subject.validate_host(hosts, logger)
325
+
326
+ end
327
+
328
+ it "can validate windows hosts" do
329
+ @platform = 'windows'
330
+
331
+ hosts.each do |host|
332
+ pkgs.each do |pkg|
333
+ host.should_receive( :check_for_package ).with( pkg ).once.and_return( false )
334
+ host.should_receive( :install_package ).with( pkg ).once
335
+ end
336
+ unix_only_pkgs.each do |pkg|
337
+ host.should_receive( :check_for_package).with( pkg ).never
338
+ host.should_receive( :install_package ).with( pkg ).never
339
+ end
340
+ end
341
+
342
+ subject.validate_host(hosts, logger)
343
+
344
+ end
345
+
346
+ it "can validate SLES hosts" do
347
+ @platform = 'sles-13.1-x64'
348
+
349
+ hosts.each do |host|
350
+ pkgs.each do |pkg|
351
+ host.should_receive( :check_for_package ).with( pkg ).once.and_return( false )
352
+ host.should_receive( :install_package ).with( pkg ).once
353
+ end
354
+ unix_only_pkgs.each do |pkg|
355
+ host.should_receive( :check_for_package).with( pkg ).never
356
+ host.should_receive( :install_package ).with( pkg ).never
357
+ end
358
+ sles_only_pkgs.each do |pkg|
359
+ host.should_receive( :check_for_package).with( pkg ).once.and_return( false )
360
+ host.should_receive( :install_package ).with( pkg ).once
361
+ end
362
+
363
+ end
364
+
365
+ subject.validate_host(hosts, logger)
366
+
367
+ end
368
+ end
369
+
370
+ context 'get_domain_name' do
371
+ subject { dummy_class.new }
372
+
373
+ it "can find the domain for a host" do
374
+ host = make_host('name', { :stdout => "domain labs.lan d.labs.net dc1.labs.net labs.com\nnameserver 10.16.22.10\nnameserver 10.16.22.11" } )
375
+
376
+ Beaker::Command.should_receive( :new ).with( "cat /etc/resolv.conf" ).once
377
+
378
+ expect( subject.get_domain_name( host ) ).to be === "labs.lan"
379
+
380
+ end
381
+
382
+ it "can find the search for a host" do
383
+ host = make_host('name', { :stdout => "search labs.lan d.labs.net dc1.labs.net labs.com\nnameserver 10.16.22.10\nnameserver 10.16.22.11" } )
384
+
385
+ Beaker::Command.should_receive( :new ).with( "cat /etc/resolv.conf" ).once
386
+
387
+ expect( subject.get_domain_name( host ) ).to be === "labs.lan"
388
+
389
+ end
390
+ end
391
+
392
+ context "get_ip" do
393
+ subject { dummy_class.new }
394
+
395
+ it "can exec the get_ip command" do
396
+ host = make_host('name', { :stdout => "192.168.2.130\n" } )
397
+
398
+ Beaker::Command.should_receive( :new ).with( "ip a|awk '/global/{print$2}' | cut -d/ -f1 | head -1" ).once
399
+
400
+ expect( subject.get_ip( host ) ).to be === "192.168.2.130"
401
+
402
+ end
403
+
404
+ end
405
+
406
+ context "set_etc_hosts" do
407
+ subject { dummy_class.new }
408
+
409
+ it "can set the /etc/hosts string on a host" do
410
+ host = make_host('name', {})
411
+ etc_hosts = "127.0.0.1 localhost\n192.168.2.130 pe-ubuntu-lucid\n192.168.2.128 pe-centos6\n192.168.2.131 pe-debian6"
412
+
413
+ Beaker::Command.should_receive( :new ).with( "echo '#{etc_hosts}' > /etc/hosts" ).once
414
+ host.should_receive( :exec ).once
415
+
416
+ subject.set_etc_hosts(host, etc_hosts)
417
+ end
418
+
419
+ end
420
+
421
+ end