ridley-connectors 2.2.0 → 2.3.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
  SHA1:
3
- metadata.gz: 75a45b3d5ebe84723f39a4eab4449f2d62232a7e
4
- data.tar.gz: c35e78280d736f252028d9a167092d8bdfe85b7f
3
+ metadata.gz: 0963bedc809b1573895731a6ef403acd8bb22d36
4
+ data.tar.gz: 585e09bb5fe887c8b234c93e447353c5c632eca4
5
5
  SHA512:
6
- metadata.gz: d55c6296fc29e58250b15c4d80dc01eda0efd20014c8beb2e5ca707145cc8824251a0350e6fb470b319dbc1e05d65f2404ec0a2ff56dc98984cfb8d0bab36e85
7
- data.tar.gz: c7bbc2ae0143b1db7c5c6bc52a4fc5b8c848fe8b753a3853098f6f7d851324e25cd485791ecb4b7b5c9eed452cc0053ee2263820f7e1ce9cdf09990f85ce94ef
6
+ metadata.gz: 85cd162eede9fb6ef393460caf4a71e77a00149242876906c10ea19c1d9d6665347d67856bc71f463d20fd7d59a267adca978c3e80fc3f5c960ffb49c6be50f2
7
+ data.tar.gz: bd05027c733e9b157de24014fcff761191a880e59f1a78366c23f625d7c9d401d9b12baa7aef021d758f20434c3374883c936dcd649ae36956601f8a104d5dd0
@@ -23,24 +23,11 @@ module Ridley
23
23
  include Celluloid
24
24
  include Ridley::Logging
25
25
 
26
- PORT_CHECK_TIMEOUT = 3
27
- RETRY_COUNT = 3
28
-
29
26
  DEFAULT_WINDOWS_CONNECTOR = "winrm"
30
27
  DEFAULT_LINUX_CONNECTOR = "ssh"
31
28
 
32
29
  VALID_CONNECTORS = [ DEFAULT_WINDOWS_CONNECTOR, DEFAULT_LINUX_CONNECTOR ]
33
30
 
34
- CONNECTOR_PORT_ERRORS = [
35
- Errno::ETIMEDOUT, Timeout::Error, SocketError,
36
- Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EADDRNOTAVAIL,
37
- Resolv::ResolvError
38
- ]
39
-
40
- if Buff::RubyEngine.jruby?
41
- CONNECTOR_PORT_ERRORS << Java::JavaNet::ConnectException
42
- end
43
-
44
31
  finalizer :finalize_callback
45
32
 
46
33
  def initialize(connector_pool_size=nil)
@@ -228,6 +215,7 @@ module Ridley
228
215
  # @option options [Hash] :ssh
229
216
  # * :port (Fixnum) the ssh port to connect on the node the bootstrap will be performed on (22)
230
217
  # * :timeout (Float) [5.0] timeout value for testing SSH connection
218
+ # * :gateway (String) user@host:port
231
219
  # @option options [Hash] :winrm
232
220
  # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
233
221
  # @option options [String] :connector
@@ -237,12 +225,6 @@ module Ridley
237
225
  #
238
226
  # @return [HostConnector::SSH, HostConnector::WinRM, NilClass]
239
227
  def connector_for(host, options = {})
240
- options[:ssh] ||= Hash.new
241
- options[:winrm] ||= Hash.new
242
- options[:ssh][:port] ||= HostConnector::SSH::DEFAULT_PORT
243
- options[:winrm][:port] ||= HostConnector::WinRM::DEFAULT_PORT
244
- options[:retries] ||= RETRY_COUNT
245
-
246
228
  connector = options[:connector]
247
229
 
248
230
  if !VALID_CONNECTORS.include?(connector)
@@ -250,10 +232,12 @@ module Ridley
250
232
  connector = nil
251
233
  end
252
234
 
253
- if (connector == DEFAULT_WINDOWS_CONNECTOR || connector.nil?) && connector_port_open?(host, options[:winrm][:port], options[:winrm][:timeout], options[:retries])
235
+ if (connector == DEFAULT_WINDOWS_CONNECTOR || connector.nil?) &&
236
+ winrm.connector_port_open?(host, options)
254
237
  options.delete(:ssh)
255
238
  winrm
256
- elsif (connector == DEFAULT_LINUX_CONNECTOR || connector.nil?) && connector_port_open?(host, options[:ssh][:port], options[:ssh][:timeout], options[:retries])
239
+ elsif (connector == DEFAULT_LINUX_CONNECTOR || connector.nil?) &&
240
+ ssh.connector_port_open?(host, options)
257
241
  options.delete(:winrm)
258
242
  ssh
259
243
  else
@@ -286,75 +270,6 @@ module Ridley
286
270
  end
287
271
  end
288
272
 
289
- # Checks to see if the given port is open for TCP connections
290
- # on the given host.
291
- #
292
- # @param [String] host
293
- # the host to attempt to connect to
294
- # @param [Fixnum] port
295
- # the port to attempt to connect on
296
- # @param [Float] timeout ({PORT_CHECK_TIMEOUT})
297
- # the number of seconds to wait
298
- # @param [Int] retries ({RETRY_COUNT})
299
- # the number of times to retry the connection before counting it unavailable
300
- #
301
- # @return [Boolean]
302
- def connector_port_open?(host, port, timeout = PORT_CHECK_TIMEOUT, retries = RETRY_COUNT)
303
- @retry_count = retries
304
- begin
305
- defer {
306
- connectable?(host, port, timeout || PORT_CHECK_TIMEOUT)
307
- }
308
- rescue *CONNECTOR_PORT_ERRORS => ex
309
- @retry_count -= 1
310
- if @retry_count > 0
311
- log.info { "Retrying connector_port_open? on '#{host}' #{port} due to: #{ex.class}" }
312
- retry
313
- end
314
- false
315
- end
316
- end
317
-
318
- # Check if a port on a host is able to be connected, failing if the timeout transpires.
319
- #
320
- # @param [String] host
321
- # the host to attempt to connect to
322
- # @param [Fixnum] port
323
- # the port to attempt to connect on
324
- # @param [Fixnum] timeout ({PORT_CHECK_TIMEOUT})
325
- #
326
- # @return [Boolean]
327
- def connectable?(host, port, timeout = PORT_CHECK_TIMEOUT)
328
- addr = Socket.getaddrinfo(host, nil)
329
- sockaddr = Socket.pack_sockaddr_in(port, addr[0][3])
330
- socket = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0)
331
- socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
332
-
333
- success = false
334
- begin
335
- socket.connect_nonblock(sockaddr)
336
- success = true
337
- rescue ::IO::WaitWritable
338
- if ::IO.select(nil, [socket], nil, timeout || PORT_CHECK_TIMEOUT)
339
- begin
340
- socket.connect_nonblock(sockaddr)
341
- success = true
342
- rescue Errno::EISCONN
343
- success = true
344
- rescue
345
- begin
346
- socket.close
347
- rescue Errno::EBADF
348
- # socket is not open
349
- end
350
- end
351
- else
352
- socket.close
353
- end
354
- end
355
- success
356
- end
357
-
358
273
  def finalize_callback
359
274
  @connector_supervisor.async.terminate if @connector_supervisor && @connector_supervisor.alive?
360
275
  end
@@ -4,6 +4,20 @@ module Ridley
4
4
  include Celluloid
5
5
  include Ridley::Logging
6
6
 
7
+ PORT_CHECK_TIMEOUT = 3
8
+ RETRY_COUNT = 3
9
+ CONNECTOR_PORT_ERRORS = [Errno::ETIMEDOUT,
10
+ Timeout::Error,
11
+ SocketError,
12
+ Errno::ECONNREFUSED,
13
+ Errno::EHOSTUNREACH,
14
+ Errno::EADDRNOTAVAIL,
15
+ Resolv::ResolvError]
16
+
17
+ if Buff::RubyEngine.jruby?
18
+ CONNECTOR_PORT_ERRORS << Java::JavaNet::ConnectException
19
+ end
20
+
7
21
  # Execute a shell command on a node
8
22
  #
9
23
  # @param [String] host
@@ -74,6 +88,79 @@ module Ridley
74
88
  def uninstall_chef(host, options = {})
75
89
  raise RuntimeError, "abstract function: must be implemented on includer"
76
90
  end
91
+
92
+ def connector_port_open?
93
+ raise RuntimeError, "abstract function: must be implemented on includer"
94
+ end
95
+
96
+ # Checks to see if the given port is open for TCP connections
97
+ # on the given host.
98
+ #
99
+ # @param [String] host
100
+ # the host to attempt to connect to
101
+ # @param [Fixnum] port
102
+ # the port to attempt to connect on
103
+ # @param [Float] timeout ({PORT_CHECK_TIMEOUT})
104
+ # the number of seconds to wait
105
+ # @param [Int] retries ({RETRY_COUNT})
106
+ # the number of times to retry the connection before counting it unavailable
107
+ #
108
+ # @return [Boolean]
109
+ def port_open?(host, port, timeout = PORT_CHECK_TIMEOUT, retries = RETRY_COUNT)
110
+ @retry_count = retries
111
+ begin
112
+ defer {
113
+ connectable?(host, port, timeout || PORT_CHECK_TIMEOUT)
114
+ }
115
+ rescue *CONNECTOR_PORT_ERRORS => ex
116
+ @retry_count -= 1
117
+ if @retry_count > 0
118
+ log.info { "Retrying connector_port_open? on '#{host}' #{port} due to: #{ex.class}" }
119
+ retry
120
+ end
121
+ false
122
+ end
123
+ end
124
+
125
+ # Check if a port on a host is able to be connected, failing if the timeout transpires.
126
+ #
127
+ # @param [String] host
128
+ # the host to attempt to connect to
129
+ # @param [Fixnum] port
130
+ # the port to attempt to connect on
131
+ # @param [Fixnum] timeout ({PORT_CHECK_TIMEOUT})
132
+ #
133
+ # @return [Boolean]
134
+ def connectable?(host, port, timeout = PORT_CHECK_TIMEOUT)
135
+ addr = Socket.getaddrinfo(host, nil)
136
+ sockaddr = Socket.pack_sockaddr_in(port, addr[0][3])
137
+ socket = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0)
138
+ socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
139
+
140
+ success = false
141
+ begin
142
+ socket.connect_nonblock(sockaddr)
143
+ success = true
144
+ rescue ::IO::WaitWritable
145
+ if ::IO.select(nil, [socket], nil, timeout || PORT_CHECK_TIMEOUT)
146
+ begin
147
+ socket.connect_nonblock(sockaddr)
148
+ success = true
149
+ rescue Errno::EISCONN
150
+ success = true
151
+ rescue
152
+ begin
153
+ socket.close
154
+ rescue Errno::EBADF
155
+ # socket is not open
156
+ end
157
+ end
158
+ else
159
+ socket.close
160
+ end
161
+ end
162
+ success
163
+ end
77
164
  end
78
165
 
79
166
  require_relative 'host_connector/response'
@@ -1,4 +1,5 @@
1
1
  require 'net/ssh'
2
+ require 'net/ssh/gateway'
2
3
 
3
4
  module Ridley
4
5
  module HostConnector
@@ -6,7 +7,8 @@ module Ridley
6
7
  DEFAULT_PORT = 22
7
8
  EMBEDDED_RUBY_PATH = '/opt/chef/embedded/bin/ruby'.freeze
8
9
 
9
- # Execute a shell command on a node
10
+ # Execute a shell command on a node using ssh. If the gateway option is present then
11
+ # execute the command through the gateway.
10
12
  #
11
13
  # @param [String] host
12
14
  # the host to perform the action on
@@ -18,6 +20,7 @@ module Ridley
18
20
  # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
19
21
  # * :timeout (Float) timeout value for SSH bootstrap (5.0)
20
22
  # * :sudo (Boolean) run as sudo
23
+ # * :gateway (String) user@host:port
21
24
  #
22
25
  # @return [HostConnector::Response]
23
26
  def run(host, command, options = {})
@@ -31,7 +34,7 @@ module Ridley
31
34
  log.info "Running SSH command: '#{command}' on: '#{host}' as: '#{options[:ssh][:user]}'"
32
35
 
33
36
  defer {
34
- Net::SSH.start(host, options[:ssh][:user], options[:ssh].slice(*Net::SSH::VALID_OPTIONS)) do |ssh|
37
+ ssh(host, options) do |ssh|
35
38
  ssh.open_channel do |channel|
36
39
  if options[:sudo]
37
40
  channel.request_pty do |channel, success|
@@ -225,8 +228,66 @@ module Ridley
225
228
  run(host, CommandContext::UnixUpdateOmnibus.command(options), options)
226
229
  end
227
230
 
231
+ # Checks to see if the given port is open for TCP connections
232
+ # on the given host. If a gateway is provided in the ssh
233
+ # options, then return true if we can connect to the gateway host.
234
+ # If no gateway config is found then just verify we can connect to
235
+ # the destination host.
236
+ #
237
+ # @param [String] host
238
+ # the host to attempt to connect to
239
+ # @option options [Hash] :ssh
240
+ # * :gateway (String) user@host:port
241
+ # * :timeout (Float) timeout value for SSH
242
+ # * :port (Fixnum) the SSH port
243
+ # @return [Boolean]
244
+ def connector_port_open?(host, options = {})
245
+ options[:ssh] ||= Hash.new
246
+ options[:ssh][:port] ||= HostConnector::SSH::DEFAULT_PORT
247
+
248
+ if options[:ssh][:gateway]
249
+ gw_host, gw_port, _ = gateway(options)
250
+ log.info("Connecting to host '#{gw_host}' via SSH gateway over port '#{gw_port}'")
251
+ port_open?(gw_host, gw_port, options[:ssh][:timeout])
252
+ else
253
+ port_open?(host, options[:ssh][:port], options[:ssh][:timeout])
254
+ end
255
+ end
256
+
228
257
  private
229
258
 
259
+ def gateway(options)
260
+ options[:ssh] ||= Hash.new
261
+
262
+ if options[:ssh][:gateway]
263
+ gw_host, gw_user = options[:ssh][:gateway].split("@").reverse
264
+ gw_host, gw_port = gw_host.split(":")
265
+ gw_port ||= HostConnector::SSH::DEFAULT_PORT
266
+ [gw_host, gw_port, gw_user]
267
+ else
268
+ [nil, nil, nil]
269
+ end
270
+ end
271
+
272
+ # Open an SSH connection either directly or through a gateway.
273
+ def ssh(host, options, &block)
274
+ if options[:ssh][:gateway]
275
+ gw_host, gw_port, gw_user = gateway(options)
276
+ gateway = Net::SSH::Gateway.new(gw_host, gw_user, {:port => gw_port})
277
+ begin
278
+ gateway.ssh(host, options[:ssh][:user], options[:ssh].slice(*Net::SSH::VALID_OPTIONS)) do |ssh|
279
+ yield ssh
280
+ end
281
+ ensure
282
+ gateway.shutdown!
283
+ end
284
+ else
285
+ Net::SSH.start(host, options[:ssh][:user], options[:ssh].slice(*Net::SSH::VALID_OPTIONS)) do |ssh|
286
+ yield ssh
287
+ end
288
+ end
289
+ end
290
+
230
291
  def channel_exec(channel, command, host, response)
231
292
  channel.exec(command) do |ch, success|
232
293
  unless success
@@ -218,6 +218,23 @@ module Ridley
218
218
  run(host, CommandContext::WindowsUpdateOmnibus.command(options), options)
219
219
  end
220
220
 
221
+ # Checks to see if the given port is open for TCP connections
222
+ # on the given host.
223
+ #
224
+ # @param [String] host
225
+ # the host to attempt to connect to
226
+ # @option options [Hash] :winrm
227
+ # * port (Fixnum) the winrm port to connect to
228
+ # @option options [Fixnum] :retries
229
+ #
230
+ # @return [Boolean]
231
+ def connector_port_open?(host, options = {})
232
+ options[:winrm] ||= Hash.new
233
+ options[:winrm][:port] ||= HostConnector::WinRM::DEFAULT_PORT
234
+
235
+ port_open?(host, options[:winrm][:port], options[:retries])
236
+ end
237
+
221
238
  private
222
239
 
223
240
  # @param [String] host
@@ -1,5 +1,5 @@
1
1
  module Ridley
2
2
  module Connectors
3
- VERSION = "2.2.0"
3
+ VERSION = "2.3.0"
4
4
  end
5
5
  end
@@ -21,7 +21,8 @@ Gem::Specification.new do |s|
21
21
  s.add_dependency 'celluloid-io', '~> 0.16.0.pre'
22
22
  s.add_dependency 'erubis'
23
23
  s.add_dependency 'net-ssh'
24
- s.add_dependency 'ridley', '~> 3.1'
24
+ s.add_dependency 'net-ssh-gateway'
25
+ s.add_dependency 'ridley', '~> 4.0'
25
26
  s.add_dependency 'winrm', '~> 1.1.0'
26
27
 
27
28
  s.add_development_dependency 'buff-ruby_engine', '~> 0.1'
@@ -12,8 +12,8 @@ describe Ridley::HostCommander do
12
12
 
13
13
  context "when communicating to a unix node" do
14
14
  before do
15
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(false)
16
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(true)
15
+ subject.send(:winrm).stub(:port_open?).and_return(false)
16
+ subject.send(:ssh).stub(:port_open?).and_return(true)
17
17
  end
18
18
 
19
19
  it "sends a #run message to the ssh host connector" do
@@ -24,8 +24,8 @@ describe Ridley::HostCommander do
24
24
 
25
25
  context "when communicating to a windows node" do
26
26
  before do
27
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(true)
28
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(false)
27
+ subject.send(:winrm).stub(:port_open?).and_return(true)
28
+ subject.send(:ssh).stub(:port_open?).and_return(false)
29
29
  end
30
30
 
31
31
  it "sends a #run message to the ssh host connector" do
@@ -43,8 +43,8 @@ describe Ridley::HostCommander do
43
43
 
44
44
  context "when communicating to a unix node" do
45
45
  before do
46
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(false)
47
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(true)
46
+ subject.send(:winrm).stub(:port_open?).and_return(false)
47
+ subject.send(:ssh).stub(:port_open?).and_return(true)
48
48
  end
49
49
 
50
50
  it "sends a #bootstrap message to the ssh host connector" do
@@ -56,8 +56,8 @@ describe Ridley::HostCommander do
56
56
 
57
57
  context "when communicating to a windows node" do
58
58
  before do
59
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(true)
60
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(false)
59
+ subject.send(:winrm).stub(:port_open?).and_return(true)
60
+ subject.send(:ssh).stub(:port_open?).and_return(false)
61
61
  end
62
62
 
63
63
  it "sends a #bootstrap message to the winrm host connector" do
@@ -75,8 +75,8 @@ describe Ridley::HostCommander do
75
75
 
76
76
  context "when communicating to a unix node" do
77
77
  before do
78
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(false)
79
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(true)
78
+ subject.send(:winrm).stub(:port_open?).and_return(false)
79
+ subject.send(:ssh).stub(:port_open?).and_return(true)
80
80
  end
81
81
 
82
82
  it "sends a #chef_client message to the ssh host connector" do
@@ -88,8 +88,8 @@ describe Ridley::HostCommander do
88
88
 
89
89
  context "when communicating to a windows node" do
90
90
  before do
91
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(true)
92
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(false)
91
+ subject.send(:winrm).stub(:port_open?).and_return(true)
92
+ subject.send(:ssh).stub(:port_open?).and_return(false)
93
93
  end
94
94
 
95
95
  it "sends a #chef_client message to the ssh host connector" do
@@ -108,8 +108,8 @@ describe Ridley::HostCommander do
108
108
 
109
109
  context "when communicating to a unix node" do
110
110
  before do
111
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(false)
112
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(true)
111
+ subject.send(:winrm).stub(:port_open?).and_return(false)
112
+ subject.send(:ssh).stub(:port_open?).and_return(true)
113
113
  end
114
114
 
115
115
  it "sends a #put_secret message to the ssh host connector" do
@@ -121,8 +121,8 @@ describe Ridley::HostCommander do
121
121
 
122
122
  context "when communicating to a windows node" do
123
123
  before do
124
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(true)
125
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(false)
124
+ subject.send(:winrm).stub(:port_open?).and_return(true)
125
+ subject.send(:ssh).stub(:port_open?).and_return(false)
126
126
  end
127
127
 
128
128
  it "sends a #put_secret message to the ssh host connector" do
@@ -141,8 +141,8 @@ describe Ridley::HostCommander do
141
141
 
142
142
  context "when communicating to a unix node" do
143
143
  before do
144
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(false)
145
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(true)
144
+ subject.send(:winrm).stub(:port_open?).and_return(false)
145
+ subject.send(:ssh).stub(:port_open?).and_return(true)
146
146
  end
147
147
 
148
148
  it "sends a #ruby_script message to the ssh host connector" do
@@ -154,8 +154,8 @@ describe Ridley::HostCommander do
154
154
 
155
155
  context "when communicating to a windows node" do
156
156
  before do
157
- subject.stub(:connector_port_open?).with(host, options[:winrm][:port], anything, anything).and_return(true)
158
- subject.stub(:connector_port_open?).with(host, options[:ssh][:port], anything, anything).and_return(false)
157
+ subject.send(:winrm).stub(:port_open?).and_return(true)
158
+ subject.send(:ssh).stub(:port_open?).and_return(false)
159
159
  end
160
160
 
161
161
  it "sends a #ruby_script message to the ssh host connector" do
@@ -171,12 +171,12 @@ describe Ridley::HostCommander do
171
171
  { ssh: { port: 22, timeout: 3 }, winrm: { port: 5985, timeout: 3 }, retries: 3 }
172
172
  end
173
173
 
174
- context "when connector_port_open? experiences an error" do
174
+ context "when port_open? experiences an error" do
175
175
  let(:socket) { double(close: true) }
176
176
 
177
177
  it "executes retry logic" do
178
178
  @times_called = 0
179
- subject.should_receive(:connectable?).twice.and_return do
179
+ subject.send(:winrm).should_receive(:connectable?).twice.and_return do
180
180
  @times_called += 1
181
181
  if @times_called == 1
182
182
  raise Errno::ETIMEDOUT
@@ -190,22 +190,14 @@ describe Ridley::HostCommander do
190
190
  end
191
191
 
192
192
  it "should return winrm if winrm is open" do
193
- subject.stub(:connector_port_open?).with(host, Ridley::HostConnector::WinRM::DEFAULT_PORT, anything, anything).and_return(true)
194
- subject.should_receive(:winrm)
195
- subject.connector_for(host)
193
+ subject.send(:winrm).stub(:port_open?).and_return(true)
194
+ expect(subject.connector_for(host).class).to eq(Ridley::HostConnector::WinRM)
196
195
  end
197
196
 
198
197
  it "should return ssh if winrm is closed" do
199
- subject.stub(:connector_port_open?).with(host, Ridley::HostConnector::WinRM::DEFAULT_PORT, anything, anything).and_return(false)
200
- subject.stub(:connector_port_open?).with(host, Ridley::HostConnector::SSH::DEFAULT_PORT, anything, anything).and_return(true)
201
- subject.should_receive(:ssh)
202
- subject.connector_for(host)
203
- end
204
-
205
- it "should still set the default ports if an explicit nil is passed in" do
206
- subject.stub(:connector_port_open?).with(host, Ridley::HostConnector::WinRM::DEFAULT_PORT, anything, anything).and_return(true)
207
- subject.should_receive(:winrm)
208
- subject.connector_for(host, winrm: nil, ssh: nil)
198
+ subject.send(:winrm).stub(:port_open?).and_return(false)
199
+ subject.send(:ssh).stub(:port_open?).and_return(true)
200
+ expect(subject.connector_for(host).class).to eq(Ridley::HostConnector::SSH)
209
201
  end
210
202
 
211
203
  context "when a connector of winrm is given" do
@@ -213,31 +205,28 @@ describe Ridley::HostCommander do
213
205
  let(:winrm) { double }
214
206
 
215
207
  it "should return winrm if winrm is open" do
216
- subject.stub(:connector_port_open?).with(host, Ridley::HostConnector::WinRM::DEFAULT_PORT, anything, anything).and_return(true)
217
- subject.stub(:winrm).and_return(winrm)
218
- expect(subject.connector_for(host, connector_options)).to eql(winrm)
208
+ subject.send(:winrm).stub(:port_open?).and_return(true)
209
+ expect(subject.connector_for(host, options).class).to eql(Ridley::HostConnector::WinRM)
219
210
  end
220
211
 
221
212
  it "should return nil if winrm is closed" do
222
- subject.stub(:connector_port_open?).with(host, Ridley::HostConnector::WinRM::DEFAULT_PORT, anything, anything).and_return(false)
213
+ subject.stub(:port_open?).and_return(false)
223
214
  expect(subject.connector_for(host, connector_options)).to be_nil
224
215
  end
225
216
  end
226
217
 
227
218
  context "when a connector of ssh is given" do
228
219
  let(:connector_options) { options.merge(connector: "ssh") }
229
- let(:ssh) { double }
230
220
 
231
221
  it "should return ssh if ssh is open" do
232
- subject.stub(:connector_port_open?).with(host, Ridley::HostConnector::SSH::DEFAULT_PORT, anything, anything).and_return(true)
233
- subject.stub(:ssh).and_return(ssh)
234
- subject.should_not_receive(:connector_port_open?).with(host, Ridley::HostConnector::WinRM::DEFAULT_PORT, anything, anything)
235
- expect(subject.connector_for(host, connector_options)).to eql(ssh)
222
+ subject.send(:ssh).stub(:port_open?).and_return(true)
223
+ subject.send(:winrm).should_not_receive(:port_open?)
224
+ expect(subject.connector_for(host, connector_options).class).to eql(Ridley::HostConnector::SSH)
236
225
  end
237
226
 
238
227
  it "should return nil if ssh is closed" do
239
- subject.stub(:connector_port_open?).with(host, Ridley::HostConnector::SSH::DEFAULT_PORT, anything, anything).and_return(false)
240
- subject.should_not_receive(:connector_port_open?).with(host, Ridley::HostConnector::WinRM::DEFAULT_PORT, anything, anything)
228
+ subject.send(:ssh).stub(:port_open?).and_return(false)
229
+ subject.send(:winrm).should_not_receive(:port_open?)
241
230
  expect(subject.connector_for(host, connector_options)).to be_nil
242
231
  end
243
232
  end
@@ -246,87 +235,9 @@ describe Ridley::HostCommander do
246
235
  let(:connector_options) { options.merge(connector: "foo") }
247
236
 
248
237
  it "should try both connectors" do
249
- subject.should_receive(:connector_port_open?).twice
238
+ [:winrm, :ssh].each { |c| subject.send(c).should_receive(:port_open?) }
250
239
  subject.connector_for(host, connector_options)
251
240
  end
252
241
  end
253
242
  end
254
-
255
- describe "#connectable?" do
256
- let(:port) { 1234 }
257
-
258
- before do
259
- Socket
260
- .stub(:getaddrinfo)
261
- .with(host, nil)
262
- .and_return [["AF_INET", 0, "33.33.33.10", "33.33.33.10", 2, 2, 17],
263
- ["AF_INET", 0, "33.33.33.10", "33.33.33.10", 2, 1, 6]]
264
- end
265
-
266
- context "when the target is accessible" do
267
- before do
268
- calls = 0
269
- Socket.any_instance.stub(:connect_nonblock).and_return do
270
- calls += 1
271
- if calls == 1
272
- raise WaitWritableError.new
273
- end
274
- raise Errno::EISCONN.new
275
- end
276
- end
277
-
278
- it "should return true when a connection is initiated" do
279
- ::IO.stub(:select).and_return ["an array!"]
280
-
281
- expect(subject.send(:connectable?, host, port)).to be_true
282
- end
283
-
284
- it "should return true when a connection is initiated and an explicit nil is passed as the timeout" do
285
- ::IO.stub(:select).with(anything, anything, anything, Ridley::HostCommander::PORT_CHECK_TIMEOUT).and_return ["an array!"]
286
-
287
- expect(subject.send(:connectable?, host, port, nil)).to be_true
288
- end
289
-
290
- it "should return false when select times out" do
291
- ::IO.stub(:select).and_return nil
292
-
293
- expect(subject.send(:connectable?, host, port)).to be_false
294
- end
295
-
296
- it "should return true when the connection does not have to wait" do
297
- Socket.any_instance.stub(:connect_nonblock).and_return 0
298
-
299
- expect(subject.send(:connectable?, host, port)).to be_true
300
- end
301
- end
302
-
303
- Ridley::HostCommander::CONNECTOR_PORT_ERRORS.each do |error|
304
- context "when the target causes #{error}" do
305
- before do
306
- calls = 0
307
- Socket.any_instance.stub(:connect_nonblock).and_return do
308
- calls += 1
309
- if calls == 1
310
- raise WaitWritableError.new
311
- end
312
- raise error.new
313
- end
314
-
315
- ::IO.stub(:select).and_return []
316
- end
317
-
318
- context "should return false" do
319
- it "" do
320
- expect(subject.send(:connectable?, host, port)).to be_false
321
- end
322
-
323
- it "when the socket close throws EBAFD" do
324
- Socket.any_instance.stub(:close).and_return { raise Errno::EBADF.new }
325
-
326
- expect(subject.send(:connectable?, host, port)).to be_false
327
- end
328
- end
329
- end
330
- end
331
- end
332
243
  end
@@ -16,6 +16,34 @@ describe Ridley::HostConnector::SSH do
16
16
  }
17
17
  end
18
18
 
19
+ describe "#run" do
20
+ let(:ssh_user) { 'ssh_user' }
21
+
22
+ context "when a gateway is given" do
23
+ let(:gw_host) { "bar.com" }
24
+ let(:gw_user) { "foo" }
25
+ let(:gw_port) { "1234" }
26
+ let(:gateway) { double(Net::SSH::Gateway) }
27
+
28
+ before do
29
+ Net::SSH::Gateway.stub(:new).with(gw_host, gw_user, {:port => gw_port}).and_return(gateway)
30
+ end
31
+
32
+ it "should connect to the gateway with Net::SSH::Gateway and then to the destination host via the gateway" do
33
+ gateway.should_receive(:ssh).with(host, ssh_user, anything).ordered
34
+ gateway.should_receive(:shutdown!).ordered
35
+ subject.run(host, "some_command", ssh: { user: ssh_user, gateway: 'foo@bar.com:1234' })
36
+ end
37
+ end
38
+
39
+ context "when a gateway is not given" do
40
+ it "should use Net::SSH to connect to the destination host" do
41
+ Net::SSH.should_receive(:start).with(host, ssh_user, {:paranoid=>false, :port=>"1234", :user=>"ssh_user"})
42
+ subject.run(host, "some_command", ssh: { user: ssh_user, port: "1234" })
43
+ end
44
+ end
45
+ end
46
+
19
47
  describe "#bootstrap" do
20
48
  let(:bootstrap_context) { Ridley::BootstrapContext::Unix.new(options) }
21
49
 
@@ -94,4 +122,32 @@ describe Ridley::HostConnector::SSH do
94
122
  connector.update_omnibus(host, options)
95
123
  end
96
124
  end
125
+
126
+ describe "#connector_port_open?" do
127
+ context "when there are no ssh options specified" do
128
+ it "should try to connect to the host on the defaul ssh port" do
129
+ subject.should_receive(:port_open?).with(host, Ridley::HostConnector::SSH::DEFAULT_PORT, nil)
130
+ subject.connector_port_open?(host, {})
131
+ end
132
+ end
133
+
134
+ context "when the port is specified" do
135
+ it "should try to connecto to the host on the given port" do
136
+ subject.should_receive(:port_open?).with(host, 1234, nil)
137
+ subject.connector_port_open?(host, ssh: {port: 1234} )
138
+ end
139
+ end
140
+
141
+ context "when the gateway is given" do
142
+ it "should try to connect to the gateway host" do
143
+ subject.should_receive(:port_open?).with("bar.com", "1234", nil)
144
+ subject.connector_port_open?(host, ssh: {gateway: 'foo@bar.com:1234'} )
145
+ end
146
+
147
+ it "should use the timeout from the ssh settings" do
148
+ subject.should_receive(:port_open?).with("bar.com", "1234", 12)
149
+ subject.connector_port_open?(host, ssh: {timeout: 12, gateway: 'foo@bar.com:1234'} )
150
+ end
151
+ end
152
+ end
97
153
  end
@@ -180,4 +180,20 @@ describe Ridley::HostConnector::WinRM do
180
180
  ruby_script
181
181
  end
182
182
  end
183
+
184
+ describe "#connector_port_open?" do
185
+ context "when no winrm options are specified" do
186
+ it "should connect using the default winrm port" do
187
+ subject.should_receive(:port_open?).with(host, Ridley::HostConnector::WinRM::DEFAULT_PORT, nil)
188
+ subject.connector_port_open?(host, {})
189
+ end
190
+ end
191
+
192
+ context "when winrm options are given" do
193
+ it "should use the winrm port" do
194
+ subject.should_receive(:port_open?).with(host, 1234, nil)
195
+ subject.connector_port_open?(host, winrm: {port: 1234})
196
+ end
197
+ end
198
+ end
183
199
  end
@@ -47,4 +47,82 @@ describe Ridley::HostConnector::Base do
47
47
  expect { subject.uninstall_chef(host, options) }.to raise_error(RuntimeError)
48
48
  end
49
49
  end
50
+
51
+ describe "#connectable?" do
52
+ let(:port) { 1234 }
53
+
54
+ before do
55
+ Socket
56
+ .stub(:getaddrinfo)
57
+ .with(host, nil)
58
+ .and_return [["AF_INET", 0, "33.33.33.10", "33.33.33.10", 2, 2, 17],
59
+ ["AF_INET", 0, "33.33.33.10", "33.33.33.10", 2, 1, 6]]
60
+ end
61
+
62
+ context "when the target is accessible" do
63
+ before do
64
+ calls = 0
65
+ Socket.any_instance.stub(:connect_nonblock).and_return do
66
+ calls += 1
67
+ if calls == 1
68
+ raise WaitWritableError.new
69
+ end
70
+ raise Errno::EISCONN.new
71
+ end
72
+ end
73
+
74
+ it "should return true when a connection is initiated" do
75
+ ::IO.stub(:select).and_return ["an array!"]
76
+
77
+ expect(subject.send(:connectable?, host, port)).to be_true
78
+ end
79
+
80
+ it "should return true when a connection is initiated and an explicit nil is passed as the timeout" do
81
+ ::IO.stub(:select).with(anything, anything, anything, Ridley::HostConnector::Base::PORT_CHECK_TIMEOUT).and_return ["an array!"]
82
+
83
+ expect(subject.send(:connectable?, host, port, nil)).to be_true
84
+ end
85
+
86
+ it "should return false when select times out" do
87
+ ::IO.stub(:select).and_return nil
88
+
89
+ expect(subject.send(:connectable?, host, port)).to be_false
90
+ end
91
+
92
+ it "should return true when the connection does not have to wait" do
93
+ Socket.any_instance.stub(:connect_nonblock).and_return 0
94
+
95
+ expect(subject.send(:connectable?, host, port)).to be_true
96
+ end
97
+ end
98
+
99
+ Ridley::HostConnector::Base::CONNECTOR_PORT_ERRORS.each do |error|
100
+ context "when the target causes #{error}" do
101
+ before do
102
+ calls = 0
103
+ Socket.any_instance.stub(:connect_nonblock).and_return do
104
+ calls += 1
105
+ if calls == 1
106
+ raise WaitWritableError.new
107
+ end
108
+ raise error.new
109
+ end
110
+
111
+ ::IO.stub(:select).and_return []
112
+ end
113
+
114
+ context "should return false" do
115
+ it "" do
116
+ expect(subject.send(:connectable?, host, port)).to be_false
117
+ end
118
+
119
+ it "when the socket close throws EBAFD" do
120
+ Socket.any_instance.stub(:close).and_return { raise Errno::EBADF.new }
121
+
122
+ expect(subject.send(:connectable?, host, port)).to be_false
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
50
128
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ridley-connectors
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie Winsor
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-20 00:00:00.000000000 Z
12
+ date: 2014-06-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: celluloid
@@ -67,20 +67,34 @@ dependencies:
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
69
  version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: net-ssh-gateway
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
70
84
  - !ruby/object:Gem::Dependency
71
85
  name: ridley
72
86
  requirement: !ruby/object:Gem::Requirement
73
87
  requirements:
74
88
  - - "~>"
75
89
  - !ruby/object:Gem::Version
76
- version: '3.1'
90
+ version: '4.0'
77
91
  type: :runtime
78
92
  prerelease: false
79
93
  version_requirements: !ruby/object:Gem::Requirement
80
94
  requirements:
81
95
  - - "~>"
82
96
  - !ruby/object:Gem::Version
83
- version: '3.1'
97
+ version: '4.0'
84
98
  - !ruby/object:Gem::Dependency
85
99
  name: winrm
86
100
  requirement: !ruby/object:Gem::Requirement