Skip to content

fix: resolve per-host ssh_config connection settings per node instead of once per dispatch #249

Description

@inureyes

Follow-up from the review of #247 (which implements #246).

Problem / Background

build_ssh_connection_config and resolve_address_family in src/app/dispatcher.rs (around lines 105 to 107, and 59, 69, 77) resolve SSH config connection settings once per dispatch, using a hostname that is Some(..) only in is_ssh_mode(). Everywhere else the lookup falls back to the literal "*".

Consequence: for a multi-host invocation such as bssh -H v6node uptime, the lookup queries "*" and misses a per-host block like:

Host v6node
    AddressFamily inet6

The same miss applies to the ping, upload, and download paths.

This is not a regression introduced by PR #247. The identical pattern already governs Compression (line 77) and the keepalive pair ServerAliveInterval / ServerAliveCountMax (lines 59 and 69). PR #247's AddressFamily simply joins the existing set.

There is a second facet. The resolved value rides on SshConnectionConfig into JumpHostChain (src/jump/chain.rs around line 403), which has no ssh_config awareness of its own. The first jump hop therefore inherits the destination's resolved settings rather than its own Host bastion block. This also already affects Compression and keepalive today.

Proposed Solution

Restructure per-node connection-setting resolution so the ssh_config lookup runs against the actual target host, and do it for all four settings at once rather than piecemeal per setting (piecemeal would mean touching the same call sites four times).

Settings in scope:

  • AddressFamily
  • Compression
  • ServerAliveInterval
  • ServerAliveCountMax

Also correct jump host resolution so each hop is resolved against its own Host block instead of inheriting the destination's values.

CLI precedence must be preserved: explicit CLI flags still beat any per-host ssh_config value, which beats YAML config, which beats the built-in defaults.

Acceptance Criteria

  • Connection settings are resolved per node against that node's hostname, for exec, ping, upload, and download, not once per dispatch against "*".
  • The per-node resolution is wired into the real dispatch flow (each node's connection actually uses its own resolved config), not exposed only as an unused helper.
  • Jump hosts resolve their connection settings against their own Host block rather than inheriting the destination's.
  • All four settings (AddressFamily, Compression, ServerAliveInterval, ServerAliveCountMax) go through the same per-node path.
  • Existing precedence is unchanged: CLI flags override per-host ssh_config, which overrides YAML config, which overrides defaults.
  • Tests cover a multi-host invocation where two hosts have different per-host values, asserting each connection receives its own resolved settings.
  • A test covers a jump host whose Host block differs from the destination's.

Technical Considerations

The natural shape is to move build_ssh_connection_config from a once-per-dispatch call into a per-node resolution performed where the node list is expanded, then carry the resolved config alongside each node. JumpHostChain needs either its own ssh_config handle or a pre-resolved per-hop config supplied by the caller. Wildcard and Match directive handling in the existing ssh_config parser should be reused rather than reimplemented at the call site.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions