train 2.0.2 → 2.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|