beaker 4.24.0 → 4.25.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 +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!
|