diff --git a/pkgs/clan-cli/clan_cli/config/__init__.py b/pkgs/clan-cli/clan_cli/config/__init__.py index ee5ebafc9..ec3df55f0 100644 --- a/pkgs/clan-cli/clan_cli/config/__init__.py +++ b/pkgs/clan-cli/clan_cli/config/__init__.py @@ -11,6 +11,7 @@ from typing import Any, Optional, Tuple, get_origin from clan_cli.dirs import machine_settings_file, specific_flake_dir from clan_cli.errors import ClanError +from clan_cli.flakes.types import FlakeName from clan_cli.git import commit_file from clan_cli.nix import nix_eval @@ -104,7 +105,7 @@ def cast(value: Any, type: Any, opt_description: str) -> Any: def options_for_machine( - flake_name: str, machine_name: str, show_trace: bool = False + flake_name: FlakeName, machine_name: str, show_trace: bool = False ) -> dict: clan_dir = specific_flake_dir(flake_name) flags = [] @@ -127,7 +128,7 @@ def options_for_machine( def read_machine_option_value( - flake_name: str, machine_name: str, option: str, show_trace: bool = False + flake_name: FlakeName, machine_name: str, option: str, show_trace: bool = False ) -> str: clan_dir = specific_flake_dir(flake_name) # use nix eval to read from .#nixosConfigurations.default.config.{option} @@ -240,7 +241,7 @@ def find_option( def set_option( - flake_name: str, + flake_name: FlakeName, option: str, value: Any, options: dict, diff --git a/pkgs/clan-cli/clan_cli/config/machine.py b/pkgs/clan-cli/clan_cli/config/machine.py index e15617313..1a5582cfd 100644 --- a/pkgs/clan-cli/clan_cli/config/machine.py +++ b/pkgs/clan-cli/clan_cli/config/machine.py @@ -15,6 +15,8 @@ from clan_cli.dirs import ( from clan_cli.git import commit_file, find_git_repo_root from clan_cli.nix import nix_eval +from ..flakes.types import FlakeName + def verify_machine_config( machine_name: str, config: Optional[dict] = None, flake: Optional[Path] = None @@ -52,7 +54,8 @@ def verify_machine_config( return None -def config_for_machine(machine_name: str) -> dict: + +def config_for_machine(flake_name: FlakeName, machine_name: str) -> dict: # read the config from a json file located at {flake}/machines/{machine_name}/settings.json if not specific_machine_dir(flake_name, machine_name).exists(): raise HTTPException( @@ -66,7 +69,9 @@ def config_for_machine(machine_name: str) -> dict: return json.load(f) -def set_config_for_machine(flake_name: str, machine_name: str, config: dict) -> None: +def set_config_for_machine( + flake_name: FlakeName, machine_name: str, config: dict +) -> None: # write the config to a json file located at {flake}/machines/{machine_name}/settings.json if not specific_machine_dir(flake_name, machine_name).exists(): raise HTTPException( @@ -83,7 +88,7 @@ def set_config_for_machine(flake_name: str, machine_name: str, config: dict) -> commit_file(settings_path, repo_dir) -def schema_for_machine(flake_name: str, machine_name: str) -> dict: +def schema_for_machine(flake_name: FlakeName, machine_name: str) -> dict: flake = specific_flake_dir(flake_name) # use nix eval to lib.evalModules .#nixosModules.machine-{machine_name} diff --git a/pkgs/clan-cli/clan_cli/dirs.py b/pkgs/clan-cli/clan_cli/dirs.py index 1ea596b17..17a0bc137 100644 --- a/pkgs/clan-cli/clan_cli/dirs.py +++ b/pkgs/clan-cli/clan_cli/dirs.py @@ -4,6 +4,7 @@ from pathlib import Path from typing import Optional from .errors import ClanError +from .flakes.types import FlakeName def _get_clan_flake_toplevel() -> Path: @@ -68,22 +69,22 @@ def clan_flakes_dir() -> Path: return path.resolve() -def specific_flake_dir(name: str) -> Path: - flake_dir = clan_flakes_dir() / name +def specific_flake_dir(flake_name: FlakeName) -> Path: + flake_dir = clan_flakes_dir() / flake_name if not flake_dir.exists(): - raise ClanError(f"Flake {name} does not exist") + raise ClanError(f"Flake {flake_name} does not exist") return flake_dir -def machines_dir(flake_name: str) -> Path: +def machines_dir(flake_name: FlakeName) -> Path: return specific_flake_dir(flake_name) / "machines" -def specific_machine_dir(flake_name: str, machine: str) -> Path: +def specific_machine_dir(flake_name: FlakeName, machine: str) -> Path: return machines_dir(flake_name) / machine -def machine_settings_file(flake_name: str, machine: str) -> Path: +def machine_settings_file(flake_name: FlakeName, machine: str) -> Path: return specific_machine_dir(flake_name, machine) / "settings.json" diff --git a/pkgs/clan-cli/clan_cli/flakes/types.py b/pkgs/clan-cli/clan_cli/flakes/types.py new file mode 100644 index 000000000..16e38c879 --- /dev/null +++ b/pkgs/clan-cli/clan_cli/flakes/types.py @@ -0,0 +1,3 @@ +from typing import NewType + +FlakeName = NewType("FlakeName", str) diff --git a/pkgs/clan-cli/clan_cli/machines/create.py b/pkgs/clan-cli/clan_cli/machines/create.py index f96beead9..a4880f0e9 100644 --- a/pkgs/clan-cli/clan_cli/machines/create.py +++ b/pkgs/clan-cli/clan_cli/machines/create.py @@ -5,12 +5,13 @@ from typing import Dict from ..async_cmd import CmdOut, run, runforcli from ..dirs import specific_flake_dir, specific_machine_dir from ..errors import ClanError +from ..flakes.types import FlakeName from ..nix import nix_shell log = logging.getLogger(__name__) -async def create_machine(flake_name: str, machine_name: str) -> Dict[str, CmdOut]: +async def create_machine(flake_name: FlakeName, machine_name: str) -> Dict[str, CmdOut]: folder = specific_machine_dir(flake_name, machine_name) folder.mkdir(parents=True, exist_ok=True) diff --git a/pkgs/clan-cli/clan_cli/machines/facts.py b/pkgs/clan-cli/clan_cli/machines/facts.py index ed471ebc1..7b665b536 100644 --- a/pkgs/clan-cli/clan_cli/machines/facts.py +++ b/pkgs/clan-cli/clan_cli/machines/facts.py @@ -1,9 +1,10 @@ from ..dirs import specific_machine_dir +from ..flakes.types import FlakeName -def machine_has_fact(flake_name: str, machine: str, fact: str) -> bool: +def machine_has_fact(flake_name: FlakeName, machine: str, fact: str) -> bool: return (specific_machine_dir(flake_name, machine) / "facts" / fact).exists() -def machine_get_fact(flake_name: str, machine: str, fact: str) -> str: +def machine_get_fact(flake_name: FlakeName, machine: str, fact: str) -> str: return (specific_machine_dir(flake_name, machine) / "facts" / fact).read_text() diff --git a/pkgs/clan-cli/clan_cli/machines/list.py b/pkgs/clan-cli/clan_cli/machines/list.py index 3558967a4..d78adb239 100644 --- a/pkgs/clan-cli/clan_cli/machines/list.py +++ b/pkgs/clan-cli/clan_cli/machines/list.py @@ -3,12 +3,13 @@ import logging import os from ..dirs import machines_dir +from ..flakes.types import FlakeName from .types import validate_hostname log = logging.getLogger(__name__) -def list_machines(flake_name: str) -> list[str]: +def list_machines(flake_name: FlakeName) -> list[str]: path = machines_dir(flake_name) log.debug(f"Listing machines in {path}") if not path.exists(): diff --git a/pkgs/clan-cli/clan_cli/secrets/folders.py b/pkgs/clan-cli/clan_cli/secrets/folders.py index 4659a7ffd..8a551cc7a 100644 --- a/pkgs/clan-cli/clan_cli/secrets/folders.py +++ b/pkgs/clan-cli/clan_cli/secrets/folders.py @@ -5,14 +5,15 @@ from typing import Callable from ..dirs import specific_flake_dir from ..errors import ClanError +from ..flakes.types import FlakeName -def get_sops_folder(flake_name: str) -> Path: +def get_sops_folder(flake_name: FlakeName) -> Path: return specific_flake_dir(flake_name) / "sops" -def gen_sops_subfolder(subdir: str) -> Callable[[str], Path]: - def folder(flake_name: str) -> Path: +def gen_sops_subfolder(subdir: str) -> Callable[[FlakeName], Path]: + def folder(flake_name: FlakeName) -> Path: return specific_flake_dir(flake_name) / "sops" / subdir return folder diff --git a/pkgs/clan-cli/clan_cli/secrets/groups.py b/pkgs/clan-cli/clan_cli/secrets/groups.py index 4e5faf069..b944560c3 100644 --- a/pkgs/clan-cli/clan_cli/secrets/groups.py +++ b/pkgs/clan-cli/clan_cli/secrets/groups.py @@ -3,6 +3,7 @@ import os from pathlib import Path from ..errors import ClanError +from ..flakes.types import FlakeName from ..machines.types import machine_name_type, validate_hostname from . import secrets from .folders import ( @@ -20,17 +21,17 @@ from .types import ( ) -def machines_folder(flake_name: str, group: str) -> Path: +def machines_folder(flake_name: FlakeName, group: str) -> Path: return sops_groups_folder(flake_name) / group / "machines" -def users_folder(flake_name: str, group: str) -> Path: +def users_folder(flake_name: FlakeName, group: str) -> Path: return sops_groups_folder(flake_name) / group / "users" class Group: def __init__( - self, flake_name: str, name: str, machines: list[str], users: list[str] + self, flake_name: FlakeName, name: str, machines: list[str], users: list[str] ) -> None: self.name = name self.machines = machines @@ -38,7 +39,7 @@ class Group: self.flake_name = flake_name -def list_groups(flake_name: str) -> list[Group]: +def list_groups(flake_name: FlakeName) -> list[Group]: groups: list[Group] = [] folder = sops_groups_folder(flake_name) if not folder.exists(): @@ -87,7 +88,7 @@ def list_directory(directory: Path) -> str: return msg -def update_group_keys(flake_name: str, group: str) -> None: +def update_group_keys(flake_name: FlakeName, group: str) -> None: for secret_ in secrets.list_secrets(flake_name): secret = sops_secrets_folder(flake_name) / secret_ if (secret / "groups" / group).is_symlink(): @@ -98,7 +99,7 @@ def update_group_keys(flake_name: str, group: str) -> None: def add_member( - flake_name: str, group_folder: Path, source_folder: Path, name: str + flake_name: FlakeName, group_folder: Path, source_folder: Path, name: str ) -> None: source = source_folder / name if not source.exists(): @@ -117,7 +118,7 @@ def add_member( update_group_keys(flake_name, group_folder.parent.name) -def remove_member(flake_name: str, group_folder: Path, name: str) -> None: +def remove_member(flake_name: FlakeName, group_folder: Path, name: str) -> None: target = group_folder / name if not target.exists(): msg = f"{name} does not exist in group in {group_folder}: " @@ -135,7 +136,7 @@ def remove_member(flake_name: str, group_folder: Path, name: str) -> None: os.rmdir(group_folder.parent) -def add_user(flake_name: str, group: str, name: str) -> None: +def add_user(flake_name: FlakeName, group: str, name: str) -> None: add_member( flake_name, users_folder(flake_name, group), sops_users_folder(flake_name), name ) @@ -145,7 +146,7 @@ def add_user_command(args: argparse.Namespace) -> None: add_user(args.flake, args.group, args.user) -def remove_user(flake_name: str, group: str, name: str) -> None: +def remove_user(flake_name: FlakeName, group: str, name: str) -> None: remove_member(flake_name, users_folder(flake_name, group), name) @@ -153,7 +154,7 @@ def remove_user_command(args: argparse.Namespace) -> None: remove_user(args.flake, args.group, args.user) -def add_machine(flake_name: str, group: str, name: str) -> None: +def add_machine(flake_name: FlakeName, group: str, name: str) -> None: add_member( flake_name, machines_folder(flake_name, group), @@ -166,7 +167,7 @@ def add_machine_command(args: argparse.Namespace) -> None: add_machine(args.flake, args.group, args.machine) -def remove_machine(flake_name: str, group: str, name: str) -> None: +def remove_machine(flake_name: FlakeName, group: str, name: str) -> None: remove_member(flake_name, machines_folder(flake_name, group), name) @@ -178,7 +179,7 @@ def add_group_argument(parser: argparse.ArgumentParser) -> None: parser.add_argument("group", help="the name of the secret", type=group_name_type) -def add_secret(flake_name: str, group: str, name: str) -> None: +def add_secret(flake_name: FlakeName, group: str, name: str) -> None: secrets.allow_member( secrets.groups_folder(flake_name, name), sops_groups_folder(flake_name), group ) @@ -188,7 +189,7 @@ def add_secret_command(args: argparse.Namespace) -> None: add_secret(args.flake, args.group, args.secret) -def remove_secret(flake_name: str, group: str, name: str) -> None: +def remove_secret(flake_name: FlakeName, group: str, name: str) -> None: secrets.disallow_member(secrets.groups_folder(flake_name, name), group) diff --git a/pkgs/clan-cli/clan_cli/secrets/machines.py b/pkgs/clan-cli/clan_cli/secrets/machines.py index b78d52d88..bb01212e9 100644 --- a/pkgs/clan-cli/clan_cli/secrets/machines.py +++ b/pkgs/clan-cli/clan_cli/secrets/machines.py @@ -1,5 +1,6 @@ import argparse +from ..flakes.types import FlakeName from ..machines.types import machine_name_type, validate_hostname from . import secrets from .folders import list_objects, remove_object, sops_machines_folder @@ -7,23 +8,23 @@ from .sops import read_key, write_key from .types import public_or_private_age_key_type, secret_name_type -def add_machine(flake_name: str, name: str, key: str, force: bool) -> None: +def add_machine(flake_name: FlakeName, name: str, key: str, force: bool) -> None: write_key(sops_machines_folder(flake_name) / name, key, force) -def remove_machine(flake_name: str, name: str) -> None: +def remove_machine(flake_name: FlakeName, name: str) -> None: remove_object(sops_machines_folder(flake_name), name) -def get_machine(flake_name: str, name: str) -> str: +def get_machine(flake_name: FlakeName, name: str) -> str: return read_key(sops_machines_folder(flake_name) / name) -def has_machine(flake_name: str, name: str) -> bool: +def has_machine(flake_name: FlakeName, name: str) -> bool: return (sops_machines_folder(flake_name) / name / "key.json").exists() -def list_machines(flake_name: str) -> list[str]: +def list_machines(flake_name: FlakeName) -> list[str]: path = sops_machines_folder(flake_name) def validate(name: str) -> bool: @@ -32,7 +33,7 @@ def list_machines(flake_name: str) -> list[str]: return list_objects(path, validate) -def add_secret(flake_name: str, machine: str, secret: str) -> None: +def add_secret(flake_name: FlakeName, machine: str, secret: str) -> None: secrets.allow_member( secrets.machines_folder(flake_name, secret), sops_machines_folder(flake_name), @@ -40,7 +41,7 @@ def add_secret(flake_name: str, machine: str, secret: str) -> None: ) -def remove_secret(flake_name: str, machine: str, secret: str) -> None: +def remove_secret(flake_name: FlakeName, machine: str, secret: str) -> None: secrets.disallow_member(secrets.machines_folder(flake_name, secret), machine) diff --git a/pkgs/clan-cli/clan_cli/secrets/secrets.py b/pkgs/clan-cli/clan_cli/secrets/secrets.py index 62065fd60..d7a29542b 100644 --- a/pkgs/clan-cli/clan_cli/secrets/secrets.py +++ b/pkgs/clan-cli/clan_cli/secrets/secrets.py @@ -8,6 +8,7 @@ from typing import IO from .. import tty from ..errors import ClanError +from ..flakes.types import FlakeName from .folders import ( list_objects, sops_groups_folder, @@ -53,7 +54,7 @@ def collect_keys_for_path(path: Path) -> set[str]: def encrypt_secret( - flake_name: str, + flake_name: FlakeName, secret: Path, value: IO[str] | str | None, add_users: list[str] = [], @@ -101,7 +102,7 @@ def encrypt_secret( encrypt_file(secret / "secret", value, list(sorted(keys))) -def remove_secret(flake_name: str, secret: str) -> None: +def remove_secret(flake_name: FlakeName, secret: str) -> None: path = sops_secrets_folder(flake_name) / secret if not path.exists(): raise ClanError(f"Secret '{secret}' does not exist") @@ -116,15 +117,15 @@ def add_secret_argument(parser: argparse.ArgumentParser) -> None: parser.add_argument("secret", help="the name of the secret", type=secret_name_type) -def machines_folder(flake_name: str, group: str) -> Path: +def machines_folder(flake_name: FlakeName, group: str) -> Path: return sops_secrets_folder(flake_name) / group / "machines" -def users_folder(flake_name: str, group: str) -> Path: +def users_folder(flake_name: FlakeName, group: str) -> Path: return sops_secrets_folder(flake_name) / group / "users" -def groups_folder(flake_name: str, group: str) -> Path: +def groups_folder(flake_name: FlakeName, group: str) -> Path: return sops_secrets_folder(flake_name) / group / "groups" @@ -188,11 +189,11 @@ def disallow_member(group_folder: Path, name: str) -> None: ) -def has_secret(flake_name: str, secret: str) -> bool: +def has_secret(flake_name: FlakeName, secret: str) -> bool: return (sops_secrets_folder(flake_name) / secret / "secret").exists() -def list_secrets(flake_name: str) -> list[str]: +def list_secrets(flake_name: FlakeName) -> list[str]: path = sops_secrets_folder(flake_name) def validate(name: str) -> bool: @@ -209,7 +210,7 @@ def list_command(args: argparse.Namespace) -> None: print("\n".join(lst)) -def decrypt_secret(flake_name: str, secret: str) -> str: +def decrypt_secret(flake_name: FlakeName, secret: str) -> str: ensure_sops_key(flake_name) secret_path = sops_secrets_folder(flake_name) / secret / "secret" if not secret_path.exists(): diff --git a/pkgs/clan-cli/clan_cli/secrets/sops.py b/pkgs/clan-cli/clan_cli/secrets/sops.py index c9a389bbf..c6f2b2bf2 100644 --- a/pkgs/clan-cli/clan_cli/secrets/sops.py +++ b/pkgs/clan-cli/clan_cli/secrets/sops.py @@ -9,6 +9,7 @@ from typing import IO, Iterator from ..dirs import user_config_dir from ..errors import ClanError +from ..flakes.types import FlakeName from ..nix import nix_shell from .folders import sops_machines_folder, sops_users_folder @@ -51,7 +52,7 @@ def generate_private_key() -> tuple[str, str]: raise ClanError("Failed to generate private sops key") from e -def get_user_name(flake_name: str, user: str) -> str: +def get_user_name(flake_name: FlakeName, user: str) -> str: """Ask the user for their name until a unique one is provided.""" while True: name = input( @@ -64,7 +65,7 @@ def get_user_name(flake_name: str, user: str) -> str: print(f"{sops_users_folder(flake_name) / user} already exists") -def ensure_user_or_machine(flake_name: str, pub_key: str) -> SopsKey: +def ensure_user_or_machine(flake_name: FlakeName, pub_key: str) -> SopsKey: key = SopsKey(pub_key, username="") folders = [sops_users_folder(flake_name), sops_machines_folder(flake_name)] for folder in folders: @@ -90,7 +91,7 @@ def default_sops_key_path() -> Path: return user_config_dir() / "sops" / "age" / "keys.txt" -def ensure_sops_key(flake_name: str) -> SopsKey: +def ensure_sops_key(flake_name: FlakeName) -> SopsKey: key = os.environ.get("SOPS_AGE_KEY") if key: return ensure_user_or_machine(flake_name, get_public_key(key)) diff --git a/pkgs/clan-cli/clan_cli/secrets/sops_generate.py b/pkgs/clan-cli/clan_cli/secrets/sops_generate.py index f6657a5a8..fdac72df9 100644 --- a/pkgs/clan-cli/clan_cli/secrets/sops_generate.py +++ b/pkgs/clan-cli/clan_cli/secrets/sops_generate.py @@ -11,13 +11,14 @@ from clan_cli.nix import nix_shell from ..dirs import specific_flake_dir from ..errors import ClanError +from ..flakes.types import FlakeName from .folders import sops_secrets_folder from .machines import add_machine, has_machine from .secrets import decrypt_secret, encrypt_secret, has_secret from .sops import generate_private_key -def generate_host_key(flake_name: str, machine_name: str) -> None: +def generate_host_key(flake_name: FlakeName, machine_name: str) -> None: if has_machine(flake_name, machine_name): return priv_key, pub_key = generate_private_key() @@ -30,7 +31,7 @@ def generate_host_key(flake_name: str, machine_name: str) -> None: def generate_secrets_group( - flake_name: str, + flake_name: FlakeName, secret_group: str, machine_name: str, tempdir: Path, @@ -88,7 +89,7 @@ export secrets={shlex.quote(str(secrets_dir))} # this is called by the sops.nix clan core module def generate_secrets_from_nix( - flake_name: str, + flake_name: FlakeName, machine_name: str, secret_submodules: dict[str, Any], ) -> None: @@ -112,7 +113,7 @@ def generate_secrets_from_nix( # this is called by the sops.nix clan core module def upload_age_key_from_nix( - flake_name: str, + flake_name: FlakeName, machine_name: str, ) -> None: secret_name = f"{machine_name}-age.key" diff --git a/pkgs/clan-cli/clan_cli/secrets/users.py b/pkgs/clan-cli/clan_cli/secrets/users.py index a653f2959..c5b51e994 100644 --- a/pkgs/clan-cli/clan_cli/secrets/users.py +++ b/pkgs/clan-cli/clan_cli/secrets/users.py @@ -1,5 +1,6 @@ import argparse +from ..flakes.types import FlakeName from . import secrets from .folders import list_objects, remove_object, sops_users_folder from .sops import read_key, write_key @@ -11,19 +12,19 @@ from .types import ( ) -def add_user(flake_name: str, name: str, key: str, force: bool) -> None: +def add_user(flake_name: FlakeName, name: str, key: str, force: bool) -> None: write_key(sops_users_folder(flake_name) / name, key, force) -def remove_user(flake_name: str, name: str) -> None: +def remove_user(flake_name: FlakeName, name: str) -> None: remove_object(sops_users_folder(flake_name), name) -def get_user(flake_name: str, name: str) -> str: +def get_user(flake_name: FlakeName, name: str) -> str: return read_key(sops_users_folder(flake_name) / name) -def list_users(flake_name: str) -> list[str]: +def list_users(flake_name: FlakeName) -> list[str]: path = sops_users_folder(flake_name) def validate(name: str) -> bool: @@ -35,13 +36,13 @@ def list_users(flake_name: str) -> list[str]: return list_objects(path, validate) -def add_secret(flake_name: str, user: str, secret: str) -> None: +def add_secret(flake_name: FlakeName, user: str, secret: str) -> None: secrets.allow_member( secrets.users_folder(flake_name, secret), sops_users_folder(flake_name), user ) -def remove_secret(flake_name: str, user: str, secret: str) -> None: +def remove_secret(flake_name: FlakeName, user: str, secret: str) -> None: secrets.disallow_member(secrets.users_folder(flake_name, secret), user) diff --git a/pkgs/clan-cli/clan_cli/webui/routers/machines.py b/pkgs/clan-cli/clan_cli/webui/routers/machines.py index 0b6fd281e..9668b8b41 100644 --- a/pkgs/clan-cli/clan_cli/webui/routers/machines.py +++ b/pkgs/clan-cli/clan_cli/webui/routers/machines.py @@ -10,6 +10,7 @@ from ...config.machine import ( set_config_for_machine, verify_machine_config, ) +from ...flakes.types import FlakeName from ...machines.create import create_machine as _create_machine from ...machines.list import list_machines as _list_machines from ..api_outputs import ( @@ -28,7 +29,7 @@ router = APIRouter() @router.get("/api/{flake_name}/machines") -async def list_machines(flake_name: str) -> MachinesResponse: +async def list_machines(flake_name: FlakeName) -> MachinesResponse: machines = [] for m in _list_machines(flake_name): machines.append(Machine(name=m, status=Status.UNKNOWN)) @@ -37,7 +38,7 @@ async def list_machines(flake_name: str) -> MachinesResponse: @router.post("/api/{flake_name}/machines", status_code=201) async def create_machine( - flake_name: str, machine: Annotated[MachineCreate, Body()] + flake_name: FlakeName, machine: Annotated[MachineCreate, Body()] ) -> MachineResponse: out = await _create_machine(flake_name, machine.name) log.debug(out) @@ -51,21 +52,21 @@ async def get_machine(name: str) -> MachineResponse: @router.get("/api/{flake_name}/machines/{name}/config") -async def get_machine_config(flake_name: str, name: str) -> ConfigResponse: +async def get_machine_config(flake_name: FlakeName, name: str) -> ConfigResponse: config = config_for_machine(flake_name, name) return ConfigResponse(config=config) @router.put("/api/{flake_name}/machines/{name}/config") async def set_machine_config( - flake_name: str, name: str, config: Annotated[dict, Body()] + flake_name: FlakeName, name: str, config: Annotated[dict, Body()] ) -> ConfigResponse: set_config_for_machine(flake_name, name, config) return ConfigResponse(config=config) @router.get("/api/{flake_name}/machines/{name}/schema") -async def get_machine_schema(flake_name: str, name: str) -> SchemaResponse: +async def get_machine_schema(flake_name: FlakeName, name: str) -> SchemaResponse: schema = schema_for_machine(flake_name, name) return SchemaResponse(schema=schema) diff --git a/pkgs/clan-cli/tests/fixtures_flakes.py b/pkgs/clan-cli/tests/fixtures_flakes.py index e488440a7..b775790d5 100644 --- a/pkgs/clan-cli/tests/fixtures_flakes.py +++ b/pkgs/clan-cli/tests/fixtures_flakes.py @@ -8,6 +8,7 @@ import pytest from root import CLAN_CORE from clan_cli.dirs import nixpkgs_source +from clan_cli.flakes.types import FlakeName # substitutes string sin a file. @@ -28,13 +29,13 @@ def substitute( class TestFlake(NamedTuple): - name: str + name: FlakeName path: Path def create_flake( monkeypatch: pytest.MonkeyPatch, - flake_name: str, + flake_name: FlakeName, clan_core_flake: Path | None = None, machines: list[str] = [], remote: bool = False, @@ -74,7 +75,7 @@ def create_flake( @pytest.fixture def test_flake(monkeypatch: pytest.MonkeyPatch) -> Iterator[TestFlake]: - yield from create_flake(monkeypatch, "test_flake") + yield from create_flake(monkeypatch, FlakeName("test_flake")) @pytest.fixture @@ -83,7 +84,7 @@ def test_flake_with_core(monkeypatch: pytest.MonkeyPatch) -> Iterator[TestFlake] raise Exception( "clan-core flake not found. This test requires the clan-core flake to be present" ) - yield from create_flake(monkeypatch, "test_flake_with_core", CLAN_CORE) + yield from create_flake(monkeypatch, FlakeName("test_flake_with_core"), CLAN_CORE) @pytest.fixture @@ -94,4 +95,6 @@ def test_flake_with_core_and_pass( raise Exception( "clan-core flake not found. This test requires the clan-core flake to be present" ) - yield from create_flake(monkeypatch, "test_flake_with_core_and_pass", CLAN_CORE) + yield from create_flake( + monkeypatch, FlakeName("test_flake_with_core_and_pass"), CLAN_CORE + ) diff --git a/pkgs/clan-cli/tests/test_vms_api_create.py b/pkgs/clan-cli/tests/test_vms_api_create.py index 25bedf2f5..1de515d53 100644 --- a/pkgs/clan-cli/tests/test_vms_api_create.py +++ b/pkgs/clan-cli/tests/test_vms_api_create.py @@ -9,6 +9,8 @@ from fixtures_flakes import TestFlake, create_flake from httpx import SyncByteStream from root import CLAN_CORE +from clan_cli.flakes.types import FlakeName + if TYPE_CHECKING: from age_keys import KeyPair @@ -17,7 +19,7 @@ if TYPE_CHECKING: def flake_with_vm_with_secrets(monkeypatch: pytest.MonkeyPatch) -> Iterator[TestFlake]: yield from create_flake( monkeypatch, - "test_flake_with_core_dynamic_machines", + FlakeName("test_flake_with_core_dynamic_machines"), CLAN_CORE, machines=["vm_with_secrets"], ) @@ -29,7 +31,7 @@ def remote_flake_with_vm_without_secrets( ) -> Iterator[TestFlake]: yield from create_flake( monkeypatch, - "test_flake_with_core_dynamic_machines", + FlakeName("test_flake_with_core_dynamic_machines"), CLAN_CORE, machines=["vm_without_secrets"], remote=True,