net-ssh-cli 1.9.1 → 1.9.2

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: 7056a8a1973f705133135914df49d4b16e1b9213b35b987677094b9993b3b059
4
- data.tar.gz: 5520b049f17149f5a17849f396b150451a0b7f50f0ceee4e79d616f23ec876e9
3
+ metadata.gz: 0e1db663e9e79a41c9c5fbb7b0dce5918a0bd61b83fb98f8d9314f1a4602a698
4
+ data.tar.gz: d7841ea18aefa288771a8ef64459373824b2c307b5f4b8e89a0b636fdfceb172
5
5
  SHA512:
6
- metadata.gz: b5d34700dc16a246ce3706828d2043993b34496d5b1a742f5dbbff366a62591ae2327bf7f9a1ec0044281962ae65f7f6297f2b49025f4acc1ba2175d2004ae12
7
- data.tar.gz: 0231d51bb361bbb6181138d1f0ec3350071c804f06e0e863bbe9d97fb85e5e9a156019f0fb6e7332a3e36baeda0d67050f34bbe519b275d8b0fa4c5439331878
6
+ metadata.gz: 5e33f5fd908ea9c927913692add3a4a112359e85875eb64af988c4f8d9b6d0fc6e3fa877583ec5be8ebb2f6dd62c83c2c5eebd8df858d07897e08c62bfa0452e
7
+ data.tar.gz: 92007ac57dd811683cc6715592c2544ab28e7a0be42237e65f8d3d71ed44e2c3d2df815d1bb6395b1f73294e00529b6a5f8a11cd257396b6a2623b34dcab7126
@@ -3,7 +3,7 @@
3
3
  module Net
4
4
  module SSH
5
5
  module CLI
6
- VERSION = '1.9.1'
6
+ VERSION = '1.9.2'
7
7
  end
8
8
  end
9
9
  end
data/lib/net/ssh/cli.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'net/ssh/cli/version'
4
- require 'net/ssh'
5
- require 'active_support/core_ext/hash/indifferent_access'
6
- require 'active_support/core_ext/object/blank'
7
- require 'timeout'
8
- require 'logger'
3
+ require "net/ssh/cli/version"
4
+ require "net/ssh"
5
+ require "active_support/core_ext/hash/indifferent_access"
6
+ require "active_support/core_ext/object/blank"
7
+ require "timeout"
8
+ require "logger"
9
9
 
10
10
  module Net
11
11
  module SSH
@@ -40,36 +40,36 @@ module Net
40
40
  attr_accessor :channel, :stdout, :net_ssh, :logger, :new_data, :process_count
41
41
 
42
42
  OPTIONS = ActiveSupport::HashWithIndifferentAccess.new(
43
- default_prompt: /\n?^(\S+@.*)\z/, # the default prompt to search for. It is recommended to use \z to ensure you don't match the prompt too early.
44
- cmd_rm_prompt: false, # whether the prompt should be removed in the output of #cmd
45
- cmd_rm_command: false, # whether the given command should be removed in the output of #cmd
46
- cmd_rm_command_tail: "\n", # which format does the end of line return after a command has been submitted. Could be something like "ls\n" "ls\r\n" or "ls \n" (extra spaces)
47
- cmd_minimum_duration: 0, # how long do you want to wait/sleep after sending the command. After this waiting time, the output will be processed and the prompt will be searched.
48
- run_impact: false, # whether to run #impact commands. This might align with testing|development|production. example #impact("reboot")
49
- read_till_timeout: nil, # timeout for #read_till to find the match
50
- read_till_hard_timeout: nil, # hard timeout for #read_till to find the match using Timeout.timeout(hard_timeout) {}. Might creates unpredicted sideffects
51
- read_till_hard_timeout_factor: 1.2, # hard timeout factor in case read_till_hard_timeout is true
52
- named_prompts: ActiveSupport::HashWithIndifferentAccess.new, # you can used named prompts for #with_prompt {}
53
- before_cmd_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call before #cmd
54
- after_cmd_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call after #cmd
55
- before_on_stdout_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call before data arrives from the underlying connection
56
- after_on_stdout_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call after data arrives from the underlying connection
57
- before_on_stdin_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call before data is sent to the underlying channel
58
- after_on_stdin_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call after data is sent to the underlying channel
43
+ default_prompt: /\n?^(\S+@.*)\z/, # the default prompt to search for. It is recommended to use \z to ensure you don't match the prompt too early.
44
+ cmd_rm_prompt: false, # whether the prompt should be removed in the output of #cmd
45
+ cmd_rm_command: false, # whether the given command should be removed in the output of #cmd
46
+ cmd_rm_command_tail: "\n", # which format does the end of line return after a command has been submitted. Could be something like "ls\n" "ls\r\n" or "ls \n" (extra spaces)
47
+ cmd_minimum_duration: 0, # how long do you want to wait/sleep after sending the command. After this waiting time, the output will be processed and the prompt will be searched.
48
+ run_impact: false, # whether to run #impact commands. This might align with testing|development|production. example #impact("reboot")
49
+ read_till_timeout: nil, # timeout for #read_till to find the match
50
+ read_till_hard_timeout: nil, # hard timeout for #read_till to find the match using Timeout.timeout(hard_timeout) {}. Might creates unpredicted sideffects
51
+ read_till_hard_timeout_factor: 1.2, # hard timeout factor in case read_till_hard_timeout is true
52
+ named_prompts: ActiveSupport::HashWithIndifferentAccess.new, # you can used named prompts for #with_prompt {}
53
+ before_cmd_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call before #cmd
54
+ after_cmd_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call after #cmd
55
+ before_on_stdout_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call before data arrives from the underlying connection
56
+ after_on_stdout_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call after data arrives from the underlying connection
57
+ before_on_stdin_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call before data is sent to the underlying channel
58
+ after_on_stdin_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call after data is sent to the underlying channel
59
59
  before_open_channel_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call before opening a channel
60
- after_open_channel_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call after opening a channel, for example you could call #detect_prompt or #read_till
61
- open_channel_timeout: nil, # timeout to open the channel
62
- net_ssh_options: ActiveSupport::HashWithIndifferentAccess.new, # a wrapper for options to pass to Net::SSH.start in case net_ssh is undefined
63
- process_time: 0.00001, # how long #process is processing net_ssh#process or sleeping (waiting for something)
64
- background_processing: false, # default false, whether the process method maps to the underlying net_ssh#process or the net_ssh#process happens in a separate loop
65
- on_stdout_processing: 100, # whether to optimize the on_stdout performance by calling #process #optimize_on_stdout-times in case more data arrives
66
- sleep_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call instead of Kernel.sleep(), perfect for async hooks
67
- terminal_chars_width: 320, # Sets and sends the terminal dimensions during the opening of the channel. It does not send a channel_request on change.
68
- terminal_chars_height: 120, # See also https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/connection/channel.rb#L220 section 'def request_pty'
69
- terminal_pixels_width: 1920, # See also https://www.ietf.org/rfc/rfc4254.txt section pty-req and section window-change
70
- terminal_pixels_height: 1080, #
71
- terminal_term: nil, # Sets the terminal term, usually xterm
72
- terminal_modes: nil, #
60
+ after_open_channel_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call after opening a channel, for example you could call #detect_prompt or #read_till
61
+ open_channel_timeout: nil, # timeout to open the channel
62
+ net_ssh_options: ActiveSupport::HashWithIndifferentAccess.new, # a wrapper for options to pass to Net::SSH.start in case net_ssh is undefined
63
+ process_time: 0.00001, # how long #process is processing net_ssh#process or sleeping (waiting for something)
64
+ background_processing: false, # default false, whether the process method maps to the underlying net_ssh#process or the net_ssh#process happens in a separate loop
65
+ on_stdout_processing: 100, # whether to optimize the on_stdout performance by calling #process #optimize_on_stdout-times in case more data arrives
66
+ sleep_procs: ActiveSupport::HashWithIndifferentAccess.new, # procs to call instead of Kernel.sleep(), perfect for async hooks
67
+ terminal_chars_width: 320, # Sets and sends the terminal dimensions during the opening of the channel. It does not send a channel_request on change.
68
+ terminal_chars_height: 120, # See also https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/connection/channel.rb#L220 section 'def request_pty'
69
+ terminal_pixels_width: 1920, # See also https://www.ietf.org/rfc/rfc4254.txt section pty-req and section window-change
70
+ terminal_pixels_height: 1080, #
71
+ terminal_term: nil, # Sets the terminal term, usually xterm
72
+ terminal_modes: nil #
73
73
  )
74
74
 
75
75
  def options
@@ -103,10 +103,10 @@ module Net
103
103
  end
104
104
  end
105
105
 
106
- OPTIONS.keys.select {|key| key.to_s.include? "procs"}.each do |name|
107
- define_method name.sub("_procs","") do |&blk|
106
+ OPTIONS.keys.select { |key| key.to_s.include? "procs" }.each do |name|
107
+ define_method name.sub("_procs", "") do |&blk|
108
108
  id = SecureRandom.uuid
109
- self.send(name)[id] = Proc.new {blk.call}
109
+ send(name)[id] = proc { blk.call }
110
110
  id
111
111
  end
112
112
  end
@@ -168,12 +168,10 @@ module Net
168
168
  # end
169
169
  # cmd("exit")
170
170
  #
171
- def with_named_prompt(name)
171
+ def with_named_prompt(name, &block)
172
172
  raise Error::UndefinedMatch, "unknown named_prompt #{name}" unless named_prompts[name]
173
173
 
174
- with_prompt(named_prompts[name]) do
175
- yield
176
- end
174
+ with_prompt(named_prompts[name], &block)
177
175
  end
178
176
 
179
177
  # tries to detect the prompt
@@ -217,17 +215,17 @@ module Net
217
215
  # - hard_timeout_factor: nil, true, or a number
218
216
  # - when hard_timeout == true, this will set the hard_timeout as (read_till_hard_timeout_factor * read_till_timeout), defaults to 1.2 = +20%
219
217
  def read_till(prompt: current_prompt, timeout: read_till_timeout, hard_timeout: read_till_hard_timeout, hard_timeout_factor: read_till_hard_timeout_factor, **_opts)
220
- raise Error::UndefinedMatch, 'no prompt given or default_prompt defined' unless prompt
218
+ raise Error::UndefinedMatch, "no prompt given or default_prompt defined" unless prompt
219
+
221
220
  hard_timeout = (read_till_hard_timeout_factor * timeout) if timeout and hard_timeout == true
222
221
  hard_timeout = nil if hard_timeout == true
223
222
 
224
223
  with_prompt(prompt) do
225
224
  ::Timeout.timeout(hard_timeout, Error::ReadTillTimeout, "#{current_prompt.inspect} didn't match on #{stdout.inspect} within #{hard_timeout}s") do
226
225
  soft_timeout = Time.now + timeout if timeout
227
- until prompt_in_stdout? do
228
- if timeout and soft_timeout < Time.now
229
- raise Error::ReadTillTimeout, "#{current_prompt.inspect} didn't match on #{stdout.inspect} within #{timeout}s"
230
- end
226
+ until prompt_in_stdout?
227
+ raise Error::ReadTillTimeout, "#{current_prompt.inspect} didn't match on #{stdout.inspect} within #{timeout}s" if timeout and soft_timeout < Time.now
228
+
231
229
  process
232
230
  sleep 0.01 # don't race for CPU
233
231
  end
@@ -253,7 +251,7 @@ module Net
253
251
  end
254
252
 
255
253
  def dialog(command, prompt, **opts)
256
- opts = opts.clone.merge(prompt: prompt)
254
+ opts = opts.clone.merge(prompt:)
257
255
  cmd(command, **opts)
258
256
  end
259
257
 
@@ -265,7 +263,7 @@ module Net
265
263
  # Hint: 'read' first on purpose as a feature. once you cmd you ignore what happend before. otherwise use read|write directly.
266
264
  # this should avoid many horrible state issues where the prompt is not the last prompt
267
265
  def cmd(command, pre_read: true, rm_prompt: cmd_rm_prompt, rm_command: cmd_rm_command, prompt: current_prompt, minimum_duration: cmd_minimum_duration, **opts)
268
- opts = opts.clone.merge(pre_read: pre_read, rm_prompt: rm_prompt, rm_command: rm_command, prompt: prompt)
266
+ opts = opts.clone.merge(pre_read:, rm_prompt:, rm_command:, prompt:)
269
267
  if pre_read
270
268
  pre_read_data = read
271
269
  logger.debug { "#cmd ignoring pre-command output: #{pre_read_data.inspect}" } if pre_read_data.present?
@@ -291,7 +289,7 @@ module Net
291
289
  alias commands cmds
292
290
 
293
291
  def rm_command!(output, command, **opts)
294
- output[command + cmd_rm_command_tail] = '' if rm_command?(**opts) && output[command + cmd_rm_command_tail]
292
+ output[command + cmd_rm_command_tail] = "" if rm_command?(**opts) && output[command + cmd_rm_command_tail]
295
293
  end
296
294
 
297
295
  # removes the prompt from the given output
@@ -299,19 +297,17 @@ module Net
299
297
  # for backwards compatibility it also tries to replace the first match of the prompt /(something)\z/
300
298
  # it removes the whole match if no matches are given /something\z/
301
299
  def rm_prompt!(output, prompt: current_prompt, **opts)
302
- if rm_prompt?(**opts)
303
- if output[prompt]
304
- case prompt
305
- when String then output[prompt] = ''
306
- when Regexp
307
- if prompt.names.include?("prompt")
308
- output[prompt, "prompt"] = ''
309
- else
310
- begin
311
- output[prompt, 1] = ''
312
- rescue IndexError
313
- output[prompt] = ''
314
- end
300
+ if rm_prompt?(**opts) && (output[prompt])
301
+ case prompt
302
+ when String then output[prompt] = ""
303
+ when Regexp
304
+ if prompt.names.include?("prompt")
305
+ output[prompt, "prompt"] = ""
306
+ else
307
+ begin
308
+ output[prompt, 1] = ""
309
+ rescue IndexError
310
+ output[prompt] = ""
315
311
  end
316
312
  end
317
313
  end
@@ -359,8 +355,8 @@ module Net
359
355
  def net_ssh
360
356
  return @net_ssh if @net_ssh
361
357
 
362
- logger.debug { 'Net:SSH #start' }
363
- self.net_ssh = Net::SSH.start(net_ssh_options[:ip] || net_ssh_options[:host] || 'localhost', net_ssh_options[:user] || ENV['USER'], **formatted_net_ssh_options)
358
+ logger.debug { "Net:SSH #start" }
359
+ self.net_ssh = Net::SSH.start(net_ssh_options[:ip] || net_ssh_options[:host] || "localhost", net_ssh_options[:user] || ENV["USER"], **formatted_net_ssh_options)
364
360
  rescue StandardError => error
365
361
  self.net_ssh = nil
366
362
  raise
@@ -381,13 +377,13 @@ module Net
381
377
  before_open_channel_procs.each { |_name, a_proc| instance_eval(&a_proc) }
382
378
  ::Timeout.timeout(open_channel_timeout, Error::OpenChannelTimeout) do
383
379
  net_ssh.open_channel do |new_channel|
384
- logger.debug 'channel is open'
380
+ logger.debug "channel is open"
385
381
  self.channel = new_channel
386
382
  new_channel.request_pty(terminal_options) do |_ch, success|
387
383
  raise Error::Pty, "#{host || ip} Failed to open ssh pty" unless success
388
384
  end
389
- new_channel.send_channel_request('shell') do |_ch, success|
390
- raise Error::RequestShell, 'Failed to open ssh shell' unless success
385
+ new_channel.send_channel_request("shell") do |_ch, success|
386
+ raise Error::RequestShell, "Failed to open ssh shell" unless success
391
387
  end
392
388
  new_channel.on_data do |_ch, data|
393
389
  on_stdout(data)
@@ -395,9 +391,9 @@ module Net
395
391
  # new_channel.on_extended_data do |_ch, type, data| end
396
392
  # new_channel.on_close do end
397
393
  end
398
- until channel do process end
394
+ process until channel
399
395
  end
400
- logger.debug 'channel is ready, running callbacks now'
396
+ logger.debug "channel is ready, running callbacks now"
401
397
  after_open_channel_procs.each { |_name, a_proc| instance_eval(&a_proc) }
402
398
  process
403
399
  self
@@ -415,7 +411,7 @@ module Net
415
411
  end
416
412
 
417
413
  def formatted_net_ssh_options
418
- net_ssh_options.symbolize_keys.reject {|k,v| [:host, :ip, :user].include?(k)}
414
+ net_ssh_options.symbolize_keys.reject { |k, _v| [:host, :ip, :user].include?(k) }
419
415
  end
420
416
 
421
417
  def rm_prompt?(**opts)
@@ -445,7 +441,7 @@ module Net
445
441
  pixels_wide: terminal_pixels_width,
446
442
  pixels_high: terminal_pixels_height,
447
443
  modes: terminal_modes
448
- }.reject {|k,v| v.nil?}
444
+ }.reject { |_k, v| v.nil? }
449
445
  end
450
446
  end
451
447
  end
@@ -457,8 +453,9 @@ end
457
453
 
458
454
  class Net::SSH::Connection::Session
459
455
  attr_accessor :cli_channels
456
+
460
457
  def cli(**opts)
461
- cli_session = Net::SSH::CLI::Session.new({ net_ssh: self }.merge(opts))
458
+ cli_session = Net::SSH::CLI::Session.new(**{ net_ssh: self }.merge(opts))
462
459
  cli_session.open_channel
463
460
  cli_session
464
461
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-ssh-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.1
4
+ version: 1.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabian Stillhart
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-21 00:00:00.000000000 Z
11
+ date: 2022-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bump
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
140
  - !ruby/object:Gem::Version
141
141
  version: '0'
142
142
  requirements: []
143
- rubygems_version: 3.3.25
143
+ rubygems_version: 3.3.26
144
144
  signing_key:
145
145
  specification_version: 4
146
146
  summary: 'Net::SSH::CLI: A library to handle CLI Sessions'