diff --git a/pkgs/clan-cli/clan_cli/completions.py b/pkgs/clan-cli/clan_cli/completions.py index c0b8dc981..b38cea208 100644 --- a/pkgs/clan-cli/clan_cli/completions.py +++ b/pkgs/clan-cli/clan_cli/completions.py @@ -289,6 +289,49 @@ def complete_templates_clan( return [] +def complete_vars_for_machine( + prefix: str, parsed_args: argparse.Namespace, **kwargs: Any +) -> Iterable[str]: + """ + Provides completion functionality for variable names for a specific machine. + Only completes vars that already exist in the vars directory on disk. + This is fast as it only scans the filesystem without any evaluation. + """ + from pathlib import Path + + machine_name = getattr(parsed_args, "machine", None) + if not machine_name: + return [] + + if (clan_dir_result := clan_dir(None)) is not None: + flake_path = Path(clan_dir_result) + else: + flake_path = Path() + + vars_dir = flake_path / "vars" / "per-machine" / machine_name + vars_list: list[str] = [] + + if vars_dir.exists() and vars_dir.is_dir(): + try: + for generator_dir in vars_dir.iterdir(): + if not generator_dir.is_dir(): + continue + + generator_name = generator_dir.name + + for var_dir in generator_dir.iterdir(): + if var_dir.is_dir(): + var_name = var_dir.name + var_id = f"{generator_name}/{var_name}" + vars_list.append(var_id) + + except Exception: + pass + + vars_dict = dict.fromkeys(vars_list, "var") + return vars_dict + + def complete_target_host( prefix: str, parsed_args: argparse.Namespace, **kwargs: Any ) -> Iterable[str]: diff --git a/pkgs/clan-cli/clan_cli/vars/get.py b/pkgs/clan-cli/clan_cli/vars/get.py index 60b4164bb..fe0e67d27 100644 --- a/pkgs/clan-cli/clan_cli/vars/get.py +++ b/pkgs/clan-cli/clan_cli/vars/get.py @@ -2,7 +2,11 @@ import argparse import logging import sys -from clan_cli.completions import add_dynamic_completer, complete_machines +from clan_cli.completions import ( + add_dynamic_completer, + complete_machines, + complete_vars_for_machine, +) from clan_lib.errors import ClanError from clan_lib.flake import Flake, require_flake @@ -67,9 +71,10 @@ def register_get_parser(parser: argparse.ArgumentParser) -> None: ) add_dynamic_completer(machines_arg, complete_machines) - parser.add_argument( + var_id_arg = parser.add_argument( "var_id", help="The var id to get the value for. Example: ssh-keys/pubkey", ) + add_dynamic_completer(var_id_arg, complete_vars_for_machine) parser.set_defaults(func=_get_command) diff --git a/pkgs/clan-cli/clan_cli/vars/set.py b/pkgs/clan-cli/clan_cli/vars/set.py index cd67b7522..d67be818e 100644 --- a/pkgs/clan-cli/clan_cli/vars/set.py +++ b/pkgs/clan-cli/clan_cli/vars/set.py @@ -2,7 +2,11 @@ import argparse import logging import sys -from clan_cli.completions import add_dynamic_completer, complete_machines +from clan_cli.completions import ( + add_dynamic_completer, + complete_machines, + complete_vars_for_machine, +) from clan_cli.vars.get import get_machine_var from clan_cli.vars.prompt import PromptType from clan_lib.flake import Flake @@ -59,9 +63,10 @@ def register_set_parser(parser: argparse.ArgumentParser) -> None: ) add_dynamic_completer(machines_arg, complete_machines) - parser.add_argument( + var_id_arg = parser.add_argument( "var_id", help="The var id for which to set the value. Example: ssh-keys/pubkey", ) + add_dynamic_completer(var_id_arg, complete_vars_for_machine) parser.set_defaults(func=_set_command)