beaker 4.24.0 → 4.25.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 +11 -1
- data/lib/beaker/host.rb +6 -1
- data/lib/beaker/host/unix/exec.rb +18 -2
- data/lib/beaker/local_connection.rb +86 -0
- data/lib/beaker/version.rb +1 -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: 9a980145fbc318a89a888401bd94260c191604431b1eaa73b3fde746a4c405f5
|
4
|
+
data.tar.gz: 58a17db7a9772ff339511bb8e96bb71d121291df8fe328fc1e4f3e25d795c765
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1e4d5183c9816d8259daa604c5ec0874c66e1373f7826dcb18745cf1436b9210be67cc79becd5e5a1cdf338f968a7b5daefc5aa3eb56118b8720910c7ec23dd
|
7
|
+
data.tar.gz: 94ba6fe73b1ca744dcaff5b4e010e992d995fc908ce8bb7951116a2853d268deb125a7e91923225d5c81d1685669e50a0ca3bbe82253b8a919868ea97a088309
|
data/CHANGELOG.md
CHANGED
@@ -20,7 +20,17 @@ 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))
|
24
34
|
|
25
35
|
# [4.24.0](https://github.com/puppetlabs/beaker/compare/4.23.0...4.24.0) - 2020-06-05
|
26
36
|
|
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]} )
|
@@ -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}")
|
@@ -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
|
data/lib/beaker/version.rb
CHANGED
@@ -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.25.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-06-
|
11
|
+
date: 2020-06-15 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!
|