Merge pull request 'clan-lib: Move nix_options from Machine class to Flake class' (#4048) from Qubasa/clan-core:move_nix_options into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4048 Reviewed-by: lassulus <clanlol@lassul.us>
This commit is contained in:
@@ -106,6 +106,13 @@
|
|||||||
extraPythonPackages = (self'.packages.clan-app.devshellPyDeps pkgs.python3Packages);
|
extraPythonPackages = (self'.packages.clan-app.devshellPyDeps pkgs.python3Packages);
|
||||||
extraPythonPaths = [ "../../clan-cli" ];
|
extraPythonPaths = [ "../../clan-cli" ];
|
||||||
};
|
};
|
||||||
|
"generate-test-vars" = {
|
||||||
|
directory = "pkgs/generate-test-vars";
|
||||||
|
extraPythonPackages = [
|
||||||
|
(pkgs.python3.withPackages (ps: self'.packages.clan-cli.devshellPyDeps ps))
|
||||||
|
];
|
||||||
|
extraPythonPaths = [ "../clan-cli" ];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// (
|
// (
|
||||||
if pkgs.stdenv.isLinux then
|
if pkgs.stdenv.isLinux then
|
||||||
|
|||||||
@@ -35,20 +35,27 @@ with contextlib.suppress(ImportError):
|
|||||||
import argcomplete # type: ignore[no-redef]
|
import argcomplete # type: ignore[no-redef]
|
||||||
|
|
||||||
|
|
||||||
def flake_path(arg: str) -> Flake:
|
def flake_path(arg: str) -> str:
|
||||||
flake_dir = Path(arg).resolve()
|
flake_dir = Path(arg).resolve()
|
||||||
if flake_dir.exists() and flake_dir.is_dir():
|
if flake_dir.exists() and flake_dir.is_dir():
|
||||||
return Flake(str(flake_dir))
|
return str(flake_dir)
|
||||||
return Flake(arg)
|
return arg
|
||||||
|
|
||||||
|
|
||||||
def default_flake() -> Flake | None:
|
def default_flake() -> str | None:
|
||||||
val = get_clan_flake_toplevel_or_env()
|
val = get_clan_flake_toplevel_or_env()
|
||||||
if val:
|
if val:
|
||||||
return Flake(str(val))
|
return str(val)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def create_flake_from_args(args: argparse.Namespace) -> Flake:
|
||||||
|
"""Create a Flake object from parsed arguments, including nix_options."""
|
||||||
|
flake_path_str = args.flake
|
||||||
|
nix_options = getattr(args, "option", [])
|
||||||
|
return Flake(flake_path_str, nix_options=nix_options)
|
||||||
|
|
||||||
|
|
||||||
def add_common_flags(parser: argparse.ArgumentParser) -> None:
|
def add_common_flags(parser: argparse.ArgumentParser) -> None:
|
||||||
def argument_exists(parser: argparse.ArgumentParser, arg: str) -> bool:
|
def argument_exists(parser: argparse.ArgumentParser, arg: str) -> bool:
|
||||||
"""
|
"""
|
||||||
@@ -450,6 +457,10 @@ def main() -> None:
|
|||||||
if not hasattr(args, "func"):
|
if not hasattr(args, "func"):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Convert flake path to Flake object with nix_options if flake argument exists
|
||||||
|
if hasattr(args, "flake") and args.flake is not None:
|
||||||
|
args.flake = create_flake_from_args(args)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
args.func(args)
|
args.func(args)
|
||||||
except ClanError as e:
|
except ClanError as e:
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ class FlashOptions:
|
|||||||
debug: bool
|
debug: bool
|
||||||
mode: str
|
mode: str
|
||||||
write_efi_boot_entries: bool
|
write_efi_boot_entries: bool
|
||||||
nix_options: list[str]
|
|
||||||
system_config: SystemConfig
|
system_config: SystemConfig
|
||||||
|
|
||||||
|
|
||||||
@@ -72,7 +71,6 @@ def flash_command(args: argparse.Namespace) -> None:
|
|||||||
ssh_keys_path=args.ssh_pubkey,
|
ssh_keys_path=args.ssh_pubkey,
|
||||||
),
|
),
|
||||||
write_efi_boot_entries=args.write_efi_boot_entries,
|
write_efi_boot_entries=args.write_efi_boot_entries,
|
||||||
nix_options=args.option,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
machine = Machine(opts.machine, flake=opts.flake)
|
machine = Machine(opts.machine, flake=opts.flake)
|
||||||
@@ -94,7 +92,6 @@ def flash_command(args: argparse.Namespace) -> None:
|
|||||||
dry_run=opts.dry_run,
|
dry_run=opts.dry_run,
|
||||||
debug=opts.debug,
|
debug=opts.debug,
|
||||||
write_efi_boot_entries=opts.write_efi_boot_entries,
|
write_efi_boot_entries=opts.write_efi_boot_entries,
|
||||||
extra_args=opts.nix_options,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ def install_command(args: argparse.Namespace) -> None:
|
|||||||
else:
|
else:
|
||||||
password = None
|
password = None
|
||||||
|
|
||||||
machine = Machine(name=args.machine, flake=args.flake, nix_options=args.option)
|
machine = Machine(name=args.machine, flake=args.flake)
|
||||||
host_key_check = args.host_key_check
|
host_key_check = args.host_key_check
|
||||||
|
|
||||||
if target_host_str is not None:
|
if target_host_str is not None:
|
||||||
@@ -72,7 +72,6 @@ def install_command(args: argparse.Namespace) -> None:
|
|||||||
phases=args.phases,
|
phases=args.phases,
|
||||||
debug=args.debug,
|
debug=args.debug,
|
||||||
no_reboot=args.no_reboot,
|
no_reboot=args.no_reboot,
|
||||||
nix_options=args.option,
|
|
||||||
build_on=BuildOn(args.build_on) if args.build_on is not None else None,
|
build_on=BuildOn(args.build_on) if args.build_on is not None else None,
|
||||||
update_hardware_config=HardwareConfig(args.update_hardware_config),
|
update_hardware_config=HardwareConfig(args.update_hardware_config),
|
||||||
password=password,
|
password=password,
|
||||||
|
|||||||
@@ -46,9 +46,7 @@ def update_command(args: argparse.Namespace) -> None:
|
|||||||
raise ClanError(msg)
|
raise ClanError(msg)
|
||||||
|
|
||||||
for machine_name in selected_machines:
|
for machine_name in selected_machines:
|
||||||
machine = Machine(
|
machine = Machine(name=machine_name, flake=args.flake)
|
||||||
name=machine_name, flake=args.flake, nix_options=args.option
|
|
||||||
)
|
|
||||||
machines.append(machine)
|
machines.append(machine)
|
||||||
|
|
||||||
if args.target_host is not None and len(machines) > 1:
|
if args.target_host is not None and len(machines) > 1:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import argparse
|
|||||||
import logging
|
import logging
|
||||||
import shlex
|
import shlex
|
||||||
|
|
||||||
from clan_cli import create_parser
|
from clan_cli import create_flake_from_args, create_parser
|
||||||
from clan_lib.custom_logger import print_trace
|
from clan_lib.custom_logger import print_trace
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@@ -13,6 +13,10 @@ def run(args: list[str]) -> argparse.Namespace:
|
|||||||
parsed = parser.parse_args(args)
|
parsed = parser.parse_args(args)
|
||||||
cmd = shlex.join(["clan", *args])
|
cmd = shlex.join(["clan", *args])
|
||||||
|
|
||||||
|
# Convert flake path to Flake object with nix_options if flake argument exists
|
||||||
|
if hasattr(parsed, "flake") and parsed.flake is not None:
|
||||||
|
parsed.flake = create_flake_from_args(parsed)
|
||||||
|
|
||||||
print_trace(f"$ {cmd}", log, "localhost")
|
print_trace(f"$ {cmd}", log, "localhost")
|
||||||
if hasattr(parsed, "func"):
|
if hasattr(parsed, "func"):
|
||||||
parsed.func(parsed)
|
parsed.func(parsed)
|
||||||
|
|||||||
@@ -511,7 +511,7 @@ def generate_command(args: argparse.Namespace) -> None:
|
|||||||
msg = "Could not find clan flake toplevel directory"
|
msg = "Could not find clan flake toplevel directory"
|
||||||
raise ClanError(msg)
|
raise ClanError(msg)
|
||||||
|
|
||||||
machines: list[Machine] = list(list_full_machines(args.flake, args.option).values())
|
machines: list[Machine] = list(list_full_machines(args.flake).values())
|
||||||
|
|
||||||
if len(args.machines) > 0:
|
if len(args.machines) > 0:
|
||||||
machines = list(
|
machines = list(
|
||||||
|
|||||||
@@ -49,20 +49,15 @@ def facts_to_nixos_config(facts: dict[str, dict[str, bytes]]) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
# TODO move this to the Machines class
|
# TODO move this to the Machines class
|
||||||
def build_vm(
|
def build_vm(machine: Machine, tmpdir: Path) -> dict[str, str]:
|
||||||
machine: Machine, tmpdir: Path, nix_options: list[str] | None = None
|
|
||||||
) -> dict[str, str]:
|
|
||||||
# TODO pass prompt here for the GTK gui
|
# TODO pass prompt here for the GTK gui
|
||||||
if nix_options is None:
|
|
||||||
nix_options = []
|
|
||||||
secrets_dir = get_secrets(machine, tmpdir)
|
secrets_dir = get_secrets(machine, tmpdir)
|
||||||
|
|
||||||
public_facts = machine.public_facts_store.get_all()
|
public_facts = machine.public_facts_store.get_all()
|
||||||
|
|
||||||
nixos_config_file = machine.build_nix(
|
nixos_config_file = machine.build_nix(
|
||||||
"config.system.clan.vm.create",
|
"config.system.clan.vm.create", extra_config=facts_to_nixos_config(public_facts)
|
||||||
extra_config=facts_to_nixos_config(public_facts),
|
|
||||||
nix_options=nix_options,
|
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
vm_data = json.loads(Path(nixos_config_file).read_text())
|
vm_data = json.loads(Path(nixos_config_file).read_text())
|
||||||
@@ -204,7 +199,6 @@ def spawn_vm(
|
|||||||
*,
|
*,
|
||||||
cachedir: Path | None = None,
|
cachedir: Path | None = None,
|
||||||
socketdir: Path | None = None,
|
socketdir: Path | None = None,
|
||||||
nix_options: list[str] | None = None,
|
|
||||||
portmap: dict[int, int] | None = None,
|
portmap: dict[int, int] | None = None,
|
||||||
stdout: int | None = None,
|
stdout: int | None = None,
|
||||||
stderr: int | None = None,
|
stderr: int | None = None,
|
||||||
@@ -212,8 +206,7 @@ def spawn_vm(
|
|||||||
) -> Iterator[QemuVm]:
|
) -> Iterator[QemuVm]:
|
||||||
if portmap is None:
|
if portmap is None:
|
||||||
portmap = {}
|
portmap = {}
|
||||||
if nix_options is None:
|
|
||||||
nix_options = []
|
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
machine = Machine(name=vm.machine_name, flake=vm.flake_url)
|
machine = Machine(name=vm.machine_name, flake=vm.flake_url)
|
||||||
machine.debug(f"Creating VM for {machine}")
|
machine.debug(f"Creating VM for {machine}")
|
||||||
@@ -234,7 +227,7 @@ def spawn_vm(
|
|||||||
socketdir = Path(socket_tmp)
|
socketdir = Path(socket_tmp)
|
||||||
|
|
||||||
# TODO: We should get this from the vm argument
|
# TODO: We should get this from the vm argument
|
||||||
nixos_config = build_vm(machine, cachedir, nix_options)
|
nixos_config = build_vm(machine, cachedir)
|
||||||
|
|
||||||
state_dir = vm_state_dir(vm.flake_url.identifier, machine.name)
|
state_dir = vm_state_dir(vm.flake_url.identifier, machine.name)
|
||||||
state_dir.mkdir(parents=True, exist_ok=True)
|
state_dir.mkdir(parents=True, exist_ok=True)
|
||||||
@@ -321,7 +314,6 @@ def spawn_vm(
|
|||||||
class RuntimeConfig:
|
class RuntimeConfig:
|
||||||
cachedir: Path | None = None
|
cachedir: Path | None = None
|
||||||
socketdir: Path | None = None
|
socketdir: Path | None = None
|
||||||
nix_options: list[str] | None = None
|
|
||||||
portmap: dict[int, int] | None = None
|
portmap: dict[int, int] | None = None
|
||||||
command: list[str] | None = None
|
command: list[str] | None = None
|
||||||
no_block: bool = False
|
no_block: bool = False
|
||||||
@@ -339,7 +331,6 @@ def run_vm(
|
|||||||
vm_config,
|
vm_config,
|
||||||
cachedir=runtime_config.cachedir,
|
cachedir=runtime_config.cachedir,
|
||||||
socketdir=runtime_config.socketdir,
|
socketdir=runtime_config.socketdir,
|
||||||
nix_options=runtime_config.nix_options,
|
|
||||||
portmap=runtime_config.portmap,
|
portmap=runtime_config.portmap,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
@@ -395,7 +386,6 @@ def run_command(
|
|||||||
portmap = dict(p.split(":") for p in args.publish)
|
portmap = dict(p.split(":") for p in args.publish)
|
||||||
|
|
||||||
runtime_config = RuntimeConfig(
|
runtime_config = RuntimeConfig(
|
||||||
nix_options=args.option,
|
|
||||||
portmap=portmap,
|
portmap=portmap,
|
||||||
command=args.command,
|
command=args.command,
|
||||||
no_block=args.no_block,
|
no_block=args.no_block,
|
||||||
|
|||||||
@@ -576,6 +576,7 @@ class Flake:
|
|||||||
identifier: str
|
identifier: str
|
||||||
hash: str | None = None
|
hash: str | None = None
|
||||||
store_path: str | None = None
|
store_path: str | None = None
|
||||||
|
nix_options: list[str] | None = None
|
||||||
|
|
||||||
_flake_cache_path: Path | None = field(init=False, default=None)
|
_flake_cache_path: Path | None = field(init=False, default=None)
|
||||||
_cache: FlakeCache | None = field(init=False, default=None)
|
_cache: FlakeCache | None = field(init=False, default=None)
|
||||||
@@ -583,8 +584,13 @@ class Flake:
|
|||||||
_is_local: bool | None = field(init=False, default=None)
|
_is_local: bool | None = field(init=False, default=None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_json(cls: type["Flake"], data: dict[str, Any]) -> "Flake":
|
def from_json(
|
||||||
return cls(data["identifier"])
|
cls: type["Flake"],
|
||||||
|
data: dict[str, Any],
|
||||||
|
*,
|
||||||
|
nix_options: list[str] | None = None,
|
||||||
|
) -> "Flake":
|
||||||
|
return cls(data["identifier"], nix_options=nix_options)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.identifier
|
return self.identifier
|
||||||
@@ -632,10 +638,14 @@ class Flake:
|
|||||||
nix_command,
|
nix_command,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.nix_options is None:
|
||||||
|
self.nix_options = []
|
||||||
|
|
||||||
cmd = [
|
cmd = [
|
||||||
"flake",
|
"flake",
|
||||||
"prefetch",
|
"prefetch",
|
||||||
"--json",
|
"--json",
|
||||||
|
*self.nix_options,
|
||||||
"--option",
|
"--option",
|
||||||
"flake-registry",
|
"flake-registry",
|
||||||
"",
|
"",
|
||||||
@@ -690,7 +700,6 @@ class Flake:
|
|||||||
def get_from_nix(
|
def get_from_nix(
|
||||||
self,
|
self,
|
||||||
selectors: list[str],
|
selectors: list[str],
|
||||||
nix_options: list[str] | None = None,
|
|
||||||
apply: str = "v: v",
|
apply: str = "v: v",
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -722,8 +731,7 @@ class Flake:
|
|||||||
self.invalidate_cache()
|
self.invalidate_cache()
|
||||||
assert self._cache is not None
|
assert self._cache is not None
|
||||||
|
|
||||||
if nix_options is None:
|
nix_options = self.nix_options if self.nix_options is not None else []
|
||||||
nix_options = []
|
|
||||||
|
|
||||||
str_selectors: list[str] = []
|
str_selectors: list[str] = []
|
||||||
for selector in selectors:
|
for selector in selectors:
|
||||||
@@ -736,7 +744,9 @@ class Flake:
|
|||||||
# method to getting the NAR hash
|
# method to getting the NAR hash
|
||||||
fallback_nixpkgs_hash = "@fallback_nixpkgs_hash@"
|
fallback_nixpkgs_hash = "@fallback_nixpkgs_hash@"
|
||||||
if not fallback_nixpkgs_hash.startswith("sha256-"):
|
if not fallback_nixpkgs_hash.startswith("sha256-"):
|
||||||
fallback_nixpkgs = Flake(str(nixpkgs_source()))
|
fallback_nixpkgs = Flake(
|
||||||
|
str(nixpkgs_source()), nix_options=self.nix_options
|
||||||
|
)
|
||||||
fallback_nixpkgs.invalidate_cache()
|
fallback_nixpkgs.invalidate_cache()
|
||||||
assert fallback_nixpkgs.hash is not None, (
|
assert fallback_nixpkgs.hash is not None, (
|
||||||
"this should be impossible as invalidate_cache() should always set `hash`"
|
"this should be impossible as invalidate_cache() should always set `hash`"
|
||||||
@@ -745,7 +755,7 @@ class Flake:
|
|||||||
|
|
||||||
select_hash = "@select_hash@"
|
select_hash = "@select_hash@"
|
||||||
if not select_hash.startswith("sha256-"):
|
if not select_hash.startswith("sha256-"):
|
||||||
select_flake = Flake(str(select_source()))
|
select_flake = Flake(str(select_source()), nix_options=self.nix_options)
|
||||||
select_flake.invalidate_cache()
|
select_flake.invalidate_cache()
|
||||||
assert select_flake.hash is not None, (
|
assert select_flake.hash is not None, (
|
||||||
"this should be impossible as invalidate_cache() should always set `hash`"
|
"this should be impossible as invalidate_cache() should always set `hash`"
|
||||||
@@ -808,11 +818,7 @@ class Flake:
|
|||||||
if self.flake_cache_path:
|
if self.flake_cache_path:
|
||||||
self._cache.save_to_file(self.flake_cache_path)
|
self._cache.save_to_file(self.flake_cache_path)
|
||||||
|
|
||||||
def precache(
|
def precache(self, selectors: list[str]) -> None:
|
||||||
self,
|
|
||||||
selectors: list[str],
|
|
||||||
nix_options: list[str] | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""
|
"""
|
||||||
Ensures that the specified selectors are cached locally.
|
Ensures that the specified selectors are cached locally.
|
||||||
|
|
||||||
@@ -822,7 +828,6 @@ class Flake:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
selectors (list[str]): A list of attribute selectors to check and cache.
|
selectors (list[str]): A list of attribute selectors to check and cache.
|
||||||
nix_options (list[str] | None): Optional additional options to pass to the Nix build command.
|
|
||||||
"""
|
"""
|
||||||
if self._cache is None:
|
if self._cache is None:
|
||||||
self.invalidate_cache()
|
self.invalidate_cache()
|
||||||
@@ -833,12 +838,11 @@ class Flake:
|
|||||||
if not self._cache.is_cached(selector):
|
if not self._cache.is_cached(selector):
|
||||||
not_fetched_selectors.append(selector)
|
not_fetched_selectors.append(selector)
|
||||||
if not_fetched_selectors:
|
if not_fetched_selectors:
|
||||||
self.get_from_nix(not_fetched_selectors, nix_options)
|
self.get_from_nix(not_fetched_selectors)
|
||||||
|
|
||||||
def select(
|
def select(
|
||||||
self,
|
self,
|
||||||
selector: str,
|
selector: str,
|
||||||
nix_options: list[str] | None = None,
|
|
||||||
apply: str = "v: v",
|
apply: str = "v: v",
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""
|
"""
|
||||||
@@ -847,7 +851,6 @@ class Flake:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
selector (str): The attribute selector string to fetch the value for.
|
selector (str): The attribute selector string to fetch the value for.
|
||||||
nix_options (list[str] | None): Optional additional options to pass to the Nix build command.
|
|
||||||
"""
|
"""
|
||||||
if self._cache is None:
|
if self._cache is None:
|
||||||
self.invalidate_cache()
|
self.invalidate_cache()
|
||||||
@@ -856,6 +859,6 @@ class Flake:
|
|||||||
|
|
||||||
if not self._cache.is_cached(selector):
|
if not self._cache.is_cached(selector):
|
||||||
log.debug(f"Cache miss for {selector}")
|
log.debug(f"Cache miss for {selector}")
|
||||||
self.get_from_nix([selector], nix_options, apply=apply)
|
self.get_from_nix([selector], apply=apply)
|
||||||
value = self._cache.select(selector)
|
value = self._cache.select(selector)
|
||||||
return value
|
return value
|
||||||
|
|||||||
@@ -284,13 +284,14 @@ def test_cache_gc(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
my_flake = Flake(str(tmp_path / "flake"))
|
my_flake = Flake(
|
||||||
|
str(tmp_path / "flake"),
|
||||||
|
nix_options=["--sandbox-build-dir", str(tmp_path / "build")],
|
||||||
|
)
|
||||||
if platform == "darwin":
|
if platform == "darwin":
|
||||||
my_flake.select("testfile")
|
my_flake.select("testfile")
|
||||||
else:
|
else:
|
||||||
my_flake.select(
|
my_flake.select("testfile")
|
||||||
"testfile", nix_options=["--sandbox-build-dir", str(tmp_path / "build")]
|
|
||||||
)
|
|
||||||
assert my_flake._cache is not None # noqa: SLF001
|
assert my_flake._cache is not None # noqa: SLF001
|
||||||
assert my_flake._cache.is_cached("testfile") # noqa: SLF001
|
assert my_flake._cache.is_cached("testfile") # noqa: SLF001
|
||||||
subprocess.run(["nix-collect-garbage"], check=True)
|
subprocess.run(["nix-collect-garbage"], check=True)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
@@ -32,7 +32,6 @@ class InstallOptions:
|
|||||||
no_reboot: bool = False
|
no_reboot: bool = False
|
||||||
phases: str | None = None
|
phases: str | None = None
|
||||||
build_on: BuildOn | None = None
|
build_on: BuildOn | None = None
|
||||||
nix_options: list[str] = field(default_factory=list)
|
|
||||||
update_hardware_config: HardwareConfig = HardwareConfig.NONE
|
update_hardware_config: HardwareConfig = HardwareConfig.NONE
|
||||||
password: str | None = None
|
password: str | None = None
|
||||||
identity_file: Path | None = None
|
identity_file: Path | None = None
|
||||||
@@ -127,7 +126,7 @@ def install_machine(opts: InstallOptions, target_host: Remote) -> None:
|
|||||||
cmd.append("--debug")
|
cmd.append("--debug")
|
||||||
|
|
||||||
# Add nix options to nixos-anywhere
|
# Add nix options to nixos-anywhere
|
||||||
cmd.extend(opts.nix_options)
|
cmd.extend(opts.machine.flake.nix_options or [])
|
||||||
|
|
||||||
cmd.append(target_host.target)
|
cmd.append(target_host.target)
|
||||||
if opts.use_tor:
|
if opts.use_tor:
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ from clan_lib.nix_models.clan import InventoryMachine
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def list_full_machines(
|
def list_full_machines(flake: Flake) -> dict[str, Machine]:
|
||||||
flake: Flake, nix_options: list[str] | None = None
|
|
||||||
) -> dict[str, Machine]:
|
|
||||||
"""
|
"""
|
||||||
Like `list_machines`, but returns a full 'machine' instance for each machine.
|
Like `list_machines`, but returns a full 'machine' instance for each machine.
|
||||||
"""
|
"""
|
||||||
@@ -27,9 +25,6 @@ def list_full_machines(
|
|||||||
|
|
||||||
res: dict[str, Machine] = {}
|
res: dict[str, Machine] = {}
|
||||||
|
|
||||||
if nix_options is None:
|
|
||||||
nix_options = []
|
|
||||||
|
|
||||||
for inv_machine in machines.values():
|
for inv_machine in machines.values():
|
||||||
name = inv_machine.get("name")
|
name = inv_machine.get("name")
|
||||||
# Technically, this should not happen, but we are defensive here.
|
# Technically, this should not happen, but we are defensive here.
|
||||||
@@ -37,11 +32,7 @@ def list_full_machines(
|
|||||||
msg = "InternalError: Machine name is required. But got a machine without a name."
|
msg = "InternalError: Machine name is required. But got a machine without a name."
|
||||||
raise ClanError(msg)
|
raise ClanError(msg)
|
||||||
|
|
||||||
machine = Machine(
|
machine = Machine(name=name, flake=flake)
|
||||||
name=name,
|
|
||||||
flake=flake,
|
|
||||||
nix_options=nix_options,
|
|
||||||
)
|
|
||||||
res[machine.name] = machine
|
res[machine.name] = machine
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import importlib
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Any, Literal
|
from typing import TYPE_CHECKING, Any, Literal
|
||||||
@@ -30,8 +30,6 @@ class Machine:
|
|||||||
name: str
|
name: str
|
||||||
flake: Flake
|
flake: Flake
|
||||||
|
|
||||||
nix_options: list[str] = field(default_factory=list)
|
|
||||||
|
|
||||||
def get_inv_machine(self) -> "InventoryMachine":
|
def get_inv_machine(self) -> "InventoryMachine":
|
||||||
return get_machine(self.flake, self.name)
|
return get_machine(self.flake, self.name)
|
||||||
|
|
||||||
@@ -164,29 +162,20 @@ class Machine:
|
|||||||
def nix(
|
def nix(
|
||||||
self,
|
self,
|
||||||
attr: str,
|
attr: str,
|
||||||
nix_options: list[str] | None = None,
|
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""
|
"""
|
||||||
Build the machine and return the path to the result
|
Build the machine and return the path to the result
|
||||||
accepts a secret store and a facts store # TODO
|
accepts a secret store and a facts store # TODO
|
||||||
"""
|
"""
|
||||||
if nix_options is None:
|
|
||||||
nix_options = []
|
|
||||||
|
|
||||||
config = nix_config()
|
config = nix_config()
|
||||||
system = config["system"]
|
system = config["system"]
|
||||||
|
|
||||||
return self.flake.select(
|
return self.flake.select(
|
||||||
f'clanInternals.machines."{system}"."{self.name}".{attr}',
|
f'clanInternals.machines."{system}"."{self.name}".{attr}'
|
||||||
nix_options=nix_options,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def eval_nix(
|
def eval_nix(self, attr: str, extra_config: None | dict = None) -> Any:
|
||||||
self,
|
|
||||||
attr: str,
|
|
||||||
extra_config: None | dict = None,
|
|
||||||
nix_options: list[str] | None = None,
|
|
||||||
) -> Any:
|
|
||||||
"""
|
"""
|
||||||
eval a nix attribute of the machine
|
eval a nix attribute of the machine
|
||||||
@attr: the attribute to get
|
@attr: the attribute to get
|
||||||
@@ -195,17 +184,9 @@ class Machine:
|
|||||||
if extra_config:
|
if extra_config:
|
||||||
log.warning("extra_config in eval_nix is no longer supported")
|
log.warning("extra_config in eval_nix is no longer supported")
|
||||||
|
|
||||||
if nix_options is None:
|
return self.nix(attr)
|
||||||
nix_options = []
|
|
||||||
|
|
||||||
return self.nix(attr, nix_options)
|
def build_nix(self, attr: str, extra_config: None | dict = None) -> Path:
|
||||||
|
|
||||||
def build_nix(
|
|
||||||
self,
|
|
||||||
attr: str,
|
|
||||||
extra_config: None | dict = None,
|
|
||||||
nix_options: list[str] | None = None,
|
|
||||||
) -> Path:
|
|
||||||
"""
|
"""
|
||||||
build a nix attribute of the machine
|
build a nix attribute of the machine
|
||||||
@attr: the attribute to get
|
@attr: the attribute to get
|
||||||
@@ -214,10 +195,7 @@ class Machine:
|
|||||||
if extra_config:
|
if extra_config:
|
||||||
log.warning("extra_config in build_nix is no longer supported")
|
log.warning("extra_config in build_nix is no longer supported")
|
||||||
|
|
||||||
if nix_options is None:
|
output = self.nix(attr)
|
||||||
nix_options = []
|
|
||||||
|
|
||||||
output = self.nix(attr, nix_options)
|
|
||||||
output = Path(output)
|
output = Path(output)
|
||||||
if tmp_store := nix_test_store():
|
if tmp_store := nix_test_store():
|
||||||
output = tmp_store.joinpath(*output.parts[1:])
|
output = tmp_store.joinpath(*output.parts[1:])
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ def deploy_machine(
|
|||||||
|
|
||||||
path = upload_sources(machine, sudo_host)
|
path = upload_sources(machine, sudo_host)
|
||||||
|
|
||||||
|
nix_options = machine.flake.nix_options if machine.flake.nix_options else []
|
||||||
|
|
||||||
nix_options = [
|
nix_options = [
|
||||||
"--show-trace",
|
"--show-trace",
|
||||||
"--option",
|
"--option",
|
||||||
@@ -133,7 +135,7 @@ def deploy_machine(
|
|||||||
"accept-flake-config",
|
"accept-flake-config",
|
||||||
"true",
|
"true",
|
||||||
"-L",
|
"-L",
|
||||||
*machine.nix_options,
|
*nix_options,
|
||||||
"--flake",
|
"--flake",
|
||||||
f"{path}#{machine.name}",
|
f"{path}#{machine.name}",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -86,11 +86,7 @@ class WriteInfo:
|
|||||||
|
|
||||||
|
|
||||||
class FlakeInterface(Protocol):
|
class FlakeInterface(Protocol):
|
||||||
def select(
|
def select(self, selector: str) -> Any: ...
|
||||||
self,
|
|
||||||
selector: str,
|
|
||||||
nix_options: list[str] | None = None,
|
|
||||||
) -> Any: ...
|
|
||||||
|
|
||||||
def invalidate_cache(self) -> None: ...
|
def invalidate_cache(self) -> None: ...
|
||||||
|
|
||||||
|
|||||||
@@ -64,17 +64,11 @@ class TestMachine(Machine):
|
|||||||
return self.test_dir
|
return self.test_dir
|
||||||
|
|
||||||
@override
|
@override
|
||||||
def nix(
|
def nix(self, attr: str) -> Any:
|
||||||
self,
|
|
||||||
attr: str,
|
|
||||||
nix_options: list[str] | None = None,
|
|
||||||
) -> Any:
|
|
||||||
"""
|
"""
|
||||||
Build the machine and return the path to the result
|
Build the machine and return the path to the result
|
||||||
accepts a secret store and a facts store # TODO
|
accepts a secret store and a facts store # TODO
|
||||||
"""
|
"""
|
||||||
if nix_options is None:
|
|
||||||
nix_options = []
|
|
||||||
|
|
||||||
config = nix_config()
|
config = nix_config()
|
||||||
system = config["system"]
|
system = config["system"]
|
||||||
@@ -83,8 +77,7 @@ class TestMachine(Machine):
|
|||||||
test_system = system.rstrip("darwin") + "linux"
|
test_system = system.rstrip("darwin") + "linux"
|
||||||
|
|
||||||
return self.flake.select(
|
return self.flake.select(
|
||||||
f'checks."{test_system}".{self.check_attr}.machinesCross.{system}.{self.name}.{attr}',
|
f'checks."{test_system}".{self.check_attr}.machinesCross.{system}.{self.name}.{attr}'
|
||||||
nix_options=nix_options,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user