beaker 4.23.0 → 4.26.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -1
- data/lib/beaker/host.rb +6 -1
- data/lib/beaker/host/pswindows/exec.rb +18 -3
- data/lib/beaker/host/pswindows/file.rb +3 -3
- data/lib/beaker/host/unix/exec.rb +35 -40
- data/lib/beaker/host/windows/exec.rb +19 -0
- data/lib/beaker/local_connection.rb +86 -0
- data/lib/beaker/ssh_connection.rb +10 -0
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/host/pswindows/exec_spec.rb +54 -0
- data/spec/beaker/host/pswindows/file_spec.rb +23 -4
- data/spec/beaker/host/unix/exec_spec.rb +24 -32
- data/spec/beaker/host/windows/exec_spec.rb +18 -0
- data/spec/beaker/host_spec.rb +7 -1
- data/spec/beaker/localhost_connection_spec.rb +106 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c39df762f99d0590a8a754edc8d6a3a411137df0980823ac7d008eda11f3a81d
|
4
|
+
data.tar.gz: 9e43461bed058372c69307cd73e69b0d8e72998a93fcd5dae345cb9a96aa09c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9abeaeb61ef396755e86fc5659ff252d7d7a3bf9fee664fab97411bce22313912e254708cd64ded4c6501d10d853ac2b5c58806be109113d6ba885350b87a7d5
|
7
|
+
data.tar.gz: a1e6c0542a97715a9d0cf50247b3625fc5e9936137a37235374cc0853e15b0b6726838034f4c5da8327bd00bdd2bf056310754c1993bbe26f4114ebe5501acea
|
data/CHANGELOG.md
CHANGED
@@ -20,7 +20,41 @@ The headers used in [Keep a Changelog](http://keepachangelog.com) are:
|
|
20
20
|
- Fixed - for any bug fixes.
|
21
21
|
- Security - in case of vulnerabilities.
|
22
22
|
|
23
|
-
# [Unreleased](https://github.com/puppetlabs/beaker/compare/4.
|
23
|
+
# [Unreleased](https://github.com/puppetlabs/beaker/compare/4.25.0...master)
|
24
|
+
|
25
|
+
# [4.25.0](https://github.com/puppetlabs/beaker/compare/4.24.0...4.25.0)
|
26
|
+
|
27
|
+
### Added
|
28
|
+
|
29
|
+
- Execution of Beaker directly through ruby on localhost #1637 ([#1637](https://github.com/puppetlabs/beaker/pull/1637))
|
30
|
+
|
31
|
+
### Fixed
|
32
|
+
|
33
|
+
- Reliability improvements to the `Host#reboot` method ([#1656](https://github.com/puppetlabs/beaker/pull/1656)) ([#1659](https://github.com/puppetlabs/beaker/pull/1659))
|
34
|
+
|
35
|
+
# [4.24.0](https://github.com/puppetlabs/beaker/compare/4.23.0...4.24.0) - 2020-06-05
|
36
|
+
|
37
|
+
### Added
|
38
|
+
|
39
|
+
- Host method which ([#1651](https://github.com/puppetlabs/beaker/pull/1651))
|
40
|
+
|
41
|
+
### Fixed
|
42
|
+
|
43
|
+
- Fixed implementation for cat and file_exists? host methods for PSWindows ([#1654](https://github.com/puppetlabs/beaker/pull/1654))
|
44
|
+
- Fixed implementation for mkdir_p host method for PSWindows ([#1657](https://github.com/puppetlabs/beaker/pull/1657))
|
45
|
+
|
46
|
+
# [4.23.2](https://github.com/puppetlabs/beaker/compare/4.23.1...4.23.2)
|
47
|
+
|
48
|
+
### Fixed
|
49
|
+
|
50
|
+
- Fixed Beaker's behavior when the `strict_host_key_checking` option is
|
51
|
+
provided in the SSH config and Net-SSH > 5 is specified. (#1652)
|
52
|
+
|
53
|
+
# [4.23.1](https://github.com/puppetlabs/beaker/compare/4.23.0...4.23.1)
|
54
|
+
|
55
|
+
### Changed/Removed
|
56
|
+
|
57
|
+
- Reversed the quoting changes on Unix from #1644 in favor of only quoting on Windows. (#1650)
|
24
58
|
|
25
59
|
# [4.23.0](https://github.com/puppetlabs/beaker/compare/4.22.1...4.23.0)
|
26
60
|
|
data/lib/beaker/host.rb
CHANGED
@@ -6,7 +6,7 @@ require 'rsync'
|
|
6
6
|
require 'beaker/dsl/helpers'
|
7
7
|
require 'beaker/dsl/patterns'
|
8
8
|
|
9
|
-
[ 'command', 'ssh_connection'].each do |lib|
|
9
|
+
[ 'command', 'ssh_connection', 'local_connection' ].each do |lib|
|
10
10
|
require "beaker/#{lib}"
|
11
11
|
end
|
12
12
|
|
@@ -294,6 +294,11 @@ module Beaker
|
|
294
294
|
|
295
295
|
def connection
|
296
296
|
# create new connection object if necessary
|
297
|
+
if self['hypervisor'] == 'none' && @name == 'localhost'
|
298
|
+
@connection ||= LocalConnection.connect( { :ssh_env_file => self['ssh_env_file'], :logger => @logger })
|
299
|
+
return @connection
|
300
|
+
end
|
301
|
+
|
297
302
|
@connection ||= SshConnection.connect( { :ip => self['ip'], :vmhostname => self['vmhostname'], :hostname => @name },
|
298
303
|
self['user'],
|
299
304
|
self['ssh'], { :logger => @logger, :ssh_connection_preference => self[:ssh_connection_preference]} )
|
@@ -104,9 +104,9 @@ module PSWindows::Exec
|
|
104
104
|
# @param [String] dir The directory structure to create on the host
|
105
105
|
# @return [Boolean] True, if directory construction succeeded, otherwise False
|
106
106
|
def mkdir_p dir
|
107
|
-
|
108
|
-
|
109
|
-
|
107
|
+
normalized_path = dir.gsub('/','\\')
|
108
|
+
result = exec(powershell("New-Item -Path '#{normalized_path}' -ItemType 'directory'"),
|
109
|
+
:acceptable_exit_codes => [0, 1])
|
110
110
|
result.exit_code == 0
|
111
111
|
end
|
112
112
|
|
@@ -237,4 +237,19 @@ module PSWindows::Exec
|
|
237
237
|
end
|
238
238
|
end
|
239
239
|
|
240
|
+
#First path it finds for the command executable
|
241
|
+
#@param [String] command The command executable to search for
|
242
|
+
#
|
243
|
+
# @return [String] Path to the searched executable or empty string if not found
|
244
|
+
#
|
245
|
+
#@example
|
246
|
+
# host.which('ruby')
|
247
|
+
def which(command)
|
248
|
+
where_command = "cmd /C \"where #{command}\""
|
249
|
+
|
250
|
+
result = execute(where_command, :accept_all_exit_codes => true)
|
251
|
+
return '' if result.empty?
|
252
|
+
|
253
|
+
result
|
254
|
+
end
|
240
255
|
end
|
@@ -21,11 +21,11 @@ module PSWindows::File
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def cat(path)
|
24
|
-
exec(powershell("type #{path}"))
|
24
|
+
exec(powershell("type #{path}")).stdout
|
25
25
|
end
|
26
26
|
|
27
27
|
def file_exist?(path)
|
28
|
-
result = exec(Beaker::Command.new("if exist #{path} echo true"), :
|
29
|
-
result.stdout
|
28
|
+
result = exec(Beaker::Command.new("if exist #{path} echo true"), accept_all_exit_codes: true)
|
29
|
+
result.stdout.strip == 'true'
|
30
30
|
end
|
31
31
|
end
|
@@ -14,15 +14,27 @@ module Unix::Exec
|
|
14
14
|
def reboot(wait_time=10, max_connection_tries=9, uptime_retries=18)
|
15
15
|
require 'time'
|
16
16
|
|
17
|
+
attempts = 0
|
18
|
+
|
19
|
+
original_boot_time_str = nil
|
20
|
+
original_boot_time_line = nil
|
17
21
|
begin
|
18
22
|
original_boot_time_str = exec(Beaker::Command.new('who -b'), {:max_connection_tries => max_connection_tries, :silent => true}).stdout
|
19
23
|
original_boot_time_line = original_boot_time_str.lines.grep(/boot/).first
|
20
24
|
|
21
|
-
raise Beaker::Host::RebootFailure, "Could not find system boot time using 'who -b': #{original_boot_time_str}" unless original_boot_time_line
|
25
|
+
raise Beaker::Host::RebootFailure, "Could not find system boot time using 'who -b': '#{original_boot_time_str}'" unless original_boot_time_line
|
22
26
|
|
23
27
|
original_boot_time = Time.parse(original_boot_time_line)
|
24
28
|
|
25
29
|
exec(Beaker::Command.new('/bin/systemctl reboot -i || reboot || /sbin/shutdown -r now'), :expect_connection_failure => true)
|
30
|
+
rescue Beaker::Host::RebootFailure => e
|
31
|
+
attempts += 1
|
32
|
+
if attempts < uptime_retries
|
33
|
+
@logger.debug("Could not get initial boot time. Will retry #{uptime_retries - attempts} more times.")
|
34
|
+
retry
|
35
|
+
else
|
36
|
+
raise
|
37
|
+
end
|
26
38
|
rescue Beaker::Host::CommandFailure => e
|
27
39
|
raise Beaker::Host::RebootFailure, "Command failed when attempting to reboot: #{e.message}"
|
28
40
|
rescue RuntimeError => e
|
@@ -38,7 +50,11 @@ module Unix::Exec
|
|
38
50
|
sleep wait_time
|
39
51
|
|
40
52
|
current_boot_time_str = exec(Beaker::Command.new('who -b'), {:max_connection_tries => max_connection_tries, :silent => true}).stdout
|
41
|
-
|
53
|
+
current_boot_time_line = current_boot_time_str.lines.grep(/boot/).first
|
54
|
+
|
55
|
+
raise Beaker::Host::RebootFailure, "Could not find system boot time using 'who -b': '#{current_boot_time_str}'" unless current_boot_time_line
|
56
|
+
|
57
|
+
current_boot_time = Time.parse(current_boot_time_line)
|
42
58
|
|
43
59
|
@logger.debug("Original Boot Time: #{original_boot_time}")
|
44
60
|
@logger.debug("Current Boot Time: #{current_boot_time}")
|
@@ -63,42 +79,6 @@ module Unix::Exec
|
|
63
79
|
end
|
64
80
|
end
|
65
81
|
|
66
|
-
def uptime_int(uptime_str)
|
67
|
-
time_array = uptime_str.split(", ")
|
68
|
-
accumulated_mins = 0
|
69
|
-
time_array.each do |time_segment|
|
70
|
-
value, unit = time_segment.split
|
71
|
-
if unit.nil?
|
72
|
-
# 20:47 case: hours & mins
|
73
|
-
hours, mins = value.split(":")
|
74
|
-
accumulated_mins += (hours.to_i * 60 + mins.to_i)
|
75
|
-
elsif unit =~ /day(s)?/
|
76
|
-
accumulated_mins += (value.to_i * 1440) # 60 * 24 = 1440
|
77
|
-
elsif unit =~ /min(s)?/
|
78
|
-
accumulated_mins += value.to_i
|
79
|
-
else
|
80
|
-
raise ArgumentError, "can't parse uptime segment: #{time_segment}"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
accumulated_mins
|
85
|
-
end
|
86
|
-
|
87
|
-
def parse_uptime(uptime)
|
88
|
-
# get String from up to users
|
89
|
-
# eg 19:52 up 14 mins, 2 users, load averages: 2.95 4.19 4.31
|
90
|
-
# 8:03 up 52 days, 20:47, 3 users, load averages: 1.36 1.42 1.40
|
91
|
-
# 22:19 up 54 days, 1 min, 4 users, load averages: 2.08 2.06 2.27
|
92
|
-
regexp = /.*up (.*)[[:space:]]+[[:digit:]]+ user.*/
|
93
|
-
result = uptime.match regexp
|
94
|
-
if self['platform'] =~ /solaris-/ && result[1].empty?
|
95
|
-
return "0 min"
|
96
|
-
end
|
97
|
-
raise "Couldn't parse uptime: #{uptime}" if result.nil?
|
98
|
-
|
99
|
-
result[1].strip.chomp(",")
|
100
|
-
end
|
101
|
-
|
102
82
|
def echo(msg, abs=true)
|
103
83
|
(abs ? '/bin/echo' : 'echo') + " #{msg}"
|
104
84
|
end
|
@@ -133,7 +113,7 @@ module Unix::Exec
|
|
133
113
|
# @param [String] dir The directory structure to create on the host
|
134
114
|
# @return [Boolean] True, if directory construction succeeded, otherwise False
|
135
115
|
def mkdir_p dir
|
136
|
-
cmd = "mkdir -p
|
116
|
+
cmd = "mkdir -p #{dir}"
|
137
117
|
result = exec(Beaker::Command.new(cmd), :acceptable_exit_codes => [0, 1])
|
138
118
|
result.exit_code == 0
|
139
119
|
end
|
@@ -150,7 +130,7 @@ module Unix::Exec
|
|
150
130
|
# @param [Boolean] rm Remove the destination prior to move
|
151
131
|
def mv orig, dest, rm=true
|
152
132
|
rm_rf dest unless !rm
|
153
|
-
execute("mv
|
133
|
+
execute("mv #{orig} #{dest}")
|
154
134
|
end
|
155
135
|
|
156
136
|
# Attempt to ping the provided target hostname
|
@@ -435,4 +415,19 @@ module Unix::Exec
|
|
435
415
|
true
|
436
416
|
end
|
437
417
|
|
418
|
+
#First path it finds for the command executable
|
419
|
+
#@param [String] command The command executable to search for
|
420
|
+
#
|
421
|
+
# @return [String] Path to the searched executable or empty string if not found
|
422
|
+
#
|
423
|
+
#@example
|
424
|
+
# host.which('ruby')
|
425
|
+
def which(command)
|
426
|
+
which_command = "which #{command}"
|
427
|
+
|
428
|
+
result = execute(which_command, :accept_all_exit_codes => true)
|
429
|
+
return '' if result.empty?
|
430
|
+
|
431
|
+
result
|
432
|
+
end
|
438
433
|
end
|
@@ -119,6 +119,25 @@ module Windows::Exec
|
|
119
119
|
false
|
120
120
|
end
|
121
121
|
|
122
|
+
# Create the provided directory structure on the host
|
123
|
+
# @param [String] dir The directory structure to create on the host
|
124
|
+
# @return [Boolean] True, if directory construction succeeded, otherwise False
|
125
|
+
def mkdir_p dir
|
126
|
+
cmd = "mkdir -p \"#{dir}\""
|
127
|
+
result = exec(Beaker::Command.new(cmd), :acceptable_exit_codes => [0, 1])
|
128
|
+
result.exit_code == 0
|
129
|
+
end
|
130
|
+
|
131
|
+
# Move the origin to destination. The destination is removed prior to moving.
|
132
|
+
# @param [String] orig The origin path
|
133
|
+
# @param [String] dest the destination path
|
134
|
+
# @param [Boolean] rm Remove the destination prior to move
|
135
|
+
def mv orig, dest, rm=true
|
136
|
+
rm_rf dest unless !rm
|
137
|
+
execute("mv \"#{orig}\" \"#{dest}\"")
|
138
|
+
end
|
139
|
+
|
140
|
+
|
122
141
|
# Determine if cygwin is actually installed on the SUT. Differs from
|
123
142
|
# is_cygwin?, which is just a type check for a Windows::Host.
|
124
143
|
#
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Beaker
|
4
|
+
class LocalConnection
|
5
|
+
|
6
|
+
attr_accessor :logger, :hostname, :ip
|
7
|
+
|
8
|
+
def initialize options = {}
|
9
|
+
@logger = options[:logger]
|
10
|
+
@ssh_env_file = File.expand_path(options[:ssh_env_file])
|
11
|
+
@hostname = 'localhost'
|
12
|
+
@ip = '127.0.0.1'
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.connect options = {}
|
17
|
+
connection = new options
|
18
|
+
connection.connect
|
19
|
+
connection
|
20
|
+
end
|
21
|
+
|
22
|
+
def connect options = {}
|
23
|
+
@logger.debug "Local connection, no connection to start"
|
24
|
+
end
|
25
|
+
|
26
|
+
def close
|
27
|
+
@logger.debug "Local connection, no connection to close"
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_env(env)
|
31
|
+
backup = ENV.to_hash
|
32
|
+
ENV.replace(env)
|
33
|
+
yield
|
34
|
+
ensure
|
35
|
+
ENV.replace(backup)
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute command, options = {}, stdout_callback = nil, stderr_callback = stdout_callback
|
39
|
+
result = Result.new(@hostname, command)
|
40
|
+
envs = {}
|
41
|
+
if File.readable?(@ssh_env_file)
|
42
|
+
File.foreach(@ssh_env_file) do |line|
|
43
|
+
key, value = line.split('=')
|
44
|
+
envs[key] = value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
begin
|
49
|
+
clean_env = ENV.reject{ |k| k =~ /^BUNDLE|^RUBY|^GEM/ }
|
50
|
+
|
51
|
+
with_env(clean_env) do
|
52
|
+
std_out, std_err, status = Open3.capture3(envs, command)
|
53
|
+
result.stdout << std_out
|
54
|
+
result.stderr << std_err
|
55
|
+
result.exit_code = status.exitstatus
|
56
|
+
end
|
57
|
+
rescue => e
|
58
|
+
result.stderr << e.inspect
|
59
|
+
result.exit_code = 1
|
60
|
+
end
|
61
|
+
|
62
|
+
result.finalize!
|
63
|
+
@logger.last_result = result
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
def scp_to(source, target, _options = {})
|
68
|
+
|
69
|
+
result = Result.new(@hostname, [source, target])
|
70
|
+
begin
|
71
|
+
FileUtils.cp_r source, target
|
72
|
+
rescue Errno::ENOENT => e
|
73
|
+
@logger.warn "#{e.class} error in cp'ing. Forcing the connection to close, which should " \
|
74
|
+
"raise an error."
|
75
|
+
end
|
76
|
+
|
77
|
+
result.stdout << " CP'ed file #{source} to #{target}"
|
78
|
+
result.exit_code = 0
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
def scp_from(source, target, options = {})
|
83
|
+
scp_to(target, source, options)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -68,6 +68,16 @@ module Beaker
|
|
68
68
|
max_connection_tries = options[:max_connection_tries] || 11
|
69
69
|
begin
|
70
70
|
@logger.debug "Attempting ssh connection to #{host}, user: #{user}, opts: #{ssh_opts}"
|
71
|
+
|
72
|
+
# Work around net-ssh 6+ incompatibilities
|
73
|
+
if ssh_opts.include?(:strict_host_key_checking) && (Net::SSH::Version::CURRENT.major > 5)
|
74
|
+
strict_host_key_checking = ssh_opts.delete(:strict_host_key_checking)
|
75
|
+
|
76
|
+
unless ssh_opts[:verify_host_key].is_a?(Symbol)
|
77
|
+
ssh_opts[:verify_host_key] ||= strict_host_key_checking ? :always : :never
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
71
81
|
Net::SSH.start(host, user, ssh_opts)
|
72
82
|
rescue *RETRYABLE_EXCEPTIONS => e
|
73
83
|
if try <= max_connection_tries
|
data/lib/beaker/version.rb
CHANGED
@@ -99,5 +99,59 @@ module Beaker
|
|
99
99
|
to be == "set \"LD_PATH=/:/tmp\" && "
|
100
100
|
end
|
101
101
|
end
|
102
|
+
|
103
|
+
describe '#which' do
|
104
|
+
before do
|
105
|
+
allow(instance).to receive(:execute)
|
106
|
+
.with(where_command, :accept_all_exit_codes => true).and_return(result)
|
107
|
+
end
|
108
|
+
let(:where_command) { "cmd /C \"where ruby\"" }
|
109
|
+
|
110
|
+
context 'when only the environment variable PATH is used' do
|
111
|
+
let(:result) { "C:\\Ruby26-x64\\bin\\ruby.exe" }
|
112
|
+
|
113
|
+
it 'returns the correct path' do
|
114
|
+
response = instance.which('ruby')
|
115
|
+
|
116
|
+
expect(response).to eq(result)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'when command is not found' do
|
121
|
+
let(:where_command) { "cmd /C \"where unknown\"" }
|
122
|
+
let(:result) { '' }
|
123
|
+
|
124
|
+
it 'return empty string if command is not found' do
|
125
|
+
response = instance.which('unknown')
|
126
|
+
|
127
|
+
expect(response).to eq(result)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '#mkdir_p' do
|
133
|
+
let(:dir_path) { "C:\\tmpdir\\my_dir" }
|
134
|
+
let(:beaker_command) { instance_spy(Beaker::Command) }
|
135
|
+
let(:command) {"-Command New-Item -Path '#{dir_path}' -ItemType 'directory'"}
|
136
|
+
let(:result) { instance_spy(Beaker::Result) }
|
137
|
+
|
138
|
+
before do
|
139
|
+
allow(Beaker::Command).to receive(:new).
|
140
|
+
with('powershell.exe', array_including(command)).and_return(beaker_command)
|
141
|
+
allow(instance).to receive(:exec).with(beaker_command, :acceptable_exit_codes => [0, 1]).and_return(result)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'returns true and creates folder structure' do
|
145
|
+
allow(result).to receive(:exit_code).and_return(0)
|
146
|
+
|
147
|
+
expect(instance.mkdir_p(dir_path)).to be(true)
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'returns false if failed to create directory structure' do
|
151
|
+
allow(result).to receive(:exit_code).and_return(1)
|
152
|
+
|
153
|
+
expect(instance.mkdir_p(dir_path)).to be(false)
|
154
|
+
end
|
155
|
+
end
|
102
156
|
end
|
103
157
|
end
|
@@ -25,11 +25,31 @@ module Beaker
|
|
25
25
|
let (:instance) { PSWindowsFileTest.new(opts, logger) }
|
26
26
|
|
27
27
|
describe '#cat' do
|
28
|
+
let(:path) { '/path/to/cat' }
|
29
|
+
let(:content) { 'file content' }
|
28
30
|
it 'reads output for file' do
|
29
|
-
|
30
|
-
expect(instance).to receive(:exec)
|
31
|
+
expect(instance).to receive(:exec).and_return(double(stdout: content))
|
31
32
|
expect(Beaker::Command).to receive(:new).with('powershell.exe', array_including("-Command type #{path}"))
|
32
|
-
instance.cat(path)
|
33
|
+
expect(instance.cat(path)).to eq(content)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#file_exist?' do
|
38
|
+
let(:path) { '/path/to/test/file.txt' }
|
39
|
+
context 'file exists' do
|
40
|
+
it 'returns true' do
|
41
|
+
expect(instance).to receive(:exec).and_return(double(stdout: "true\n"))
|
42
|
+
expect(Beaker::Command).to receive(:new).with("if exist #{path} echo true")
|
43
|
+
expect(instance.file_exist?(path)).to eq(true)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'file does not exist' do
|
48
|
+
it 'returns false' do
|
49
|
+
expect(instance).to receive(:exec).and_return(double(stdout: ""))
|
50
|
+
expect(Beaker::Command).to receive(:new).with("if exist #{path} echo true")
|
51
|
+
expect(instance.file_exist?(path)).to eq(false)
|
52
|
+
end
|
33
53
|
end
|
34
54
|
end
|
35
55
|
|
@@ -39,7 +59,6 @@ module Beaker
|
|
39
59
|
|
40
60
|
before do
|
41
61
|
allow(instance).to receive(:execute).with(anything)
|
42
|
-
|
43
62
|
end
|
44
63
|
|
45
64
|
context 'with dirname sent' do
|
@@ -40,13 +40,13 @@ module Beaker
|
|
40
40
|
|
41
41
|
it 'rm first' do
|
42
42
|
expect( instance ).to receive(:execute).with("rm -rf #{destination}").and_return(0)
|
43
|
-
expect( instance ).to receive(:execute).with("mv
|
43
|
+
expect( instance ).to receive(:execute).with("mv #{origin} #{destination}").and_return(0)
|
44
44
|
expect( instance.mv(origin, destination) ).to be === 0
|
45
45
|
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'does not rm' do
|
49
|
-
expect( instance ).to receive(:execute).with("mv
|
49
|
+
expect( instance ).to receive(:execute).with("mv #{origin} #{destination}").and_return(0)
|
50
50
|
expect( instance.mv(origin, destination, false) ).to be === 0
|
51
51
|
end
|
52
52
|
end
|
@@ -313,40 +313,32 @@ module Beaker
|
|
313
313
|
|
314
314
|
end
|
315
315
|
|
316
|
-
describe '#
|
317
|
-
|
318
|
-
|
316
|
+
describe '#which' do
|
317
|
+
before do
|
318
|
+
allow(instance).to receive(:execute)
|
319
|
+
.with(where_command, :accept_all_exit_codes => true).and_return(result)
|
319
320
|
end
|
320
|
-
it 'parses variation 2 of uptime string' do
|
321
|
-
expect(instance.parse_uptime("8:03 up 52 days, 20:47, 3 users, load averages: 1.36 1.42 1.40")).to be == "52 days, 20:47"
|
322
|
-
end
|
323
|
-
it 'parses variation 3 of uptime string' do
|
324
|
-
expect(instance.parse_uptime("22:19 up 54 days, 1 min, 4 users, load averages: 2.08 2.06 2.27")).to be == "54 days, 1 min"
|
325
|
-
end
|
326
|
-
it 'parses variation 4 of uptime string' do
|
327
|
-
expect(instance.parse_uptime("18:44:45 up 5 min, 0 users, load average: 0.14, 0.11, 0.05")).to be == "5 min"
|
328
|
-
end
|
329
|
-
it 'parses solaris\'s "just up" without time message' do
|
330
|
-
opts['platform'] = 'solaris-11-x86_64'
|
331
|
-
expect(instance.parse_uptime("10:05am up 0 users, load average: 0.66, 0.14, 0.05")).to be == "0 min"
|
332
|
-
end
|
333
|
-
end
|
334
321
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
expect(instance.uptime_int("54 days, 1 min")).to be == 77761
|
322
|
+
context 'when only the environment variable PATH is used' do
|
323
|
+
let(:where_command) { "which ruby" }
|
324
|
+
let(:result) { "/usr/bin/ruby.exe" }
|
325
|
+
|
326
|
+
it 'returns the correct path' do
|
327
|
+
response = instance.which('ruby')
|
328
|
+
|
329
|
+
expect(response).to eq(result)
|
344
330
|
end
|
345
|
-
it 'parses time segment variation 4 into a minute value' do
|
346
|
-
expect(instance.uptime_int("54 days")).to be == 77760
|
347
331
|
end
|
348
|
-
|
349
|
-
|
332
|
+
|
333
|
+
context 'when command is not found' do
|
334
|
+
let(:where_command) { "which unknown" }
|
335
|
+
let(:result) { '' }
|
336
|
+
|
337
|
+
it 'return empty string if command is not found' do
|
338
|
+
response = instance.which('unknown')
|
339
|
+
|
340
|
+
expect(response).to eq(result)
|
341
|
+
end
|
350
342
|
end
|
351
343
|
end
|
352
344
|
end
|
@@ -3,6 +3,7 @@ require 'spec_helper'
|
|
3
3
|
module Beaker
|
4
4
|
describe Windows::Exec do
|
5
5
|
class WindowsExecTest
|
6
|
+
include Unix::Exec
|
6
7
|
include Windows::Exec
|
7
8
|
|
8
9
|
def initialize(hash, logger)
|
@@ -78,5 +79,22 @@ module Beaker
|
|
78
79
|
expect(instance.cygwin_installed?).to eq(false)
|
79
80
|
end
|
80
81
|
end
|
82
|
+
|
83
|
+
context 'mv' do
|
84
|
+
let(:origin) { '/origin/path/of/content' }
|
85
|
+
let(:destination) { '/destination/path/of/content' }
|
86
|
+
|
87
|
+
it 'rm first' do
|
88
|
+
expect( instance ).to receive(:execute).with("rm -rf #{destination}").and_return(0)
|
89
|
+
expect( instance ).to receive(:execute).with("mv \"#{origin}\" \"#{destination}\"").and_return(0)
|
90
|
+
expect( instance.mv(origin, destination) ).to be === 0
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'does not rm' do
|
95
|
+
expect( instance ).to receive(:execute).with("mv \"#{origin}\" \"#{destination}\"").and_return(0)
|
96
|
+
expect( instance.mv(origin, destination, false) ).to be === 0
|
97
|
+
end
|
98
|
+
end
|
81
99
|
end
|
82
100
|
end
|
data/spec/beaker/host_spec.rb
CHANGED
@@ -349,7 +349,13 @@ module Beaker
|
|
349
349
|
allow( result ).to receive( :exit_code ).and_return( 0 )
|
350
350
|
allow( host ).to receive( :exec ).and_return( result )
|
351
351
|
|
352
|
-
expect( Beaker::Command ).to receive(:new).
|
352
|
+
expect( Beaker::Command ).to receive(:new).
|
353
|
+
with("powershell.exe", ["-ExecutionPolicy Bypass",
|
354
|
+
"-InputFormat None",
|
355
|
+
"-NoLogo",
|
356
|
+
"-NoProfile",
|
357
|
+
"-NonInteractive",
|
358
|
+
"-Command New-Item -Path 'test\\test\\test' -ItemType 'directory'"])
|
353
359
|
expect( host.mkdir_p('test/test/test') ).to be == true
|
354
360
|
|
355
361
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'net/ssh'
|
3
|
+
|
4
|
+
module Beaker
|
5
|
+
describe LocalConnection do
|
6
|
+
let( :options ) { { :logger => double('logger').as_null_object, :ssh_env_file => '/path/to/ssh/file'} }
|
7
|
+
subject(:connection) { LocalConnection.new(options) }
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
allow( subject ).to receive(:sleep)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#self.connect' do
|
14
|
+
it 'loggs message' do
|
15
|
+
expect(options[:logger]).to receive(:debug).with('Local connection, no connection to start')
|
16
|
+
connection_constructor = LocalConnection.connect(options)
|
17
|
+
expect( connection_constructor ).to be_a_kind_of LocalConnection
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#close' do
|
22
|
+
it 'logs message' do
|
23
|
+
expect(options[:logger]).to receive(:debug).with('Local connection, no connection to close')
|
24
|
+
connection.close
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#with_env' do
|
29
|
+
it 'sets envs temporarily' do
|
30
|
+
connection.connect
|
31
|
+
connection.with_env({'my_env' => 'my_env_value'}) do
|
32
|
+
expect(ENV.to_hash).to include({'my_env' => 'my_env_value'})
|
33
|
+
end
|
34
|
+
expect(ENV.to_hash).not_to include({'my_env' => 'my_env_value'})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#execute' do
|
39
|
+
it 'calls open3' do
|
40
|
+
expect( Open3 ).to receive( :capture3 ).with({}, 'my_command')
|
41
|
+
connection.connect
|
42
|
+
expect(connection.execute('my_command')).to be_a_kind_of Result
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'sets stdout, stderr and exitcode' do
|
46
|
+
allow(Open3).to receive(:capture3).and_return(['stdout', 'stderr', double({exitstatus: 0})])
|
47
|
+
connection.connect
|
48
|
+
result = connection.execute('my_command')
|
49
|
+
expect(result.exit_code).to eq(0)
|
50
|
+
expect(result.stdout).to eq('stdout')
|
51
|
+
expect(result.stderr).to eq('stderr')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'sets logger last_result' do
|
55
|
+
allow(Open3).to receive(:capture3).and_return(['stdout', 'stderr', double({exitstatus: 0})])
|
56
|
+
expect(options[:logger]).to receive(:last_result=).with(an_instance_of(Result))
|
57
|
+
connection.connect
|
58
|
+
connection.execute('my_command')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'sets exitcode to 1, when Open3 raises exeception' do
|
62
|
+
allow(Open3).to receive(:capture3).and_raise Errno::ENOENT
|
63
|
+
connection.connect
|
64
|
+
result = connection.execute('my_failing_command')
|
65
|
+
expect(result.exit_code).to eq(1)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#scp_to' do
|
70
|
+
let(:source) { '/source/path' }
|
71
|
+
let(:dest) { '/dest/path' }
|
72
|
+
|
73
|
+
it 'calls FileUtils.cp_r' do
|
74
|
+
connection.connect
|
75
|
+
expect(FileUtils).to receive(:cp_r).with(source, dest)
|
76
|
+
connection.scp_to(source, dest)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'returns and Result object' do
|
80
|
+
expect(FileUtils).to receive(:cp_r).and_return(true)
|
81
|
+
connection.connect
|
82
|
+
result = connection.scp_to(source, dest)
|
83
|
+
expect(result.exit_code).to eq(0)
|
84
|
+
expect(result.stdout).to eq(" CP'ed file #{source} to #{dest}")
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'catches exception and logs warning message' do
|
88
|
+
allow(FileUtils).to receive(:cp_r).and_raise Errno::ENOENT
|
89
|
+
expect(options[:logger]).to receive(:warn).with("Errno::ENOENT error in cp'ing. Forcing the connection to close, which should raise an error.")
|
90
|
+
connection.connect
|
91
|
+
connection.scp_to(source, dest)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#scp_from' do
|
96
|
+
let(:source) { '/source/path' }
|
97
|
+
let(:dest) { '/dest/path' }
|
98
|
+
|
99
|
+
it 'callse scp_to with reversed params' do
|
100
|
+
expect(connection).to receive(:scp_to).with(dest, source, {})
|
101
|
+
connection.connect
|
102
|
+
connection.scp_from(source, dest)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beaker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.26.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -576,6 +576,7 @@ files:
|
|
576
576
|
- lib/beaker/hypervisor.rb
|
577
577
|
- lib/beaker/hypervisor/noop.rb
|
578
578
|
- lib/beaker/junit.xsl
|
579
|
+
- lib/beaker/local_connection.rb
|
579
580
|
- lib/beaker/logger.rb
|
580
581
|
- lib/beaker/logger_junit.rb
|
581
582
|
- lib/beaker/network_manager.rb
|
@@ -646,6 +647,7 @@ files:
|
|
646
647
|
- spec/beaker/host_prebuilt_steps_spec.rb
|
647
648
|
- spec/beaker/host_spec.rb
|
648
649
|
- spec/beaker/hypervisor/hypervisor_spec.rb
|
650
|
+
- spec/beaker/localhost_connection_spec.rb
|
649
651
|
- spec/beaker/logger_junit_spec.rb
|
650
652
|
- spec/beaker/logger_spec.rb
|
651
653
|
- spec/beaker/network_manager_spec.rb
|
@@ -699,7 +701,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
699
701
|
- !ruby/object:Gem::Version
|
700
702
|
version: '0'
|
701
703
|
requirements: []
|
702
|
-
rubygems_version: 3.0.
|
704
|
+
rubygems_version: 3.0.8
|
703
705
|
signing_key:
|
704
706
|
specification_version: 4
|
705
707
|
summary: Let's test Puppet!
|