train 2.0.2 → 2.0.5
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 +4 -4
- data/lib/train/platforms/detect/helpers/os_common.rb +1 -2
- data/lib/train/platforms/detect/helpers/os_linux.rb +1 -0
- data/lib/train/plugins/base_connection.rb +13 -4
- data/lib/train/transports/cisco_ios_connection.rb +1 -1
- data/lib/train/transports/docker.rb +1 -1
- data/lib/train/transports/local.rb +1 -1
- data/lib/train/transports/mock.rb +1 -1
- data/lib/train/transports/ssh.rb +2 -1
- data/lib/train/transports/ssh_connection.rb +48 -34
- data/lib/train/transports/vmware.rb +1 -1
- data/lib/train/transports/winrm.rb +4 -0
- data/lib/train/transports/winrm_connection.rb +4 -1
- data/lib/train/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc5c0aaf06370bfbf2ee1308c13dfd87a0da5a736536c4bf3024dd3400a62861
|
4
|
+
data.tar.gz: 04e7e0b56d0acd587ce5a567e8c81b2a2b701fd87c0165271048158340958d05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68a9846a2638f11c3d5d34f340f20cd42748206307f10b930c4967745d6c6db7e803109322c36f9ee15c5b4c7e15c4c05bcbbc58acad15878ca058b2c05e1f34
|
7
|
+
data.tar.gz: 343a8c70c0e73ff1c3169e28696ad073c5611afa8bcd8425b27b25ff6bd0220084c02139ef96a95c074737df29e8418b03bb91790646c1675b552010b1514f19
|
@@ -14,8 +14,7 @@ module Train::Platforms::Detect::Helpers
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def winrm?
|
17
|
-
|
18
|
-
@backend.class == Train::Transports::WinRM::Connection
|
17
|
+
@backend.class.to_s == 'Train::Transports::WinRM::Connection'
|
19
18
|
end
|
20
19
|
|
21
20
|
def unix_file_contents(path)
|
@@ -114,10 +114,14 @@ class Train::Plugins::Transport
|
|
114
114
|
|
115
115
|
# This is the main command call for all connections. This will call the private
|
116
116
|
# run_command_via_connection on the connection with optional caching
|
117
|
-
|
118
|
-
|
117
|
+
#
|
118
|
+
# This command accepts an optional data handler block. When provided,
|
119
|
+
# inbound data will be published vi `data_handler.call(data)`. This can allow
|
120
|
+
# callers to receive and render updates from remote command execution.
|
121
|
+
def run_command(cmd, &data_handler)
|
122
|
+
return run_command_via_connection(cmd, &data_handler) unless cache_enabled?(:command)
|
119
123
|
|
120
|
-
@cache[:command][cmd] ||= run_command_via_connection(cmd)
|
124
|
+
@cache[:command][cmd] ||= run_command_via_connection(cmd, &data_handler)
|
121
125
|
end
|
122
126
|
|
123
127
|
# This is the main file call for all connections. This will call the private
|
@@ -150,8 +154,13 @@ class Train::Plugins::Transport
|
|
150
154
|
# Execute a command using this connection.
|
151
155
|
#
|
152
156
|
# @param command [String] command string to execute
|
157
|
+
# @param &data_handler(data) [Proc] proc that is called when data arrives from
|
158
|
+
# the connection. This block is optional. Individual transports will need
|
159
|
+
# to explicitly invoke the block in their implementation of run_command_via_connection;
|
160
|
+
# if they do not, the block is ignored and will not be used to report data back to the caller.
|
161
|
+
#
|
153
162
|
# @return [CommandResult] contains the result of running the command
|
154
|
-
def run_command_via_connection(_command)
|
163
|
+
def run_command_via_connection(_command, &_data_handler)
|
155
164
|
fail NotImplementedError, "#{self.class} does not implement #run_command_via_connection()"
|
156
165
|
end
|
157
166
|
|
data/lib/train/transports/ssh.rb
CHANGED
@@ -63,6 +63,7 @@ module Train::Transports
|
|
63
63
|
option :bastion_user, default: 'root'
|
64
64
|
option :bastion_port, default: 22
|
65
65
|
option :non_interactive, default: false
|
66
|
+
option :verify_host_key, default: false
|
66
67
|
|
67
68
|
option :compression_level do |opts|
|
68
69
|
# on nil or false: set compression level to 0
|
@@ -168,7 +169,7 @@ module Train::Transports
|
|
168
169
|
}
|
169
170
|
# disable host key verification. The hash key to use
|
170
171
|
# depends on the version of net-ssh in use.
|
171
|
-
connection_options[verify_host_key_option] = false
|
172
|
+
connection_options[verify_host_key_option] = opts[:verify_host_key] || false
|
172
173
|
|
173
174
|
connection_options
|
174
175
|
end
|
@@ -207,44 +207,12 @@ class Train::Transports::SSH
|
|
207
207
|
end
|
208
208
|
end
|
209
209
|
|
210
|
-
def run_command_via_connection(cmd)
|
211
|
-
stdout = stderr = ''
|
212
|
-
exit_status = nil
|
210
|
+
def run_command_via_connection(cmd, &data_handler)
|
213
211
|
cmd.dup.force_encoding('binary') if cmd.respond_to?(:force_encoding)
|
214
212
|
logger.debug("[SSH] #{self} (#{cmd})")
|
215
213
|
|
216
214
|
reset_session if session.closed?
|
217
|
-
|
218
|
-
# wrap commands if that is configured
|
219
|
-
cmd = @cmd_wrapper.run(cmd) unless @cmd_wrapper.nil?
|
220
|
-
|
221
|
-
if @transport_options[:pty]
|
222
|
-
channel.request_pty do |_ch, success|
|
223
|
-
fail Train::Transports::SSHPTYFailed, 'Requesting PTY failed' unless success
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
channel.exec(cmd) do |_, success|
|
228
|
-
abort 'Couldn\'t execute command on SSH.' unless success
|
229
|
-
|
230
|
-
channel.on_data do |_, data|
|
231
|
-
stdout += data
|
232
|
-
end
|
233
|
-
|
234
|
-
channel.on_extended_data do |_, _type, data|
|
235
|
-
stderr += data
|
236
|
-
end
|
237
|
-
|
238
|
-
channel.on_request('exit-status') do |_, data|
|
239
|
-
exit_status = data.read_long
|
240
|
-
end
|
241
|
-
|
242
|
-
channel.on_request('exit-signal') do |_, data|
|
243
|
-
exit_status = data.read_long
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
@session.loop
|
215
|
+
exit_status, stdout, stderr = execute_on_channel(cmd, &data_handler)
|
248
216
|
|
249
217
|
# Since `@session.loop` succeeded, reset the IOS command retry counter
|
250
218
|
@ios_cmd_retries = 0
|
@@ -293,5 +261,51 @@ class Train::Transports::SSH
|
|
293
261
|
options_to_print[:password] = '<hidden>' if options_to_print.key?(:password)
|
294
262
|
"#{@username}@#{@hostname}<#{options_to_print.inspect}>"
|
295
263
|
end
|
264
|
+
|
265
|
+
# Given a channel and a command string, it will execute the command on the channel
|
266
|
+
# and accumulate results in @stdout/@stderr.
|
267
|
+
#
|
268
|
+
# @param channel [Net::SSH::Connection::Channel] an open ssh channel
|
269
|
+
# @param cmd [String] the command to execute
|
270
|
+
# @return [Integer] exit status or nil if exit-status/exit-signal requests
|
271
|
+
# not received.
|
272
|
+
#
|
273
|
+
# @api private
|
274
|
+
def execute_on_channel(cmd, &data_handler)
|
275
|
+
stdout = stderr = ''
|
276
|
+
exit_status = nil
|
277
|
+
session.open_channel do |channel|
|
278
|
+
# wrap commands if that is configured
|
279
|
+
cmd = @cmd_wrapper.run(cmd) unless @cmd_wrapper.nil?
|
280
|
+
|
281
|
+
if @transport_options[:pty]
|
282
|
+
channel.request_pty do |_ch, success|
|
283
|
+
fail Train::Transports::SSHPTYFailed, 'Requesting PTY failed' unless success
|
284
|
+
end
|
285
|
+
end
|
286
|
+
channel.exec(cmd) do |_, success|
|
287
|
+
abort 'Couldn\'t execute command on SSH.' unless success
|
288
|
+
channel.on_data do |_, data|
|
289
|
+
yield(data) unless data_handler.nil?
|
290
|
+
stdout += data
|
291
|
+
end
|
292
|
+
|
293
|
+
channel.on_extended_data do |_, _type, data|
|
294
|
+
yield(data) unless data_handler.nil?
|
295
|
+
stderr += data
|
296
|
+
end
|
297
|
+
|
298
|
+
channel.on_request('exit-status') do |_, data|
|
299
|
+
exit_status = data.read_long
|
300
|
+
end
|
301
|
+
|
302
|
+
channel.on_request('exit-signal') do |_, data|
|
303
|
+
exit_status = data.read_long
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
session.loop
|
308
|
+
[exit_status, stdout, stderr]
|
309
|
+
end
|
296
310
|
end
|
297
311
|
end
|
@@ -64,6 +64,10 @@ module Train::Transports
|
|
64
64
|
option :kerberos_realm, default: nil
|
65
65
|
option :kerberos_service, default: nil
|
66
66
|
option :ca_trust_file, default: nil
|
67
|
+
# The amount of time in SECONDS for which each operation must get an ack
|
68
|
+
# from the winrm endpoint. Does not mean that the command has
|
69
|
+
# completed in this time, only that the server has ack'd the request.
|
70
|
+
option :operation_timeout, default: nil
|
67
71
|
|
68
72
|
def initialize(opts)
|
69
73
|
super(opts)
|
@@ -36,6 +36,7 @@ class Train::Transports::WinRM
|
|
36
36
|
@connection_retries = @options.delete(:connection_retries)
|
37
37
|
@connection_retry_sleep = @options.delete(:connection_retry_sleep)
|
38
38
|
@max_wait_until_ready = @options.delete(:max_wait_until_ready)
|
39
|
+
@operation_timeout = @options.delete(:operation_timeout)
|
39
40
|
end
|
40
41
|
|
41
42
|
# (see Base::Connection#close)
|
@@ -95,12 +96,13 @@ class Train::Transports::WinRM
|
|
95
96
|
Train::File::Remote::Windows.new(self, path)
|
96
97
|
end
|
97
98
|
|
98
|
-
def run_command_via_connection(command)
|
99
|
+
def run_command_via_connection(command, &data_handler)
|
99
100
|
return if command.nil?
|
100
101
|
logger.debug("[WinRM] #{self} (#{command})")
|
101
102
|
out = ''
|
102
103
|
|
103
104
|
response = session.run(command) do |stdout, _|
|
105
|
+
yield(stdout) if data_handler && stdout
|
104
106
|
out << stdout if stdout
|
105
107
|
end
|
106
108
|
|
@@ -178,6 +180,7 @@ class Train::Transports::WinRM
|
|
178
180
|
retry_delay: @connection_retry_sleep.to_i,
|
179
181
|
}.merge(retry_options)
|
180
182
|
|
183
|
+
opts[:operation_timeout] = @operation_timeout unless @operation_timeout.nil?
|
181
184
|
@service = ::WinRM::Connection.new(options.merge(opts))
|
182
185
|
@service.logger = logger
|
183
186
|
@service.shell(:powershell)
|
data/lib/train/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: train
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Richter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -308,7 +308,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
308
308
|
- !ruby/object:Gem::Version
|
309
309
|
version: '0'
|
310
310
|
requirements: []
|
311
|
-
rubygems_version: 3.0.
|
311
|
+
rubygems_version: 3.0.3
|
312
312
|
signing_key:
|
313
313
|
specification_version: 4
|
314
314
|
summary: Transport interface to talk to different backends.
|