train-core 3.3.6 → 3.3.27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) 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 +4 -4
  22. data/lib/train/platforms/detect/helpers/os_linux.rb +0 -2
  23. data/lib/train/platforms/detect/helpers/os_windows.rb +15 -10
  24. data/lib/train/platforms/detect/scanner.rb +0 -2
  25. data/lib/train/platforms/detect/specifications/api.rb +0 -2
  26. data/lib/train/platforms/detect/specifications/os.rb +1 -1
  27. data/lib/train/platforms/detect/uuid.rb +3 -3
  28. data/lib/train/platforms/family.rb +0 -2
  29. data/lib/train/platforms/platform.rb +1 -3
  30. data/lib/train/plugin_test_helper.rb +5 -5
  31. data/lib/train/plugins.rb +1 -2
  32. data/lib/train/plugins/base_connection.rb +22 -7
  33. data/lib/train/plugins/transport.rb +0 -1
  34. data/lib/train/transports/cisco_ios_connection.rb +0 -2
  35. data/lib/train/transports/local.rb +7 -8
  36. data/lib/train/transports/mock.rb +1 -1
  37. data/lib/train/transports/ssh.rb +2 -3
  38. data/lib/train/transports/ssh_connection.rb +21 -8
  39. data/lib/train/version.rb +1 -2
  40. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6481551d7379b4a6cdee61568a1252e7feae2dc2d83def688417945eced8776
4
- data.tar.gz: 3bec9acaea41dba70ed5c55cb7d6460d40e1c900002a172356419c80da222f7e
3
+ metadata.gz: 73c36e29da576607716f40e56d269c20dc0f340eb6db173401920d31780b0795
4
+ data.tar.gz: 7dc1d05255dfe2ee94ce9c485a17542128c23981f806a2f232ec7c4e748055d0
5
5
  SHA512:
6
- metadata.gz: '09b0f40e16fc0533bb474a460d3526fd767cacd2e2c18e35a6f9aa825e953adc7de241116d12a832c179c6e7383afbb7357ecf31bdeb75347854083fee328caa'
7
- data.tar.gz: c1bcbb41f3c7e3e832f1adf70b5f02634906e6f40d8ed989ff7aafb56b2e5008ba4cab5ce483dc39badaf8142e8e685a7f262c1f154d28c078ce0d899d9561fc
6
+ metadata.gz: 0c93f29190920583a17b6a03f07fdd082802ce6e4a3f1d991a2e20a31a186527c487e168cb99aab77a973f648603456eb4932d02a21bdf08ab915bfc2e0f5af6
7
+ data.tar.gz: 3037542a3872731085cd7b859d79a400038ba1f5091c0433ee40fd3d3c4298b5db9d9682b4c5b60bf3c9ed94bcadeeff0a5d9e441e7dba13f7856a622cee9a33
@@ -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
@@ -37,8 +37,8 @@ module Train::Platforms::Detect::Helpers
37
37
  res = @backend.run_command(cmd)
38
38
  stdout = res.stdout
39
39
  stderr = res.stderr
40
- # When you try to execute command using ssh connction as root user and you have provided ssh user identity file
41
- # it gives standard output to login as authorised user other than root. To show this standard ouput as an error
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
42
42
  # to user we are matching the string of stdout and raising the error here so that user gets exact information.
43
43
  if @backend.class.to_s == "Train::Transports::SSH::Connection"
44
44
  if stdout =~ /Please login as the user/
@@ -165,7 +165,7 @@ module Train::Platforms::Detect::Helpers
165
165
  def json_cmd(cmd)
166
166
  cmd = @backend.run_command(cmd)
167
167
  if cmd.exit_status == 0 && !cmd.stdout.empty?
168
- require "json"
168
+ require "json" unless defined?(JSON)
169
169
  eos_ver = JSON.parse(cmd.stdout)
170
170
  @platform[:release] = eos_ver["version"]
171
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)
@@ -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
- return false if (command.exit_status != 0) || command.stdout.empty?
37
-
38
- payload = JSON.parse(command.stdout)
39
- @platform[:family] = "windows"
40
- @platform[:release] = payload["Version"]
41
- @platform[:name] = payload["Caption"]
42
-
43
- read_wmic
44
- true
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"] if json["node_uuid"]
134
+ json["node_uuid"]
130
135
  end
131
136
 
132
137
  def windows_uuid_from_wmic
@@ -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"))
@@ -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.6".freeze
5
+ VERSION = "3.3.27".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.6
4
+ version: 3.3.27
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-07-02 00:00:00.000000000 Z
11
+ date: 2020-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable