net-ssh-cli 1.9.0 → 1.9.2

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: fe1c60d30e59f8fc15074b0a59f9a0c868f47472df17d1ad156c301b3582bc22
4
- data.tar.gz: bd9f7a6dd71fb3429440f2fd6713d7f04322aba58705bd63d474156a7932cf00
3
+ metadata.gz: 0e1db663e9e79a41c9c5fbb7b0dce5918a0bd61b83fb98f8d9314f1a4602a698
4
+ data.tar.gz: d7841ea18aefa288771a8ef64459373824b2c307b5f4b8e89a0b636fdfceb172
5
5
  SHA512:
6
- metadata.gz: c81d16a0fd072fea7563c55aaae2bbd0f17622ff27294ec080c14084cf11a106a6bbadb7aeb6516aab8cbb5e35ee8a8be501b33f45f0ed8afff5e0fbb36a08dd
7
- data.tar.gz: 8f27e6a09b431191571d90d360486a4141c3b314bf291b948fe401737049e6deebfdd25d8aeaeb830cdeb8727074ae628880c03ea3987f988775a349958c31f8
6
+ metadata.gz: 5e33f5fd908ea9c927913692add3a4a112359e85875eb64af988c4f8d9b6d0fc6e3fa877583ec5be8ebb2f6dd62c83c2c5eebd8df858d07897e08c62bfa0452e
7
+ data.tar.gz: 92007ac57dd811683cc6715592c2544ab28e7a0be42237e65f8d3d71ed44e2c3d2df815d1bb6395b1f73294e00529b6a5f8a11cd257396b6a2623b34dcab7126
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.0
1
+ 3.1
@@ -3,7 +3,7 @@
3
3
  module Net
4
4
  module SSH
5
5
  module CLI
6
- VERSION = '1.9.0'
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
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, #
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
+ 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 #
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,27 +289,25 @@ 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
298
296
  # prompt should contain a named match 'prompt' /(?<prompt>.*something.*)\z/
299
297
  # for backwards compatibility it also tries to replace the first match of the prompt /(something)\z/
300
- # it removes the whole match if no matches are given /something\z/
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
@@ -320,10 +316,10 @@ module Net
320
316
 
321
317
  # the same as #cmd but it will only run the command if the option run_impact is set to true.
322
318
  # this can be used for commands which you might not want to run in development|testing mode but in production
323
- # cli.impact("reboot")
319
+ # cli.impact("reboot")
324
320
  # => "skip: reboot"
325
321
  # cli.run_impact = true
326
- # cli.impact("reboot")
322
+ # cli.impact("reboot")
327
323
  # => "system is going to reboot NOW"
328
324
  def impact(command, **opts)
329
325
  run_impact? ? cmd(command, **opts) : "skip: #{command.inspect}"
@@ -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
data/net-ssh-cli.gemspec CHANGED
@@ -1,19 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('lib', __dir__)
3
+ lib = File.expand_path("lib", __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'net/ssh/cli/version'
5
+ require "net/ssh/cli/version"
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.name = 'net-ssh-cli'
8
+ spec.name = "net-ssh-cli"
9
9
  spec.version = Net::SSH::CLI::VERSION
10
- spec.authors = ['Fabian Stillhart']
11
- spec.email = ['fabian.stillhart1@swisscom.com']
10
+ spec.authors = ["Fabian Stillhart"]
11
+ spec.email = ["fabian.stillhart1@swisscom.com"]
12
12
 
13
- spec.summary = 'Net::SSH::CLI: A library to handle CLI Sessions'
14
- spec.description = 'Net::SSH::CLI: A library to handle CLI Sessions. It allows you to write programs that invoke and interact with (long-running) CLI Sessions via NET::SSH.'
15
- spec.homepage = 'https://github.com/swisscom/net-ssh-cli'
16
- spec.license = 'MIT'
13
+ spec.summary = "Net::SSH::CLI: A library to handle CLI Sessions"
14
+ spec.description = "Net::SSH::CLI: A library to handle CLI Sessions. It allows you to write programs that invoke and interact with (long-running) CLI Sessions via NET::SSH."
15
+ spec.homepage = "https://github.com/swisscom/net-ssh-cli"
16
+ spec.license = "MIT"
17
17
 
18
18
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
19
  # to allow pushing to a single host or delete this section to allow pushing to any host.
@@ -33,14 +33,14 @@ Gem::Specification.new do |spec|
33
33
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
34
34
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
35
35
  end
36
- spec.bindir = 'exe'
36
+ spec.bindir = "exe"
37
37
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
- spec.require_paths = ['lib']
38
+ spec.require_paths = ["lib"]
39
39
 
40
- spec.add_development_dependency 'bundler'
41
- spec.add_development_dependency 'bump'
42
- spec.add_development_dependency 'rake', '~> 13.0'
43
- spec.add_development_dependency 'rspec', '~> 3.0'
44
- spec.add_dependency 'activesupport', '>= 4.0'
45
- spec.add_dependency 'net-ssh', '>= 4.0'
40
+ spec.add_development_dependency "bump"
41
+ spec.add_development_dependency "bundler"
42
+ spec.add_development_dependency "rake", "~> 13.0"
43
+ spec.add_development_dependency "rspec", "~> 3.0"
44
+ spec.add_dependency "activesupport", ">= 4.0"
45
+ spec.add_dependency "net-ssh", ">= 7.0"
46
46
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-ssh-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
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: 2021-09-07 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
- name: bundler
14
+ name: bump
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bump
28
+ name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '4.0'
89
+ version: '7.0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '4.0'
96
+ version: '7.0'
97
97
  description: 'Net::SSH::CLI: A library to handle CLI Sessions. It allows you to write
98
98
  programs that invoke and interact with (long-running) CLI Sessions via NET::SSH.'
99
99
  email:
@@ -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.2.24
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'