Class: Nvoi::External::SshTunnel

Inherits:
Object
  • Object
show all
Defined in:
lib/nvoi/external/ssh_tunnel.rb

Overview

SshTunnel manages SSH port forwarding using net-ssh

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ip:, user:, key_path:, local_port:, remote_port:) ⇒ SshTunnel

Returns a new instance of SshTunnel.



11
12
13
14
15
16
17
18
19
20
# File 'lib/nvoi/external/ssh_tunnel.rb', line 11

def initialize(ip:, user:, key_path:, local_port:, remote_port:)
  @ip = ip
  @user = user
  @key_path = key_path
  @local_port = local_port
  @remote_port = remote_port
  @session = nil
  @thread = nil
  @running = false
end

Instance Attribute Details

#local_portObject (readonly)

Returns the value of attribute local_port.



9
10
11
# File 'lib/nvoi/external/ssh_tunnel.rb', line 9

def local_port
  @local_port
end

#remote_portObject (readonly)

Returns the value of attribute remote_port.



9
10
11
# File 'lib/nvoi/external/ssh_tunnel.rb', line 9

def remote_port
  @remote_port
end

Instance Method Details

#alive?Boolean

Returns:

  • (Boolean)


80
81
82
# File 'lib/nvoi/external/ssh_tunnel.rb', line 80

def alive?
  @running && @thread&.alive? && @session && !@session.closed?
end

#startObject



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/nvoi/external/ssh_tunnel.rb', line 22

def start
  Nvoi.logger.info "Starting SSH tunnel: localhost:%d -> %s:%d", @local_port, @ip, @remote_port

  @session = Net::SSH.start(
    @ip,
    @user,
    keys: [@key_path],
    non_interactive: true,
    verify_host_key: :never
  )

  @session.forward.local(@local_port, "localhost", @remote_port)
  @running = true

  @thread = Thread.new do
    Thread.current.report_on_exception = false
    @session.loop { @running }
  rescue IOError, Net::SSH::Disconnect, Errno::EBADF
    # Session closed during shutdown, exit gracefully
  end

  # Wait for tunnel to establish
  sleep 0.3
  verify_tunnel!

  Nvoi.logger.success "SSH tunnel established"
end

#stopObject



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/nvoi/external/ssh_tunnel.rb', line 50

def stop
  return unless @running

  Nvoi.logger.info "Stopping SSH tunnel"
  @running = false

  # Give the event loop a moment to see @running = false
  sleep 0.1

  begin
    @session&.forward&.cancel_local(@local_port)
  rescue StandardError
    # Ignore errors during cleanup
  end

  begin
    @session&.close
  rescue StandardError
    # Ignore errors during cleanup
  end

  # Wait for thread to exit gracefully
  @thread&.join(1)

  @session = nil
  @thread = nil

  Nvoi.logger.success "SSH tunnel closed"
end