train-core 3.6.2 → 3.7.0

Sign up to get free protection for your applications and to get access to all the features.
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