train-core 3.6.2 → 3.7.0

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: bc67d13ca7a06113a56b506c659ad2a8b7cb0ce9468a632aad6d9716d2bfbbb3
4
- data.tar.gz: 8f77e2c0ed1e8e18f55b8d96f2a74c43cb135818a3d945c9740c26f37bed3475
3
+ metadata.gz: 7e0529be878892640599f401af47c6c012a8d060fea3113895872b0af7e24127
4
+ data.tar.gz: 4b387bc5129fbf652b37713a63d74173d8d04f3ea5dbdf9993cadf0d276f3add
5
5
  SHA512:
6
- metadata.gz: 32b328597cccde06aa86d32fc84d3255c66310c2b8544f4fe1aebf4bfd42b93e422a04e69a85b281954956f6e2ff8c035c672ac64c18fd89107edf94cd666049
7
- data.tar.gz: 2eb61ddb2225dfa731fb32f1895b35703b152d80a23a46f0e2550b829bbbac955f753c028d50bb7bce020f692416934b908d35379ccefeaa6b4a17efbc58dd97
6
+ metadata.gz: 7fdf259b32a3dc0f033681b2f98e164f2ef76c8b4e7f51fb5bc1fe2412a1501039cdddfc06ef409f7b235dbcefef693f97c7fff21c02d7011618fdfc5ad09a9d
7
+ data.tar.gz: 2f90638d94542daf5e70488f6fd5e592986d3a76ac6b10f188414a109b53fffc8000202ce0a853f68bc1a8c1dfee9178107da5fee2b51728a01b1863b3976baf
data/lib/train/options.rb CHANGED
@@ -59,6 +59,9 @@ module Train
59
59
  default = hm[:default]
60
60
  if default.is_a? Proc
61
61
  res[field] = default.call(res)
62
+ elsif hm.key?(:coerce)
63
+ field_value = hm[:coerce].call(res)
64
+ res[field] = field_value.nil? ? default : field_value
62
65
  else
63
66
  res[field] = default
64
67
  end
@@ -43,8 +43,8 @@ module Train::Transports
43
43
 
44
44
  # common target configuration
45
45
  option :host, required: true
46
- option :port, default: 22, required: true
47
- option :user, default: "root", required: true
46
+ option :port, default: 22, coerce: proc { |u| read_options_from_ssh_config(u, :port) }, required: true
47
+ option :user, default: "root", coerce: proc { |u| read_options_from_ssh_config(u, :user) }, required: true
48
48
  option :key_files, default: nil
49
49
  option :password, default: nil
50
50
 
@@ -86,6 +86,14 @@ module Train::Transports
86
86
  end
87
87
  end
88
88
 
89
+ # Returns the ssh config option like user, port from config files
90
+ # Params options [Hash], option_type [String]
91
+ # Return String
92
+ def self.read_options_from_ssh_config(options, option_type)
93
+ config_options = Net::SSH.configuration_for(options[:host], true)
94
+ config_options[option_type]
95
+ end
96
+
89
97
  private
90
98
 
91
99
  def reusable_connection?(conn_opts)
@@ -278,5 +286,6 @@ module Train::Transports
278
286
  yield @connection if block_given?
279
287
  @connection
280
288
  end
289
+
281
290
  end
282
291
  end
@@ -32,6 +32,10 @@ class Train::Transports::SSH
32
32
  attr_reader :hostname
33
33
  attr_accessor :transport_options
34
34
 
35
+ # If we use the GNU timeout utility to timout a command server-side, it will
36
+ # exit with this status code if the command timed out.
37
+ GNU_TIMEOUT_EXIT_STATUS = 124
38
+
35
39
  def initialize(options)
36
40
  # Track IOS command retries to prevent infinite loop on IOError. This must
37
41
  # be done before `super()` because the parent runs detection commands.
@@ -321,6 +325,9 @@ class Train::Transports::SSH
321
325
  # wrap commands if that is configured
322
326
  cmd = @cmd_wrapper.run(cmd) if @cmd_wrapper
323
327
 
328
+ # Timeout the command if requested and able
329
+ cmd = "timeout #{timeout}s #{cmd}" if timeout && timeoutable?(cmd)
330
+
324
331
  logger.debug("[SSH] #{self} cmd = #{cmd}")
325
332
 
326
333
  if @transport_options[:pty]
@@ -350,21 +357,30 @@ class Train::Transports::SSH
350
357
  end
351
358
  end
352
359
  end
360
+ session.loop
353
361
 
354
- thr = Thread.new { session.loop }
355
-
356
- if timeout
357
- res = thr.join(timeout)
358
- unless res
359
- logger.debug("train ssh command '#{cmd}' reached requested timeout (#{timeout}s)")
360
- session.channels.each_value { |c| c.eof!; c.close }
361
- raise Train::CommandTimeoutReached.new "ssh command reached timeout (#{timeout}s)"
362
- end
363
- else
364
- thr.join
362
+ if timeout && timeoutable?(cmd) && exit_status == GNU_TIMEOUT_EXIT_STATUS
363
+ logger.debug("train ssh command '#{cmd}' reached requested timeout (#{timeout}s)")
364
+ session.channels.each_value { |c| c.eof!; c.close }
365
+ raise Train::CommandTimeoutReached.new "ssh command reached timeout (#{timeout}s)"
365
366
  end
366
367
 
367
368
  [exit_status, stdout, stderr]
368
369
  end
370
+
371
+ # Returns true if we think we can attempt to timeout the command
372
+ def timeoutable?(cmd)
373
+ have_timeout_cli? && !cmd.include?("|") # Don't try to timeout a command that has pipes
374
+ end
375
+
376
+ # Returns true if the GNU timeout command is available
377
+ def have_timeout_cli?
378
+ return @have_timeout_cli unless @have_timeout_cli.nil?
379
+
380
+ res = session.exec!("timeout --version")
381
+ @have_timeout_cli = res.exitstatus == 0
382
+ logger.debug("train ssh have_timeout_cli status is '#{@have_timeout_cli}'")
383
+ @have_timeout_cli
384
+ end
369
385
  end
370
386
  end
data/lib/train/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # Author:: Dominik Richter (<dominik.richter@gmail.com>)
3
3
 
4
4
  module Train
5
- VERSION = "3.6.2".freeze
5
+ VERSION = "3.7.0".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.6.2
4
+ version: 3.7.0
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: 2021-04-14 00:00:00.000000000 Z
11
+ date: 2021-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable