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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a564a311561c124625926ad527bf42a3fe0681e3a0a1c8f7780217a6b00f82dc
4
- data.tar.gz: 27c0f8cbae1a3f30226cb1dbc08db0cb4464e9e6340114b2b49d13b66e79d587
3
+ metadata.gz: 9a980145fbc318a89a888401bd94260c191604431b1eaa73b3fde746a4c405f5
4
+ data.tar.gz: 58a17db7a9772ff339511bb8e96bb71d121291df8fe328fc1e4f3e25d795c765
5
5
  SHA512:
6
- metadata.gz: 2f5c86fd2c82c44dd258d952d404741281a502dc2a2f987014795e940aa7e1f5f56937b628fe62a3fba8105a9f12866bd6a1a1367859f6ab9acbf6b7224d8d42
7
- data.tar.gz: 095358374f8ff2dfe5c0d95c41d5ff6ac621f69ef95a58580c7151d8f7d13bdbd89e0afa5b70be25ce0f3e14121b56c668765c78705bfe9868233cee37feb687
6
+ metadata.gz: a1e4d5183c9816d8259daa604c5ec0874c66e1373f7826dcb18745cf1436b9210be67cc79becd5e5a1cdf338f968a7b5daefc5aa3eb56118b8720910c7ec23dd
7
+ data.tar.gz: 94ba6fe73b1ca744dcaff5b4e010e992d995fc908ce8bb7951116a2853d268deb125a7e91923225d5c81d1685669e50a0ca3bbe82253b8a919868ea97a088309
@@ -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.2...master)
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
 
@@ -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
- 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}")
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Beaker
2
2
  module Version
3
- STRING = '4.24.0'
3
+ STRING = '4.25.0'
4
4
  end
5
5
  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.24.0
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-05 00:00:00.000000000 Z
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.6
704
+ rubygems_version: 3.0.8
703
705
  signing_key:
704
706
  specification_version: 4
705
707
  summary: Let's test Puppet!