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 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!