ridley-connectors 2.2.0 → 2.3.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
  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