Merge pull request 'Implement clan ssh <hostname>' (#2722) from pinpox/clan-core:clan-ssh-hostname into main

This commit is contained in:
clan-bot
2025-01-11 22:23:00 +00:00
2 changed files with 29 additions and 2 deletions

View File

@@ -214,10 +214,15 @@ For more detailed information, visit: {help_hyperlink("getting-started", "https:
description="Ssh to a remote machine",
epilog=(
f"""
This subcommand allows seamless ssh access to the nixos-image builders.
This subcommand allows seamless ssh access to the nixos-image builders or a machine of your clan.
Examples:
$ clan ssh [ssh_args ...] berlin`
Will ssh in to the machine called `berlin`, using the
`clan.core.networking.targetHost` specified in its configuration
$ clan ssh [ssh_args ...] --json [JSON]
Will ssh in to the machine based on the deployment information contained in
the json string. [JSON] can either be a json formatted string itself, or point

View File

@@ -8,7 +8,12 @@ from typing import Any
from clan_cli.async_run import AsyncRuntime
from clan_cli.cmd import run
from clan_cli.completions import (
add_dynamic_completer,
complete_machines,
)
from clan_cli.errors import ClanError
from clan_cli.machines.machines import Machine
from clan_cli.nix import nix_shell
from clan_cli.ssh.host import Host, is_ssh_reachable
from clan_cli.ssh.host_key import HostKeyCheck
@@ -24,6 +29,11 @@ class DeployInfo:
tor: str | None = None
pwd: str | None = None
@staticmethod
def from_hostname(hostname: str, args: argparse.Namespace) -> "DeployInfo":
m = Machine(hostname, flake=args.flake)
return DeployInfo(addrs=[m.target_host_address])
@staticmethod
def from_json(data: dict[str, Any]) -> "DeployInfo":
return DeployInfo(
@@ -101,6 +111,8 @@ def ssh_command_parse(args: argparse.Namespace) -> DeployInfo | None:
return DeployInfo.from_json(data)
if args.png:
return parse_qr_code(Path(args.png))
if hasattr(args, "machines"):
return DeployInfo.from_hostname(args.machines[0], args)
return None
@@ -108,7 +120,7 @@ def ssh_command(args: argparse.Namespace) -> None:
host_key_check = HostKeyCheck.from_str(args.host_key_check)
deploy_info = ssh_command_parse(args)
if not deploy_info:
msg = "No --json or --png data provided"
msg = "No MACHINE, --json or --png data provided"
raise ClanError(msg)
with AsyncRuntime() as runtime:
@@ -117,6 +129,16 @@ def ssh_command(args: argparse.Namespace) -> None:
def register_parser(parser: argparse.ArgumentParser) -> None:
group = parser.add_mutually_exclusive_group(required=True)
machines_parser = group.add_argument(
"machines",
type=str,
nargs="*",
default=[],
metavar="MACHINE",
help="Machine to ssh into.",
)
add_dynamic_completer(machines_parser, complete_machines)
group.add_argument(
"-j",
"--json",