train-core 3.3.21 → 3.4.7
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.rb +3 -0
- data/lib/train/errors.rb +3 -0
- data/lib/train/extras/command_wrapper.rb +1 -1
- data/lib/train/platforms/detect/helpers/os_windows.rb +15 -10
- data/lib/train/platforms/detect/uuid.rb +1 -1
- data/lib/train/plugins/base_connection.rb +21 -4
- data/lib/train/transports/local.rb +2 -2
- data/lib/train/transports/mock.rb +1 -1
- data/lib/train/transports/ssh.rb +1 -0
- data/lib/train/transports/ssh_connection.rb +28 -9
- 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: e85ed8cc37da145f7dabcff7855b85b9c2a6bc8f216945aeaa693843c07f8b95
|
4
|
+
data.tar.gz: a4ac06f8b1c2ced955d933ba1a9553d9434c9d255d11ec5d8cc43e14e1cc0469
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b920c8d01dbdd94eae308fcca501cf9dc5f24619f8e023e4c5cedbdd11eebcfc4b4bcb41683435325f3ede4afa5b6a7981164e1cf8242aa472e2e801282c284
|
7
|
+
data.tar.gz: e3d5e835b15d0cc84f86066fe66aafc7456544f53fbe91d2a66c7341ed4db3b2f6a3d890e98aab26d0fe294af587fc246a89a10c7d56b9f4ac1cf09a99fae9d8
|
data/lib/train.rb
CHANGED
@@ -113,6 +113,9 @@ module Train
|
|
113
113
|
# TODO: rewrite next line using compact! once we drop support for ruby 2.3
|
114
114
|
creds = creds.delete_if { |_, value| value.nil? }
|
115
115
|
|
116
|
+
# merge train options in from the URI query string
|
117
|
+
creds.merge!(uri.query_values.map { |k, v| [k.to_sym, v] }.to_h) unless uri.query_values.nil?
|
118
|
+
|
116
119
|
# return the updated config
|
117
120
|
creds
|
118
121
|
end
|
data/lib/train/errors.rb
CHANGED
@@ -33,15 +33,20 @@ module Train::Platforms::Detect::Helpers
|
|
33
33
|
command = @backend.run_command(
|
34
34
|
"Get-WmiObject Win32_OperatingSystem | Select Caption,Version | ConvertTo-Json"
|
35
35
|
)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
36
|
+
# some targets (e.g. Cisco) may return 0 and print an error to stdout
|
37
|
+
return false if (command.exit_status != 0) || command.stdout.downcase !~ /window/
|
38
|
+
|
39
|
+
begin
|
40
|
+
payload = JSON.parse(command.stdout)
|
41
|
+
@platform[:family] = "windows"
|
42
|
+
@platform[:release] = payload["Version"]
|
43
|
+
@platform[:name] = payload["Caption"]
|
44
|
+
|
45
|
+
read_wmic
|
46
|
+
true
|
47
|
+
rescue
|
48
|
+
false
|
49
|
+
end
|
45
50
|
end
|
46
51
|
|
47
52
|
def local_windows?
|
@@ -126,7 +131,7 @@ module Train::Platforms::Detect::Helpers
|
|
126
131
|
return if !file.exist? || file.size == 0
|
127
132
|
|
128
133
|
json = JSON.parse(file.content)
|
129
|
-
json["node_uuid"]
|
134
|
+
json["node_uuid"]
|
130
135
|
end
|
131
136
|
|
132
137
|
def windows_uuid_from_wmic
|
@@ -130,10 +130,27 @@ class Train::Plugins::Transport
|
|
130
130
|
# This command accepts an optional data handler block. When provided,
|
131
131
|
# inbound data will be published vi `data_handler.call(data)`. This can allow
|
132
132
|
# callers to receive and render updates from remote command execution.
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
133
|
+
#
|
134
|
+
# @param [String] the command to run
|
135
|
+
# @param [Hash] optional hash of options for this command. The derived connection
|
136
|
+
# class's implementation of run_command_via_connection should receive
|
137
|
+
# and apply these options.
|
138
|
+
def run_command(cmd, opts = {}, &data_handler)
|
139
|
+
# Some implementations do not accept an opts argument.
|
140
|
+
# We cannot update all implementations to accept opts due to them being separate plugins.
|
141
|
+
# Therefore here we check the implementation's arity to maintain compatibility.
|
142
|
+
case method(:run_command_via_connection).arity.abs
|
143
|
+
when 1
|
144
|
+
return run_command_via_connection(cmd, &data_handler) unless cache_enabled?(:command)
|
145
|
+
|
146
|
+
@cache[:command][cmd] ||= run_command_via_connection(cmd, &data_handler)
|
147
|
+
when 2
|
148
|
+
return run_command_via_connection(cmd, opts, &data_handler) unless cache_enabled?(:command)
|
149
|
+
|
150
|
+
@cache[:command][cmd] ||= run_command_via_connection(cmd, opts, &data_handler)
|
151
|
+
else
|
152
|
+
raise NotImplementedError, "#{self.class} does not implement run_command_via_connection with arity #{method(:run_command_via_connection).arity}"
|
153
|
+
end
|
137
154
|
end
|
138
155
|
|
139
156
|
# This is the main file call for all connections. This will call the private
|
@@ -112,7 +112,7 @@ module Train::Transports
|
|
112
112
|
|
113
113
|
class WindowsShellRunner
|
114
114
|
require "json" unless defined?(JSON)
|
115
|
-
require "base64"
|
115
|
+
require "base64" unless defined?(Base64)
|
116
116
|
|
117
117
|
def initialize(powershell_cmd = "powershell")
|
118
118
|
@powershell_cmd = powershell_cmd
|
@@ -136,7 +136,7 @@ module Train::Transports
|
|
136
136
|
|
137
137
|
class WindowsPipeRunner
|
138
138
|
require "json" unless defined?(JSON)
|
139
|
-
require "base64"
|
139
|
+
require "base64" unless defined?(Base64)
|
140
140
|
require "securerandom" unless defined?(SecureRandom)
|
141
141
|
|
142
142
|
def initialize(powershell_cmd = "powershell")
|
data/lib/train/transports/ssh.rb
CHANGED
@@ -63,6 +63,7 @@ module Train::Transports
|
|
63
63
|
option :bastion_port, default: 22
|
64
64
|
option :non_interactive, default: false
|
65
65
|
option :verify_host_key, default: false
|
66
|
+
option :forward_agent, default: false
|
66
67
|
|
67
68
|
# Allow connecting with older algorithms
|
68
69
|
option :append_all_supported_algorithms, default: true
|
@@ -72,13 +72,18 @@ class Train::Transports::SSH
|
|
72
72
|
|
73
73
|
args = %w{ -o UserKnownHostsFile=/dev/null }
|
74
74
|
args += %w{ -o StrictHostKeyChecking=no }
|
75
|
-
args += %w{ -o
|
76
|
-
args += %w{ -o BatchMode=yes } if options[:non_interactive]
|
75
|
+
args += %w{ -o BatchMode=yes } if options[:non_interactive]
|
77
76
|
args += %W{ -o LogLevel=#{level} }
|
78
77
|
args += %W{ -o ForwardAgent=#{fwd_agent} } if options.key?(:forward_agent)
|
79
|
-
|
80
|
-
|
78
|
+
|
79
|
+
keys = Array(options[:keys])
|
80
|
+
unless keys.empty?
|
81
|
+
args += %w{ -o IdentitiesOnly=yes }
|
82
|
+
keys.each do |ssh_key|
|
83
|
+
args += %W{ -i #{ssh_key} }
|
84
|
+
end
|
81
85
|
end
|
86
|
+
|
82
87
|
args
|
83
88
|
end
|
84
89
|
|
@@ -235,12 +240,12 @@ class Train::Transports::SSH
|
|
235
240
|
end
|
236
241
|
end
|
237
242
|
|
238
|
-
def run_command_via_connection(cmd, &data_handler)
|
243
|
+
def run_command_via_connection(cmd, opts = {}, &data_handler)
|
239
244
|
cmd.dup.force_encoding("binary") if cmd.respond_to?(:force_encoding)
|
240
245
|
|
241
246
|
reset_session if session.closed?
|
242
247
|
|
243
|
-
exit_status, stdout, stderr = execute_on_channel(cmd, &data_handler)
|
248
|
+
exit_status, stdout, stderr = execute_on_channel(cmd, opts, &data_handler)
|
244
249
|
|
245
250
|
# Since `@session.loop` succeeded, reset the IOS command retry counter
|
246
251
|
@ios_cmd_retries = 0
|
@@ -297,7 +302,8 @@ class Train::Transports::SSH
|
|
297
302
|
# not received.
|
298
303
|
#
|
299
304
|
# @api private
|
300
|
-
def execute_on_channel(cmd)
|
305
|
+
def execute_on_channel(cmd, opts)
|
306
|
+
timeout = opts[:timeout]&.to_i
|
301
307
|
stdout = ""
|
302
308
|
stderr = ""
|
303
309
|
exit_status = nil
|
@@ -307,7 +313,7 @@ class Train::Transports::SSH
|
|
307
313
|
|
308
314
|
logger.debug("[SSH] #{self} cmd = #{cmd}")
|
309
315
|
|
310
|
-
if @transport_options[:pty]
|
316
|
+
if @transport_options[:pty] || timeout
|
311
317
|
channel.request_pty do |_ch, success|
|
312
318
|
raise Train::Transports::SSHPTYFailed, "Requesting PTY failed" unless success
|
313
319
|
end
|
@@ -334,7 +340,20 @@ class Train::Transports::SSH
|
|
334
340
|
end
|
335
341
|
end
|
336
342
|
end
|
337
|
-
|
343
|
+
|
344
|
+
thr = Thread.new { session.loop }
|
345
|
+
|
346
|
+
if timeout
|
347
|
+
res = thr.join(timeout)
|
348
|
+
unless res
|
349
|
+
logger.debug("train ssh command '#{cmd}' reached requested timeout (#{timeout}s)")
|
350
|
+
session.channels.each_value { |c| c.eof!; c.close }
|
351
|
+
raise Train::CommandTimeoutReached.new "ssh command reached timeout (#{timeout}s)"
|
352
|
+
end
|
353
|
+
else
|
354
|
+
thr.join
|
355
|
+
end
|
356
|
+
|
338
357
|
[exit_status, stdout, stderr]
|
339
358
|
end
|
340
359
|
end
|
data/lib/train/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: train-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef InSpec Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -188,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
188
|
- !ruby/object:Gem::Version
|
189
189
|
version: '0'
|
190
190
|
requirements: []
|
191
|
-
rubygems_version: 3.
|
191
|
+
rubygems_version: 3.1.4
|
192
192
|
signing_key:
|
193
193
|
specification_version: 4
|
194
194
|
summary: Transport interface to talk to a selected set of backends.
|