import argparse from dataclasses import dataclass from pathlib import Path from ..clan_uri import FlakeId from ..cmd import run from ..dirs import machine_gcroot from ..errors import ClanError from ..machines.list import list_machines from ..machines.machines import Machine from ..nix import nix_add_to_gcroots, nix_build, nix_config, nix_eval, nix_metadata from ..vms.inspect import VmConfig, inspect_vm @dataclass class FlakeConfig: flake_url: FlakeId flake_attr: str clan_name: str nar_hash: str icon: str | None description: str | None last_updated: str revision: str | None vm: VmConfig def __post_init__(self) -> None: if isinstance(self.vm, dict): self.vm = VmConfig(**self.vm) def run_cmd(cmd: list[str]) -> str: proc = run(cmd) return proc.stdout.strip() def inspect_flake(flake_url: str | Path, machine_name: str) -> FlakeConfig: config = nix_config() system = config["system"] # Check if the machine exists machines = list_machines(flake_url, False) if machine_name not in machines: raise ClanError( f"Machine {machine_name} not found in {flake_url}. Available machines: {', '.join(machines)}" ) machine = Machine(machine_name, FlakeId(flake_url)) vm = inspect_vm(machine) # Make symlink to gcroots from vm.machine_icon if vm.machine_icon: gcroot_icon: Path = machine_gcroot(flake_url=str(flake_url)) / vm.machine_name nix_add_to_gcroots(vm.machine_icon, gcroot_icon) # Get the Clan name cmd = nix_eval( [ f'{flake_url}#clanInternals.machines."{system}"."{machine_name}".config.clan.core.clanName' ] ) res = run_cmd(cmd) clan_name = res.strip('"') # Get the clan icon path cmd = nix_eval( [ f'{flake_url}#clanInternals.machines."{system}"."{machine_name}".config.clan.core.clanIcon' ] ) res = run_cmd(cmd) # If the icon is null, no icon is set for this Clan if res == "null": icon_path = None else: icon_path = res.strip('"') cmd = nix_build( [ f'{flake_url}#clanInternals.machines."{system}"."{machine_name}".config.clan.core.clanIcon' ], machine_gcroot(flake_url=str(flake_url)) / "clanIcon", ) run_cmd(cmd) # Get the flake metadata meta = nix_metadata(flake_url) return FlakeConfig( vm=vm, flake_url=FlakeId(flake_url), clan_name=clan_name, flake_attr=machine_name, nar_hash=meta["locked"]["narHash"], icon=icon_path, description=meta.get("description"), last_updated=meta["lastModified"], revision=meta.get("revision"), ) @dataclass class InspectOptions: machine: str flake: FlakeId def inspect_command(args: argparse.Namespace) -> None: inspect_options = InspectOptions( machine=args.machine, flake=args.flake or FlakeId(Path.cwd()), ) res = inspect_flake( flake_url=str(inspect_options.flake), machine_name=inspect_options.machine ) print("Clan name:", res.clan_name) print("Icon:", res.icon) print("Description:", res.description) print("Last updated:", res.last_updated) print("Revision:", res.revision) def register_inspect_parser(parser: argparse.ArgumentParser) -> None: parser.add_argument("--machine", type=str, default="defaultVM") parser.set_defaults(func=inspect_command)