mirror of
https://github.com/henrygd/beszel.git
synced 2026-10-01 22:07:48 +02:00
refactor(hub): make SSHTransport the single owner of each system's SSH connection
The updater and on-demand requests kept separate copies of the SSH client (sys.client and the transport's client) and synced them after each request. That allowed a closed client to be reinstalled over a newer one and leaked connections that were replaced without being closed. The updater now dials, opens sessions and tears down timed-out connections through the transport. The dial keeps the TCP keepalive and handshake deadline, and an OnConnect callback handles the per-connection resets. The transport is created under a lock and agentVersion is now atomic.
This commit is contained in:
@@ -42,12 +42,14 @@ func TestSSHNetworkMonitorReconnectSync(t *testing.T) {
|
||||
t.Cleanup(sys.closeSSHConnection)
|
||||
requests := make(chan monitor.SyncRequest, 10)
|
||||
var failSync atomic.Bool
|
||||
var connections atomic.Int32
|
||||
go func() {
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
connections.Add(1)
|
||||
go func() {
|
||||
server, channels, reqs, err := ssh.NewServerConn(conn, config)
|
||||
if err != nil {
|
||||
@@ -138,15 +140,17 @@ func TestSSHNetworkMonitorReconnectSync(t *testing.T) {
|
||||
require.False(t, sys.monitorsNeedSync.Load())
|
||||
fetch()
|
||||
require.Empty(t, requests, "steady-state fetch must not resync")
|
||||
require.Equal(t, int32(1), connections.Load(), "stats and monitor sync must share one connection")
|
||||
|
||||
// Simulate loss of the agent process/connection and its in-memory monitors.
|
||||
require.NoError(t, sys.client.Load().Close())
|
||||
require.NoError(t, sys.sshTransport.GetClient().Close())
|
||||
fetch()
|
||||
require.ElementsMatch(t, configs, receive().Configs)
|
||||
require.False(t, sys.monitorsNeedSync.Load())
|
||||
require.Equal(t, int32(2), connections.Load(), "reconnect must open exactly one new connection")
|
||||
|
||||
// Failed replacements are retried on the next successful stats fetch.
|
||||
require.NoError(t, sys.client.Load().Close())
|
||||
require.NoError(t, sys.sshTransport.GetClient().Close())
|
||||
failSync.Store(true)
|
||||
fetch()
|
||||
require.ElementsMatch(t, configs, receive().Configs)
|
||||
@@ -160,7 +164,7 @@ func TestSSHNetworkMonitorReconnectSync(t *testing.T) {
|
||||
probe.Set("enabled", false)
|
||||
require.NoError(t, app.SaveNoValidate(probe))
|
||||
}
|
||||
require.NoError(t, sys.client.Load().Close())
|
||||
require.NoError(t, sys.sshTransport.GetClient().Close())
|
||||
fetch()
|
||||
require.Empty(t, receive().Configs, "empty replacement must clear stale monitors")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user