train-core 3.3.4 → 3.3.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/train.rb +1 -2
- data/lib/train/errors.rb +3 -1
- data/lib/train/extras.rb +0 -1
- data/lib/train/extras/command_wrapper.rb +1 -2
- data/lib/train/extras/stat.rb +0 -1
- data/lib/train/file.rb +0 -1
- data/lib/train/file/local.rb +0 -2
- data/lib/train/file/local/unix.rb +1 -3
- data/lib/train/file/local/windows.rb +0 -2
- data/lib/train/file/remote.rb +0 -2
- data/lib/train/file/remote/aix.rb +0 -2
- data/lib/train/file/remote/linux.rb +0 -2
- data/lib/train/file/remote/qnx.rb +0 -1
- data/lib/train/file/remote/unix.rb +1 -1
- data/lib/train/file/remote/windows.rb +0 -2
- data/lib/train/options.rb +0 -1
- data/lib/train/platforms.rb +0 -2
- data/lib/train/platforms/common.rb +0 -2
- data/lib/train/platforms/detect.rb +0 -2
- data/lib/train/platforms/detect/helpers/os_common.rb +17 -9
- data/lib/train/platforms/detect/helpers/os_linux.rb +0 -2
- data/lib/train/platforms/detect/scanner.rb +0 -2
- data/lib/train/platforms/detect/specifications/api.rb +0 -2
- data/lib/train/platforms/detect/specifications/os.rb +2 -2
- data/lib/train/platforms/detect/uuid.rb +3 -3
- data/lib/train/platforms/family.rb +0 -2
- data/lib/train/platforms/platform.rb +1 -3
- data/lib/train/plugin_test_helper.rb +5 -5
- data/lib/train/plugins.rb +1 -2
- data/lib/train/plugins/base_connection.rb +22 -7
- data/lib/train/plugins/transport.rb +0 -1
- data/lib/train/transports/cisco_ios_connection.rb +0 -2
- data/lib/train/transports/local.rb +7 -8
- data/lib/train/transports/mock.rb +1 -1
- data/lib/train/transports/ssh.rb +2 -3
- data/lib/train/transports/ssh_connection.rb +21 -8
- data/lib/train/version.rb +1 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b4cd9dbab0f4f3706d077a9c26185998bbdc4925ef03783b90c9244e268990d
|
4
|
+
data.tar.gz: a13777cd6b9e682fae479da36147ef17cbf01cf09c2d70f3377bf916e021be0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36d220f296af3ac7d239a38726c0ccf6764ff171ea73004ea700c637b05233132e79619ea05de4fedbc098493baef6ea1095126325fd988475cf4a0a05ccce66
|
7
|
+
data.tar.gz: 6f8b09680a850f138c217bbfc03ae18e44a117d08842d8ca00a7055931a39e95e3be3652a851a4904171f7a80e58776cf1ff2220affaa19833c495d28e10cbe7
|
data/lib/train.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
#
|
3
2
|
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
4
3
|
|
@@ -7,7 +6,7 @@ require_relative "train/options"
|
|
7
6
|
require_relative "train/plugins"
|
8
7
|
require_relative "train/errors"
|
9
8
|
require_relative "train/platforms"
|
10
|
-
require "addressable/uri"
|
9
|
+
require "addressable/uri" unless defined?(Addressable::URI)
|
11
10
|
|
12
11
|
module Train
|
13
12
|
# Create a new transport instance, with the plugin indicated by the
|
data/lib/train/errors.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
#
|
3
2
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
3
|
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
@@ -41,4 +40,7 @@ module Train
|
|
41
40
|
|
42
41
|
# Exception for when a invalid cache type is passed.
|
43
42
|
class UnknownCacheType < Error; end
|
43
|
+
|
44
|
+
# Exception for when a command reaches configured timeout
|
45
|
+
class CommandTimeoutReached < Error; end
|
44
46
|
end
|
data/lib/train/extras.rb
CHANGED
data/lib/train/extras/stat.rb
CHANGED
data/lib/train/file.rb
CHANGED
data/lib/train/file/local.rb
CHANGED
data/lib/train/file/remote.rb
CHANGED
data/lib/train/options.rb
CHANGED
data/lib/train/platforms.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative "os_linux"
|
2
2
|
require_relative "os_windows"
|
3
|
-
require "rbconfig"
|
3
|
+
require "rbconfig" unless defined?(RbConfig)
|
4
4
|
|
5
5
|
module Train::Platforms::Detect::Helpers
|
6
6
|
module OSCommon
|
@@ -34,16 +34,24 @@ module Train::Platforms::Detect::Helpers
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def command_output(cmd)
|
37
|
-
res = @backend.run_command(cmd)
|
38
|
-
|
39
|
-
|
37
|
+
res = @backend.run_command(cmd)
|
38
|
+
stdout = res.stdout
|
39
|
+
stderr = res.stderr
|
40
|
+
# When you try to execute command using ssh connection as root user and you have provided ssh user identity file
|
41
|
+
# it gives standard output to login as authorized user other than root. To show this standard output as an error
|
40
42
|
# to user we are matching the string of stdout and raising the error here so that user gets exact information.
|
41
|
-
if @backend.class.to_s == "Train::Transports::SSH::Connection"
|
42
|
-
|
43
|
+
if @backend.class.to_s == "Train::Transports::SSH::Connection"
|
44
|
+
if stdout =~ /Please login as the user/
|
45
|
+
raise Train::UserError, "SSH failed: #{stdout}"
|
46
|
+
end
|
47
|
+
|
48
|
+
if stderr =~ /WARNING: Your password has expired/
|
49
|
+
raise Train::UserError, "SSH failed: #{stderr}"
|
50
|
+
end
|
43
51
|
end
|
44
52
|
|
45
|
-
|
46
|
-
|
53
|
+
stdout.strip! unless stdout.nil?
|
54
|
+
stdout
|
47
55
|
end
|
48
56
|
|
49
57
|
def unix_uname_s
|
@@ -157,7 +165,7 @@ module Train::Platforms::Detect::Helpers
|
|
157
165
|
def json_cmd(cmd)
|
158
166
|
cmd = @backend.run_command(cmd)
|
159
167
|
if cmd.exit_status == 0 && !cmd.stdout.empty?
|
160
|
-
require "json"
|
168
|
+
require "json" unless defined?(JSON)
|
161
169
|
eos_ver = JSON.parse(cmd.stdout)
|
162
170
|
@platform[:release] = eos_ver["version"]
|
163
171
|
@platform[:arch] = eos_ver["architecture"]
|
@@ -128,7 +128,7 @@ module Train::Platforms::Detect::Specifications
|
|
128
128
|
|
129
129
|
declare_lsb("scientific", "Scientific Linux", "redhat", /scientific/i)
|
130
130
|
|
131
|
-
declare_lsb("xenserver", "
|
131
|
+
declare_lsb("xenserver", "Xenserver Linux", "redhat", /xenserver/i)
|
132
132
|
|
133
133
|
declare_instance("parallels-release", "Parallels Linux", "redhat") do
|
134
134
|
if (raw = unix_file_contents("/etc/parallels-release"))
|
@@ -357,7 +357,7 @@ module Train::Platforms::Detect::Specifications
|
|
357
357
|
declare_instance("mac_os_x", "macOS X", "darwin") do
|
358
358
|
cmd = unix_file_contents("/System/Library/CoreServices/SystemVersion.plist")
|
359
359
|
@platform[:uuid_command] = "system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }'"
|
360
|
-
cmd =~ /Mac OS X/i
|
360
|
+
cmd =~ /Mac OS X|macOS/i
|
361
361
|
end
|
362
362
|
|
363
363
|
declare_instance("darwin", "Darwin", "darwin") do
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Train::Platforms
|
4
2
|
class Platform
|
5
3
|
include Train::Platforms::Common
|
@@ -47,7 +45,7 @@ module Train::Platforms
|
|
47
45
|
@uuid ||= Train::Platforms::Detect::UUID.new(self).find_or_create_uuid.downcase
|
48
46
|
end
|
49
47
|
|
50
|
-
# This is for
|
48
|
+
# This is for backwards compatibility with
|
51
49
|
# the current inspec os resource.
|
52
50
|
def[](name)
|
53
51
|
if respond_to?(name)
|
@@ -13,13 +13,13 @@ require "minitest/spec"
|
|
13
13
|
require "minitest/autorun"
|
14
14
|
|
15
15
|
# Data formats commonly used in testing
|
16
|
-
require "json"
|
17
|
-
require "ostruct"
|
16
|
+
require "json" unless defined?(JSON)
|
17
|
+
require "ostruct" unless defined?(OpenStruct)
|
18
18
|
|
19
19
|
# Utilities often needed
|
20
|
-
require "fileutils"
|
21
|
-
require "tmpdir"
|
22
|
-
require "pathname"
|
20
|
+
require "fileutils" unless defined?(FileUtils)
|
21
|
+
require "tmpdir" unless defined?(Dir.mktmpdir)
|
22
|
+
require "pathname" unless defined?(Pathname)
|
23
23
|
|
24
24
|
# You might want to put some debugging tools here. We run tests to find bugs,
|
25
25
|
# after all.
|
data/lib/train/plugins.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
#
|
3
2
|
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
4
3
|
# Author:: Christoph Hartmann (<chris@lollyrock.com>)
|
@@ -24,7 +23,7 @@ module Train
|
|
24
23
|
# Create a versioned plugin by providing the transport layer plugin version
|
25
24
|
# to this method. It will then select the correct class to inherit from.
|
26
25
|
#
|
27
|
-
# The plugin version
|
26
|
+
# The plugin version determines what methods will be available to your plugin.
|
28
27
|
#
|
29
28
|
# @param [Int] version = 1 the plugin version to use
|
30
29
|
# @return [Transport] the versioned transport base class
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require_relative "../errors"
|
4
2
|
require_relative "../extras"
|
5
3
|
require_relative "../file"
|
@@ -132,10 +130,27 @@ class Train::Plugins::Transport
|
|
132
130
|
# This command accepts an optional data handler block. When provided,
|
133
131
|
# inbound data will be published vi `data_handler.call(data)`. This can allow
|
134
132
|
# callers to receive and render updates from remote command execution.
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
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
|
139
154
|
end
|
140
155
|
|
141
156
|
# This is the main file call for all connections. This will call the private
|
@@ -160,7 +175,7 @@ class Train::Plugins::Transport
|
|
160
175
|
# service is preferred to simply waiting on a socket to become
|
161
176
|
# available.
|
162
177
|
def wait_until_ready
|
163
|
-
# this method may be left unimplemented if that is
|
178
|
+
# this method may be left unimplemented if that is applicable log
|
164
179
|
end
|
165
180
|
|
166
181
|
private
|
@@ -1,11 +1,10 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
#
|
3
2
|
# author: Dominik Richter
|
4
3
|
# author: Christoph Hartmann
|
5
4
|
|
6
5
|
require_relative "../plugins"
|
7
6
|
require_relative "../errors"
|
8
|
-
require "mixlib/shellout"
|
7
|
+
require "mixlib/shellout" unless defined?(Mixlib::ShellOut)
|
9
8
|
|
10
9
|
module Train::Transports
|
11
10
|
class Local < Train.plugin(1)
|
@@ -112,8 +111,8 @@ module Train::Transports
|
|
112
111
|
end
|
113
112
|
|
114
113
|
class WindowsShellRunner
|
115
|
-
require "json"
|
116
|
-
require "base64"
|
114
|
+
require "json" unless defined?(JSON)
|
115
|
+
require "base64" unless defined?(Base64)
|
117
116
|
|
118
117
|
def initialize(powershell_cmd = "powershell")
|
119
118
|
@powershell_cmd = powershell_cmd
|
@@ -136,9 +135,9 @@ module Train::Transports
|
|
136
135
|
end
|
137
136
|
|
138
137
|
class WindowsPipeRunner
|
139
|
-
require "json"
|
140
|
-
require "base64"
|
141
|
-
require "securerandom"
|
138
|
+
require "json" unless defined?(JSON)
|
139
|
+
require "base64" unless defined?(Base64)
|
140
|
+
require "securerandom" unless defined?(SecureRandom)
|
142
141
|
|
143
142
|
def initialize(powershell_cmd = "powershell")
|
144
143
|
@powershell_cmd = powershell_cmd
|
@@ -147,7 +146,7 @@ module Train::Transports
|
|
147
146
|
end
|
148
147
|
|
149
148
|
# @param cmd The command to execute
|
150
|
-
# @return Local::
|
149
|
+
# @return Local::CommandResult with stdout, stderr and exitstatus
|
151
150
|
# Note that exitstatus ($?) in PowerShell is boolean, but we use a numeric exit code.
|
152
151
|
# A command that succeeds without setting an exit code will have exitstatus 0
|
153
152
|
# A command that exits with an exit code will have that value as exitstatus
|
data/lib/train/transports/ssh.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
#
|
3
2
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
3
|
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
@@ -18,7 +17,7 @@
|
|
18
17
|
# See the License for the specific language governing permissions and
|
19
18
|
# limitations under the License.
|
20
19
|
|
21
|
-
require "net/ssh"
|
20
|
+
require "net/ssh" unless defined?(Net::SSH)
|
22
21
|
require "net/scp"
|
23
22
|
require_relative "../errors"
|
24
23
|
|
@@ -238,7 +237,7 @@ module Train::Transports
|
|
238
237
|
# Creates a new SSH Connection instance and save it for potential future
|
239
238
|
# reuse.
|
240
239
|
#
|
241
|
-
# @param options [Hash]
|
240
|
+
# @param options [Hash] connection options
|
242
241
|
# @return [Ssh::Connection] an SSH Connection instance
|
243
242
|
# @api private
|
244
243
|
def create_new_connection(options, &block)
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
#
|
3
2
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
3
|
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
@@ -18,9 +17,9 @@
|
|
18
17
|
# See the License for the specific language governing permissions and
|
19
18
|
# limitations under the License.
|
20
19
|
|
21
|
-
require "net/ssh"
|
20
|
+
require "net/ssh" unless defined?(Net::SSH)
|
22
21
|
require "net/scp"
|
23
|
-
require "timeout"
|
22
|
+
require "timeout" unless defined?(Timeout)
|
24
23
|
|
25
24
|
class Train::Transports::SSH
|
26
25
|
# A Connection instance can be generated and re-generated, given new
|
@@ -236,12 +235,12 @@ class Train::Transports::SSH
|
|
236
235
|
end
|
237
236
|
end
|
238
237
|
|
239
|
-
def run_command_via_connection(cmd, &data_handler)
|
238
|
+
def run_command_via_connection(cmd, opts = {}, &data_handler)
|
240
239
|
cmd.dup.force_encoding("binary") if cmd.respond_to?(:force_encoding)
|
241
240
|
|
242
241
|
reset_session if session.closed?
|
243
242
|
|
244
|
-
exit_status, stdout, stderr = execute_on_channel(cmd, &data_handler)
|
243
|
+
exit_status, stdout, stderr = execute_on_channel(cmd, opts, &data_handler)
|
245
244
|
|
246
245
|
# Since `@session.loop` succeeded, reset the IOS command retry counter
|
247
246
|
@ios_cmd_retries = 0
|
@@ -298,7 +297,8 @@ class Train::Transports::SSH
|
|
298
297
|
# not received.
|
299
298
|
#
|
300
299
|
# @api private
|
301
|
-
def execute_on_channel(cmd)
|
300
|
+
def execute_on_channel(cmd, opts)
|
301
|
+
timeout = opts[:timeout]&.to_i
|
302
302
|
stdout = ""
|
303
303
|
stderr = ""
|
304
304
|
exit_status = nil
|
@@ -308,7 +308,7 @@ class Train::Transports::SSH
|
|
308
308
|
|
309
309
|
logger.debug("[SSH] #{self} cmd = #{cmd}")
|
310
310
|
|
311
|
-
if @transport_options[:pty]
|
311
|
+
if @transport_options[:pty] || timeout
|
312
312
|
channel.request_pty do |_ch, success|
|
313
313
|
raise Train::Transports::SSHPTYFailed, "Requesting PTY failed" unless success
|
314
314
|
end
|
@@ -335,7 +335,20 @@ class Train::Transports::SSH
|
|
335
335
|
end
|
336
336
|
end
|
337
337
|
end
|
338
|
-
|
338
|
+
|
339
|
+
thr = Thread.new { session.loop }
|
340
|
+
|
341
|
+
if timeout
|
342
|
+
res = thr.join(timeout)
|
343
|
+
unless res
|
344
|
+
logger.info("ssh command reached requested timeout (#{timeout}s)")
|
345
|
+
session.channels.each_value { |c| c.eof!; c.close }
|
346
|
+
raise Train::CommandTimeoutReached.new "ssh command reached timeout (#{timeout}s)"
|
347
|
+
end
|
348
|
+
else
|
349
|
+
thr.join
|
350
|
+
end
|
351
|
+
|
339
352
|
[exit_status, stdout, stderr]
|
340
353
|
end
|
341
354
|
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.3.
|
4
|
+
version: 3.3.24
|
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: 2020-
|
11
|
+
date: 2020-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|