beaker 3.34.0 → 3.35.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/acceptance/tests/base/external_resources_test.rb +18 -3
- data/acceptance/tests/base/host/host_test.rb +1 -1
- data/docs/concepts/testing_beaker_itself.md +4 -4
- data/docs/concepts/ticket_process.md +12 -12
- data/docs/concepts/types_puppet_4_and_the_all_in_one_agent.md +1 -1
- data/docs/how_to/change_terminal_output_coloring.md +1 -1
- data/docs/how_to/confine.md +3 -3
- data/docs/how_to/debug_beaker_tests.md +19 -19
- data/docs/how_to/enabling_cross_sut_access.md +1 -1
- data/docs/how_to/hosts/README.md +1 -1
- data/docs/how_to/hosts/cisco.md +1 -1
- data/docs/how_to/hypervisors/README.md +1 -1
- data/docs/how_to/platform_specific_tag_confines.md +2 -2
- data/docs/how_to/preserve_hosts.md +2 -2
- data/docs/how_to/rake_tasks.md +3 -4
- data/docs/how_to/test_arbitrary_beaker_versions.md +3 -3
- data/docs/how_to/upgrade_from_2_to_3.md +4 -4
- data/docs/tutorials/README.md +1 -1
- data/docs/tutorials/test_suites.md +1 -1
- data/lib/beaker/cli.rb +1 -0
- data/lib/beaker/command.rb +2 -2
- data/lib/beaker/dsl/assertions.rb +1 -1
- data/lib/beaker/dsl/helpers/facter_helpers.rb +1 -1
- data/lib/beaker/dsl/install_utils/pe_defaults.rb +1 -1
- data/lib/beaker/dsl/roles.rb +1 -1
- data/lib/beaker/dsl/structure.rb +2 -2
- data/lib/beaker/host/cisco.rb +3 -3
- data/lib/beaker/host/mac/exec.rb +1 -1
- data/lib/beaker/host/windows/exec.rb +1 -1
- data/lib/beaker/host_prebuilt_steps.rb +3 -0
- data/lib/beaker/options/hosts_file_parser.rb +9 -2
- data/lib/beaker/options/parser.rb +1 -1
- data/lib/beaker/shared/options_resolver.rb +6 -6
- data/lib/beaker/subcommand.rb +13 -8
- data/lib/beaker/tasks/quick_start.rb +2 -2
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/host/unix/exec_spec.rb +1 -1
- data/spec/beaker/host_prebuilt_steps_spec.rb +1 -0
- data/spec/beaker/options/hosts_file_parser_spec.rb +15 -7
- data/spec/beaker/shared/error_handler_spec.rb +2 -2
- data/spec/beaker/shared/repetition_spec.rb +2 -2
- data/spec/beaker/subcommand_spec.rb +82 -30
- data/spec/helpers.rb +1 -1
- data/spec/mock_fission.rb +4 -4
- data/spec/mock_vsphere.rb +5 -5
- data/spec/mock_vsphere_helper.rb +1 -1
- metadata +2 -2
@@ -1,8 +1,8 @@
|
|
1
1
|
# How To Upgrade from 2.y to 3.0
|
2
2
|
|
3
3
|
This is a guide detailing all the issues to be aware of, and to help people make
|
4
|
-
any changes that you might need to move from beaker 2.y to 3.0. To test out
|
5
|
-
beaker 3.0.0, we recommend implementing the strategy outlined [here](test_arbitrary_beaker_versions.md)
|
4
|
+
any changes that you might need to move from beaker 2.y to 3.0. To test out
|
5
|
+
beaker 3.0.0, we recommend implementing the strategy outlined [here](test_arbitrary_beaker_versions.md)
|
6
6
|
to ensure this new major release does not break your existing testing.
|
7
7
|
|
8
8
|
## Ruby version 1.9.3 no longer supported
|
@@ -39,10 +39,10 @@ doc for info on how to do this.
|
|
39
39
|
|
40
40
|
## EPEL package update
|
41
41
|
|
42
|
-
In beaker < 3.0.0, the epel package names had hardcoded defaults listed in the
|
42
|
+
In beaker < 3.0.0, the epel package names had hardcoded defaults listed in the
|
43
43
|
presets default; in beaker >= 3.0.0, beaker utilizes the `release-latest` file
|
44
44
|
provided on epel mirrors for el versions 5, 6, and 7. Since only the latest epel
|
45
|
-
packages are available on epel mirrors, beaker only supports installation of
|
45
|
+
packages are available on epel mirrors, beaker only supports installation of
|
46
46
|
that latest version.
|
47
47
|
|
48
48
|
## Solaris and AIX Hypervisors removed
|
data/docs/tutorials/README.md
CHANGED
@@ -22,7 +22,7 @@ If you haven't installed beaker yet, your guide to doing
|
|
22
22
|
so can be found [here](installation.md).
|
23
23
|
|
24
24
|
## Quick Start
|
25
|
-
|
25
|
+
|
26
26
|
As a completely new beaker user, the
|
27
27
|
[quick start rake tasks doc](quick_start_rake_tasks.md)
|
28
28
|
will take you through getting beaker running for the
|
@@ -47,7 +47,7 @@ failure modes.
|
|
47
47
|
|
48
48
|
The pre-suite is for setting up the Systems Under Test (SUTs) for the testing
|
49
49
|
suite. No surprises here, usually these files are filled with the setup and
|
50
|
-
installation code needed to verify that the operating assumptions of the
|
50
|
+
installation code needed to verify that the operating assumptions of the
|
51
51
|
software being tested are true.
|
52
52
|
|
53
53
|
Pre-suites, since they’re supposed to contain just setup code, will fail-fast
|
data/lib/beaker/cli.rb
CHANGED
data/lib/beaker/command.rb
CHANGED
@@ -66,7 +66,7 @@ module Beaker
|
|
66
66
|
# interface.
|
67
67
|
# @param [String] cmd An command to call.
|
68
68
|
# @param [Hash] env An optional hash of environment variables to be used
|
69
|
-
# @param [String] pc An optional list of commands to prepend
|
69
|
+
# @param [String] pc An optional list of commands to prepend
|
70
70
|
#
|
71
71
|
# @return [String] This returns the fully formed command line invocation.
|
72
72
|
def cmd_line host, cmd = @command, env = @environment, pc = @prepend_cmds
|
@@ -78,7 +78,7 @@ module Beaker
|
|
78
78
|
end
|
79
79
|
|
80
80
|
# This will cause things like `puppet -t -v agent` which is maybe bad.
|
81
|
-
if host[:platform] =~ /cisco_ios_xr/
|
81
|
+
if host[:platform] =~ /cisco_ios_xr/
|
82
82
|
cmd_line_array = [prepend_commands, env_string, cmd, options_string, args_string]
|
83
83
|
else
|
84
84
|
cmd_line_array = [env_string, prepend_commands, cmd, options_string, args_string]
|
@@ -98,7 +98,7 @@ module Beaker
|
|
98
98
|
# Assert that the provided string does not match the provided regular expression, can pass optional message
|
99
99
|
# @deprecated This is placed her for backwards compatability for tests that used Test::Unit::Assertions,
|
100
100
|
# http://apidock.com/ruby/Test/Unit/Assertions/assert_no_match
|
101
|
-
#
|
101
|
+
#
|
102
102
|
def assert_no_match(regexp, string, msg=nil)
|
103
103
|
assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.")
|
104
104
|
msg = message(msg) { "<#{mu_pp(regexp)}> expected to not match\n<#{mu_pp(string)}>" }
|
@@ -13,7 +13,7 @@ module Beaker
|
|
13
13
|
# (or range) of integer exit codes that should be considered
|
14
14
|
# acceptable. An error will be thrown if the exit code does not
|
15
15
|
# match one of the values in this list.
|
16
|
-
# @option opts [Boolean] :accept_all_exit_codes (false) Consider all
|
16
|
+
# @option opts [Boolean] :accept_all_exit_codes (false) Consider all
|
17
17
|
# exit codes as passing.
|
18
18
|
# @option opts [Boolean] :dry_run (false) Do not actually execute any
|
19
19
|
# commands on the SUT
|
@@ -72,7 +72,7 @@ module Beaker
|
|
72
72
|
PE_DEFAULTS[platform].each_pair do |key, val|
|
73
73
|
host[key] = val
|
74
74
|
end
|
75
|
-
# add the type and group here for backwards compatability
|
75
|
+
# add the type and group here for backwards compatability
|
76
76
|
if host['platform'] =~ /windows/
|
77
77
|
host['group'] = 'Administrators'
|
78
78
|
else
|
data/lib/beaker/dsl/roles.rb
CHANGED
@@ -161,7 +161,7 @@ module Beaker
|
|
161
161
|
end
|
162
162
|
|
163
163
|
#Create a new role method for a given arbitrary role name. Makes it possible to be able to run
|
164
|
-
#commands without having to refer to role by String or Symbol. Will not add a new method
|
164
|
+
#commands without having to refer to role by String or Symbol. Will not add a new method
|
165
165
|
#definition if the name is already in use.
|
166
166
|
# @param [String, Symbol, Array[String,Symbol]] role The role that you wish to create a definition for, either a String
|
167
167
|
# Symbol or an Array of Strings or Symbols.
|
data/lib/beaker/dsl/structure.rb
CHANGED
@@ -68,7 +68,7 @@ module Beaker
|
|
68
68
|
|
69
69
|
set_current_step_name(step_name)
|
70
70
|
# Here we prompt the user to tell us if the step passed or failed
|
71
|
-
loop do
|
71
|
+
loop do
|
72
72
|
input = Readline.readline('Did this step pass, Y/n? ', true).squeeze(" ").strip.downcase
|
73
73
|
if %w(y yes).include?(input)
|
74
74
|
break
|
@@ -102,7 +102,7 @@ module Beaker
|
|
102
102
|
def manual_test manual_test_name, &block
|
103
103
|
if(@options.has_key?(:exec_manual_tests) && @options[:exec_manual_tests] == true)
|
104
104
|
# here the option is set so we run the test as normal
|
105
|
-
test_name manual_test_name, &block
|
105
|
+
test_name manual_test_name, &block
|
106
106
|
else
|
107
107
|
# here no option was set so we log the test name and skip it
|
108
108
|
test_name manual_test_name
|
data/lib/beaker/host/cisco.rb
CHANGED
@@ -119,15 +119,15 @@ module Cisco
|
|
119
119
|
# this will be raised with the appropriate message
|
120
120
|
def validate_setup
|
121
121
|
msg = nil
|
122
|
-
if self[:platform] =~ /cisco_nexus/
|
122
|
+
if self[:platform] =~ /cisco_nexus/
|
123
123
|
if !self[:vrf]
|
124
|
-
msg = 'Cisco Nexus hosts must be provided with a :vrf value.'
|
124
|
+
msg = 'Cisco Nexus hosts must be provided with a :vrf value.'
|
125
125
|
end
|
126
126
|
if !self[:user]
|
127
127
|
msg = 'Cisco hosts must be provided with a :user value'
|
128
128
|
end
|
129
129
|
end
|
130
|
-
if self[:platform] =~ /cisco_ios_xr/
|
130
|
+
if self[:platform] =~ /cisco_ios_xr/
|
131
131
|
if !self[:user]
|
132
132
|
msg = 'Cisco hosts must be provided with a :user value'
|
133
133
|
end
|
data/lib/beaker/host/mac/exec.rb
CHANGED
@@ -113,7 +113,7 @@ module Windows::Exec
|
|
113
113
|
#
|
114
114
|
# @return [Boolean]
|
115
115
|
def cygwin_installed?
|
116
|
-
output = exec(Beaker::Command.new('cygcheck --check-setup cygwin'), :accept_all_exit_codes => true).stdout
|
116
|
+
output = exec(Beaker::Command.new('cygcheck --check-setup cygwin'), :accept_all_exit_codes => true).stdout
|
117
117
|
return true if output.match(/cygwin/) && output.match(/OK/)
|
118
118
|
false
|
119
119
|
end
|
@@ -432,6 +432,9 @@ module Beaker
|
|
432
432
|
elsif host['platform'] =~ /solaris-11/
|
433
433
|
host.exec(Command.new("if grep \"root::::type=role\" /etc/user_attr; then sudo rolemod -K type=normal root; else echo \"root user already type=normal\"; fi"), {:pty => true} )
|
434
434
|
host.exec(Command.new("sudo gsed -i -e 's/PermitRootLogin no/PermitRootLogin yes/g' /etc/ssh/sshd_config"), {:pty => true} )
|
435
|
+
elsif host['platform'] =~ /f5/
|
436
|
+
#interacting with f5 should using tmsh
|
437
|
+
logger.warn("Attempting to enable root login non-supported platform: #{host.name}: #{host['platform']}")
|
435
438
|
elsif host.is_cygwin?
|
436
439
|
host.exec(Command.new("sed -ri 's/^#?PermitRootLogin /PermitRootLogin yes/' /etc/sshd_config"), {:pty => true})
|
437
440
|
elsif host.is_powershell?
|
@@ -14,12 +14,17 @@ module Beaker
|
|
14
14
|
# @raise [ArgumentError] Raises if hosts_file_path is not a valid YAML file
|
15
15
|
# @raise [Errno::ENOENT] File not found error: hosts_file doesn't exist
|
16
16
|
def self.parse_hosts_file(hosts_file_path = nil)
|
17
|
+
require 'erb'
|
18
|
+
|
17
19
|
host_options = new_host_options
|
18
20
|
return host_options unless hosts_file_path
|
19
21
|
error_message = "#{hosts_file_path} is not a valid YAML file\n\t"
|
20
22
|
host_options = self.merge_hosts_yaml( host_options, error_message ) {
|
21
23
|
hosts_file_path = File.expand_path( hosts_file_path )
|
22
|
-
|
24
|
+
|
25
|
+
raise "#{hosts_file_path} is not a valid path" unless File.exist?(hosts_file_path)
|
26
|
+
|
27
|
+
YAML.load(ERB.new(File.read(hosts_file_path), nil, '-').result(binding))
|
23
28
|
}
|
24
29
|
fix_roles_array( host_options )
|
25
30
|
end
|
@@ -31,11 +36,13 @@ module Beaker
|
|
31
36
|
# @return [OptionsHash] Contents of the hosts file as an OptionsHash
|
32
37
|
# @raise [ArgumentError] If hosts_def_yaml is not a valid YAML string
|
33
38
|
def self.parse_hosts_string(hosts_def_yaml = nil)
|
39
|
+
require 'erb'
|
40
|
+
|
34
41
|
host_options = new_host_options
|
35
42
|
return host_options unless hosts_def_yaml
|
36
43
|
error_message = "#{hosts_def_yaml}\nis not a valid YAML string\n\t"
|
37
44
|
host_options = self.merge_hosts_yaml( host_options, error_message ) {
|
38
|
-
YAML.load(
|
45
|
+
YAML.load(ERB.new(hosts_def_yaml, nil, '-').result(binding))
|
39
46
|
}
|
40
47
|
fix_roles_array( host_options )
|
41
48
|
end
|
@@ -171,7 +171,7 @@ module Beaker
|
|
171
171
|
|
172
172
|
# Update the @attribution hash with the source of each key in the options_hash
|
173
173
|
#
|
174
|
-
# @param [Hash] options_hash Options hash
|
174
|
+
# @param [Hash] options_hash Options hash
|
175
175
|
# @param [String] source Where the options were specified
|
176
176
|
# @return [Hash] hash Hash of sources for each key
|
177
177
|
def tag_sources(options_hash, source)
|
@@ -3,25 +3,25 @@ module Beaker
|
|
3
3
|
# Methods for parsing options.
|
4
4
|
module OptionsResolver
|
5
5
|
# parses local and global options to determine if a particular mode should
|
6
|
-
# be run in parallel. typically, local_options will specify a true/false
|
6
|
+
# be run in parallel. typically, local_options will specify a true/false
|
7
7
|
# value, while global_options will specify an array of mode names that should
|
8
8
|
# be run in parallel. the value specified in local_options will take precedence
|
9
|
-
# over the values specified in global_options.
|
9
|
+
# over the values specified in global_options.
|
10
10
|
# @param [Hash] local_options local options for running in parallel
|
11
11
|
# @option local_options [Boolean] :run_in_parallel flag for running in parallel
|
12
12
|
# @param [Hash] global_options global options for running in parallel
|
13
13
|
# @option global_options [Array<String>] :run_in_parallel list of modes to run in parallel
|
14
14
|
# @param [String] mode the mode we want to query global_options for
|
15
|
-
# @return [Boolean] true if the specified mode is in global_options and :run_in_parallel in local_options is not false,
|
15
|
+
# @return [Boolean] true if the specified mode is in global_options and :run_in_parallel in local_options is not false,
|
16
16
|
# or if :run_in_parallel in local_options is true, false otherwise
|
17
17
|
# @example
|
18
|
-
# run_in_parallel?({:run_in_parallel => true})
|
18
|
+
# run_in_parallel?({:run_in_parallel => true})
|
19
19
|
# -> will return true
|
20
20
|
#
|
21
|
-
# run_in_parallel?({:run_in_parallel => true}, {:run_in_parallel => ['install','configure']}, 'install')
|
21
|
+
# run_in_parallel?({:run_in_parallel => true}, {:run_in_parallel => ['install','configure']}, 'install')
|
22
22
|
# -> will return true
|
23
23
|
#
|
24
|
-
# run_in_parallel?({:run_in_parallel => false}, {:run_in_parallel => ['install','configure']}, 'install')
|
24
|
+
# run_in_parallel?({:run_in_parallel => false}, {:run_in_parallel => ['install','configure']}, 'install')
|
25
25
|
# -> will return false
|
26
26
|
def run_in_parallel?(local_options=nil, global_options=nil, mode=nil)
|
27
27
|
run_in_parallel = local_options[:run_in_parallel] unless local_options.nil?
|
data/lib/beaker/subcommand.rb
CHANGED
@@ -6,6 +6,7 @@ module Beaker
|
|
6
6
|
class Subcommand < Thor
|
7
7
|
SubcommandUtil = Beaker::Subcommands::SubcommandUtil
|
8
8
|
|
9
|
+
attr_reader :cli
|
9
10
|
|
10
11
|
def initialize(*args)
|
11
12
|
super
|
@@ -171,8 +172,9 @@ module Beaker
|
|
171
172
|
end
|
172
173
|
|
173
174
|
beaker_suites = [:pre_suite, :tests, :post_suite, :pre_cleanup]
|
174
|
-
|
175
|
-
|
175
|
+
resources = resource.split(',')
|
176
|
+
paths = resources.map { |r| Pathname(r) }
|
177
|
+
if paths.all?(&:exist?)
|
176
178
|
# If we determine the resource is a valid file resource, then we empty
|
177
179
|
# all the suites and run that file resource in the tests suite. In the
|
178
180
|
# future, when we have the ability to have custom suites, we should change
|
@@ -180,12 +182,14 @@ module Beaker
|
|
180
182
|
beaker_suites.each do |suite|
|
181
183
|
@cli.options[suite] = []
|
182
184
|
end
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
185
|
+
@cli.options[:tests] = paths.map do |path|
|
186
|
+
if path.directory?
|
187
|
+
Dir.glob("#{path}/**/*.rb")
|
188
|
+
else
|
189
|
+
path.to_s
|
190
|
+
end
|
191
|
+
end.flatten
|
192
|
+
elsif resources.all? { |r| r =~ /^(pre-suite|tests|post-suite|pre-cleanup)$/ }
|
189
193
|
# The regex match here is loose so that users can supply multiple suites,
|
190
194
|
# such as `beaker exec pre-suite,tests`.
|
191
195
|
beaker_suites.each do |suite|
|
@@ -194,6 +198,7 @@ module Beaker
|
|
194
198
|
else
|
195
199
|
raise ArgumentError, "Unable to parse #{resource} with beaker exec"
|
196
200
|
end
|
201
|
+
|
197
202
|
@cli.execute!
|
198
203
|
end
|
199
204
|
|
@@ -50,11 +50,11 @@ namespace :beaker_quickstart do
|
|
50
50
|
|
51
51
|
desc 'Generate Default Smoke Test'
|
52
52
|
task :gen_smoke_test do
|
53
|
-
smoke_test_file = "acceptance/
|
53
|
+
smoke_test_file = "acceptance/tests/default_smoke_test.rb"
|
54
54
|
FileUtils.mkdir_p('acceptance/tests') # -p ignores when dir already exists
|
55
55
|
if !File.exist?(smoke_test_file) then
|
56
56
|
puts "Writing default smoke test to file - #{smoke_test_file}"
|
57
|
-
File.open(
|
57
|
+
File.open(smoke_test_file, 'w') do |fh|
|
58
58
|
fh.print("test_name 'puppet install smoketest' do
|
59
59
|
step 'puppet install smoketest: verify \\'puppet help\\' can be successfully called on
|
60
60
|
all hosts' do
|
data/lib/beaker/version.rb
CHANGED
@@ -102,7 +102,7 @@ module Beaker
|
|
102
102
|
describe '#ssh_service_restart' do
|
103
103
|
PlatformHelpers::SYSTEMDPLATFORMS.each do |platform|
|
104
104
|
it "calls the correct command for #{platform}" do
|
105
|
-
opts['platform'] = platform
|
105
|
+
opts['platform'] = platform
|
106
106
|
expect(instance).to receive(:exec)
|
107
107
|
expect(Beaker::Command).to receive(:new).with("systemctl restart sshd.service")
|
108
108
|
expect{instance.ssh_service_restart}.to_not raise_error
|
@@ -28,14 +28,14 @@ module Beaker
|
|
28
28
|
|
29
29
|
it "raises an error on no file found" do
|
30
30
|
FakeFS.deactivate!
|
31
|
-
expect{parser.parse_hosts_file("not a valid path")}.to raise_error(
|
31
|
+
expect{parser.parse_hosts_file("not a valid path")}.to raise_error(/is not a valid path/)
|
32
32
|
end
|
33
33
|
|
34
34
|
it "raises an error on bad yaml file" do
|
35
35
|
FakeFS.deactivate!
|
36
|
-
|
37
|
-
|
38
|
-
expect { parser.parse_hosts_file("not a valid path") }.to raise_error(
|
36
|
+
expect( File ).to receive(:exist?).and_return(true)
|
37
|
+
|
38
|
+
expect { parser.parse_hosts_file("not a valid path") }.to raise_error(Errno::ENOENT)
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'returns a #new_host_options hash if given no arguments' do
|
@@ -43,12 +43,20 @@ module Beaker
|
|
43
43
|
expect( host_options ).to be === parser.new_host_options
|
44
44
|
end
|
45
45
|
|
46
|
-
it 'passes a YAML.
|
46
|
+
it 'passes a YAML.load call through to #merge_hosts_yaml' do
|
47
47
|
yaml_string = 'not actually yaml, but that wont matter'
|
48
|
-
|
49
|
-
expect(
|
48
|
+
expect( File ).to receive( :exist?).and_return(true)
|
49
|
+
expect( File ).to receive( :read ).and_return(yaml_string)
|
50
50
|
parser.parse_hosts_file( yaml_string )
|
51
51
|
end
|
52
|
+
|
53
|
+
it 'processes ERB in the host YAML successfully' do
|
54
|
+
yaml_string = '1 plus 2: <%= 1 + 2 %>'
|
55
|
+
expect( File ).to receive( :exist?).and_return(true)
|
56
|
+
expect( File ).to receive( :read ).and_return(yaml_string)
|
57
|
+
beaker_options_hash = parser.parse_hosts_file( yaml_string )
|
58
|
+
expect(beaker_options_hash['1 plus 2']).to eq(3)
|
59
|
+
end
|
52
60
|
end
|
53
61
|
|
54
62
|
describe '#parse_hosts_string' do
|
@@ -19,14 +19,14 @@ module Beaker
|
|
19
19
|
ex = Exception.new("ArgumentError")
|
20
20
|
allow( ex ).to receive( :backtrace ).and_return(backtrace)
|
21
21
|
mesg = "I'm the extra message"
|
22
|
-
|
22
|
+
|
23
23
|
backtrace.each_line do |line|
|
24
24
|
expect( logger ).to receive( :error ).with(line)
|
25
25
|
end
|
26
26
|
|
27
27
|
expect( subject ).to receive( :raise ).once
|
28
28
|
|
29
|
-
subject.report_and_raise(logger, ex, mesg)
|
29
|
+
subject.report_and_raise(logger, ex, mesg)
|
30
30
|
|
31
31
|
end
|
32
32
|
|
@@ -10,7 +10,7 @@ module Beaker
|
|
10
10
|
|
11
11
|
block = double( 'block' )
|
12
12
|
expect( block ).to receive( :exec ).exactly( 5 ).times.and_return( false )
|
13
|
-
|
13
|
+
|
14
14
|
subject.repeat_for( 5 ) do
|
15
15
|
block.exec
|
16
16
|
end
|
@@ -21,7 +21,7 @@ module Beaker
|
|
21
21
|
|
22
22
|
block = double( 'block' )
|
23
23
|
expect( block ).to receive( :exec ).once.and_return( true )
|
24
|
-
|
24
|
+
|
25
25
|
subject.repeat_for( 5 ) do
|
26
26
|
block.exec
|
27
27
|
end
|
@@ -9,9 +9,9 @@ module Beaker
|
|
9
9
|
|
10
10
|
context '#initialize' do
|
11
11
|
it 'creates a cli object' do
|
12
|
-
expect(
|
13
|
-
subcommand
|
12
|
+
expect(subcommand.cli).to be
|
14
13
|
end
|
14
|
+
|
15
15
|
describe 'File operation initialization for subcommands' do
|
16
16
|
it 'checks to ensure subcommand file resources exist' do
|
17
17
|
expect(FileUtils).to receive(:mkdir_p).with(SubcommandUtil::CONFIG_DIR)
|
@@ -28,7 +28,6 @@ module Beaker
|
|
28
28
|
expect(FileUtils).to receive(:touch).with(SubcommandUtil::SUBCOMMAND_STATE)
|
29
29
|
subcommand
|
30
30
|
end
|
31
|
-
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
@@ -80,6 +79,9 @@ module Beaker
|
|
80
79
|
|
81
80
|
it 'should not error with valid beaker options' do
|
82
81
|
beaker_options_list.each do |option|
|
82
|
+
allow_any_instance_of(Beaker::CLI).to receive(:parse_options)
|
83
|
+
allow_any_instance_of(Beaker::CLI).to receive(:configured_options).and_return({})
|
84
|
+
|
83
85
|
allow(YAML::Store).to receive(:new).with(SubcommandUtil::SUBCOMMAND_STATE).and_return(yaml_store_mock)
|
84
86
|
allow(yaml_store_mock).to receive(:transaction).and_yield
|
85
87
|
allow(yaml_store_mock).to receive(:[]=).with('provisioned', false)
|
@@ -87,6 +89,7 @@ module Beaker
|
|
87
89
|
allow_any_instance_of(Beaker::Logger).to receive(:notify).twice
|
88
90
|
expect(SubcommandUtil::SUBCOMMAND_OPTIONS).to receive(:exist?).and_return(true)
|
89
91
|
expect(SubcommandUtil::SUBCOMMAND_STATE).to receive(:exist?).and_return(true)
|
92
|
+
|
90
93
|
expect {Beaker::Subcommand.start(['init', '--hosts', 'centos', "--#{option}"])}.to_not output(/ERROR/).to_stderr
|
91
94
|
end
|
92
95
|
end
|
@@ -103,13 +106,16 @@ module Beaker
|
|
103
106
|
end
|
104
107
|
|
105
108
|
context '#init' do
|
106
|
-
let( :cli ) { subcommand.
|
109
|
+
let( :cli ) { subcommand.cli }
|
107
110
|
let( :mock_options ) { {:timestamp => 'noon', :other_key => 'cordite'}}
|
108
111
|
let( :yaml_store_mock ) { double('yaml_store_mock') }
|
109
|
-
|
110
|
-
|
112
|
+
|
113
|
+
before :each do
|
114
|
+
allow(cli).to receive(:parse_options)
|
111
115
|
allow(cli).to receive(:configured_options).and_return(mock_options)
|
116
|
+
end
|
112
117
|
|
118
|
+
it 'calculates options and writes them to disk and deletes the' do
|
113
119
|
allow(File).to receive(:open)
|
114
120
|
allow(YAML::Store).to receive(:new).with(SubcommandUtil::SUBCOMMAND_STATE).and_return(yaml_store_mock)
|
115
121
|
allow(yaml_store_mock).to receive(:transaction).and_yield
|
@@ -117,13 +123,14 @@ module Beaker
|
|
117
123
|
subcommand.init
|
118
124
|
expect(mock_options).not_to have_key(:timestamp)
|
119
125
|
end
|
126
|
+
|
120
127
|
it 'requires hosts flag' do
|
121
128
|
expect{subcommand.init}.to raise_error(NotImplementedError)
|
122
129
|
end
|
123
130
|
end
|
124
131
|
|
125
132
|
context '#provision' do
|
126
|
-
let ( :cli ) { subcommand.
|
133
|
+
let ( :cli ) { subcommand.cli }
|
127
134
|
let( :yaml_store_mock ) { double('yaml_store_mock') }
|
128
135
|
let ( :host_hash ) { {'mynode.net' => {:name => 'mynode', :platform => Beaker::Platform.new('centos-6-x86_64')}}}
|
129
136
|
let ( :cleaned_hosts ) {double()}
|
@@ -133,6 +140,7 @@ module Beaker
|
|
133
140
|
let ( :hosts) {double('hosts')}
|
134
141
|
let ( :hypervisors) {double('hypervisors')}
|
135
142
|
let (:options) {double ('options')}
|
143
|
+
|
136
144
|
it 'provisions the host and saves the host info' do
|
137
145
|
expect(YAML::Store).to receive(:new).with(SubcommandUtil::SUBCOMMAND_STATE).and_return(yaml_store_mock)
|
138
146
|
allow(yaml_store_mock).to receive(:[]).and_return(false)
|
@@ -157,59 +165,103 @@ module Beaker
|
|
157
165
|
expect(yaml_store_mock).to receive(:[]=).with('provisioned', true)
|
158
166
|
subcommand.provision
|
159
167
|
end
|
168
|
+
|
160
169
|
it 'does not allow hosts to be passed' do
|
161
170
|
subcommand.options = {:hosts => "myhost"}
|
162
171
|
expect{subcommand.provision()}.to raise_error(NotImplementedError)
|
163
172
|
end
|
164
173
|
end
|
165
174
|
|
166
|
-
|
167
175
|
context 'exec' do
|
176
|
+
before :each do
|
177
|
+
allow(subcommand.cli).to receive(:parse_options)
|
178
|
+
allow(subcommand.cli).to receive(:initialize_network_manager)
|
179
|
+
end
|
180
|
+
|
168
181
|
it 'calls execute! when no resource is given' do
|
169
182
|
expect_any_instance_of(Pathname).to_not receive(:directory?)
|
170
183
|
expect_any_instance_of(Pathname).to_not receive(:exist?)
|
171
|
-
|
172
|
-
expect_any_instance_of(Beaker::CLI).to receive(:initialize_network_manager).once
|
173
|
-
expect_any_instance_of(Beaker::CLI).to receive(:execute!).once
|
184
|
+
expect(subcommand.cli).to receive(:execute!).once
|
174
185
|
expect{subcommand.exec}.to_not raise_error
|
175
186
|
end
|
176
187
|
|
177
|
-
it '
|
188
|
+
it 'allows hard coded suite names to be specified' do
|
189
|
+
subcommand.cli.options[:pre_suite] = %w[step1.rb]
|
190
|
+
subcommand.cli.options[:post_suite] = %w[step2.rb]
|
191
|
+
subcommand.cli.options[:tests] = %w[tests/1.rb]
|
192
|
+
|
193
|
+
subcommand.exec('pre-suite,tests')
|
194
|
+
|
195
|
+
expect(subcommand.cli.options[:pre_suite]).to eq(%w[step1.rb])
|
196
|
+
expect(subcommand.cli.options[:post_suite]).to eq([])
|
197
|
+
expect(subcommand.cli.options[:tests]).to eq(%w[tests/1.rb])
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'errors when a resource is neither a valid file resource or suite name' do
|
201
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(false)
|
202
|
+
expect{subcommand.exec('blahblahblah')}.to raise_error(ArgumentError)
|
203
|
+
end
|
178
204
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
205
|
+
it 'accepts a tests directory, clearing all other suites' do
|
206
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
207
|
+
allow_any_instance_of(Pathname).to receive(:directory?).and_return(true)
|
208
|
+
allow(Dir).to receive(:glob)
|
209
|
+
.with('tests/**/*.rb')
|
210
|
+
.and_return(%w[tests/a.rb tests/b/c.rb])
|
211
|
+
|
212
|
+
subcommand.exec('tests')
|
213
|
+
|
214
|
+
expect(subcommand.cli.options[:pre_suite]).to eq([])
|
215
|
+
expect(subcommand.cli.options[:post_suite]).to eq([])
|
216
|
+
expect(subcommand.cli.options[:pre_cleanup]).to eq([])
|
217
|
+
expect(subcommand.cli.options[:tests]).to eq(%w[tests/a.rb tests/b/c.rb])
|
183
218
|
end
|
184
219
|
|
185
|
-
it '
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
220
|
+
it 'accepts comma-separated list of tests, clearing all other suites' do
|
221
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
222
|
+
allow_any_instance_of(Pathname).to receive(:file?).and_return(true)
|
223
|
+
|
224
|
+
subcommand.exec('tests/1.rb,tests/2.rb')
|
225
|
+
|
226
|
+
expect(subcommand.cli.options[:pre_suite]).to eq([])
|
227
|
+
expect(subcommand.cli.options[:post_suite]).to eq([])
|
228
|
+
expect(subcommand.cli.options[:pre_cleanup]).to eq([])
|
229
|
+
expect(subcommand.cli.options[:tests]).to eq(%w[tests/1.rb tests/2.rb])
|
191
230
|
end
|
192
231
|
|
193
|
-
it '
|
232
|
+
it 'accepts comma-separated list of directories, recursively scanning each' do
|
233
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
234
|
+
allow_any_instance_of(Pathname).to receive(:directory?).and_return(true)
|
235
|
+
allow(Dir).to receive(:glob).with('tests/a/**/*.rb').and_return(%w[tests/a/x.rb])
|
236
|
+
allow(Dir).to receive(:glob).with('tests/b/**/*.rb').and_return(%w[tests/b/x/y.rb tests/b/x/z.rb])
|
194
237
|
|
195
|
-
|
196
|
-
|
197
|
-
expect
|
238
|
+
subcommand.exec('tests/a,tests/b')
|
239
|
+
|
240
|
+
expect(subcommand.cli.options[:tests]).to eq(%w[tests/a/x.rb tests/b/x/y.rb tests/b/x/z.rb])
|
198
241
|
end
|
199
242
|
|
200
|
-
it '
|
243
|
+
it 'rejects comma-separated file and suite name' do
|
201
244
|
allow_any_instance_of(Pathname).to receive(:exist?).and_return(false)
|
202
|
-
|
245
|
+
|
246
|
+
expect {
|
247
|
+
subcommand.exec('pre-suite,tests/whoops')
|
248
|
+
}.to raise_error(ArgumentError, %r{Unable to parse pre-suite,tests/whoops})
|
203
249
|
end
|
204
250
|
end
|
205
251
|
|
206
252
|
context 'destroy' do
|
207
|
-
let( :cli ) { subcommand.
|
253
|
+
let( :cli ) { subcommand.cli }
|
208
254
|
let( :mock_options ) { {:timestamp => 'noon', :other_key => 'cordite'}}
|
209
255
|
let( :yaml_store_mock ) { double('yaml_store_mock') }
|
256
|
+
let( :network_manager) {double('network_manager')}
|
257
|
+
|
210
258
|
it 'calls destroy and updates the yaml store' do
|
259
|
+
allow(cli).to receive(:parse_options)
|
260
|
+
allow(cli).to receive(:initialize_network_manager)
|
261
|
+
allow(cli).to receive(:network_manager).and_return(network_manager)
|
262
|
+
expect(network_manager).to receive(:cleanup)
|
263
|
+
|
211
264
|
expect(YAML::Store).to receive(:new).with(SubcommandUtil::SUBCOMMAND_STATE).and_return(yaml_store_mock)
|
212
|
-
allow(SubcommandUtil).to receive(:cleanup).with(cli).and_return(true)
|
213
265
|
allow(yaml_store_mock).to receive(:transaction).and_yield
|
214
266
|
allow(yaml_store_mock).to receive(:[]).with('provisioned').and_return(true)
|
215
267
|
allow(yaml_store_mock).to receive(:delete).with('provisioned').and_return(true)
|