beaker 4.23.1 → 4.27.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 442731199e19c2bfbd64dbc64851c80155659e8e7deee3e6512fe05006056efb
4
- data.tar.gz: 51c93bf9df5a4ef96c3739dbbae19d41ca70e91f03a250a4e6c5418294d7cfc9
3
+ metadata.gz: b7bc325aade2e41145790de7c1c5d8c3f07b054dc22999762cbbe812f81deeca
4
+ data.tar.gz: 403bc79d97df6b8b30d59a5caa8ef26434e1adfc6420025cc15d3267c149aaef
5
5
  SHA512:
6
- metadata.gz: 838c910a425573e64ae111686c1a3b1da59c2cfc4d485b177af8374d103a1879aab0a41fd0f9074a438c0adda41d4acbd3adc55017d7e49a52df79ffc1c91403
7
- data.tar.gz: 6869be1711abcdeaf5166213ec3ba082e5e1210576c0fab3d777cb0a902793465acd44bd4e36a8ae6e7aa2ebb2be5cf6f4d0f096c65c12c0ac765163e891741c
6
+ metadata.gz: fe7a3e52bc3db292ae174f97f2c93b2455e032693956931b60e6bc5cc1c0caf84be93f92d877d9bcdb7698f77e3367c08e0781e2e858b5c9a5d335d99d6b059f
7
+ data.tar.gz: 6616a6a1bb3399a30defc9536b64b67d7f742d67dddf09f8dad70604a0df9b9c4460c414080e70f42001495bdb47e1dcab8a9354210fb67348453ea065933707
@@ -0,0 +1,8 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ time: "13:00"
8
+ open-pull-requests-limit: 10
@@ -1,5 +1,5 @@
1
1
  before_install:
2
- - gem update --system 2.2.1
2
+ - gem update
3
3
  - gem --version
4
4
  language: ruby
5
5
  script: "bundle exec rake travis"
@@ -7,6 +7,4 @@ notifications:
7
7
  email: false
8
8
  rvm:
9
9
  - 2.6
10
- - 2.0.0
11
- - 1.9.3
12
- - 1.8.7-p374
10
+ - 2.4
@@ -20,7 +20,55 @@ 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.1...master)
23
+ # [Unreleased](https://github.com/puppetlabs/beaker/compare/4.27.0...master)
24
+
25
+ # [4.27.0](https://github.com/puppetlabs/beaker/compare/4.26.0...4.27.0) - 07-24-2020
26
+
27
+ ### Changed
28
+
29
+ - Updated dependency versions and minimum Ruby version in gemspec to Ruby 2.4, which is the minimum
30
+ version Beaker will run with.
31
+ - Added Travis unit testing and disabled Jenkins integrations in preparation for transferring the
32
+ repo to Vox Pupuli
33
+
34
+
35
+ # [4.26.0](https://github.com/puppetlabs/beaker/compare/4.25.0...4.26.0)
36
+
37
+ ### Changed
38
+
39
+ - Fixed deprecated SSH option handling for `verify_ssh_key` being passed into Net::SSH. #1655
40
+
41
+ ### Removed
42
+
43
+ - Removed deprecated use of `paranoid` flag with Net::SSH. #1655
44
+
45
+ # [4.25.0](https://github.com/puppetlabs/beaker/compare/4.24.0...4.25.0)
46
+
47
+ ### Added
48
+
49
+ - Execution of Beaker directly through ruby on localhost #1637 ([#1637](https://github.com/puppetlabs/beaker/pull/1637))
50
+
51
+ ### Fixed
52
+
53
+ - Reliability improvements to the `Host#reboot` method ([#1656](https://github.com/puppetlabs/beaker/pull/1656)) ([#1659](https://github.com/puppetlabs/beaker/pull/1659))
54
+
55
+ # [4.24.0](https://github.com/puppetlabs/beaker/compare/4.23.0...4.24.0) - 2020-06-05
56
+
57
+ ### Added
58
+
59
+ - Host method which ([#1651](https://github.com/puppetlabs/beaker/pull/1651))
60
+
61
+ ### Fixed
62
+
63
+ - Fixed implementation for cat and file_exists? host methods for PSWindows ([#1654](https://github.com/puppetlabs/beaker/pull/1654))
64
+ - Fixed implementation for mkdir_p host method for PSWindows ([#1657](https://github.com/puppetlabs/beaker/pull/1657))
65
+
66
+ # [4.23.2](https://github.com/puppetlabs/beaker/compare/4.23.1...4.23.2)
67
+
68
+ ### Fixed
69
+
70
+ - Fixed Beaker's behavior when the `strict_host_key_checking` option is
71
+ provided in the SSH config and Net-SSH > 5 is specified. (#1652)
24
72
 
25
73
  # [4.23.1](https://github.com/puppetlabs/beaker/compare/4.23.0...4.23.1)
26
74
 
data/CODEOWNERS CHANGED
@@ -1,2 +0,0 @@
1
- * @puppetlabs/beaker
2
- * @puppetlabs/dio
data/Rakefile CHANGED
@@ -26,10 +26,7 @@ task :history do
26
26
  Rake::Task['history:gen'].invoke
27
27
  end
28
28
 
29
- task :travis do
30
- Rake::Task['yard'].invoke if !Beaker::Shared::Semvar.version_is_less(RUBY_VERSION, '2.0.0')
31
- Rake::Task['spec'].invoke
32
- end
29
+ task travis: [:yard, :test]
33
30
 
34
31
  module HarnessOptions
35
32
  defaults = {
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.required_ruby_version = Gem::Requirement.new('>= 2.1.8')
21
+ s.required_ruby_version = Gem::Requirement.new('>= 2.4')
22
22
 
23
23
  # Testing dependencies
24
24
  s.add_development_dependency 'rspec', '~> 3.0'
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
39
39
  # Run time dependencies
40
40
  s.add_runtime_dependency 'minitest', '~> 5.4'
41
41
  s.add_runtime_dependency 'minitar', '~> 0.6'
42
- s.add_runtime_dependency 'pry-byebug', '~> 3.6'
42
+ s.add_runtime_dependency 'pry-byebug', '~> 3.9'
43
43
  # pry-byebug can have issues with native readline libs so add rb-readline
44
44
  s.add_runtime_dependency 'rb-readline', '~> 0.5.3'
45
45
 
@@ -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
- windows_dirstring = dir.gsub('/','\\')
108
- cmd = "if not exist #{windows_dirstring} (md #{windows_dirstring})"
109
- result = exec(Beaker::Command.new(cmd), :acceptable_exit_codes => [0, 1])
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"), :acceptable_exit_codes => [0, 1])
29
- result.stdout =~ /true/
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
- current_boot_time = Time.parse(current_boot_time_str.lines.grep(/boot/).first)
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
@@ -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
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Beaker
2
2
  module Version
3
- STRING = '4.23.1'
3
+ STRING = '4.27.0'
4
4
  end
5
5
  end
@@ -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
- path = '/path/to/delete'
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
@@ -313,40 +313,32 @@ module Beaker
313
313
 
314
314
  end
315
315
 
316
- describe '#parse_uptime' do
317
- it 'parses variation of uptime string' do
318
- expect(instance.parse_uptime("19:52 up 14 mins, 2 users, load averages: 2.95 4.19 4.31")).to be == "14 mins"
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
- describe '#uptime_int' do
336
- it 'parses time segment variation into a minute value' do
337
- expect(instance.uptime_int("14 mins")).to be == 14
338
- end
339
- it 'parses time segment variation 2 into a minute value' do
340
- expect(instance.uptime_int("52 days, 20:47")).to be == 76127
341
- end
342
- it 'parses time segment variation 3 into a minute value' do
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
- it 'raises if we pass garbage to it' do
349
- expect { instance.uptime_int("solaris roxx my soxx") }.to raise_error
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
@@ -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).with("if not exist test\\test\\test (md test\\test\\test)")
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.23.1
4
+ version: 4.27.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-05-20 00:00:00.000000000 Z
11
+ date: 2020-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -176,14 +176,14 @@ dependencies:
176
176
  requirements:
177
177
  - - "~>"
178
178
  - !ruby/object:Gem::Version
179
- version: '3.6'
179
+ version: '3.9'
180
180
  type: :runtime
181
181
  prerelease: false
182
182
  version_requirements: !ruby/object:Gem::Requirement
183
183
  requirements:
184
184
  - - "~>"
185
185
  - !ruby/object:Gem::Version
186
- version: '3.6'
186
+ version: '3.9'
187
187
  - !ruby/object:Gem::Dependency
188
188
  name: rb-readline
189
189
  requirement: !ruby/object:Gem::Requirement
@@ -352,6 +352,7 @@ executables:
352
352
  extensions: []
353
353
  extra_rdoc_files: []
354
354
  files:
355
+ - ".github/dependabot.yml"
355
356
  - ".gitignore"
356
357
  - ".rspec"
357
358
  - ".simplecov"
@@ -576,6 +577,7 @@ files:
576
577
  - lib/beaker/hypervisor.rb
577
578
  - lib/beaker/hypervisor/noop.rb
578
579
  - lib/beaker/junit.xsl
580
+ - lib/beaker/local_connection.rb
579
581
  - lib/beaker/logger.rb
580
582
  - lib/beaker/logger_junit.rb
581
583
  - lib/beaker/network_manager.rb
@@ -646,6 +648,7 @@ files:
646
648
  - spec/beaker/host_prebuilt_steps_spec.rb
647
649
  - spec/beaker/host_spec.rb
648
650
  - spec/beaker/hypervisor/hypervisor_spec.rb
651
+ - spec/beaker/localhost_connection_spec.rb
649
652
  - spec/beaker/logger_junit_spec.rb
650
653
  - spec/beaker/logger_spec.rb
651
654
  - spec/beaker/network_manager_spec.rb
@@ -692,14 +695,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
692
695
  requirements:
693
696
  - - ">="
694
697
  - !ruby/object:Gem::Version
695
- version: 2.1.8
698
+ version: '2.4'
696
699
  required_rubygems_version: !ruby/object:Gem::Requirement
697
700
  requirements:
698
701
  - - ">="
699
702
  - !ruby/object:Gem::Version
700
703
  version: '0'
701
704
  requirements: []
702
- rubygems_version: 3.0.6
705
+ rubygems_version: 3.0.8
703
706
  signing_key:
704
707
  specification_version: 4
705
708
  summary: Let's test Puppet!