train-core 3.3.21 → 3.3.24

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4bfda9949a3f24a3c7d48f8bb23384c73f064eccfa0f44029872e13913880c9
4
- data.tar.gz: 6598c63e265c79e1344010ace35b40d1f5bd1919bb8039d4ae868c54f9f85dc5
3
+ metadata.gz: 2b4cd9dbab0f4f3706d077a9c26185998bbdc4925ef03783b90c9244e268990d
4
+ data.tar.gz: a13777cd6b9e682fae479da36147ef17cbf01cf09c2d70f3377bf916e021be0f
5
5
  SHA512:
6
- metadata.gz: aeb75022b5ff8c0f93ce22b35a6d8af8b31c8f3906fe357e502cd6f7ab8e7cb0bf55df61c8e891579b5338f875413b6c1372535e5af30d3011d54fd8b7822968
7
- data.tar.gz: 3c23b61031fe8c0e8d691929ccb9007a8272d1de9736b8c5bef1ffcfd8a3078b31f556454f6676cc9d9a2515333015852f64f8e5ce47d2313e393eb4b230f9f7
6
+ metadata.gz: 36d220f296af3ac7d239a38726c0ccf6764ff171ea73004ea700c637b05233132e79619ea05de4fedbc098493baef6ea1095126325fd988475cf4a0a05ccce66
7
+ data.tar.gz: 6f8b09680a850f138c217bbfc03ae18e44a117d08842d8ca00a7055931a39e95e3be3652a851a4904171f7a80e58776cf1ff2220affaa19833c495d28e10cbe7
@@ -40,4 +40,7 @@ module Train
40
40
 
41
41
  # Exception for when a invalid cache type is passed.
42
42
  class UnknownCacheType < Error; end
43
+
44
+ # Exception for when a command reaches configured timeout
45
+ class CommandTimeoutReached < Error; end
43
46
  end
@@ -1,7 +1,7 @@
1
1
  # author: Dominik Richter
2
2
  # author: Christoph Hartmann
3
3
 
4
- require "base64"
4
+ require "base64" unless defined?(Base64)
5
5
  require_relative "../errors"
6
6
 
7
7
  module Train::Extras
@@ -1,4 +1,4 @@
1
- require "digest/sha1"
1
+ require "digest/sha1" unless defined?(Digest::SHA1)
2
2
  require "securerandom" unless defined?(SecureRandom)
3
3
  require "json" unless defined?(JSON)
4
4
 
@@ -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
- def run_command(cmd, &data_handler)
134
- return run_command_via_connection(cmd, &data_handler) unless cache_enabled?(:command)
135
-
136
- @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
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")
@@ -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)
@@ -235,12 +235,12 @@ class Train::Transports::SSH
235
235
  end
236
236
  end
237
237
 
238
- def run_command_via_connection(cmd, &data_handler)
238
+ def run_command_via_connection(cmd, opts = {}, &data_handler)
239
239
  cmd.dup.force_encoding("binary") if cmd.respond_to?(:force_encoding)
240
240
 
241
241
  reset_session if session.closed?
242
242
 
243
- exit_status, stdout, stderr = execute_on_channel(cmd, &data_handler)
243
+ exit_status, stdout, stderr = execute_on_channel(cmd, opts, &data_handler)
244
244
 
245
245
  # Since `@session.loop` succeeded, reset the IOS command retry counter
246
246
  @ios_cmd_retries = 0
@@ -297,7 +297,8 @@ class Train::Transports::SSH
297
297
  # not received.
298
298
  #
299
299
  # @api private
300
- def execute_on_channel(cmd)
300
+ def execute_on_channel(cmd, opts)
301
+ timeout = opts[:timeout]&.to_i
301
302
  stdout = ""
302
303
  stderr = ""
303
304
  exit_status = nil
@@ -307,7 +308,7 @@ class Train::Transports::SSH
307
308
 
308
309
  logger.debug("[SSH] #{self} cmd = #{cmd}")
309
310
 
310
- if @transport_options[:pty]
311
+ if @transport_options[:pty] || timeout
311
312
  channel.request_pty do |_ch, success|
312
313
  raise Train::Transports::SSHPTYFailed, "Requesting PTY failed" unless success
313
314
  end
@@ -334,7 +335,20 @@ class Train::Transports::SSH
334
335
  end
335
336
  end
336
337
  end
337
- 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
+
338
352
  [exit_status, stdout, stderr]
339
353
  end
340
354
  end
@@ -2,5 +2,5 @@
2
2
  # Author:: Dominik Richter (<dominik.richter@gmail.com>)
3
3
 
4
4
  module Train
5
- VERSION = "3.3.21".freeze
5
+ VERSION = "3.3.24".freeze
6
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.21
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-09-14 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