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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/train.rb +1 -2
  3. data/lib/train/errors.rb +3 -1
  4. data/lib/train/extras.rb +0 -1
  5. data/lib/train/extras/command_wrapper.rb +1 -2
  6. data/lib/train/extras/stat.rb +0 -1
  7. data/lib/train/file.rb +0 -1
  8. data/lib/train/file/local.rb +0 -2
  9. data/lib/train/file/local/unix.rb +1 -3
  10. data/lib/train/file/local/windows.rb +0 -2
  11. data/lib/train/file/remote.rb +0 -2
  12. data/lib/train/file/remote/aix.rb +0 -2
  13. data/lib/train/file/remote/linux.rb +0 -2
  14. data/lib/train/file/remote/qnx.rb +0 -1
  15. data/lib/train/file/remote/unix.rb +1 -1
  16. data/lib/train/file/remote/windows.rb +0 -2
  17. data/lib/train/options.rb +0 -1
  18. data/lib/train/platforms.rb +0 -2
  19. data/lib/train/platforms/common.rb +0 -2
  20. data/lib/train/platforms/detect.rb +0 -2
  21. data/lib/train/platforms/detect/helpers/os_common.rb +17 -9
  22. data/lib/train/platforms/detect/helpers/os_linux.rb +0 -2
  23. data/lib/train/platforms/detect/scanner.rb +0 -2
  24. data/lib/train/platforms/detect/specifications/api.rb +0 -2
  25. data/lib/train/platforms/detect/specifications/os.rb +2 -2
  26. data/lib/train/platforms/detect/uuid.rb +3 -3
  27. data/lib/train/platforms/family.rb +0 -2
  28. data/lib/train/platforms/platform.rb +1 -3
  29. data/lib/train/plugin_test_helper.rb +5 -5
  30. data/lib/train/plugins.rb +1 -2
  31. data/lib/train/plugins/base_connection.rb +22 -7
  32. data/lib/train/plugins/transport.rb +0 -1
  33. data/lib/train/transports/cisco_ios_connection.rb +0 -2
  34. data/lib/train/transports/local.rb +7 -8
  35. data/lib/train/transports/mock.rb +1 -1
  36. data/lib/train/transports/ssh.rb +2 -3
  37. data/lib/train/transports/ssh_connection.rb +21 -8
  38. data/lib/train/version.rb +1 -2
  39. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d1528d472a38847644b9b12d7e7ebfd304e696bdfc50f7562b4b5bf387f5059
4
- data.tar.gz: 4913341d6670668289ccc69ab4d67335d4529da28fb449a0f9fcb1dc191b571b
3
+ metadata.gz: 2b4cd9dbab0f4f3706d077a9c26185998bbdc4925ef03783b90c9244e268990d
4
+ data.tar.gz: a13777cd6b9e682fae479da36147ef17cbf01cf09c2d70f3377bf916e021be0f
5
5
  SHA512:
6
- metadata.gz: 2ab551ae2ab9e8ef40628edb76cf77f5ce0391483a2ae3aaf9ade688244817286d48bf4d92f0f3ca78e488dcf71c6783808e98a56a226df0a09867b0a281fff9
7
- data.tar.gz: df2cc712d56b9e91239e6e10dd537b9233b0d97cfb8cb29771bb3539915f81df61523b222875791dd5dc8a9d0edbfa9f71f789cf7be74ee0164e0f504eba9c27
6
+ metadata.gz: 36d220f296af3ac7d239a38726c0ccf6764ff171ea73004ea700c637b05233132e79619ea05de4fedbc098493baef6ea1095126325fd988475cf4a0a05ccce66
7
+ data.tar.gz: 6f8b09680a850f138c217bbfc03ae18e44a117d08842d8ca00a7055931a39e95e3be3652a851a4904171f7a80e58776cf1ff2220affaa19833c495d28e10cbe7
@@ -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
@@ -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
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  #
3
2
  # Author:: Dominik Richter (<dominik.richter@gmail.com>)
4
3
 
@@ -1,8 +1,7 @@
1
- # encoding: utf-8
2
1
  # author: Dominik Richter
3
2
  # author: Christoph Hartmann
4
3
 
5
- require "base64"
4
+ require "base64" unless defined?(Base64)
6
5
  require_relative "../errors"
7
6
 
8
7
  module Train::Extras
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # author: Dominik Richter
3
2
  # author: Christoph Hartmann
4
3
  module Train::Extras
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  #
3
2
  # author: Christoph Hartmann
4
3
  # author: Dominik Richter
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Train
4
2
  class File
5
3
  class Local < Train::File
@@ -1,6 +1,4 @@
1
- # encoding: utf-8
2
-
3
- require "shellwords"
1
+ require "shellwords" unless defined?(Shellwords)
4
2
  require_relative "../../extras/stat"
5
3
 
6
4
  module Train
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Train
4
2
  class File
5
3
  class Local
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Train
4
2
  class File
5
3
  class Remote < Train::File
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require_relative "unix"
4
2
 
5
3
  module Train
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require_relative "unix"
4
2
 
5
3
  module Train
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  #
3
2
  # author: Christoph Hartmann
4
3
  # author: Dominik Richter
@@ -1,4 +1,4 @@
1
- require "shellwords"
1
+ require "shellwords" unless defined?(Shellwords)
2
2
 
3
3
  module Train
4
4
  class File
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Train
4
2
  class File
5
3
  class Remote
@@ -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>)
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require_relative "platforms/common"
4
2
  require_relative "platforms/detect"
5
3
  require_relative "platforms/detect/scanner"
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Train::Platforms
4
2
  module Common
5
3
  # Add a family connection. This will create a family
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Train::Platforms
4
2
  module Detect
5
3
  # Main detect method to scan all platforms for a match
@@ -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).stdout
38
- # When you try to execute command using ssh connction as root user and you have provided ssh user identity file
39
- # it gives standard output to login as authorised user other than root. To show this standard ouput as an error
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" && res =~ /Please login as the user/
42
- raise Train::UserError, "SSH failed: #{res}"
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
- res.strip! unless res.nil?
46
- res
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"]
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Train::Platforms::Detect::Helpers
4
2
  module Linux
5
3
  def redhatish_platform(conf)
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require_relative "helpers/os_common"
4
2
 
5
3
  module Train::Platforms::Detect
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Train::Platforms::Detect::Specifications
4
2
  class Api
5
3
  def self.load
@@ -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", "Xenserer Linux", "redhat", /xenserver/i)
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,6 +1,6 @@
1
- require "digest/sha1"
2
- require "securerandom"
3
- require "json"
1
+ require "digest/sha1" unless defined?(Digest::SHA1)
2
+ require "securerandom" unless defined?(SecureRandom)
3
+ require "json" unless defined?(JSON)
4
4
 
5
5
  module Train::Platforms::Detect
6
6
  class UUID
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Train::Platforms
4
2
  class Family
5
3
  include Train::Platforms::Common
@@ -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 backwords compatability with
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.
@@ -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 determins what methods will be available to your plugin.
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
- def run_command(cmd, &data_handler)
136
- return run_command_via_connection(cmd, &data_handler) unless cache_enabled?(:command)
137
-
138
- @cache[:command][cmd] ||= run_command_via_connection(cmd, &data_handler)
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 applicablelog
178
+ # this method may be left unimplemented if that is applicable log
164
179
  end
165
180
 
166
181
  private
@@ -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>)
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  class Train::Transports::SSH
4
2
  class CiscoIOSConnection < BaseConnection
5
3
  class BadEnablePassword < Train::TransportError; end
@@ -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::ComandResult with stdout, stderr and exitstatus
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
@@ -1,5 +1,5 @@
1
1
  require_relative "../plugins"
2
- require "digest"
2
+ require "digest" unless defined?(Digest)
3
3
 
4
4
  module Train::Transports
5
5
  class Mock < Train.plugin(1)
@@ -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] conneciton options
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
- session.loop
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
@@ -1,7 +1,6 @@
1
- # encoding: utf-8
2
1
  #
3
2
  # Author:: Dominik Richter (<dominik.richter@gmail.com>)
4
3
 
5
4
  module Train
6
- VERSION = "3.3.4".freeze
5
+ VERSION = "3.3.24".freeze
7
6
  end
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
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-06-25 00:00:00.000000000 Z
11
+ date: 2020-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable