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 +4 -4
- data/lib/ridley-connectors/host_commander.rb +5 -90
- data/lib/ridley-connectors/host_connector.rb +87 -0
- data/lib/ridley-connectors/host_connector/ssh.rb +63 -2
- data/lib/ridley-connectors/host_connector/winrm.rb +17 -0
- data/lib/ridley-connectors/version.rb +1 -1
- data/ridley-connectors.gemspec +2 -1
- data/spec/unit/ridley-connectors/host_commander_spec.rb +36 -125
- data/spec/unit/ridley-connectors/host_connector/ssh_spec.rb +56 -0
- data/spec/unit/ridley-connectors/host_connector/winrm_spec.rb +16 -0
- data/spec/unit/ridley-connectors/host_connector_spec.rb +78 -0
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0963bedc809b1573895731a6ef403acd8bb22d36
|
4
|
+
data.tar.gz: 585e09bb5fe887c8b234c93e447353c5c632eca4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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?) &&
|
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?) &&
|
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
|
-
|
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
|
data/ridley-connectors.gemspec
CHANGED
@@ -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 '
|
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.
|
16
|
-
subject.
|
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.
|
28
|
-
subject.
|
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.
|
47
|
-
subject.
|
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.
|
60
|
-
subject.
|
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.
|
79
|
-
subject.
|
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.
|
92
|
-
subject.
|
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.
|
112
|
-
subject.
|
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.
|
125
|
-
subject.
|
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.
|
145
|
-
subject.
|
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.
|
158
|
-
subject.
|
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
|
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.
|
194
|
-
subject.
|
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.
|
200
|
-
subject.
|
201
|
-
subject.
|
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.
|
217
|
-
subject.
|
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(:
|
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.
|
233
|
-
subject.
|
234
|
-
subject.
|
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.
|
240
|
-
subject.
|
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(:
|
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.
|
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-
|
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: '
|
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: '
|
97
|
+
version: '4.0'
|
84
98
|
- !ruby/object:Gem::Dependency
|
85
99
|
name: winrm
|
86
100
|
requirement: !ruby/object:Gem::Requirement
|