beaker 3.23.0 → 3.24.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NmM3NDg3NTZhMTAzZjM5Mzc5NGMzMDJjMjU1MDQ4NDY5NmRkZGViOA==
4
+ N2FiNDY2YjhkNzI2MThmMjJiNWE4NTQyZDBiYjkyZTU3ZGMxYzViYQ==
5
5
  data.tar.gz: !binary |-
6
- ODg4NTRkZjBmZDEyZmE3NDhiNjI3OTNlYWYxOTk5ZmM4ZDIwMmE5Ng==
6
+ MGRiYzJiNDU4NDg3ZTdmYTkzZDk2YjA4NmU2MDE1MzM4ZGIyZGU2Yg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZjgwNzAyZTIxZGNjYzA1MDgwYzVkMTEyZjBjZTU0NTU3ZDQ5ODNiNTA4OTk4
10
- NGI4OTljMmJiMmM3N2M4YWNkNTliNzQ1YTExMmU3MzJhYmIzZmFmOTNhYjYx
11
- MWFhNGEzMjgzOTRlM2YzNzRlN2Q0YzhlOTdjZmExNmNkYThmOWM=
9
+ NGU5ZDg5NGIxMzUxYTNjYzc1ZWY4OGNhYzEwMTExYTllOGEzY2I1MjE2ZTQ3
10
+ MzViOTUyNmI5MmVmYzMyMjE5MTljOWI5YTAwZDdlYzZkNzMwMGQ4NDNiYjc3
11
+ MjFmZjVmN2U4YTNkN2NlYjUyNGUyOTY3ODIwMjU3MjUwMDE0MDI=
12
12
  data.tar.gz: !binary |-
13
- MTNkMmUzMWQ1MjBhZDY3OWM5ZjhiMzYzYzMxYTRiYTZkMDIxMzc2MjM5ZTI0
14
- MzA3MGExYWE2OWQzYmVmZDg1MWJkOWMxZDg1MjMzNjNkNWIwMTkwNTcyMTUw
15
- MmI3NDQwY2RiYThiYjA3ZDE3YmE5OWE3ZWFjYmFkMThlMmU1Yjg=
13
+ NWQ0YzQ3NjViMWIxNDYwMjUxZDZiNTZkOTY0MTE1NTE5NjE3Y2UyYTJhYjY3
14
+ MTY1ODYwZjZmOGZiYTJmNDFiZmFmNDM5NTBmNDc2NDlkZmNmZTM1OTc1NmRm
15
+ NDlkOTI4ZTQzZDkyNGY3YWMwMzZkNGU2OGE3Nzc3YjllZjQ5NzQ=
@@ -0,0 +1,47 @@
1
+ # Set SSH connection methods preference
2
+
3
+ Setting up a SSH connection to hosts can be tricky. Beaker supports three methods to SSH to hosts:
4
+
5
+ 1. `ip`
6
+ 2. `vmhostname (dns name)`
7
+ 3. `hostname`
8
+
9
+ Beaker tries to SSH to hosts using these methods in a particular preference (order). Default preference is mentioned above. We allow hypervisor authors and end users to provide an array of these methods that reflects their preference.
10
+
11
+ ### Why set a preference?
12
+
13
+ Depending upon your hypervisor, your host could have specific method that it uses to SSH better and faster than other methods. For example, hosts generated by vmpooler connects better with `vmhostname` as some change their ip adderess on restart. Therefore vmpooler hypervisor sets its connection preference to use vmhostname first.
14
+
15
+ ### Setting SSH connection preference at hypervisor level
16
+
17
+ Hypervisor authors can set SSH connection preference. The only thing they have to do is override the `connection_preference` method set in [hypervisor.rb](https://github.com/puppetlabs/beaker/blob/master/lib/beaker/hypervisor.rb) file in their own hypervisor file.
18
+
19
+ For example, `beaker-vmpooler` overriding this in [vmpooler.rb](https://github.com/puppetlabs/beaker-vmpooler/blob/master/lib/beaker/hypervisor/vmpooler.rb) file.
20
+
21
+ ### Setting SSH connection methods in hosts file
22
+
23
+ End users can override the connection preference that is default or set by their hypervisor. This can be done from your hosts file. All you need to do is provide a `ssh_preference` for each host. The value of this key should be an array of the methods specified above in an order you prefer. Beaker then will attempt to SSH to the hosts in that particular order.
24
+
25
+ Example of a host file:
26
+
27
+ ```
28
+ HOSTS:
29
+ ubuntu1604-64-1:
30
+ hypervisor: vmpooler
31
+ platform: ubuntu-16.04-amd64
32
+ template: ubuntu-1604-x86_64
33
+ ssh_preference: ['vmhostname', 'hostname', 'ip']
34
+ roles:
35
+ - agent
36
+ - default
37
+ ubuntu1604-64-2:
38
+ hypervisor: vmpooler
39
+ platform: ubuntu-16.04-amd64
40
+ template: ubuntu-1604-x86_64
41
+ ssh_preference: ['ip, 'vmhostname']
42
+ roles:
43
+ - agent
44
+ CONFIG:
45
+ nfs_server: none
46
+ consoleport: 443
47
+ ```
data/lib/beaker/host.rb CHANGED
@@ -276,7 +276,7 @@ module Beaker
276
276
  # create new connection object if necessary
277
277
  @connection ||= SshConnection.connect( { :ip => self['ip'], :vmhostname => self['vmhostname'], :hostname => @name },
278
278
  self['user'],
279
- self['ssh'], { :logger => @logger } )
279
+ self['ssh'], { :logger => @logger, :ssh_connection_preference => self[:ssh_connection_preference]} )
280
280
  # update connection information
281
281
  if self['ip'] && (@connection.ip != self['ip'])
282
282
  @connection.ip = self['ip']
@@ -37,6 +37,7 @@ module Beaker
37
37
  end
38
38
 
39
39
  hypervisor = hyper_class.new(hosts_to_provision, options)
40
+ self.set_ssh_connection_preference(hosts_to_provision, hypervisor)
40
41
  hypervisor.provision if options[:provision]
41
42
 
42
43
  hypervisor
@@ -57,6 +58,24 @@ module Beaker
57
58
  nil
58
59
  end
59
60
 
61
+ DEFAULT_CONNECTION_PREFERENCE = [:ip, :vmhostname, :hostname]
62
+ # SSH connection method preference. Can be overwritten by hypervisor to change the order
63
+ def connection_preference(host)
64
+ DEFAULT_CONNECTION_PREFERENCE
65
+ end
66
+
67
+ def self.set_ssh_connection_preference(hosts_to_provision, hypervisor)
68
+ hosts_to_provision.each do |host|
69
+ ssh_methods = hypervisor.connection_preference(host) + DEFAULT_CONNECTION_PREFERENCE
70
+ if host[:ssh_preference]
71
+ # If user has provided ssh_connection_preference in hosts file then concat the preference provided by hypervisor
72
+ # Followed by concatenating the default preference and keeping the unique once
73
+ ssh_methods = host[:ssh_preference] + ssh_methods
74
+ end
75
+ host[:ssh_connection_preference] = ssh_methods.uniq
76
+ end
77
+ end
78
+
60
79
  #Proxy package managers on tests hosts created by this hypervisor, runs before validation and configuration.
61
80
  def proxy_package_manager
62
81
  if @options[:package_proxy]
@@ -6,7 +6,9 @@ module Beaker
6
6
  class SshConnection
7
7
 
8
8
  attr_accessor :logger
9
- attr_accessor :ip, :vmhostname, :hostname
9
+ attr_accessor :ip, :vmhostname, :hostname, :ssh_connection_preference
10
+
11
+ SUPPORTED_CONNECTION_METHODS = [:ip, :vmhostname, :hostname]
10
12
 
11
13
  RETRYABLE_EXCEPTIONS = [
12
14
  SocketError,
@@ -33,6 +35,7 @@ module Beaker
33
35
  @ssh_opts = ssh_opts
34
36
  @logger = options[:logger]
35
37
  @options = options
38
+ @ssh_connection_preference = @options[:ssh_connection_preference]
36
39
  end
37
40
 
38
41
  def self.connect name_hash, user = 'root', ssh_opts = {}, options = {}
@@ -65,22 +68,24 @@ module Beaker
65
68
 
66
69
  # connect to the host
67
70
  def connect
68
- #try three ways to connect to host (vmhostname, ip, hostname)
69
- methods = []
70
- if @vmhostname
71
- @ssh ||= connect_block(@vmhostname, @user, @ssh_opts)
72
- methods << "vmhostname (#{@vmhostname})"
73
- end
74
- if @ip && !@ssh
75
- @ssh ||= connect_block(@ip, @user, @ssh_opts)
76
- methods << "ip (#{@ip})"
77
- end
78
- if @hostname && !@ssh
79
- @ssh ||= connect_block(@hostname, @user, @ssh_opts)
80
- methods << "hostname (#{@hostname})"
71
+ # Try three ways to connect to host (vmhostname, ip, hostname)
72
+ # Try each method in turn until we succeed
73
+ methods = @ssh_connection_preference.dup
74
+ while (not @ssh) && (not methods.empty?) do
75
+ unless instance_variable_get("@#{methods[0]}").nil?
76
+ if SUPPORTED_CONNECTION_METHODS.include?(methods[0])
77
+ @ssh = connect_block(instance_variable_get("@#{methods[0].to_s}"), @user, @ssh_opts)
78
+ else
79
+ @logger.warn "Beaker does not support #{methods[0]} to SSH to host, trying next available method."
80
+ @ssh_connection_preference.delete(methods[0])
81
+ end
82
+ else
83
+ @logger.warn "Skipping #{methods[0]} method to ssh to host as its value is not set. Refer to https://github.com/puppetlabs/beaker/tree/master/docs/how_to/ssh_connection_preference.md to remove this warning"
84
+ end
85
+ methods.shift
81
86
  end
82
- if not @ssh
83
- @logger.error "Failed to connect to #{@hostname}, attempted #{methods.join(', ')}"
87
+ unless @ssh
88
+ @logger.error "Failed to connect to #{@hostname}, attempted #{@ssh_connection_preference.join(', ')}"
84
89
  raise RuntimeError, "Cannot connect to #{@hostname}"
85
90
  end
86
91
  @ssh
@@ -1,5 +1,5 @@
1
1
  module Beaker
2
2
  module Version
3
- STRING = '3.23.0'
3
+ STRING = '3.24.0'
4
4
  end
5
5
  end
@@ -2,15 +2,45 @@ require 'spec_helper'
2
2
 
3
3
  module Beaker
4
4
  describe Hypervisor do
5
- let( :hypervisor ) { Beaker::Hypervisor }
5
+ let( :hosts ) { make_hosts( { :platform => 'el-5' } ) }
6
+
7
+ context "#create" do
8
+ let( :hypervisor ) { Beaker::Hypervisor }
9
+
10
+ it "includes custom hypervisor and call set_ssh_connection_preference" do
11
+ allow(hypervisor).to receive(:set_ssh_connection_preference).with([], hypervisor)
12
+ expect{ hypervisor.create('custom_hypervisor', [], make_opts() )}.to raise_error(RuntimeError, "Invalid hypervisor: custom_hypervisor")
13
+ end
14
+
15
+ it "sets ssh connection preference if connection_preference method is not overwritten" do
16
+ hypervisor.create('none', hosts, make_opts())
17
+ expect(hosts[0][:ssh_connection_preference]).to eq([:ip,:vmhostname,:hostname])
18
+ end
19
+
20
+ it "concats overriding connection_preference array with the default connection_preference" do
21
+ allow(hypervisor).to receive(:connection_preference).and_return([:my,:invalid,:method_name])
22
+ hypervisor.set_ssh_connection_preference(hosts, hypervisor)
23
+ expect(hosts[0][:ssh_connection_preference]).to eq([:my,:invalid,:method_name,:ip,:vmhostname,:hostname])
24
+ end
25
+
26
+ it "removes unique elements from concated array while preserving order of overriding methods" do
27
+ allow(hypervisor).to receive(:connection_preference).and_return([:my,:ip,:vmhostname,:method_name])
28
+ hypervisor.set_ssh_connection_preference(hosts, hypervisor)
29
+ expect(hosts[0][:ssh_connection_preference]).to eq([:my,:ip,:vmhostname,:method_name,:hostname])
30
+ end
31
+
32
+ it "gives highest precedence to preference specified in host file followed by hypervisor" do
33
+ hosts[0].options[:ssh_preference] = ['set', 'in', 'hostfile']
34
+ hypervisor.create('none', hosts, make_opts())
35
+ allow(hypervisor).to receive(:connection_preference).and_return([:hypervisor, :pref])
36
+ hypervisor.set_ssh_connection_preference(hosts, hypervisor)
37
+ expect(hosts[0][:ssh_connection_preference]).to eq(['set', 'in', 'hostfile', :hypervisor, :pref, :ip, :vmhostname, :hostname])
38
+ end
6
39
 
7
- it "includes custom hypervisor" do
8
- expect{ hypervisor.create('custom_hypervisor', [], make_opts() )}.to raise_error(RuntimeError, "Invalid hypervisor: custom_hypervisor")
9
40
  end
10
41
 
11
42
  context "#configure" do
12
43
  let( :options ) { make_opts.merge({ 'logger' => double().as_null_object }) }
13
- let( :hosts ) { make_hosts( { :platform => 'el-5' } ) }
14
44
  let( :hypervisor ) { Beaker::Hypervisor.new( hosts, options ) }
15
45
 
16
46
  context 'if :timesync option set true on host' do
@@ -5,7 +5,7 @@ module Beaker
5
5
  describe SshConnection do
6
6
  let( :user ) { 'root' }
7
7
  let( :ssh_opts ) { { keepalive: true, keepalive_interval: 2 } }
8
- let( :options ) { { :logger => double('logger').as_null_object } }
8
+ let( :options ) { { :logger => double('logger').as_null_object, :ssh_connection_preference => [:ip, :vmhostname, :hostname]} }
9
9
  let( :ip ) { "default.ip.address" }
10
10
  let( :vmhostname ){ "vmhostname" }
11
11
  let( :hostname) { "my_host" }
@@ -17,26 +17,24 @@ module Beaker
17
17
  end
18
18
 
19
19
  it 'self.connect creates connects and returns a proxy for that connection' do
20
- # grrr
21
- expect( Net::SSH ).to receive(:start).with( vmhostname, user, ssh_opts ).and_return(true)
20
+ expect( Net::SSH ).to receive(:start).with( "default.ip.address", user, ssh_opts ).and_return(true)
22
21
  connection_constructor = SshConnection.connect name_hash, user, ssh_opts, options
23
22
  expect( connection_constructor ).to be_a_kind_of SshConnection
24
23
  end
25
24
 
26
25
  it 'connect creates a new connection' do
27
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts).and_return(true)
26
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts).and_return(true)
28
27
  connection.connect
29
28
  end
30
29
 
31
30
  it 'connect caches its connection' do
32
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts ).once.and_return true
33
- connection.connect
31
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts ).once.and_return true
34
32
  connection.connect
35
33
  end
36
34
 
37
- it 'attempts to connect by ip address if vmhostname connection fails' do
38
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts).and_return(false)
39
- expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts).and_return(true).once
35
+ it 'attempts to connect by vmhostname address if ip connection fails' do
36
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts).and_return(false)
37
+ expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts).and_return(true).once
40
38
  expect( Net::SSH ).to receive( :start ).with( hostname, user, ssh_opts).never
41
39
  connection.connect
42
40
  end
@@ -53,7 +51,7 @@ module Beaker
53
51
 
54
52
  it 'runs ssh close' do
55
53
  mock_ssh = Object.new
56
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { mock_ssh }
54
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { mock_ssh }
57
55
  connection.connect
58
56
 
59
57
  allow( mock_ssh).to receive( :closed? ).once.and_return(false)
@@ -63,7 +61,7 @@ module Beaker
63
61
 
64
62
  it 'sets the @ssh variable to nil' do
65
63
  mock_ssh = Object.new
66
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { mock_ssh }
64
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { mock_ssh }
67
65
  connection.connect
68
66
 
69
67
  allow( mock_ssh).to receive( :closed? ).once.and_return(false)
@@ -76,7 +74,7 @@ module Beaker
76
74
  it 'calls ssh shutdown & re-raises if ssh close fails with an unexpected Error' do
77
75
  mock_ssh = Object.new
78
76
  allow( mock_ssh ).to receive( :close ) { raise StandardError }
79
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { mock_ssh }
77
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { mock_ssh }
80
78
  connection.connect
81
79
 
82
80
  allow( mock_ssh).to receive( :closed? ).once.and_return(false)
@@ -90,7 +88,7 @@ module Beaker
90
88
  describe '#execute' do
91
89
  it 'retries if failed with a retryable exception' do
92
90
  mock_ssh = Object.new
93
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { mock_ssh }
91
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { mock_ssh }
94
92
  connection.connect
95
93
 
96
94
  allow( subject ).to receive( :close )
@@ -102,7 +100,7 @@ module Beaker
102
100
 
103
101
  it 'raises an error if it fails both times' do
104
102
  mock_ssh = Object.new
105
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { mock_ssh }
103
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { mock_ssh }
106
104
  connection.connect
107
105
 
108
106
  allow( subject ).to receive( :close )
@@ -115,7 +113,7 @@ module Beaker
115
113
  describe '#request_terminal_for' do
116
114
  it 'fails correctly by raising Net::SSH::Exception' do
117
115
  mock_ssh = Object.new
118
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { mock_ssh }
116
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { mock_ssh }
119
117
  connection.connect
120
118
 
121
119
  mock_channel = Object.new
@@ -128,7 +126,7 @@ module Beaker
128
126
  describe '#register_stdout_for' do
129
127
  before :each do
130
128
  @mock_ssh = Object.new
131
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { @mock_ssh }
129
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { @mock_ssh }
132
130
  connection.connect
133
131
 
134
132
  @data = '7 of clubs'
@@ -164,7 +162,7 @@ module Beaker
164
162
 
165
163
  before :each do
166
164
  @mock_ssh = Object.new
167
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { @mock_ssh }
165
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { @mock_ssh }
168
166
  connection.connect
169
167
 
170
168
  @data = '3 of spades'
@@ -203,7 +201,7 @@ module Beaker
203
201
 
204
202
  it 'assigns the output\'s exit code correctly from the data' do
205
203
  mock_ssh = Object.new
206
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { mock_ssh }
204
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { mock_ssh }
207
205
  connection.connect
208
206
 
209
207
  data = '10 of jeromes'
@@ -236,7 +234,7 @@ module Beaker
236
234
  @mock_scp = Object.new
237
235
  allow( @mock_scp ).to receive( :upload! )
238
236
  allow( @mock_ssh ).to receive( :scp ).and_return( @mock_scp )
239
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { @mock_ssh }
237
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { @mock_ssh }
240
238
  connection.connect
241
239
  end
242
240
 
@@ -263,7 +261,7 @@ module Beaker
263
261
  @mock_scp = Object.new
264
262
  allow( @mock_scp ).to receive( :download! )
265
263
  allow( @mock_ssh ).to receive( :scp ).and_return( @mock_scp )
266
- expect( Net::SSH ).to receive( :start ).with( vmhostname, user, ssh_opts) { @mock_ssh }
264
+ expect( Net::SSH ).to receive( :start ).with( ip, user, ssh_opts) { @mock_ssh }
267
265
  connection.connect
268
266
  end
269
267
 
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: 3.23.0
4
+ version: 3.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-24 00:00:00.000000000 Z
11
+ date: 2017-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -591,6 +591,7 @@ files:
591
591
  - docs/how_to/recipes.md
592
592
  - docs/how_to/run_in_parallel.md
593
593
  - docs/how_to/ssh_agent_forwarding.md
594
+ - docs/how_to/ssh_connection_preference.md
594
595
  - docs/how_to/test_arbitrary_beaker_versions.md
595
596
  - docs/how_to/the_beaker_dsl.md
596
597
  - docs/how_to/upgrade_from_2_to_3.md