clan_cli machines: use Flake instead of FlakeId

This commit is contained in:
lassulus
2025-02-06 04:51:28 +01:00
parent cf1a4f805c
commit 2a8f40e91a
47 changed files with 242 additions and 251 deletions

View File

@@ -22,11 +22,11 @@ from . import (
state,
vms,
)
from .clan_uri import FlakeId
from .custom_logger import setup_logging
from .dirs import get_clan_flake_toplevel_or_env
from .errors import ClanError
from .facts import cli as facts
from .flake import Flake
from .flash import cli as flash_cli
from .hyperlink import help_hyperlink
from .machines import cli as machines
@@ -41,17 +41,17 @@ with contextlib.suppress(ImportError):
import argcomplete # type: ignore[no-redef]
def flake_path(arg: str) -> FlakeId:
def flake_path(arg: str) -> Flake:
flake_dir = Path(arg).resolve()
if flake_dir.exists() and flake_dir.is_dir():
return FlakeId(str(flake_dir))
return FlakeId(arg)
return Flake(str(flake_dir))
return Flake(arg)
def default_flake() -> FlakeId | None:
def default_flake() -> Flake | None:
val = get_clan_flake_toplevel_or_env()
if val:
return FlakeId(str(val))
return Flake(str(val))
return None

View File

@@ -5,9 +5,9 @@ from dataclasses import dataclass
from pathlib import Path
from clan_cli.api import API
from clan_cli.clan_uri import FlakeId
from clan_cli.cmd import CmdOut, RunOpts, run
from clan_cli.errors import ClanError
from clan_cli.flake import Flake
from clan_cli.inventory import Inventory, init_inventory
from clan_cli.nix import nix_shell
from clan_cli.templates import (
@@ -33,7 +33,7 @@ class CreateClanResponse:
class CreateOptions:
dest: Path
template_name: str
src_flake: FlakeId | None = None
src_flake: Flake | None = None
input_prio: InputPrio | None = None
setup_git: bool = True
initial: Inventory | None = None

View File

@@ -3,10 +3,10 @@ from dataclasses import dataclass
from pathlib import Path
from typing import Any
from clan_cli.clan_uri import FlakeId
from clan_cli.cmd import run
from clan_cli.dirs import machine_gcroot
from clan_cli.errors import ClanError
from clan_cli.flake import Flake
from clan_cli.machines.list import list_nixos_machines
from clan_cli.machines.machines import Machine
from clan_cli.nix import (
@@ -21,7 +21,7 @@ from clan_cli.vms.inspect import VmConfig, inspect_vm
@dataclass
class FlakeConfig:
flake_url: FlakeId
flake_url: Flake
flake_attr: str
clan_name: str
@@ -35,7 +35,7 @@ class FlakeConfig:
@classmethod
def from_json(cls: type["FlakeConfig"], data: dict[str, Any]) -> "FlakeConfig":
return cls(
flake_url=FlakeId.from_json(data["flake_url"]),
flake_url=Flake.from_json(data["flake_url"]),
flake_attr=data["flake_attr"],
clan_name=data["clan_name"],
nar_hash=data["nar_hash"],
@@ -62,7 +62,7 @@ def inspect_flake(flake_url: str | Path, machine_name: str) -> FlakeConfig:
msg = f"Machine {machine_name} not found in {flake_url}. Available machines: {', '.join(machines)}"
raise ClanError(msg)
machine = Machine(machine_name, FlakeId(str(flake_url)))
machine = Machine(machine_name, Flake(str(flake_url)))
vm = inspect_vm(machine)
# Make symlink to gcroots from vm.machine_icon
@@ -105,7 +105,7 @@ def inspect_flake(flake_url: str | Path, machine_name: str) -> FlakeConfig:
meta = nix_metadata(flake_url)
return FlakeConfig(
vm=vm,
flake_url=FlakeId(str(flake_url)),
flake_url=Flake(str(flake_url)),
clan_name=clan_name,
flake_attr=machine_name,
nar_hash=meta["locked"]["narHash"],
@@ -119,13 +119,13 @@ def inspect_flake(flake_url: str | Path, machine_name: str) -> FlakeConfig:
@dataclass
class InspectOptions:
machine: str
flake: FlakeId
flake: Flake
def inspect_command(args: argparse.Namespace) -> None:
inspect_options = InspectOptions(
machine=args.machine,
flake=args.flake or FlakeId(str(Path.cwd())),
flake=args.flake or Flake(str(Path.cwd())),
)
res = inspect_flake(
flake_url=str(inspect_options.flake), machine_name=inspect_options.machine

View File

@@ -3,68 +3,14 @@ import urllib.parse
import urllib.request
from dataclasses import dataclass
from pathlib import Path
from typing import Any
@dataclass
class FlakeId:
loc: str
@classmethod
def from_json(cls: type["FlakeId"], data: dict[str, Any]) -> "FlakeId":
return cls(loc=data["loc"])
def __str__(self) -> str:
return str(self.loc)
def __hash__(self) -> int:
return hash(str(self.loc))
@property
def path(self) -> Path:
assert self.is_local(), f"Flake {self.loc} is not a local path"
return Path(self.loc)
@property
def url(self) -> str:
assert self.is_remote(), f"Flake {self.loc} is not a remote url"
return str(self.loc)
def is_local(self) -> bool:
"""
https://nix.dev/manual/nix/2.22/language/builtins.html?highlight=urlS#source-types
Examples:
- file:///home/eelco/nix/README.md file LOCAL
- git+file://git:github.com:NixOS/nixpkgs git+file LOCAL
- https://example.com/index.html https REMOTE
- github:nixos/nixpkgs github REMOTE
- ftp://serv.file ftp REMOTE
- ./. '' LOCAL
"""
x = urllib.parse.urlparse(str(self.loc))
# See above *file* or empty are the only local schemas
return x.scheme == "" or "file" in x.scheme
def is_remote(self) -> bool:
return not self.is_local()
def _parse_url(comps: urllib.parse.ParseResult) -> FlakeId:
if comps.scheme == "" or "file" in comps.scheme:
res_p = Path(comps.path).expanduser().resolve()
flake_id = FlakeId(str(res_p))
else:
flake_id = FlakeId(comps.geturl())
return flake_id
from clan_cli.flake import Flake
# Define the ClanURI class
@dataclass
class ClanURI:
flake: FlakeId
flake: Flake
machine_name: str
def get_url(self) -> str:
@@ -104,7 +50,10 @@ class ClanURI:
clean_comps = components._replace(query=components.query, fragment="")
# Parse the URL into a ClanUrl object
flake = _parse_url(clean_comps)
if clean_comps.path and Path(clean_comps.path).exists():
flake = Flake(clean_comps.path)
else:
flake = Flake(clean_comps.geturl())
machine_name = "defaultVM"
if components.fragment:
machine_name = components.fragment

View File

@@ -207,13 +207,13 @@ def complete_secrets(
"""
Provides completion functionality for clan secrets
"""
from .clan_uri import FlakeId
from .clan_uri import Flake
from .secrets.secrets import ListSecretsOptions, list_secrets
flake = clan_dir_result if (clan_dir_result := clan_dir(None)) is not None else "."
options = ListSecretsOptions(
flake=FlakeId(flake),
flake=Flake(flake),
pattern=None,
)

View File

@@ -5,8 +5,6 @@ import urllib
from enum import Enum
from pathlib import Path
from clan_cli.clan_uri import FlakeId
from .errors import ClanError
log = logging.getLogger(__name__)
@@ -110,7 +108,7 @@ def user_history_file() -> Path:
return user_config_dir() / "clan" / "history"
def vm_state_dir(flake_url: FlakeId, vm_name: str) -> Path:
def vm_state_dir(flake_url: str, vm_name: str) -> Path:
clan_key = clan_key_safe(str(flake_url))
return user_data_dir() / "clan" / "vmstate" / clan_key / vm_name

View File

@@ -12,7 +12,7 @@ class FactStore(FactStoreBase):
self.works_remotely = False
def set(self, service: str, name: str, value: bytes) -> Path | None:
if self.machine.flake.is_local():
if self.machine.flake.is_local:
fact_path = (
self.machine.flake.path
/ "machines"

View File

@@ -14,7 +14,7 @@ class FactStore(FactStoreBase):
def __init__(self, machine: Machine) -> None:
self.machine = machine
self.works_remotely = False
self.dir = vm_state_dir(machine.flake, machine.name) / "facts"
self.dir = vm_state_dir(machine.flake.identifier, machine.name) / "facts"
machine.debug(f"FactStore initialized with dir {self.dir}")
def exists(self, service: str, name: str) -> bool:

View File

@@ -10,7 +10,7 @@ from . import SecretStoreBase
class SecretStore(SecretStoreBase):
def __init__(self, machine: Machine) -> None:
self.machine = machine
self.dir = vm_state_dir(machine.flake, machine.name) / "secrets"
self.dir = vm_state_dir(machine.flake.identifier, machine.name) / "secrets"
self.dir.mkdir(parents=True, exist_ok=True)
def set(

View File

@@ -1,7 +1,7 @@
import json
import logging
import re
from dataclasses import dataclass, field
from dataclasses import dataclass
from pathlib import Path
from typing import Any
@@ -275,9 +275,43 @@ class Flake:
"""
identifier: str
cache: FlakeCache = field(default_factory=FlakeCache)
def __post_init__(self) -> None:
self._cache: FlakeCache | None = None
self._path: Path | None = None
self._is_local: bool | None = None
@classmethod
def from_json(cls: type["Flake"], data: dict[str, Any]) -> "Flake":
return cls(data["identifier"])
def __str__(self) -> str:
return self.identifier
def __hash__(self) -> int:
return hash(self.identifier)
def __eq__(self, other: object) -> bool:
if not isinstance(other, Flake):
return NotImplemented
return self.identifier == other.identifier
@property
def is_local(self) -> bool:
if self._is_local is None:
self.prefetch()
assert isinstance(self._is_local, bool)
return self._is_local
@property
def path(self) -> Path:
if self._path is None:
self.prefetch()
assert isinstance(self._path, Path)
return self._path
def prefetch(self) -> None:
self._cache = FlakeCache()
flake_prefetch = run(
nix_command(
[
@@ -294,9 +328,23 @@ class Flake:
flake_metadata = json.loads(flake_prefetch.stdout)
self.store_path = flake_metadata["storePath"]
self.hash = flake_metadata["hash"]
self.cache = FlakeCache()
if flake_metadata["original"].get("url", "").startswith("file:"):
self._is_local = True
path = flake_metadata["original"]["url"].removeprefix("file://")
path = path.removeprefix("file:")
self._path = Path(path)
elif flake_metadata["original"].get("path"):
self._is_local = True
self._path = Path(flake_metadata["original"]["path"])
else:
self._is_local = False
self._path = Path(self.store_path)
def prepare_cache(self, selectors: list[str]) -> None:
if self._cache is None:
self.prefetch()
assert self._cache is not None
config = nix_config()
nix_code = f"""
let
@@ -312,10 +360,14 @@ class Flake:
msg = f"flake_prepare_cache: Expected {len(outputs)} outputs, got {len(outputs)}"
raise ClanError(msg)
for i, selector in enumerate(selectors):
self.cache.insert(outputs[i], selector)
self._cache.insert(outputs[i], selector)
def select(self, selector: str) -> Any:
if not self.cache.is_cached(selector):
if self._cache is None:
self.prefetch()
assert self._cache is not None
if not self._cache.is_cached(selector):
log.info(f"Cache miss for {selector}")
self.prepare_cache([selector])
return self.cache.select(selector)
return self._cache.select(selector)

View File

@@ -6,8 +6,8 @@ from dataclasses import dataclass
from pathlib import Path
from typing import Any
from clan_cli.clan_uri import FlakeId
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.flake import Flake
from clan_cli.machines.machines import Machine
from .flash import Disk, SystemConfig, flash_machine
@@ -17,7 +17,7 @@ log = logging.getLogger(__name__)
@dataclass
class FlashOptions:
flake: FlakeId
flake: Flake
machine: str
disks: list[Disk]
dry_run: bool

View File

@@ -5,10 +5,10 @@ from dataclasses import dataclass
from pathlib import Path
from clan_cli.api import API
from clan_cli.clan_uri import FlakeId
from clan_cli.completions import add_dynamic_completer, complete_tags
from clan_cli.dirs import get_clan_flake_toplevel_or_env
from clan_cli.errors import ClanError
from clan_cli.flake import Flake
from clan_cli.git import commit_file
from clan_cli.inventory import Machine as InventoryMachine
from clan_cli.inventory import (
@@ -29,7 +29,7 @@ log = logging.getLogger(__name__)
@dataclass
class CreateOptions:
clan_dir: FlakeId
clan_dir: Flake
machine: InventoryMachine
target_host: str | None = None
input_prio: InputPrio | None = None
@@ -38,7 +38,7 @@ class CreateOptions:
@API.register
def create_machine(opts: CreateOptions) -> None:
if not opts.clan_dir.is_local():
if not opts.clan_dir.is_local:
msg = f"Clan {opts.clan_dir} is not a local clan."
description = "Import machine only works on local clans"
raise ClanError(msg, description=description)
@@ -127,7 +127,7 @@ def create_command(args: argparse.Namespace) -> None:
clan_dir = args.flake
else:
tmp = get_clan_flake_toplevel_or_env()
clan_dir = FlakeId(str(tmp)) if tmp else None
clan_dir = Flake(str(tmp)) if tmp else None
if not clan_dir:
msg = "No clan found."

View File

@@ -3,7 +3,7 @@ import logging
import shutil
from clan_cli.api import API
from clan_cli.clan_uri import FlakeId
from clan_cli.clan_uri import Flake
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.dirs import specific_machine_dir
from clan_cli.errors import ClanError
@@ -13,7 +13,7 @@ log = logging.getLogger(__name__)
@API.register
def delete_machine(flake: FlakeId, name: str) -> None:
def delete_machine(flake: Flake, name: str) -> None:
inventory = get_inventory(flake.path)
if "machines" not in inventory:

View File

@@ -6,11 +6,11 @@ from enum import Enum
from pathlib import Path
from clan_cli.api import API
from clan_cli.clan_uri import FlakeId
from clan_cli.cmd import RunOpts, run, run_no_stdout
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.dirs import specific_machine_dir
from clan_cli.errors import ClanCmdError, ClanError
from clan_cli.flake import Flake
from clan_cli.git import commit_file
from clan_cli.machines.machines import Machine
from clan_cli.nix import nix_config, nix_eval, nix_shell
@@ -102,7 +102,7 @@ def show_machine_hardware_platform(clan_dir: Path, machine_name: str) -> str | N
@dataclass
class HardwareGenerateOptions:
flake: FlakeId
flake: Flake
machine: str
backend: HardwareConfig
target_host: str | None = None

View File

@@ -1,15 +1,15 @@
import json
from pathlib import Path
from clan_cli.clan_uri import FlakeId
from clan_cli.cmd import run
from clan_cli.flake import Flake
from clan_cli.nix import nix_build, nix_config, nix_test_store
from .machines import Machine
# function to speedup eval if we want to evaluate all machines
def get_all_machines(flake: FlakeId, nix_options: list[str]) -> list[Machine]:
def get_all_machines(flake: Flake, nix_options: list[str]) -> list[Machine]:
config = nix_config()
system = config["system"]
json_path = Path(
@@ -37,7 +37,7 @@ def get_all_machines(flake: FlakeId, nix_options: list[str]) -> list[Machine]:
def get_selected_machines(
flake: FlakeId, nix_options: list[str], machine_names: list[str]
flake: Flake, nix_options: list[str], machine_names: list[str]
) -> list[Machine]:
machines = []
for name in machine_names:

View File

@@ -8,11 +8,11 @@ from tempfile import NamedTemporaryFile
from time import time
from typing import TYPE_CHECKING, Any, Literal
from clan_cli.clan_uri import FlakeId
from clan_cli.cmd import RunOpts, run_no_stdout
from clan_cli.errors import ClanError
from clan_cli.facts import public_modules as facts_public_modules
from clan_cli.facts import secret_modules as facts_secret_modules
from clan_cli.flake import Flake
from clan_cli.nix import nix_build, nix_config, nix_eval, nix_metadata, nix_test_store
from clan_cli.ssh.host import Host
from clan_cli.ssh.host_key import HostKeyCheck
@@ -28,7 +28,7 @@ if TYPE_CHECKING:
@dataclass
class Machine:
name: str
flake: FlakeId
flake: Flake
nix_options: list[str] = field(default_factory=list)
cached_deployment: None | dict[str, Any] = None
override_target_host: None | str = None
@@ -201,12 +201,7 @@ class Machine:
@property
def flake_dir(self) -> Path:
if self.flake.is_local():
return self.flake.path
if self.flake.is_remote():
return Path(nix_metadata(self.flake.url)["path"])
msg = f"Unsupported flake url: {self.flake}"
raise ClanError(msg)
return self.flake.path
@property
def target_host(self) -> Host:

View File

@@ -8,7 +8,6 @@ import sys
from clan_cli.api import API
from clan_cli.async_run import AsyncContext, AsyncOpts, AsyncRuntime, is_async_cancelled
from clan_cli.clan_uri import FlakeId
from clan_cli.cmd import MsgColor, RunOpts, run
from clan_cli.colors import AnsiColor
from clan_cli.completions import (
@@ -18,6 +17,7 @@ from clan_cli.completions import (
from clan_cli.errors import ClanError
from clan_cli.facts.generate import generate_facts
from clan_cli.facts.upload import upload_secrets
from clan_cli.flake import Flake
from clan_cli.inventory import Machine as InventoryMachine
from clan_cli.machines.machines import Machine
from clan_cli.nix import nix_command, nix_metadata
@@ -46,7 +46,7 @@ def upload_sources(machine: Machine) -> str:
env = host.nix_ssh_env(os.environ.copy())
flake_url = (
str(machine.flake.path) if machine.flake.is_local() else machine.flake.url
str(machine.flake.path) if machine.flake.is_local else machine.flake.identifier
)
flake_data = nix_metadata(flake_url)
has_path_inputs = any(
@@ -96,6 +96,7 @@ def update_machines(base_path: str, machines: list[InventoryMachine]) -> None:
group_machines: list[Machine] = []
# Convert InventoryMachine to Machine
flake = Flake(base_path)
for machine in machines:
name = machine.get("name")
if not name:
@@ -103,7 +104,7 @@ def update_machines(base_path: str, machines: list[InventoryMachine]) -> None:
raise ClanError(msg)
m = Machine(
name,
flake=FlakeId(base_path),
flake=flake,
)
if not machine.get("deploy", {}).get("targetHost"):
msg = f"'TargetHost' is not set for machine '{name}'"

View File

@@ -10,7 +10,6 @@ from dataclasses import dataclass
from pathlib import Path
from typing import IO
from clan_cli.clan_uri import FlakeId
from clan_cli.completions import (
add_dynamic_completer,
complete_groups,
@@ -19,6 +18,7 @@ from clan_cli.completions import (
complete_users,
)
from clan_cli.errors import ClanError
from clan_cli.flake import Flake
from clan_cli.git import commit_files
from . import sops
@@ -341,7 +341,7 @@ def list_secrets(flake_dir: Path, pattern: str | None = None) -> list[str]:
@dataclass
class ListSecretsOptions:
flake: FlakeId
flake: Flake
pattern: str | None

View File

@@ -15,3 +15,8 @@ def register_parser(parser: argparse.ArgumentParser) -> None:
"selector",
help="select from a flake",
)
parser.add_argument(
"--impure",
action="store_true",
default=False,
)

View File

@@ -6,9 +6,9 @@ from dataclasses import dataclass, field
from pathlib import Path
from typing import Literal, NewType, TypedDict
from clan_cli.clan_uri import FlakeId
from clan_cli.cmd import run
from clan_cli.errors import ClanError
from clan_cli.flake import Flake
from clan_cli.nix import nix_eval
log = logging.getLogger(__name__)
@@ -59,7 +59,7 @@ class ClanExports(TypedDict):
self: ClanAttrset
def get_clan_nix_attrset(clan_dir: FlakeId | None = None) -> ClanExports:
def get_clan_nix_attrset(clan_dir: Flake | None = None) -> ClanExports:
# Check if the clan directory is provided, otherwise use the environment variable
if not clan_dir:
# TODO: Quickfix, templates dir seems to be missing in CLAN_CORE_PATH??
@@ -69,7 +69,7 @@ def get_clan_nix_attrset(clan_dir: FlakeId | None = None) -> ClanExports:
# msg = "Environment var CLAN_CORE_PATH is not set, this shouldn't happen"
# raise ClanError(msg)
clan_dir = FlakeId(clan_core_path)
clan_dir = Flake(clan_core_path)
log.debug(f"Evaluating flake {clan_dir} for Clan attrsets")
@@ -170,7 +170,7 @@ class TemplateList:
def list_templates(
template_type: TemplateType, clan_dir: FlakeId | None = None
template_type: TemplateType, clan_dir: Flake | None = None
) -> TemplateList:
clan_exports = get_clan_nix_attrset(clan_dir)
result = TemplateList()
@@ -204,7 +204,7 @@ def get_template(
template_type: TemplateType,
*,
input_prio: InputPrio | None = None,
clan_dir: FlakeId | None = None,
clan_dir: Flake | None = None,
) -> FoundTemplate:
log.info(f"Searching for template '{template_name}' of type '{template_type}'")

View File

@@ -3,9 +3,9 @@ import logging
import sys
from clan_cli.api import API
from clan_cli.clan_uri import FlakeId
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.errors import ClanError
from clan_cli.flake import Flake
from .generate import Var
from .list import get_vars
@@ -42,7 +42,7 @@ def get_var(base_dir: str, machine_name: str, var_id: str) -> Var:
raise ClanError(msg)
def get_command(machine_name: str, var_id: str, flake: FlakeId) -> None:
def get_command(machine_name: str, var_id: str, flake: Flake) -> None:
var = get_var(str(flake.path), machine_name, var_id)
if not var.exists:
msg = f"Var {var.id} has not been generated yet"

View File

@@ -2,8 +2,8 @@ import argparse
import logging
import os
from clan_cli.clan_uri import FlakeId
from clan_cli.errors import ClanError
from clan_cli.flake import Flake
from clan_cli.secrets.key import generate_key
from clan_cli.secrets.sops import KeyType, maybe_get_admin_public_key
from clan_cli.secrets.users import add_user
@@ -11,7 +11,7 @@ from clan_cli.secrets.users import add_user
log = logging.getLogger(__name__)
def keygen(user: str | None, flake: FlakeId, force: bool) -> None:
def keygen(user: str | None, flake: Flake, force: bool) -> None:
if user is None:
user = os.getenv("USER", None)
if not user:

View File

@@ -3,9 +3,9 @@ import importlib
import logging
from clan_cli.api import API
from clan_cli.clan_uri import FlakeId
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.errors import ClanError
from clan_cli.flake import Flake
from clan_cli.machines.machines import Machine
from clan_cli.vars._types import StoreBase
@@ -27,7 +27,7 @@ def secret_store(machine: Machine) -> StoreBase:
@API.register
def get_vars(base_dir: str, machine_name: str) -> list[Var]:
machine = Machine(name=machine_name, flake=FlakeId(base_dir))
machine = Machine(name=machine_name, flake=Flake(base_dir))
pub_store = public_store(machine)
sec_store = secret_store(machine)
all_vars = []
@@ -61,7 +61,7 @@ def _get_previous_value(
@API.register
def get_generators(base_dir: str, machine_name: str) -> list[Generator]:
machine = Machine(name=machine_name, flake=FlakeId(base_dir))
machine = Machine(name=machine_name, flake=Flake(base_dir))
generators: list[Generator] = machine.vars_generators
for generator in generators:
for prompt in generator.prompts:
@@ -76,7 +76,7 @@ def get_generators(base_dir: str, machine_name: str) -> list[Generator]:
def set_prompts(
base_dir: str, machine_name: str, updates: list[GeneratorUpdate]
) -> None:
machine = Machine(name=machine_name, flake=FlakeId(base_dir))
machine = Machine(name=machine_name, flake=Flake(base_dir))
for update in updates:
for generator in machine.vars_generators:
if generator.name == update.generator:

View File

@@ -26,7 +26,7 @@ class FactStore(StoreBase):
var: Var,
value: bytes,
) -> Path | None:
if not self.machine.flake.is_local():
if not self.machine.flake.is_local:
msg = f"in_flake fact storage is only supported for local flakes: {self.machine.flake}"
raise ClanError(msg)
folder = self.directory(generator, var.name)

View File

@@ -18,7 +18,7 @@ class FactStore(StoreBase):
def __init__(self, machine: Machine) -> None:
self.machine = machine
self.works_remotely = False
self.dir = vm_state_dir(machine.flake, machine.name) / "facts"
self.dir = vm_state_dir(machine.flake.identifier, machine.name) / "facts"
machine.debug(f"FactStore initialized with dir {self.dir}")
@property

View File

@@ -14,7 +14,7 @@ class SecretStore(StoreBase):
def __init__(self, machine: Machine) -> None:
self.machine = machine
self.dir = vm_state_dir(machine.flake, machine.name) / "secrets"
self.dir = vm_state_dir(machine.flake.identifier, machine.name) / "secrets"
self.dir.mkdir(parents=True, exist_ok=True)
@property

View File

@@ -2,8 +2,8 @@ import argparse
import logging
import sys
from clan_cli.clan_uri import FlakeId
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.flake import Flake
from clan_cli.git import commit_files
from clan_cli.machines.machines import Machine
from clan_cli.vars.get import get_var
@@ -15,9 +15,7 @@ from .prompt import ask
log = logging.getLogger(__name__)
def set_var(
machine: str | Machine, var: str | Var, value: bytes, flake: FlakeId
) -> None:
def set_var(machine: str | Machine, var: str | Var, value: bytes, flake: Flake) -> None:
if isinstance(machine, str):
_machine = Machine(name=machine, flake=flake)
else:
@@ -35,7 +33,7 @@ def set_var(
)
def set_via_stdin(machine: str, var_id: str, flake: FlakeId) -> None:
def set_via_stdin(machine: str, var_id: str, flake: Flake) -> None:
var = get_var(str(flake.path), machine, var_id)
if sys.stdin.isatty():
new_value = ask(

View File

@@ -5,8 +5,8 @@ from dataclasses import dataclass
from pathlib import Path
from typing import Any
from clan_cli.clan_uri import FlakeId
from clan_cli.completions import add_dynamic_completer, complete_machines
from clan_cli.flake import Flake
from clan_cli.machines.machines import Machine
@@ -26,7 +26,7 @@ class WaypipeConfig:
@dataclass
class VmConfig:
machine_name: str
flake_url: FlakeId
flake_url: Flake
cores: int
memory_size: int
@@ -43,7 +43,7 @@ class VmConfig:
def from_json(cls: type["VmConfig"], data: dict[str, Any]) -> "VmConfig":
return cls(
machine_name=data["machine_name"],
flake_url=FlakeId.from_json(data["flake_url"]),
flake_url=Flake.from_json(data["flake_url"]),
cores=data["cores"],
memory_size=data["memory_size"],
graphics=data["graphics"],
@@ -64,13 +64,13 @@ def inspect_vm(machine: Machine) -> VmConfig:
@dataclass
class InspectOptions:
machine: str
flake: FlakeId
flake: Flake
def inspect_command(args: argparse.Namespace) -> None:
inspect_options = InspectOptions(
machine=args.machine,
flake=args.flake or FlakeId(str(Path.cwd())),
flake=args.flake or Flake(str(Path.cwd())),
)
machine = Machine(inspect_options.machine, inspect_options.flake)

View File

@@ -236,7 +236,7 @@ def spawn_vm(
# TODO: We should get this from the vm argument
nixos_config = build_vm(machine, cachedir, nix_options)
state_dir = vm_state_dir(vm.flake_url, machine.name)
state_dir = vm_state_dir(vm.flake_url.identifier, machine.name)
state_dir.mkdir(parents=True, exist_ok=True)
# specify socket files for qmp and qga