beaker 1.8.1 → 1.8.2

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