Merge pull request 'fast-vars-gen' (#3216) from fast-vars-gen into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3216
This commit is contained in:
@@ -518,6 +518,23 @@ class Flake:
|
|||||||
selectors: list[str],
|
selectors: list[str],
|
||||||
nix_options: list[str] | None = None,
|
nix_options: list[str] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""
|
||||||
|
Retrieves specific attributes from a Nix flake using the provided selectors.
|
||||||
|
|
||||||
|
This function interacts with the Nix build system to fetch and process
|
||||||
|
attributes from a flake. It uses the provided selectors to determine which
|
||||||
|
attributes to retrieve and optionally accepts additional Nix options for
|
||||||
|
customization. The results are cached for future use.
|
||||||
|
Used mostly as a lowlevel function for `precache` and `select` methods.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
selectors (list[str]): A list of attribute selectors to fetch from the flake.
|
||||||
|
nix_options (list[str] | None): Optional additional options to pass to the Nix build command.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ClanError: If the number of outputs does not match the number of selectors.
|
||||||
|
AssertionError: If the cache or flake cache path is not properly initialized.
|
||||||
|
"""
|
||||||
if self._cache is None:
|
if self._cache is None:
|
||||||
self.prefetch()
|
self.prefetch()
|
||||||
assert self._cache is not None
|
assert self._cache is not None
|
||||||
@@ -531,7 +548,7 @@ class Flake:
|
|||||||
flake = builtins.getFlake("path:{self.store_path}?narHash={self.hash}");
|
flake = builtins.getFlake("path:{self.store_path}?narHash={self.hash}");
|
||||||
in
|
in
|
||||||
flake.inputs.nixpkgs.legacyPackages.{config["system"]}.writeText "clan-flake-select" (
|
flake.inputs.nixpkgs.legacyPackages.{config["system"]}.writeText "clan-flake-select" (
|
||||||
builtins.toJSON [ ({" ".join([f"flake.clanInternals.clanLib.select ''{attr}'' flake" for attr in selectors])}) ]
|
builtins.toJSON [ {" ".join([f"(flake.clanInternals.clanLib.select ''{attr}'' flake)" for attr in selectors])} ]
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
if tmp_store := nix_test_store():
|
if tmp_store := nix_test_store():
|
||||||
@@ -556,11 +573,46 @@ 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(
|
||||||
|
self,
|
||||||
|
selectors: list[str],
|
||||||
|
nix_options: list[str] | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Ensures that the specified selectors are cached locally.
|
||||||
|
|
||||||
|
This function checks if the given selectors are already cached. If not, it
|
||||||
|
fetches them using the Nix build system and stores them in the local cache.
|
||||||
|
It ensures that the cache is initialized before performing these operations.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
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:
|
||||||
|
self.prefetch()
|
||||||
|
assert self._cache is not None
|
||||||
|
assert self.flake_cache_path is not None
|
||||||
|
not_fetched_selectors = []
|
||||||
|
for selector in selectors:
|
||||||
|
if not self._cache.is_cached(selector):
|
||||||
|
not_fetched_selectors.append(selector)
|
||||||
|
if not_fetched_selectors:
|
||||||
|
self.get_from_nix(not_fetched_selectors, nix_options)
|
||||||
|
|
||||||
def select(
|
def select(
|
||||||
self,
|
self,
|
||||||
selector: str,
|
selector: str,
|
||||||
nix_options: list[str] | None = None,
|
nix_options: list[str] | None = None,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
|
"""
|
||||||
|
Selects a value from the cache based on the provided selector string.
|
||||||
|
Fetches it via nix_build if it is not already cached.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
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.prefetch()
|
self.prefetch()
|
||||||
assert self._cache is not None
|
assert self._cache is not None
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from clan_cli.facts.upload import upload_secrets
|
|||||||
from clan_cli.flake import Flake
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.inventory import Machine as InventoryMachine
|
from clan_cli.inventory import Machine as InventoryMachine
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.nix import nix_command, nix_metadata
|
from clan_cli.nix import nix_command, nix_config, nix_metadata
|
||||||
from clan_cli.ssh.host import Host, HostKeyCheck
|
from clan_cli.ssh.host import Host, HostKeyCheck
|
||||||
from clan_cli.vars.generate import generate_vars
|
from clan_cli.vars.generate import generate_vars
|
||||||
from clan_cli.vars.upload import upload_secret_vars
|
from clan_cli.vars.upload import upload_secret_vars
|
||||||
@@ -265,6 +265,16 @@ def update_command(args: argparse.Namespace) -> None:
|
|||||||
machine.error("Updating macOS machines is not yet supported")
|
machine.error("Updating macOS machines is not yet supported")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
config = nix_config()
|
||||||
|
system = config["system"]
|
||||||
|
machine_names = [machine.name for machine in machines]
|
||||||
|
args.flake.precache(
|
||||||
|
[
|
||||||
|
f"clanInternals.machines.{system}.{{{','.join(machine_names)}}}.config.clan.core.vars.generators.*.validationHash",
|
||||||
|
f"clanInternals.machines.{system}.{{{','.join(machine_names)}}}.config.system.clan.deployment.file",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
deploy_machines(machines)
|
deploy_machines(machines)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
log.warning("Interrupted by user")
|
log.warning("Interrupted by user")
|
||||||
|
|||||||
@@ -691,9 +691,9 @@ def test_stdout_of_generate(
|
|||||||
flake_with_sops: ClanFlake,
|
flake_with_sops: ClanFlake,
|
||||||
caplog: pytest.LogCaptureFixture,
|
caplog: pytest.LogCaptureFixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
flake = flake_with_sops
|
flake_ = flake_with_sops
|
||||||
|
|
||||||
config = flake.machines["my_machine"]
|
config = flake_.machines["my_machine"]
|
||||||
config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
|
config["nixpkgs"]["hostPlatform"] = "x86_64-linux"
|
||||||
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
|
my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"]
|
||||||
my_generator["files"]["my_value"]["secret"] = False
|
my_generator["files"]["my_value"]["secret"] = False
|
||||||
@@ -703,14 +703,15 @@ def test_stdout_of_generate(
|
|||||||
]
|
]
|
||||||
my_secret_generator["files"]["my_secret"]["secret"] = True
|
my_secret_generator["files"]["my_secret"]["secret"] = True
|
||||||
my_secret_generator["script"] = 'echo -n hello > "$out"/my_secret'
|
my_secret_generator["script"] = 'echo -n hello > "$out"/my_secret'
|
||||||
flake.refresh()
|
flake_.refresh()
|
||||||
monkeypatch.chdir(flake.path)
|
monkeypatch.chdir(flake_.path)
|
||||||
|
flake = Flake(str(flake_.path))
|
||||||
from clan_cli.vars.generate import generate_vars_for_machine
|
from clan_cli.vars.generate import generate_vars_for_machine
|
||||||
|
|
||||||
# with capture_output as output:
|
# with capture_output as output:
|
||||||
with caplog.at_level(logging.INFO):
|
with caplog.at_level(logging.INFO):
|
||||||
generate_vars_for_machine(
|
generate_vars_for_machine(
|
||||||
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
Machine(name="my_machine", flake=flake),
|
||||||
"my_generator",
|
"my_generator",
|
||||||
regenerate=False,
|
regenerate=False,
|
||||||
)
|
)
|
||||||
@@ -720,10 +721,10 @@ def test_stdout_of_generate(
|
|||||||
assert "new: hello" in caplog.text
|
assert "new: hello" in caplog.text
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
|
|
||||||
set_var("my_machine", "my_generator/my_value", b"world", Flake(str(flake.path)))
|
set_var("my_machine", "my_generator/my_value", b"world", flake)
|
||||||
with caplog.at_level(logging.INFO):
|
with caplog.at_level(logging.INFO):
|
||||||
generate_vars_for_machine(
|
generate_vars_for_machine(
|
||||||
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
Machine(name="my_machine", flake=flake),
|
||||||
"my_generator",
|
"my_generator",
|
||||||
regenerate=True,
|
regenerate=True,
|
||||||
)
|
)
|
||||||
@@ -734,7 +735,7 @@ def test_stdout_of_generate(
|
|||||||
# check the output when nothing gets regenerated
|
# check the output when nothing gets regenerated
|
||||||
with caplog.at_level(logging.INFO):
|
with caplog.at_level(logging.INFO):
|
||||||
generate_vars_for_machine(
|
generate_vars_for_machine(
|
||||||
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
Machine(name="my_machine", flake=flake),
|
||||||
"my_generator",
|
"my_generator",
|
||||||
regenerate=True,
|
regenerate=True,
|
||||||
)
|
)
|
||||||
@@ -743,7 +744,7 @@ def test_stdout_of_generate(
|
|||||||
caplog.clear()
|
caplog.clear()
|
||||||
with caplog.at_level(logging.INFO):
|
with caplog.at_level(logging.INFO):
|
||||||
generate_vars_for_machine(
|
generate_vars_for_machine(
|
||||||
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
Machine(name="my_machine", flake=flake),
|
||||||
"my_secret_generator",
|
"my_secret_generator",
|
||||||
regenerate=False,
|
regenerate=False,
|
||||||
)
|
)
|
||||||
@@ -758,7 +759,7 @@ def test_stdout_of_generate(
|
|||||||
)
|
)
|
||||||
with caplog.at_level(logging.INFO):
|
with caplog.at_level(logging.INFO):
|
||||||
generate_vars_for_machine(
|
generate_vars_for_machine(
|
||||||
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
Machine(name="my_machine", flake=flake),
|
||||||
"my_secret_generator",
|
"my_secret_generator",
|
||||||
regenerate=True,
|
regenerate=True,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from clan_cli.completions import (
|
|||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
from clan_cli.git import commit_files
|
from clan_cli.git import commit_files
|
||||||
from clan_cli.machines.inventory import get_all_machines, get_selected_machines
|
from clan_cli.machines.inventory import get_all_machines, get_selected_machines
|
||||||
from clan_cli.nix import nix_shell, nix_test_store
|
from clan_cli.nix import nix_config, nix_shell, nix_test_store
|
||||||
from clan_cli.vars._types import StoreBase
|
from clan_cli.vars._types import StoreBase
|
||||||
|
|
||||||
from .check import check_vars
|
from .check import check_vars
|
||||||
@@ -489,7 +489,6 @@ def generate_vars(
|
|||||||
was_regenerated |= generate_vars_for_machine(
|
was_regenerated |= generate_vars_for_machine(
|
||||||
machine, generator_name, regenerate, no_sandbox=no_sandbox
|
machine, generator_name, regenerate, no_sandbox=no_sandbox
|
||||||
)
|
)
|
||||||
machine.flush_caches()
|
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
errors += [(machine, exc)]
|
errors += [(machine, exc)]
|
||||||
if len(errors) == 1:
|
if len(errors) == 1:
|
||||||
@@ -515,6 +514,18 @@ def generate_command(args: argparse.Namespace) -> None:
|
|||||||
machines = get_all_machines(args.flake, args.option)
|
machines = get_all_machines(args.flake, args.option)
|
||||||
else:
|
else:
|
||||||
machines = get_selected_machines(args.flake, args.option, args.machines)
|
machines = get_selected_machines(args.flake, args.option, args.machines)
|
||||||
|
|
||||||
|
# prefetch all vars
|
||||||
|
config = nix_config()
|
||||||
|
system = config["system"]
|
||||||
|
machine_names = [machine.name for machine in machines]
|
||||||
|
# test
|
||||||
|
args.flake.precache(
|
||||||
|
[
|
||||||
|
f"clanInternals.machines.{system}.{{{','.join(machine_names)}}}.config.clan.core.vars.generators.*.validationHash",
|
||||||
|
f"clanInternals.machines.{system}.{{{','.join(machine_names)}}}.config.system.clan.deployment.file",
|
||||||
|
]
|
||||||
|
)
|
||||||
generate_vars(machines, args.generator, args.regenerate, no_sandbox=args.no_sandbox)
|
generate_vars(machines, args.generator, args.regenerate, no_sandbox=args.no_sandbox)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user