clan-cli: Fix check_machine_online to use Remote object instead of machine, this makes it possible to override HostKeyCheck properly

This commit is contained in:
Qubasa
2025-06-08 17:20:38 +02:00
parent 2540215f2e
commit 82299a5361
3 changed files with 42 additions and 16 deletions

View File

@@ -6,7 +6,7 @@ from typing import Literal
from clan_lib.api import API from clan_lib.api import API
from clan_lib.cmd import RunOpts from clan_lib.cmd import RunOpts
from clan_lib.errors import ClanError from clan_lib.errors import ClanError
from clan_lib.machines.machines import Machine from clan_lib.ssh.remote import Remote
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@@ -19,19 +19,12 @@ class ConnectionOptions:
@API.register @API.register
def check_machine_online( def check_machine_online(
machine: Machine, opts: ConnectionOptions | None = None remote: Remote, opts: ConnectionOptions | None = None
) -> Literal["Online", "Offline"]: ) -> Literal["Online", "Offline"]:
hostname = machine.target_host().target
if not hostname:
msg = f"Machine {machine.name} does not specify a targetHost"
raise ClanError(msg)
timeout = opts.timeout if opts and opts.timeout else 2 timeout = opts.timeout if opts and opts.timeout else 2
for _ in range(opts.retries if opts and opts.retries else 10): for _ in range(opts.retries if opts and opts.retries else 10):
host = machine.target_host() with remote.ssh_control_master() as ssh:
with host.ssh_control_master() as ssh:
res = ssh.run( res = ssh.run(
["true"], ["true"],
RunOpts(timeout=timeout, check=False, needs_user_terminal=True), RunOpts(timeout=timeout, check=False, needs_user_terminal=True),
@@ -39,6 +32,10 @@ def check_machine_online(
if res.returncode == 0: if res.returncode == 0:
return "Online" return "Online"
if "Host key verification failed." in res.stderr:
raise ClanError(res.stderr.strip())
time.sleep(timeout) time.sleep(timeout)
return "Offline" return "Offline"

View File

@@ -167,7 +167,20 @@ class Machine:
msg, msg,
description="See https://docs.clan.lol/guides/getting-started/deploy/#setting-the-target-host for more information.", description="See https://docs.clan.lol/guides/getting-started/deploy/#setting-the-target-host for more information.",
) )
return remote.data data = remote.data
return Remote(
address=data.address,
user=data.user,
command_prefix=data.command_prefix,
port=data.port,
private_key=self.private_key,
password=data.password,
forward_agent=data.forward_agent,
host_key_check=self.host_key_check,
verbose_ssh=data.verbose_ssh,
ssh_options=data.ssh_options,
tor_socks=data.tor_socks,
)
def build_host(self) -> Remote | None: def build_host(self) -> Remote | None:
""" """
@@ -183,9 +196,25 @@ class Machine:
private_key=self.private_key, private_key=self.private_key,
) )
remote = get_build_host(self) remote = get_build_host(self.name, self.flake)
return remote.data if remote else None if remote:
data = remote.data
return Remote(
address=data.address,
user=data.user,
command_prefix=data.command_prefix,
port=data.port,
private_key=self.private_key,
password=data.password,
forward_agent=data.forward_agent,
host_key_check=self.host_key_check,
verbose_ssh=data.verbose_ssh,
ssh_options=data.ssh_options,
tor_socks=data.tor_socks,
)
return None
def nix( def nix(
self, self,
@@ -268,7 +297,7 @@ def get_target_host(name: str, flake: Flake) -> RemoteSource | None:
machine = Machine(name=name, flake=flake) machine = Machine(name=name, flake=flake)
inv_machine = machine.get_inv_machine() inv_machine = machine.get_inv_machine()
source = "inventory" source: Literal["inventory", "nix_machine"] = "inventory"
target_host_str = inv_machine.get("deploy", {}).get("targetHost") target_host_str = inv_machine.get("deploy", {}).get("targetHost")
if target_host_str is None: if target_host_str is None:
@@ -300,7 +329,7 @@ def get_build_host(name: str, flake: Flake) -> RemoteSource | None:
machine = Machine(name=name, flake=flake) machine = Machine(name=name, flake=flake)
inv_machine = machine.get_inv_machine() inv_machine = machine.get_inv_machine()
source = "inventory" source: Literal["inventory", "nix_machine"] = "inventory"
target_host_str = inv_machine.get("deploy", {}).get("buildHost") target_host_str = inv_machine.get("deploy", {}).get("buildHost")
if target_host_str is None: if target_host_str is None:

View File

@@ -203,7 +203,7 @@ def test_clan_create_api(
# Invalidate cache because of new machine creation # Invalidate cache because of new machine creation
clan_dir_flake.invalidate_cache() clan_dir_flake.invalidate_cache()
result = check_machine_online(machine) result = check_machine_online(machine.target_host())
assert result == "Online", f"Machine {machine.name} is not online" assert result == "Online", f"Machine {machine.name} is not online"
ssh_keys = [ ssh_keys = [