remotus 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e6b07dbe42ab741bdb688bed9f6ce1d09ed2af8643291c57ec9aeedaaad0a19a
4
- data.tar.gz: a39ecf434564157c1e72d98cf840abadc1a406f91988ee7c47cf7c22d9643760
3
+ metadata.gz: 1a1fb83a5d4a7a15d98860a8342f71c5377f5c91ec842883a62cc2b6678baa96
4
+ data.tar.gz: db221756c55c43a5c0492cf8668c36e07f6e58d323b9a1b83b3688a0a9c8c92c
5
5
  SHA512:
6
- metadata.gz: f48c3e374b870a60664cf35838204755a83599a534113309abfecb40e5a5862f10091bd7bc19d8353a8a5716c71fe02dea043f891db998dd521451a998be4419
7
- data.tar.gz: 0c3d1f3e5dfbae5c2aeaec9d18f3eb4f4b99759b4c883e3298691e7cad7a91fa71d03f595cffb9bab07f9191844284a211c5fb76ff7900af56791ea6ed9a6f2a
6
+ metadata.gz: b2a57cbf28230b41b64c6e084511fa45536c8b020c7425b89d504e5ae764b16429911f5a2ff5458b2168b7ae46355e66c14279dad780d8ca38b525da66bd1694
7
+ data.tar.gz: 0bd543003bde4641d2d9527b88a72a550e700bcc65c73b76c2ef5ff0b2811c1eaae8013bb9bff34c5802b1e8fc2aa754557534908672c25eb814c8a281169788
data/.rubocop.yml CHANGED
@@ -46,3 +46,6 @@ Metrics/ParameterLists:
46
46
 
47
47
  Gemspec/RequireMFA:
48
48
  Enabled: false
49
+
50
+ Gemspec/DevelopmentDependencies:
51
+ EnforcedStyle: gemspec
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [1.2.0] - 2023-10-23
2
+ * Add `:ip` option to connection methods to accommodate credential stores that require the hostname where DNS is not available.
3
+
4
+ ## [1.1.1] - 2023-05-26
5
+ * Handle close failures and improve logging around connection status.
6
+
1
7
  ## [1.1.0] - 2023-05-25
2
8
  * Improve exponential backoff during SSH retries.
3
9
  * Force connection close on IOError (closed stream).
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- remotus (1.1.0)
4
+ remotus (1.2.0)
5
5
  connection_pool (~> 2.4)
6
6
  net-scp (~> 4.0)
7
7
  net-ssh (~> 7.1)
@@ -15,10 +15,10 @@ GEM
15
15
  specs:
16
16
  ast (2.4.2)
17
17
  builder (3.2.4)
18
- connection_pool (2.4.0)
18
+ connection_pool (2.4.1)
19
19
  diff-lcs (1.5.0)
20
20
  erubi (1.12.0)
21
- ffi (1.15.5)
21
+ ffi (1.16.3)
22
22
  gssapi (1.3.1)
23
23
  ffi (>= 1.0.1)
24
24
  gyoku (1.4.0)
@@ -33,7 +33,7 @@ GEM
33
33
  multi_json (1.15.0)
34
34
  net-scp (4.0.0)
35
35
  net-ssh (>= 2.6.5, < 8.0.0)
36
- net-ssh (7.1.0)
36
+ net-ssh (7.2.0)
37
37
  net-ssh-gateway (2.0.0)
38
38
  net-ssh (>= 4.0.0)
39
39
  nori (2.6.0)
@@ -57,7 +57,7 @@ GEM
57
57
  diff-lcs (>= 1.2.0, < 2.0)
58
58
  rspec-support (~> 3.12.0)
59
59
  rspec-support (3.12.0)
60
- rubocop (1.50.2)
60
+ rubocop (1.51.0)
61
61
  json (~> 2.3)
62
62
  parallel (~> 1.10)
63
63
  parser (>= 3.2.0.0)
@@ -67,15 +67,18 @@ GEM
67
67
  rubocop-ast (>= 1.28.0, < 2.0)
68
68
  ruby-progressbar (~> 1.7)
69
69
  unicode-display_width (>= 2.4.0, < 3.0)
70
- rubocop-ast (1.28.0)
70
+ rubocop-ast (1.28.1)
71
71
  parser (>= 3.2.1.0)
72
72
  rubocop-capybara (2.18.0)
73
73
  rubocop (~> 1.41)
74
+ rubocop-factory_bot (2.23.1)
75
+ rubocop (~> 1.33)
74
76
  rubocop-rake (0.6.0)
75
77
  rubocop (~> 1.0)
76
- rubocop-rspec (2.20.0)
78
+ rubocop-rspec (2.22.0)
77
79
  rubocop (~> 1.33)
78
80
  rubocop-capybara (~> 2.17)
81
+ rubocop-factory_bot (~> 2.22)
79
82
  ruby-progressbar (1.13.0)
80
83
  rubyntlm (0.6.3)
81
84
  rubyzip (2.3.2)
@@ -42,12 +42,16 @@ module Remotus
42
42
  # @param [Hash] metadata metadata for this connection. Useful for providing additional information to various authentication stores
43
43
  # should be specified using snake_case symbol keys. If keys are not snake_case, they will be converted.
44
44
  #
45
+ # To connect to a host via IP, the following metadata entry can be provided to the host pool:
46
+ # :ip
47
+ #
45
48
  # To configure a connection gateway, the following metadata entries can be provided to the host pool:
46
- # :gateway_host
49
+ # :gateway_host (required to use gateway)
47
50
  # :gateway_port
48
51
  # :gateway_metadata
52
+ # :gateway_ip
49
53
  #
50
- # These function similarly to the host, port, and host_pool metadata fields.
54
+ # These function similarly to the host, port, host_pool metadata, and ip fields.
51
55
  #
52
56
  def initialize(host, size: DEFAULT_POOL_SIZE, timeout: DEFAULT_EXPIRATION_SECONDS, port: nil, proto: nil, **metadata)
53
57
  Remotus.logger.debug { "Creating host pool for #{host}" }
data/lib/remotus/pool.rb CHANGED
@@ -20,6 +20,9 @@ module Remotus
20
20
  # @option options [Integer] :timeout amount of time to wait for a connection from the pool
21
21
  # @option options [Integer] :port port to use for the connection
22
22
  # @option options [Symbol] :proto protocol to use for the connection (:winrm, :ssh), must be specified if port is specified
23
+ # @option options [String] :ip IP to use for the connection, preferred over the hostname if set.
24
+ # This should be used if the hostname is required for credential retrieval
25
+ # but the hostname cannot be resolved by DNS.
23
26
  #
24
27
  # @return [Remotus::HostPool] Host pool for the given host
25
28
  #
@@ -74,13 +74,18 @@ module Remotus
74
74
  # @param [String] host hostname
75
75
  # @param [Integer] port remote port
76
76
  # @param [Remotus::HostPool] host_pool associated host pool
77
+ # To connect to a host via IP, the following metadata
78
+ # entry can be provided to the host pool:
79
+ # :ip
80
+ #
77
81
  # To configure the gateway, the following metadata
78
82
  # entries can be provided to the host pool:
79
83
  # :gateway_host
80
84
  # :gateway_port
81
85
  # :gateway_metadata
86
+ # :gateway_ip
82
87
  #
83
- # These function similarly to the host, port, and host_pool metadata fields.
88
+ # These function similarly to the host, port, host_pool metadata, and ip fields.
84
89
  #
85
90
  def initialize(host, port = REMOTE_PORT, host_pool: nil)
86
91
  Remotus.logger.debug { "Creating SshConnection #{object_id} for #{host}" }
@@ -143,10 +148,10 @@ module Remotus
143
148
 
144
149
  Remotus.logger.debug { "Initializing SSH gateway connection to #{gateway_cred.user}@#{@gateway.host}:#{gateway_options[:port]}" }
145
150
 
146
- @gateway.connection = Net::SSH::Gateway.new(@gateway.host, gateway_cred.user, **gateway_options)
147
- @connection = @gateway.connection.ssh(@host, target_cred.user, **target_options)
151
+ @gateway.connection = Net::SSH::Gateway.new(remote_gateway_host, gateway_cred.user, **gateway_options)
152
+ @connection = @gateway.connection.ssh(remote_host, target_cred.user, **target_options)
148
153
  else
149
- @connection = Net::SSH.start(@host, target_cred.user, **target_options)
154
+ @connection = Net::SSH.start(remote_host, target_cred.user, **target_options)
150
155
  end
151
156
  end
152
157
 
@@ -154,9 +159,21 @@ module Remotus
154
159
  # Closes the current SSH connection if it is active
155
160
  #
156
161
  def close
157
- @connection&.close
162
+ Remotus.logger.debug { "Closing SSH connection." }
163
+
164
+ begin
165
+ @connection&.close
166
+ rescue StandardError => e
167
+ Remotus.logger.warn { "Failed to close existing SSH connection with error #{e}" }
168
+ end
169
+
170
+ begin
171
+ @gateway&.connection&.shutdown! if via_gateway?
172
+ rescue StandardError => e
173
+ Remotus.logger.warn { "Failed to close existing SSH gateway connection with error #{e}" }
174
+ end
158
175
 
159
- @gateway&.connection&.shutdown! if via_gateway?
176
+ Remotus.logger.debug { "Setting @gateway and @connection to nil." }
160
177
 
161
178
  @gateway = nil
162
179
  @connection = nil
@@ -168,7 +185,7 @@ module Remotus
168
185
  # @return [Boolean] true if available, false otherwise
169
186
  #
170
187
  def port_open?
171
- Remotus.port_open?(@host, @port)
188
+ Remotus.port_open?(remote_host, @port)
172
189
  end
173
190
 
174
191
  #
@@ -465,7 +482,7 @@ module Remotus
465
482
  def restart_connection?
466
483
  return true unless @connection
467
484
  return true if @connection.closed?
468
- return true if @host != @connection.host
485
+ return true if remote_host != @connection.host
469
486
 
470
487
  target_cred = Remotus::Auth.credential(self)
471
488
 
@@ -481,7 +498,7 @@ module Remotus
481
498
  gateway_session = @gateway.connection.instance_variable_get(:@session)
482
499
 
483
500
  return true if gateway_session.closed?
484
- return true if @host_pool[:gateway_host] != gateway_session.host
501
+ return true if remote_gateway_host != gateway_session.host
485
502
 
486
503
  gateway_cred = Remotus::Auth.credential(@gateway)
487
504
 
@@ -572,5 +589,43 @@ module Remotus
572
589
  def via_gateway?
573
590
  host_pool && host_pool[:gateway_host]
574
591
  end
592
+
593
+ #
594
+ # Whether connecting via IP instead of hostname
595
+ #
596
+ # @return [Boolean] true if using an IP, false otherwise
597
+ #
598
+ def via_ip?
599
+ host_pool && !host_pool[:ip].to_s.empty?
600
+ end
601
+
602
+ #
603
+ # Remote host used for the connection. Will use the ip if specified, otherwise uses the hostname.
604
+ #
605
+ # @return [String] Remote host
606
+ #
607
+ def remote_host
608
+ via_ip? ? host_pool[:ip] : @host
609
+ end
610
+
611
+ #
612
+ # Whether connecting via gateway IP instead of gateway hostname
613
+ #
614
+ # @return [Boolean] true if using an IP, false otherwise
615
+ #
616
+ def via_gateway_ip?
617
+ host_pool && !host_pool[:gateway_ip].to_s.empty?
618
+ end
619
+
620
+ #
621
+ # Remote gateway host used for the connection. Will use the gateway_ip if specified, otherwise uses the hostname.
622
+ #
623
+ # @return [String] Remote gateway host
624
+ #
625
+ def remote_gateway_host
626
+ return nil unless via_gateway?
627
+
628
+ via_gateway_ip? ? host_pool[:gateway_ip] : host_pool[:gateway_host]
629
+ end
575
630
  end
576
631
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Remotus
4
4
  # Remotus gem version
5
- VERSION = "1.1.0"
5
+ VERSION = "1.2.0"
6
6
  end
@@ -69,7 +69,7 @@ module Remotus
69
69
 
70
70
  Remotus.logger.debug { "Initializing WinRM connection to #{Remotus::Auth.credential(self).user}@#{@host}:#{@port}" }
71
71
  @base_connection = WinRM::Connection.new(
72
- endpoint: "http://#{@host}:#{@port}/wsman",
72
+ endpoint: "http://#{remote_host}:#{@port}/wsman",
73
73
  transport: :negotiate,
74
74
  user: Remotus::Auth.credential(self).user,
75
75
  password: Remotus::Auth.credential(self).password
@@ -106,7 +106,7 @@ module Remotus
106
106
  # @return [Boolean] true if available, false otherwise
107
107
  #
108
108
  def port_open?
109
- Remotus.port_open?(@host, @port)
109
+ Remotus.port_open?(remote_host, @port)
110
110
  end
111
111
 
112
112
  #
@@ -195,7 +195,7 @@ module Remotus
195
195
  def restart_base_connection?
196
196
  return restart_connection?(shell: @shell) if @connection
197
197
  return true unless @base_connection
198
- return true if @host != @base_connection.instance_values["connection_opts"][:endpoint].scan(%r{//(.*):}).flatten.first
198
+ return true if remote_host != @base_connection.instance_values["connection_opts"][:endpoint].scan(%r{//(.*):}).flatten.first
199
199
  return true if Remotus::Auth.credential(self).user != @base_connection.instance_values["connection_opts"][:user]
200
200
  return true if Remotus::Auth.credential(self).password != @base_connection.instance_values["connection_opts"][:password]
201
201
 
@@ -213,11 +213,29 @@ module Remotus
213
213
  def restart_connection?(**options)
214
214
  return true unless @connection
215
215
  return true if shell && !options[:shell].casecmp?(@shell)
216
- return true if @host != @connection.connection_opts[:endpoint].scan(%r{//(.*):}).flatten.first
216
+ return true if remote_host != @connection.connection_opts[:endpoint].scan(%r{//(.*):}).flatten.first
217
217
  return true if Remotus::Auth.credential(self).user != @connection.connection_opts[:user]
218
218
  return true if Remotus::Auth.credential(self).password != @connection.connection_opts[:password]
219
219
 
220
220
  false
221
221
  end
222
+
223
+ #
224
+ # Whether connecting via IP instead of hostname
225
+ #
226
+ # @return [Boolean] true if using an IP, false otherwise
227
+ #
228
+ def via_ip?
229
+ host_pool && !host_pool[:ip].to_s.empty?
230
+ end
231
+
232
+ #
233
+ # Remote host used for the connection. Will use the ip if specified, otherwise uses the hostname.
234
+ #
235
+ # @return [String] Remote host
236
+ #
237
+ def remote_host
238
+ via_ip? ? host_pool[:ip] : @host
239
+ end
222
240
  end
223
241
  end
data/lib/remotus.rb CHANGED
@@ -18,6 +18,9 @@ module Remotus
18
18
  # @option options [Integer] :timeout amount of time to wait for a connection from the pool
19
19
  # @option options [Integer] :port port to use for the connection
20
20
  # @option options [Symbol] :proto protocol to use for the connection (:winrm, :ssh), must be specified if port is specified
21
+ # @option options [String] :ip IP to use for the connection, preferred over the hostname if set.
22
+ # This should be used if the hostname is required for credential retrieval
23
+ # but the hostname cannot be resolved by DNS.
21
24
  #
22
25
  # @return [Remotus::HostPool] Newly created or retrieved host pool
23
26
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remotus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Newell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-25 00:00:00.000000000 Z
11
+ date: 2023-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: connection_pool