beaker 2.46.0 → 2.47.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CONTRIBUTING.md +15 -10
- data/HISTORY.md +145 -2
- data/acceptance/tests/base/dsl/helpers/host_helpers/on_test.rb +32 -0
- data/acceptance/tests/base/packages.rb +2 -2
- data/acceptance/tests/base/packages_unix.rb +1 -0
- data/beaker.gemspec +5 -1
- data/docs/Argument-Processing-and-Precedence.md +30 -38
- data/docs/Shared-Options-for-Executing-Beaker-Commands.md +6 -0
- data/docs/runner/run_in_parallel.md +62 -0
- data/lib/beaker.rb +4 -1
- data/lib/beaker/cli.rb +1 -0
- data/lib/beaker/dsl.rb +2 -2
- data/lib/beaker/dsl/helpers/host_helpers.rb +5 -3
- data/lib/beaker/dsl/helpers/puppet_helpers.rb +50 -30
- data/lib/beaker/dsl/install_utils/foss_utils.rb +14 -4
- data/lib/beaker/dsl/install_utils/module_utils.rb +1 -1
- data/lib/beaker/dsl/patterns.rb +4 -2
- data/lib/beaker/host_prebuilt_steps.rb +2 -1
- data/lib/beaker/hypervisor.rb +3 -2
- data/lib/beaker/options/presets.rb +5 -0
- data/lib/beaker/shared/host_manager.rb +15 -3
- data/lib/beaker/tasks/quick_start.rb +49 -0
- data/lib/beaker/tasks/rake_task.rb +1 -1
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/dsl/helpers/host_helpers_spec.rb +16 -0
- data/spec/beaker/dsl/helpers/puppet_helpers_spec.rb +78 -0
- data/spec/beaker/dsl/install_utils/foss_utils_spec.rb +12 -0
- data/spec/beaker/host_prebuilt_steps_spec.rb +4 -4
- data/spec/beaker/hypervisor/hypervisor_spec.rb +18 -2
- data/spec/beaker/options/presets_spec.rb +6 -0
- data/spec/beaker/shared/host_manager_spec.rb +37 -0
- metadata +54 -10
@@ -41,3 +41,9 @@ Do not output any logging for this command. Defaults to `false`.
|
|
41
41
|
Specifies standard input to be provided to the command post execution. Defaults to `nil`.
|
42
42
|
|
43
43
|
on host, "this command takes input", {:stdin => "hiya"}
|
44
|
+
|
45
|
+
## [:run_in_parallel](runner/run_in_parallel.md)
|
46
|
+
|
47
|
+
Execute the command against all hosts in parallel
|
48
|
+
|
49
|
+
on hosts, puppet( 'agent -t' ), :run_in_parallel => true
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# run_in_parallel global and command options
|
2
|
+
|
3
|
+
## run_in_parallel global option
|
4
|
+
The run_in_parallel global option is an array with the following possible values: ['configure', 'install']
|
5
|
+
It defaults to an empty array []
|
6
|
+
It can be set in an options file, or overriden by the BEAKER_RUN_IN_PARALLEL environment variable
|
7
|
+
example:
|
8
|
+
|
9
|
+
export BEAKER_RUN_IN_PARALLEL=configure,install
|
10
|
+
|
11
|
+
Including 'configure' causes timesync to execute in parallel (if timesync=true for any host)
|
12
|
+
|
13
|
+
Including 'install' causes as much of the puppet install to happen in parallel as possible.
|
14
|
+
|
15
|
+
## run_in_parallel command option
|
16
|
+
The run_in_parallel command option is a boolean value, specifying whether to execute each iteration (usually of hosts)
|
17
|
+
in parallel, or not. The block_on method is the primary method accepting the run_in_parallel command option,
|
18
|
+
however many methods that call into block_on respect it as well:
|
19
|
+
- on
|
20
|
+
- run_block_on
|
21
|
+
- block_on
|
22
|
+
- install_puppet_agent_on
|
23
|
+
- apply_manifest_on
|
24
|
+
- stop_agent_on
|
25
|
+
- execute_powershell_script_on
|
26
|
+
|
27
|
+
## Using InParallel in your test scripts
|
28
|
+
In addition to the options, you can use InParallel within your test scripts as well.
|
29
|
+
|
30
|
+
Examples:
|
31
|
+
```ruby
|
32
|
+
include InParallel
|
33
|
+
|
34
|
+
test_name('test_test')
|
35
|
+
|
36
|
+
# Example 1
|
37
|
+
hosts.each_in_parallel{ |host|
|
38
|
+
# Do something on each host
|
39
|
+
}
|
40
|
+
|
41
|
+
def some_method_call
|
42
|
+
return "some_method_call"
|
43
|
+
end
|
44
|
+
|
45
|
+
def some_method_call
|
46
|
+
return "some_other_method_call"
|
47
|
+
end
|
48
|
+
|
49
|
+
# Example 2
|
50
|
+
# Runs each method within the block in parallel in a forked process
|
51
|
+
run_in_parallel{
|
52
|
+
@result = some_method_call
|
53
|
+
@result_2 = some_other_method_call
|
54
|
+
}
|
55
|
+
|
56
|
+
# results in 'some_method_callsome_other_method_call'
|
57
|
+
puts @result + @result_2
|
58
|
+
```
|
59
|
+
|
60
|
+
**_Note:_** While you can return a result from a forked process to an instance variable, any values assigned to local variables, or other changes to global state will not persist from the child process to the parent process.
|
61
|
+
|
62
|
+
Further documentation on the usage of [InParallel](http://github/puppetlabs/in-parallel/readme.md)
|
data/lib/beaker.rb
CHANGED
data/lib/beaker/cli.rb
CHANGED
@@ -14,6 +14,7 @@ module Beaker
|
|
14
14
|
@options_parser = Beaker::Options::Parser.new
|
15
15
|
@options = @options_parser.parse_args
|
16
16
|
@logger = Beaker::Logger.new(@options)
|
17
|
+
InParallel::InParallelExecutor.logger = @logger
|
17
18
|
@options[:logger] = @logger
|
18
19
|
@options[:timestamp] = @timestamp
|
19
20
|
@options[:beaker_version] = Beaker::Version::STRING
|
data/lib/beaker/dsl.rb
CHANGED
@@ -56,8 +56,8 @@ module Beaker
|
|
56
56
|
# require 'spec_helper'
|
57
57
|
#
|
58
58
|
# describe 'A Test With RSpec' do
|
59
|
-
# let(:hosts) { Host.new('blah', 'blah', 'not helpful' }
|
60
|
-
# let(:logger) { Where.is('the', 'rspec', 'logger')
|
59
|
+
# let(:hosts) { Host.new('blah', 'blah', 'not helpful') }
|
60
|
+
# let(:logger) { Where.is('the', 'rspec', 'logger') }
|
61
61
|
#
|
62
62
|
# after do
|
63
63
|
# on master, puppet('resource mything ensure=absent')
|
@@ -24,7 +24,7 @@ module Beaker
|
|
24
24
|
# @option opts [Hash{String=>String}] :environment ({}) These will be
|
25
25
|
# treated as extra environment variables that should be set before
|
26
26
|
# running the command.
|
27
|
-
#
|
27
|
+
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
28
28
|
|
29
29
|
# The primary method for executing commands *on* some set of hosts.
|
30
30
|
#
|
@@ -60,7 +60,7 @@ module Beaker
|
|
60
60
|
# @return [Result] An object representing the outcome of *command*.
|
61
61
|
# @raise [FailTest] Raises an exception if *command* obviously fails.
|
62
62
|
def on(host, command, opts = {}, &block)
|
63
|
-
block_on host do | host |
|
63
|
+
block_on host, opts do | host |
|
64
64
|
if command.is_a? String
|
65
65
|
cmd_opts = {}
|
66
66
|
#add any additional environment variables to the command
|
@@ -280,10 +280,12 @@ module Beaker
|
|
280
280
|
# that responds like
|
281
281
|
# {Beaker::Host#do_scp_from}.
|
282
282
|
# @param [String] powershell_script A string describing a set of powershell actions
|
283
|
+
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
284
|
+
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
283
285
|
#
|
284
286
|
# @return [Result] Returns the result of the powershell command execution
|
285
287
|
def execute_powershell_script_on(hosts, powershell_script, opts = {})
|
286
|
-
block_on hosts do |host|
|
288
|
+
block_on hosts, opts do |host|
|
287
289
|
script_path = "beaker_powershell_script_#{Time.now.to_i}.ps1"
|
288
290
|
create_remote_file(host, script_path, powershell_script, opts)
|
289
291
|
native_path = script_path.gsub(/\//, "\\")
|
@@ -397,6 +397,7 @@ module Beaker
|
|
397
397
|
# @option opts [String] :debug (false) If this option exists,
|
398
398
|
# the "--debug" command line parameter
|
399
399
|
# will be passed to the 'puppet apply' command.
|
400
|
+
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
400
401
|
#
|
401
402
|
# @param [Block] block This method will yield to a block of code passed
|
402
403
|
# by the caller; this can be used for additional
|
@@ -405,7 +406,7 @@ module Beaker
|
|
405
406
|
# @return [Array<Result>, Result, nil] An array of results, a result object,
|
406
407
|
# or nil. Check {#run_block_on} for more details on this.
|
407
408
|
def apply_manifest_on(host, manifest, opts = {}, &block)
|
408
|
-
block_on host do | host |
|
409
|
+
block_on host, opts do | host |
|
409
410
|
on_options = {}
|
410
411
|
on_options[:acceptable_exit_codes] = Array(opts[:acceptable_exit_codes])
|
411
412
|
|
@@ -658,12 +659,14 @@ module Beaker
|
|
658
659
|
#stops the puppet agent running on the host
|
659
660
|
# @param [Host, Array<Host>, String, Symbol] agent One or more hosts to act upon,
|
660
661
|
# or a role (String or Symbol) that identifies one or more hosts.
|
661
|
-
|
662
|
-
|
663
|
-
|
662
|
+
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
663
|
+
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
664
|
+
def stop_agent_on(agent, opts = {})
|
665
|
+
block_on agent, opts do | host |
|
666
|
+
vardir = host.puppet_configprint['vardir']
|
664
667
|
agent_running = true
|
665
668
|
while agent_running
|
666
|
-
agent_running =
|
669
|
+
agent_running = host.file_exist?("#{vardir}/state/agent_catalog_run.lock")
|
667
670
|
if agent_running
|
668
671
|
sleep 2
|
669
672
|
end
|
@@ -671,26 +674,26 @@ module Beaker
|
|
671
674
|
|
672
675
|
# In 4.0 this was changed to just be `puppet`
|
673
676
|
agent_service = 'puppet'
|
674
|
-
if !aio_version?(
|
677
|
+
if !aio_version?(host)
|
675
678
|
# The agent service is `pe-puppet` everywhere EXCEPT certain linux distros on PE 2.8
|
676
679
|
# In all the case that it is different, this init script will exist. So we can assume
|
677
680
|
# that if the script doesn't exist, we should just use `pe-puppet`
|
678
681
|
agent_service = 'pe-puppet-agent'
|
679
|
-
agent_service = 'pe-puppet' unless
|
682
|
+
agent_service = 'pe-puppet' unless host.file_exist?('/etc/init.d/pe-puppet-agent')
|
680
683
|
end
|
681
684
|
|
682
685
|
# Under a number of stupid circumstances, we can't stop the
|
683
686
|
# agent using puppet. This is usually because of issues with
|
684
687
|
# the init script or system on that particular configuration.
|
685
688
|
avoid_puppet_at_all_costs = false
|
686
|
-
avoid_puppet_at_all_costs ||=
|
687
|
-
avoid_puppet_at_all_costs ||=
|
689
|
+
avoid_puppet_at_all_costs ||= host['platform'] =~ /el-4/
|
690
|
+
avoid_puppet_at_all_costs ||= host['pe_ver'] && version_is_less(host['pe_ver'], '3.2') && host['platform'] =~ /sles/
|
688
691
|
|
689
692
|
if avoid_puppet_at_all_costs
|
690
693
|
# When upgrading, puppet is already stopped. On EL4, this causes an exit code of '1'
|
691
|
-
on
|
694
|
+
on host, "/etc/init.d/#{agent_service} stop", :acceptable_exit_codes => [0, 1]
|
692
695
|
else
|
693
|
-
on
|
696
|
+
on host, puppet_resource('service', agent_service, 'ensure=stopped')
|
694
697
|
end
|
695
698
|
end
|
696
699
|
end
|
@@ -714,35 +717,52 @@ module Beaker
|
|
714
717
|
|
715
718
|
# Ensure the host has requested a cert, then sign it
|
716
719
|
#
|
717
|
-
# @param [Host, Array<Host>, String, Symbol] host
|
718
|
-
#
|
720
|
+
# @param [Host, Array<Host>, String, Symbol] host One or more hosts, or a role (String or Symbol)
|
721
|
+
# that identifies one or more hosts to validate certificate signing.
|
722
|
+
# No argument, or an empty array means no validation of success
|
723
|
+
# for specific hosts will be performed. This will always execute
|
724
|
+
# 'cert --sign --all --allow-dns-alt-names' even for a single host.
|
719
725
|
#
|
720
726
|
# @return nil
|
721
727
|
# @raise [FailTest] if process times out
|
722
|
-
def sign_certificate_for(host)
|
723
|
-
|
724
|
-
|
728
|
+
def sign_certificate_for(host = [])
|
729
|
+
hostnames = []
|
730
|
+
hosts = host.is_a?(Array) ? host : [host]
|
731
|
+
hosts.each{ |current_host|
|
732
|
+
if [master, dashboard, database].include? current_host
|
725
733
|
|
726
|
-
on
|
727
|
-
on master, puppet( "cert --allow-dns-alt-names sign #{
|
734
|
+
on current_host, puppet( 'agent -t' ), :acceptable_exit_codes => [0,1,2]
|
735
|
+
on master, puppet( "cert --allow-dns-alt-names sign #{current_host}" ), :acceptable_exit_codes => [0,24]
|
728
736
|
|
729
737
|
else
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
738
|
+
hostnames << Regexp.escape( current_host.node_name )
|
739
|
+
end
|
740
|
+
}
|
741
|
+
if hostnames.size < 1
|
742
|
+
on master, puppet("cert --sign --all --allow-dns-alt-names"),
|
743
|
+
:acceptable_exit_codes => [0,24]
|
744
|
+
return
|
745
|
+
end
|
746
|
+
while hostnames.size > 0
|
747
|
+
last_sleep = 0
|
748
|
+
next_sleep = 1
|
749
|
+
(0..10).each do |i|
|
750
|
+
if i == 10
|
751
|
+
fail_test("Failed to sign cert for #{hostnames}")
|
752
|
+
hostnames.clear
|
753
|
+
end
|
754
|
+
on master, puppet("cert --sign --all --allow-dns-alt-names"), :acceptable_exit_codes => [0,24]
|
755
|
+
out = on(master, puppet("cert --list --all")).stdout
|
756
|
+
if hostnames.all? { |hostname| out =~ /\+ "?#{hostname}"?/ }
|
757
|
+
hostnames.clear
|
758
|
+
break
|
742
759
|
end
|
743
760
|
|
761
|
+
sleep next_sleep
|
762
|
+
(last_sleep, next_sleep) = next_sleep, last_sleep+next_sleep
|
744
763
|
end
|
745
764
|
end
|
765
|
+
host
|
746
766
|
end
|
747
767
|
|
748
768
|
#prompt the master to sign certs then check to confirm the cert for the default host is signed
|
@@ -245,6 +245,7 @@ module Beaker
|
|
245
245
|
# @option opts [String] :puppet_agent_version Version of puppet agent to download
|
246
246
|
# @option opts [String] :mac_download_url Url to download msi pattern of %url%/puppet-%version%.msi
|
247
247
|
# @option opts [String] :win_download_url Url to download dmg pattern of %url%/(puppet|hiera|facter)-%version%.msi
|
248
|
+
# @option opts [Boolean] :run_in_parallel Whether to install on all hosts in parallel. Defaults to false.
|
248
249
|
#
|
249
250
|
# @return nil
|
250
251
|
# @raise [StandardError] When encountering an unsupported platform by default, or if gem cannot be found when default_action => 'gem_install'
|
@@ -257,9 +258,13 @@ module Beaker
|
|
257
258
|
# backwards compatability
|
258
259
|
opts[:puppet_agent_version] ||= opts[:version]
|
259
260
|
install_puppet_agent_on(hosts, opts)
|
260
|
-
|
261
261
|
else
|
262
|
-
|
262
|
+
# Use option specified in the method call, otherwise check whether the global
|
263
|
+
# run_in_parallel option includes install
|
264
|
+
run_in_parallel = opts[:run_in_parallel]
|
265
|
+
run_in_parallel = ((@options && @options[:run_in_parallel].is_a?(Array)) ?
|
266
|
+
@options[:run_in_parallel].include?('install') : false) if run_in_parallel.nil?
|
267
|
+
block_on hosts, { :run_in_parallel => run_in_parallel} do |host|
|
263
268
|
if host['platform'] =~ /el-(5|6|7)/
|
264
269
|
relver = $1
|
265
270
|
install_puppet_from_rpm_on(host, opts.merge(:release => relver, :family => 'el'))
|
@@ -325,6 +330,7 @@ module Beaker
|
|
325
330
|
# @option opts [String] :mac_download_url Url to download msi pattern of %url%/puppet-agent-%version%.msi
|
326
331
|
# @option opts [String] :win_download_url Url to download dmg pattern of %url%/puppet-agent-%version%.msi
|
327
332
|
# @option opts [String] :puppet_collection Defaults to 'pc1'
|
333
|
+
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
328
334
|
#
|
329
335
|
# @return nil
|
330
336
|
# @raise [StandardError] When encountering an unsupported platform by default, or if gem cannot be found when default_action => 'gem_install'
|
@@ -334,7 +340,10 @@ module Beaker
|
|
334
340
|
opts[:puppet_collection] ||= 'pc1' #hi! i'm case sensitive! be careful!
|
335
341
|
opts[:puppet_agent_version] ||= opts[:version] #backwards compatability with old parameter name
|
336
342
|
|
337
|
-
|
343
|
+
run_in_parallel = opts[:run_in_parallel]
|
344
|
+
run_in_parallel = ((@options && @options[:run_in_parallel].is_a?(Array)) ?
|
345
|
+
@options[:run_in_parallel].include?('install') : false) if run_in_parallel.nil?
|
346
|
+
block_on hosts, { :run_in_parallel => run_in_parallel } do |host|
|
338
347
|
add_role(host, 'aio') #we are installing agent, so we want aio role
|
339
348
|
package_name = nil
|
340
349
|
case host['platform']
|
@@ -379,6 +388,7 @@ module Beaker
|
|
379
388
|
# @param [Hash{Symbol=>String}] opts
|
380
389
|
# @option opts [Hash{String=>String}] :main configure the main section of puppet.conf
|
381
390
|
# @option opts [Hash{String=>String}] :agent configure the agent section of puppet.conf
|
391
|
+
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
382
392
|
#
|
383
393
|
# @example will configure /etc/puppet.conf on the puppet master.
|
384
394
|
# config = {
|
@@ -407,7 +417,7 @@ module Beaker
|
|
407
417
|
puppet_conf_text << "\n"
|
408
418
|
end
|
409
419
|
logger.debug( "setting config '#{puppet_conf_text}' on hosts #{hosts}" )
|
410
|
-
block_on hosts do |host|
|
420
|
+
block_on hosts, opts do |host|
|
411
421
|
puppet_conf_path = host.puppet['config']
|
412
422
|
create_remote_file(host, puppet_conf_path, puppet_conf_text)
|
413
423
|
end
|
@@ -16,7 +16,7 @@ module Beaker
|
|
16
16
|
# The directories in the module directory that will not be scp-ed to the test system when using
|
17
17
|
# `copy_module_to`
|
18
18
|
PUPPET_MODULE_INSTALL_IGNORE = ['.bundle', '.git', '.idea', '.vagrant', '.vendor', 'vendor', 'acceptance',
|
19
|
-
'bundle', 'spec', 'tests', 'log']
|
19
|
+
'bundle', 'spec', 'tests', 'log', '.svn', 'junit', 'pkg', 'example']
|
20
20
|
|
21
21
|
# Install the desired module on all hosts using either the PMT or a
|
22
22
|
# staging forge
|
data/lib/beaker/dsl/patterns.rb
CHANGED
@@ -17,11 +17,13 @@ module Beaker
|
|
17
17
|
# as a String that can be used to search for
|
18
18
|
# a set of Hosts, or a {Host}
|
19
19
|
# or Array<{Host}> to run the block against
|
20
|
+
# @param [Hash{Symbol=>String}] opts Options to alter execution.
|
21
|
+
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
20
22
|
# @param [Block] block This method will yield to a block of code passed by the caller
|
21
23
|
#
|
22
24
|
# @return [Array<Result>, Result, nil] An array of results, a result object, or nil.
|
23
25
|
# Check {#run_block_on} for more details on this.
|
24
|
-
def block_on hosts_or_filter, &block
|
26
|
+
def block_on hosts_or_filter, opts={}, &block
|
25
27
|
block_hosts = nil
|
26
28
|
if defined? hosts
|
27
29
|
block_hosts = hosts
|
@@ -32,7 +34,7 @@ module Beaker
|
|
32
34
|
else
|
33
35
|
block_hosts = hosts_or_filter
|
34
36
|
end
|
35
|
-
run_block_on block_hosts, filter, &block
|
37
|
+
run_block_on block_hosts, filter, opts, &block
|
36
38
|
end
|
37
39
|
|
38
40
|
end
|
@@ -52,7 +52,7 @@ module Beaker
|
|
52
52
|
when host['platform'] =~ /sles-/
|
53
53
|
ntp_command = "sntp #{ntp_server}"
|
54
54
|
else
|
55
|
-
ntp_command = "ntpdate -t 20 #{ntp_server}"
|
55
|
+
ntp_command = "ntpdate -u -t 20 #{ntp_server}"
|
56
56
|
end
|
57
57
|
success=false
|
58
58
|
try = 0
|
@@ -71,6 +71,7 @@ module Beaker
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
74
|
+
nil
|
74
75
|
rescue => e
|
75
76
|
report_and_raise(logger, e, "timesync (--ntp)")
|
76
77
|
end
|
data/lib/beaker/hypervisor.rb
CHANGED
@@ -101,9 +101,10 @@ module Beaker
|
|
101
101
|
|
102
102
|
#Default configuration steps to be run for a given hypervisor. Any additional configuration to be done
|
103
103
|
#to the provided SUT for test execution to be successful.
|
104
|
-
def configure
|
104
|
+
def configure(opts = {})
|
105
105
|
return unless @options[:configure]
|
106
|
-
block_on @hosts
|
106
|
+
block_on @hosts, { :run_in_parallel => (@options && @options[:run_in_parallel].is_a?(Array)) ?
|
107
|
+
@options[:run_in_parallel].include?('configure') : false} do |host|
|
107
108
|
if host[:timesync]
|
108
109
|
timesync(host, @options)
|
109
110
|
end
|
@@ -36,6 +36,7 @@ module Beaker
|
|
36
36
|
:vbguest_plugin => ['BEAKER_VB_GUEST_PLUGIN', 'BEAKER_vb_guest_plugin'],
|
37
37
|
:tag_includes => ['BEAKER_TAG'],
|
38
38
|
:tag_excludes => ['BEAKER_EXCLUDE_TAG'],
|
39
|
+
:run_in_parallel => ['BEAKER_RUN_IN_PARALLEL'],
|
39
40
|
}
|
40
41
|
|
41
42
|
# Select all environment variables whose name matches provided regex
|
@@ -86,6 +87,9 @@ module Beaker
|
|
86
87
|
|
87
88
|
found_env_vars[:type] = type
|
88
89
|
end
|
90
|
+
if found_env_vars[:run_in_parallel]
|
91
|
+
found_env_vars[:run_in_parallel] = found_env_vars[:run_in_parallel].split(',')
|
92
|
+
end
|
89
93
|
|
90
94
|
found_env_vars[:pe_version_file_win] = found_env_vars[:pe_version_file]
|
91
95
|
found_env_vars
|
@@ -188,6 +192,7 @@ module Beaker
|
|
188
192
|
:nodeclassifier_port => 4433,
|
189
193
|
:cache_files_locally => true, # TODO change to false in next major version
|
190
194
|
:aws_keyname_modifier => rand(10 ** 10).to_s.rjust(10,'0'), # 10 digit random number string
|
195
|
+
:run_in_parallel => [],
|
191
196
|
:ssh => {
|
192
197
|
:config => false,
|
193
198
|
:paranoid => false,
|
@@ -72,6 +72,8 @@ module Beaker
|
|
72
72
|
#
|
73
73
|
# @param [Array<Host>, Host] hosts The host or hosts to run the provided block against
|
74
74
|
# @param [String, Symbol] filter Optional filter to apply to provided hosts - limits by name or role
|
75
|
+
# @param [Hash{Symbol=>String}] opts
|
76
|
+
# @option opts [Boolean] :run_in_parallel Whether to run on each host in parallel.
|
75
77
|
# @param [Block] block This method will yield to a block of code passed by the caller
|
76
78
|
#
|
77
79
|
# @todo (beaker3.0:BKR-571): simplify return types to Array<Result> only
|
@@ -82,7 +84,7 @@ module Beaker
|
|
82
84
|
# Else, a result object is returned. If filtering makes it such that only
|
83
85
|
# one host is left, then it's passed as a host object (not in an array),
|
84
86
|
# and thus a result object is returned.
|
85
|
-
def run_block_on hosts = [], filter = nil, &block
|
87
|
+
def run_block_on hosts = [], filter = nil, opts = {}, &block
|
86
88
|
result = nil
|
87
89
|
block_hosts = hosts #the hosts to apply the block to after any filtering
|
88
90
|
if filter
|
@@ -100,8 +102,18 @@ module Beaker
|
|
100
102
|
end
|
101
103
|
if block_hosts.is_a? Array
|
102
104
|
if block_hosts.length > 0
|
103
|
-
|
104
|
-
|
105
|
+
if opts[:run_in_parallel]
|
106
|
+
# Pass caller[1] - the line that called block_on - for logging purposes.
|
107
|
+
result = block_hosts.map.each_in_parallel(caller[1]) do |h|
|
108
|
+
run_block_on h, &block
|
109
|
+
end
|
110
|
+
hosts.each{|host| host.close}# For some reason, I have to close the SSH connection
|
111
|
+
# after spawning a process and running commands on a host,
|
112
|
+
# or else it gets into a broken state for the next call.
|
113
|
+
else
|
114
|
+
result = block_hosts.map do |h|
|
115
|
+
run_block_on h, &block
|
116
|
+
end
|
105
117
|
end
|
106
118
|
else
|
107
119
|
# there are no matching hosts to execute against
|