feat(tunnel): add direction field — support local (-L) port forwards

Previously build_ssh_command only generated -R (reverse) tunnels.
The k3s API tunnel needs -L (local forward: workstation:16443 →
CoulombCore:6443) so kubectl can reach the cluster API directly.

- TunnelConfig.direction: "reverse" (default) | "local"
- config.py: parse direction from YAML, validate allowed values
- manager.py: choose -R or -L flag based on direction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-21 13:41:55 +01:00
parent 30bbaf303d
commit bebd542a2e
3 changed files with 12 additions and 2 deletions

View File

@@ -87,6 +87,10 @@ def _parse_tunnel(name: str, data: dict) -> TunnelConfig:
timeout_seconds=hc.get("timeout_seconds", 5),
)
direction = str(data.get("direction", "reverse"))
if direction not in ("reverse", "local"):
raise ConfigError(f"Tunnel '{name}' direction must be 'reverse' or 'local', got: {direction!r}")
return TunnelConfig(
name=name,
host=str(data["host"]),
@@ -97,6 +101,7 @@ def _parse_tunnel(name: str, data: dict) -> TunnelConfig:
actor=str(data["actor"]),
reconnect=reconnect,
health_check=health_check,
direction=direction,
)

View File

@@ -18,12 +18,16 @@ log = logging.getLogger(__name__)
def build_ssh_command(cfg: TunnelConfig) -> List[str]:
"""Build the SSH reverse tunnel command."""
"""Build the SSH tunnel command (reverse -R or local -L)."""
key = os.path.expanduser(cfg.ssh_key)
if cfg.direction == "local":
forward_flag = ["-L", f"{cfg.local_port}:127.0.0.1:{cfg.remote_port}"]
else:
forward_flag = ["-R", f"{cfg.remote_port}:127.0.0.1:{cfg.local_port}"]
return [
"ssh",
"-N",
"-R", f"{cfg.remote_port}:127.0.0.1:{cfg.local_port}",
*forward_flag,
"-i", key,
"-o", "ServerAliveInterval=10",
"-o", "ServerAliveCountMax=3",

View File

@@ -40,6 +40,7 @@ class TunnelConfig:
actor: str
reconnect: ReconnectPolicy = field(default_factory=ReconnectPolicy)
health_check: Optional[HealthCheckConfig] = None
direction: str = "reverse" # "reverse" (-R) or "local" (-L)
@dataclass