clan_cli machines: use Flake instead of FlakeId
This commit is contained in:
@@ -22,11 +22,11 @@ from . import (
|
|||||||
state,
|
state,
|
||||||
vms,
|
vms,
|
||||||
)
|
)
|
||||||
from .clan_uri import FlakeId
|
|
||||||
from .custom_logger import setup_logging
|
from .custom_logger import setup_logging
|
||||||
from .dirs import get_clan_flake_toplevel_or_env
|
from .dirs import get_clan_flake_toplevel_or_env
|
||||||
from .errors import ClanError
|
from .errors import ClanError
|
||||||
from .facts import cli as facts
|
from .facts import cli as facts
|
||||||
|
from .flake import Flake
|
||||||
from .flash import cli as flash_cli
|
from .flash import cli as flash_cli
|
||||||
from .hyperlink import help_hyperlink
|
from .hyperlink import help_hyperlink
|
||||||
from .machines import cli as machines
|
from .machines import cli as machines
|
||||||
@@ -41,17 +41,17 @@ with contextlib.suppress(ImportError):
|
|||||||
import argcomplete # type: ignore[no-redef]
|
import argcomplete # type: ignore[no-redef]
|
||||||
|
|
||||||
|
|
||||||
def flake_path(arg: str) -> FlakeId:
|
def flake_path(arg: str) -> Flake:
|
||||||
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 FlakeId(str(flake_dir))
|
return Flake(str(flake_dir))
|
||||||
return FlakeId(arg)
|
return Flake(arg)
|
||||||
|
|
||||||
|
|
||||||
def default_flake() -> FlakeId | None:
|
def default_flake() -> Flake | None:
|
||||||
val = get_clan_flake_toplevel_or_env()
|
val = get_clan_flake_toplevel_or_env()
|
||||||
if val:
|
if val:
|
||||||
return FlakeId(str(val))
|
return Flake(str(val))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ from dataclasses import dataclass
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from clan_cli.api import API
|
from clan_cli.api import API
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.cmd import CmdOut, RunOpts, run
|
from clan_cli.cmd import CmdOut, RunOpts, run
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.inventory import Inventory, init_inventory
|
from clan_cli.inventory import Inventory, init_inventory
|
||||||
from clan_cli.nix import nix_shell
|
from clan_cli.nix import nix_shell
|
||||||
from clan_cli.templates import (
|
from clan_cli.templates import (
|
||||||
@@ -33,7 +33,7 @@ class CreateClanResponse:
|
|||||||
class CreateOptions:
|
class CreateOptions:
|
||||||
dest: Path
|
dest: Path
|
||||||
template_name: str
|
template_name: str
|
||||||
src_flake: FlakeId | None = None
|
src_flake: Flake | None = None
|
||||||
input_prio: InputPrio | None = None
|
input_prio: InputPrio | None = None
|
||||||
setup_git: bool = True
|
setup_git: bool = True
|
||||||
initial: Inventory | None = None
|
initial: Inventory | None = None
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ from dataclasses import dataclass
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.cmd import run
|
from clan_cli.cmd import run
|
||||||
from clan_cli.dirs import machine_gcroot
|
from clan_cli.dirs import machine_gcroot
|
||||||
from clan_cli.errors import ClanError
|
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.list import list_nixos_machines
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.nix import (
|
from clan_cli.nix import (
|
||||||
@@ -21,7 +21,7 @@ from clan_cli.vms.inspect import VmConfig, inspect_vm
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class FlakeConfig:
|
class FlakeConfig:
|
||||||
flake_url: FlakeId
|
flake_url: Flake
|
||||||
flake_attr: str
|
flake_attr: str
|
||||||
|
|
||||||
clan_name: str
|
clan_name: str
|
||||||
@@ -35,7 +35,7 @@ class FlakeConfig:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def from_json(cls: type["FlakeConfig"], data: dict[str, Any]) -> "FlakeConfig":
|
def from_json(cls: type["FlakeConfig"], data: dict[str, Any]) -> "FlakeConfig":
|
||||||
return cls(
|
return cls(
|
||||||
flake_url=FlakeId.from_json(data["flake_url"]),
|
flake_url=Flake.from_json(data["flake_url"]),
|
||||||
flake_attr=data["flake_attr"],
|
flake_attr=data["flake_attr"],
|
||||||
clan_name=data["clan_name"],
|
clan_name=data["clan_name"],
|
||||||
nar_hash=data["nar_hash"],
|
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)}"
|
msg = f"Machine {machine_name} not found in {flake_url}. Available machines: {', '.join(machines)}"
|
||||||
raise ClanError(msg)
|
raise ClanError(msg)
|
||||||
|
|
||||||
machine = Machine(machine_name, FlakeId(str(flake_url)))
|
machine = Machine(machine_name, Flake(str(flake_url)))
|
||||||
vm = inspect_vm(machine)
|
vm = inspect_vm(machine)
|
||||||
|
|
||||||
# Make symlink to gcroots from vm.machine_icon
|
# 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)
|
meta = nix_metadata(flake_url)
|
||||||
return FlakeConfig(
|
return FlakeConfig(
|
||||||
vm=vm,
|
vm=vm,
|
||||||
flake_url=FlakeId(str(flake_url)),
|
flake_url=Flake(str(flake_url)),
|
||||||
clan_name=clan_name,
|
clan_name=clan_name,
|
||||||
flake_attr=machine_name,
|
flake_attr=machine_name,
|
||||||
nar_hash=meta["locked"]["narHash"],
|
nar_hash=meta["locked"]["narHash"],
|
||||||
@@ -119,13 +119,13 @@ def inspect_flake(flake_url: str | Path, machine_name: str) -> FlakeConfig:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class InspectOptions:
|
class InspectOptions:
|
||||||
machine: str
|
machine: str
|
||||||
flake: FlakeId
|
flake: Flake
|
||||||
|
|
||||||
|
|
||||||
def inspect_command(args: argparse.Namespace) -> None:
|
def inspect_command(args: argparse.Namespace) -> None:
|
||||||
inspect_options = InspectOptions(
|
inspect_options = InspectOptions(
|
||||||
machine=args.machine,
|
machine=args.machine,
|
||||||
flake=args.flake or FlakeId(str(Path.cwd())),
|
flake=args.flake or Flake(str(Path.cwd())),
|
||||||
)
|
)
|
||||||
res = inspect_flake(
|
res = inspect_flake(
|
||||||
flake_url=str(inspect_options.flake), machine_name=inspect_options.machine
|
flake_url=str(inspect_options.flake), machine_name=inspect_options.machine
|
||||||
|
|||||||
@@ -3,68 +3,14 @@ import urllib.parse
|
|||||||
import urllib.request
|
import urllib.request
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
|
from clan_cli.flake import Flake
|
||||||
@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
|
|
||||||
|
|
||||||
|
|
||||||
# Define the ClanURI class
|
# Define the ClanURI class
|
||||||
@dataclass
|
@dataclass
|
||||||
class ClanURI:
|
class ClanURI:
|
||||||
flake: FlakeId
|
flake: Flake
|
||||||
machine_name: str
|
machine_name: str
|
||||||
|
|
||||||
def get_url(self) -> str:
|
def get_url(self) -> str:
|
||||||
@@ -104,7 +50,10 @@ class ClanURI:
|
|||||||
clean_comps = components._replace(query=components.query, fragment="")
|
clean_comps = components._replace(query=components.query, fragment="")
|
||||||
|
|
||||||
# Parse the URL into a ClanUrl object
|
# 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"
|
machine_name = "defaultVM"
|
||||||
if components.fragment:
|
if components.fragment:
|
||||||
machine_name = components.fragment
|
machine_name = components.fragment
|
||||||
|
|||||||
@@ -207,13 +207,13 @@ def complete_secrets(
|
|||||||
"""
|
"""
|
||||||
Provides completion functionality for clan secrets
|
Provides completion functionality for clan secrets
|
||||||
"""
|
"""
|
||||||
from .clan_uri import FlakeId
|
from .clan_uri import Flake
|
||||||
from .secrets.secrets import ListSecretsOptions, list_secrets
|
from .secrets.secrets import ListSecretsOptions, list_secrets
|
||||||
|
|
||||||
flake = clan_dir_result if (clan_dir_result := clan_dir(None)) is not None else "."
|
flake = clan_dir_result if (clan_dir_result := clan_dir(None)) is not None else "."
|
||||||
|
|
||||||
options = ListSecretsOptions(
|
options = ListSecretsOptions(
|
||||||
flake=FlakeId(flake),
|
flake=Flake(flake),
|
||||||
pattern=None,
|
pattern=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import urllib
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
|
|
||||||
from .errors import ClanError
|
from .errors import ClanError
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@@ -110,7 +108,7 @@ def user_history_file() -> Path:
|
|||||||
return user_config_dir() / "clan" / "history"
|
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))
|
clan_key = clan_key_safe(str(flake_url))
|
||||||
return user_data_dir() / "clan" / "vmstate" / clan_key / vm_name
|
return user_data_dir() / "clan" / "vmstate" / clan_key / vm_name
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class FactStore(FactStoreBase):
|
|||||||
self.works_remotely = False
|
self.works_remotely = False
|
||||||
|
|
||||||
def set(self, service: str, name: str, value: bytes) -> Path | None:
|
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 = (
|
fact_path = (
|
||||||
self.machine.flake.path
|
self.machine.flake.path
|
||||||
/ "machines"
|
/ "machines"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class FactStore(FactStoreBase):
|
|||||||
def __init__(self, machine: Machine) -> None:
|
def __init__(self, machine: Machine) -> None:
|
||||||
self.machine = machine
|
self.machine = machine
|
||||||
self.works_remotely = False
|
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}")
|
machine.debug(f"FactStore initialized with dir {self.dir}")
|
||||||
|
|
||||||
def exists(self, service: str, name: str) -> bool:
|
def exists(self, service: str, name: str) -> bool:
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from . import SecretStoreBase
|
|||||||
class SecretStore(SecretStoreBase):
|
class SecretStore(SecretStoreBase):
|
||||||
def __init__(self, machine: Machine) -> None:
|
def __init__(self, machine: Machine) -> None:
|
||||||
self.machine = machine
|
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)
|
self.dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
def set(
|
def set(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@@ -275,9 +275,43 @@ class Flake:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
identifier: str
|
identifier: str
|
||||||
cache: FlakeCache = field(default_factory=FlakeCache)
|
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
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(
|
flake_prefetch = run(
|
||||||
nix_command(
|
nix_command(
|
||||||
[
|
[
|
||||||
@@ -294,9 +328,23 @@ class Flake:
|
|||||||
flake_metadata = json.loads(flake_prefetch.stdout)
|
flake_metadata = json.loads(flake_prefetch.stdout)
|
||||||
self.store_path = flake_metadata["storePath"]
|
self.store_path = flake_metadata["storePath"]
|
||||||
self.hash = flake_metadata["hash"]
|
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:
|
def prepare_cache(self, selectors: list[str]) -> None:
|
||||||
|
if self._cache is None:
|
||||||
|
self.prefetch()
|
||||||
|
assert self._cache is not None
|
||||||
|
|
||||||
config = nix_config()
|
config = nix_config()
|
||||||
nix_code = f"""
|
nix_code = f"""
|
||||||
let
|
let
|
||||||
@@ -312,10 +360,14 @@ class Flake:
|
|||||||
msg = f"flake_prepare_cache: Expected {len(outputs)} outputs, got {len(outputs)}"
|
msg = f"flake_prepare_cache: Expected {len(outputs)} outputs, got {len(outputs)}"
|
||||||
raise ClanError(msg)
|
raise ClanError(msg)
|
||||||
for i, selector in enumerate(selectors):
|
for i, selector in enumerate(selectors):
|
||||||
self.cache.insert(outputs[i], selector)
|
self._cache.insert(outputs[i], selector)
|
||||||
|
|
||||||
def select(self, selector: str) -> Any:
|
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}")
|
log.info(f"Cache miss for {selector}")
|
||||||
self.prepare_cache([selector])
|
self.prepare_cache([selector])
|
||||||
return self.cache.select(selector)
|
return self._cache.select(selector)
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ from dataclasses import dataclass
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.completions import add_dynamic_completer, complete_machines
|
from clan_cli.completions import add_dynamic_completer, complete_machines
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
|
|
||||||
from .flash import Disk, SystemConfig, flash_machine
|
from .flash import Disk, SystemConfig, flash_machine
|
||||||
@@ -17,7 +17,7 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class FlashOptions:
|
class FlashOptions:
|
||||||
flake: FlakeId
|
flake: Flake
|
||||||
machine: str
|
machine: str
|
||||||
disks: list[Disk]
|
disks: list[Disk]
|
||||||
dry_run: bool
|
dry_run: bool
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ from dataclasses import dataclass
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from clan_cli.api import API
|
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.completions import add_dynamic_completer, complete_tags
|
||||||
from clan_cli.dirs import get_clan_flake_toplevel_or_env
|
from clan_cli.dirs import get_clan_flake_toplevel_or_env
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.git import commit_file
|
from clan_cli.git import commit_file
|
||||||
from clan_cli.inventory import Machine as InventoryMachine
|
from clan_cli.inventory import Machine as InventoryMachine
|
||||||
from clan_cli.inventory import (
|
from clan_cli.inventory import (
|
||||||
@@ -29,7 +29,7 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class CreateOptions:
|
class CreateOptions:
|
||||||
clan_dir: FlakeId
|
clan_dir: Flake
|
||||||
machine: InventoryMachine
|
machine: InventoryMachine
|
||||||
target_host: str | None = None
|
target_host: str | None = None
|
||||||
input_prio: InputPrio | None = None
|
input_prio: InputPrio | None = None
|
||||||
@@ -38,7 +38,7 @@ class CreateOptions:
|
|||||||
|
|
||||||
@API.register
|
@API.register
|
||||||
def create_machine(opts: CreateOptions) -> None:
|
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."
|
msg = f"Clan {opts.clan_dir} is not a local clan."
|
||||||
description = "Import machine only works on local clans"
|
description = "Import machine only works on local clans"
|
||||||
raise ClanError(msg, description=description)
|
raise ClanError(msg, description=description)
|
||||||
@@ -127,7 +127,7 @@ def create_command(args: argparse.Namespace) -> None:
|
|||||||
clan_dir = args.flake
|
clan_dir = args.flake
|
||||||
else:
|
else:
|
||||||
tmp = get_clan_flake_toplevel_or_env()
|
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:
|
if not clan_dir:
|
||||||
msg = "No clan found."
|
msg = "No clan found."
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import logging
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from clan_cli.api import API
|
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.completions import add_dynamic_completer, complete_machines
|
||||||
from clan_cli.dirs import specific_machine_dir
|
from clan_cli.dirs import specific_machine_dir
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
@@ -13,7 +13,7 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@API.register
|
@API.register
|
||||||
def delete_machine(flake: FlakeId, name: str) -> None:
|
def delete_machine(flake: Flake, name: str) -> None:
|
||||||
inventory = get_inventory(flake.path)
|
inventory = get_inventory(flake.path)
|
||||||
|
|
||||||
if "machines" not in inventory:
|
if "machines" not in inventory:
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ from enum import Enum
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from clan_cli.api import API
|
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.cmd import RunOpts, run, run_no_stdout
|
||||||
from clan_cli.completions import add_dynamic_completer, complete_machines
|
from clan_cli.completions import add_dynamic_completer, complete_machines
|
||||||
from clan_cli.dirs import specific_machine_dir
|
from clan_cli.dirs import specific_machine_dir
|
||||||
from clan_cli.errors import ClanCmdError, ClanError
|
from clan_cli.errors import ClanCmdError, ClanError
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.git import commit_file
|
from clan_cli.git import commit_file
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.nix import nix_config, nix_eval, nix_shell
|
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
|
@dataclass
|
||||||
class HardwareGenerateOptions:
|
class HardwareGenerateOptions:
|
||||||
flake: FlakeId
|
flake: Flake
|
||||||
machine: str
|
machine: str
|
||||||
backend: HardwareConfig
|
backend: HardwareConfig
|
||||||
target_host: str | None = None
|
target_host: str | None = None
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.cmd import run
|
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 clan_cli.nix import nix_build, nix_config, nix_test_store
|
||||||
|
|
||||||
from .machines import Machine
|
from .machines import Machine
|
||||||
|
|
||||||
|
|
||||||
# function to speedup eval if we want to evaluate all machines
|
# 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()
|
config = nix_config()
|
||||||
system = config["system"]
|
system = config["system"]
|
||||||
json_path = Path(
|
json_path = Path(
|
||||||
@@ -37,7 +37,7 @@ def get_all_machines(flake: FlakeId, nix_options: list[str]) -> list[Machine]:
|
|||||||
|
|
||||||
|
|
||||||
def get_selected_machines(
|
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]:
|
) -> list[Machine]:
|
||||||
machines = []
|
machines = []
|
||||||
for name in machine_names:
|
for name in machine_names:
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ from tempfile import NamedTemporaryFile
|
|||||||
from time import time
|
from time import time
|
||||||
from typing import TYPE_CHECKING, Any, Literal
|
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.cmd import RunOpts, run_no_stdout
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
from clan_cli.facts import public_modules as facts_public_modules
|
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.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.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 import Host
|
||||||
from clan_cli.ssh.host_key import HostKeyCheck
|
from clan_cli.ssh.host_key import HostKeyCheck
|
||||||
@@ -28,7 +28,7 @@ if TYPE_CHECKING:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class Machine:
|
class Machine:
|
||||||
name: str
|
name: str
|
||||||
flake: FlakeId
|
flake: Flake
|
||||||
nix_options: list[str] = field(default_factory=list)
|
nix_options: list[str] = field(default_factory=list)
|
||||||
cached_deployment: None | dict[str, Any] = None
|
cached_deployment: None | dict[str, Any] = None
|
||||||
override_target_host: None | str = None
|
override_target_host: None | str = None
|
||||||
@@ -201,12 +201,7 @@ class Machine:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def flake_dir(self) -> Path:
|
def flake_dir(self) -> Path:
|
||||||
if self.flake.is_local():
|
return self.flake.path
|
||||||
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)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_host(self) -> Host:
|
def target_host(self) -> Host:
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import sys
|
|||||||
|
|
||||||
from clan_cli.api import API
|
from clan_cli.api import API
|
||||||
from clan_cli.async_run import AsyncContext, AsyncOpts, AsyncRuntime, is_async_cancelled
|
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.cmd import MsgColor, RunOpts, run
|
||||||
from clan_cli.colors import AnsiColor
|
from clan_cli.colors import AnsiColor
|
||||||
from clan_cli.completions import (
|
from clan_cli.completions import (
|
||||||
@@ -18,6 +17,7 @@ from clan_cli.completions import (
|
|||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
from clan_cli.facts.generate import generate_facts
|
from clan_cli.facts.generate import generate_facts
|
||||||
from clan_cli.facts.upload import upload_secrets
|
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.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_metadata
|
||||||
@@ -46,7 +46,7 @@ def upload_sources(machine: Machine) -> str:
|
|||||||
env = host.nix_ssh_env(os.environ.copy())
|
env = host.nix_ssh_env(os.environ.copy())
|
||||||
|
|
||||||
flake_url = (
|
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)
|
flake_data = nix_metadata(flake_url)
|
||||||
has_path_inputs = any(
|
has_path_inputs = any(
|
||||||
@@ -96,6 +96,7 @@ def update_machines(base_path: str, machines: list[InventoryMachine]) -> None:
|
|||||||
group_machines: list[Machine] = []
|
group_machines: list[Machine] = []
|
||||||
|
|
||||||
# Convert InventoryMachine to Machine
|
# Convert InventoryMachine to Machine
|
||||||
|
flake = Flake(base_path)
|
||||||
for machine in machines:
|
for machine in machines:
|
||||||
name = machine.get("name")
|
name = machine.get("name")
|
||||||
if not name:
|
if not name:
|
||||||
@@ -103,7 +104,7 @@ def update_machines(base_path: str, machines: list[InventoryMachine]) -> None:
|
|||||||
raise ClanError(msg)
|
raise ClanError(msg)
|
||||||
m = Machine(
|
m = Machine(
|
||||||
name,
|
name,
|
||||||
flake=FlakeId(base_path),
|
flake=flake,
|
||||||
)
|
)
|
||||||
if not machine.get("deploy", {}).get("targetHost"):
|
if not machine.get("deploy", {}).get("targetHost"):
|
||||||
msg = f"'TargetHost' is not set for machine '{name}'"
|
msg = f"'TargetHost' is not set for machine '{name}'"
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ from dataclasses import dataclass
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import IO
|
from typing import IO
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.completions import (
|
from clan_cli.completions import (
|
||||||
add_dynamic_completer,
|
add_dynamic_completer,
|
||||||
complete_groups,
|
complete_groups,
|
||||||
@@ -19,6 +18,7 @@ from clan_cli.completions import (
|
|||||||
complete_users,
|
complete_users,
|
||||||
)
|
)
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.git import commit_files
|
from clan_cli.git import commit_files
|
||||||
|
|
||||||
from . import sops
|
from . import sops
|
||||||
@@ -341,7 +341,7 @@ def list_secrets(flake_dir: Path, pattern: str | None = None) -> list[str]:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ListSecretsOptions:
|
class ListSecretsOptions:
|
||||||
flake: FlakeId
|
flake: Flake
|
||||||
pattern: str | None
|
pattern: str | None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,3 +15,8 @@ def register_parser(parser: argparse.ArgumentParser) -> None:
|
|||||||
"selector",
|
"selector",
|
||||||
help="select from a flake",
|
help="select from a flake",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--impure",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ from dataclasses import dataclass, field
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Literal, NewType, TypedDict
|
from typing import Literal, NewType, TypedDict
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.cmd import run
|
from clan_cli.cmd import run
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.nix import nix_eval
|
from clan_cli.nix import nix_eval
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@@ -59,7 +59,7 @@ class ClanExports(TypedDict):
|
|||||||
self: ClanAttrset
|
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
|
# Check if the clan directory is provided, otherwise use the environment variable
|
||||||
if not clan_dir:
|
if not clan_dir:
|
||||||
# TODO: Quickfix, templates dir seems to be missing in CLAN_CORE_PATH??
|
# 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"
|
# msg = "Environment var CLAN_CORE_PATH is not set, this shouldn't happen"
|
||||||
# raise ClanError(msg)
|
# 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")
|
log.debug(f"Evaluating flake {clan_dir} for Clan attrsets")
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ class TemplateList:
|
|||||||
|
|
||||||
|
|
||||||
def list_templates(
|
def list_templates(
|
||||||
template_type: TemplateType, clan_dir: FlakeId | None = None
|
template_type: TemplateType, clan_dir: Flake | None = None
|
||||||
) -> TemplateList:
|
) -> TemplateList:
|
||||||
clan_exports = get_clan_nix_attrset(clan_dir)
|
clan_exports = get_clan_nix_attrset(clan_dir)
|
||||||
result = TemplateList()
|
result = TemplateList()
|
||||||
@@ -204,7 +204,7 @@ def get_template(
|
|||||||
template_type: TemplateType,
|
template_type: TemplateType,
|
||||||
*,
|
*,
|
||||||
input_prio: InputPrio | None = None,
|
input_prio: InputPrio | None = None,
|
||||||
clan_dir: FlakeId | None = None,
|
clan_dir: Flake | None = None,
|
||||||
) -> FoundTemplate:
|
) -> FoundTemplate:
|
||||||
log.info(f"Searching for template '{template_name}' of type '{template_type}'")
|
log.info(f"Searching for template '{template_name}' of type '{template_type}'")
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import logging
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from clan_cli.api import API
|
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.completions import add_dynamic_completer, complete_machines
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
|
from clan_cli.flake import Flake
|
||||||
|
|
||||||
from .generate import Var
|
from .generate import Var
|
||||||
from .list import get_vars
|
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)
|
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)
|
var = get_var(str(flake.path), machine_name, var_id)
|
||||||
if not var.exists:
|
if not var.exists:
|
||||||
msg = f"Var {var.id} has not been generated yet"
|
msg = f"Var {var.id} has not been generated yet"
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import argparse
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.secrets.key import generate_key
|
from clan_cli.secrets.key import generate_key
|
||||||
from clan_cli.secrets.sops import KeyType, maybe_get_admin_public_key
|
from clan_cli.secrets.sops import KeyType, maybe_get_admin_public_key
|
||||||
from clan_cli.secrets.users import add_user
|
from clan_cli.secrets.users import add_user
|
||||||
@@ -11,7 +11,7 @@ from clan_cli.secrets.users import add_user
|
|||||||
log = logging.getLogger(__name__)
|
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:
|
if user is None:
|
||||||
user = os.getenv("USER", None)
|
user = os.getenv("USER", None)
|
||||||
if not user:
|
if not user:
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import importlib
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from clan_cli.api import API
|
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.completions import add_dynamic_completer, complete_machines
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.vars._types import StoreBase
|
from clan_cli.vars._types import StoreBase
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ def secret_store(machine: Machine) -> StoreBase:
|
|||||||
|
|
||||||
@API.register
|
@API.register
|
||||||
def get_vars(base_dir: str, machine_name: str) -> list[Var]:
|
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)
|
pub_store = public_store(machine)
|
||||||
sec_store = secret_store(machine)
|
sec_store = secret_store(machine)
|
||||||
all_vars = []
|
all_vars = []
|
||||||
@@ -61,7 +61,7 @@ def _get_previous_value(
|
|||||||
|
|
||||||
@API.register
|
@API.register
|
||||||
def get_generators(base_dir: str, machine_name: str) -> list[Generator]:
|
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
|
generators: list[Generator] = machine.vars_generators
|
||||||
for generator in generators:
|
for generator in generators:
|
||||||
for prompt in generator.prompts:
|
for prompt in generator.prompts:
|
||||||
@@ -76,7 +76,7 @@ def get_generators(base_dir: str, machine_name: str) -> list[Generator]:
|
|||||||
def set_prompts(
|
def set_prompts(
|
||||||
base_dir: str, machine_name: str, updates: list[GeneratorUpdate]
|
base_dir: str, machine_name: str, updates: list[GeneratorUpdate]
|
||||||
) -> None:
|
) -> None:
|
||||||
machine = Machine(name=machine_name, flake=FlakeId(base_dir))
|
machine = Machine(name=machine_name, flake=Flake(base_dir))
|
||||||
for update in updates:
|
for update in updates:
|
||||||
for generator in machine.vars_generators:
|
for generator in machine.vars_generators:
|
||||||
if generator.name == update.generator:
|
if generator.name == update.generator:
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class FactStore(StoreBase):
|
|||||||
var: Var,
|
var: Var,
|
||||||
value: bytes,
|
value: bytes,
|
||||||
) -> Path | None:
|
) -> 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}"
|
msg = f"in_flake fact storage is only supported for local flakes: {self.machine.flake}"
|
||||||
raise ClanError(msg)
|
raise ClanError(msg)
|
||||||
folder = self.directory(generator, var.name)
|
folder = self.directory(generator, var.name)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class FactStore(StoreBase):
|
|||||||
def __init__(self, machine: Machine) -> None:
|
def __init__(self, machine: Machine) -> None:
|
||||||
self.machine = machine
|
self.machine = machine
|
||||||
self.works_remotely = False
|
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}")
|
machine.debug(f"FactStore initialized with dir {self.dir}")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class SecretStore(StoreBase):
|
|||||||
|
|
||||||
def __init__(self, machine: Machine) -> None:
|
def __init__(self, machine: Machine) -> None:
|
||||||
self.machine = machine
|
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)
|
self.dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import argparse
|
|||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.completions import add_dynamic_completer, complete_machines
|
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.git import commit_files
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.vars.get import get_var
|
from clan_cli.vars.get import get_var
|
||||||
@@ -15,9 +15,7 @@ from .prompt import ask
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def set_var(
|
def set_var(machine: str | Machine, var: str | Var, value: bytes, flake: Flake) -> None:
|
||||||
machine: str | Machine, var: str | Var, value: bytes, flake: FlakeId
|
|
||||||
) -> None:
|
|
||||||
if isinstance(machine, str):
|
if isinstance(machine, str):
|
||||||
_machine = Machine(name=machine, flake=flake)
|
_machine = Machine(name=machine, flake=flake)
|
||||||
else:
|
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)
|
var = get_var(str(flake.path), machine, var_id)
|
||||||
if sys.stdin.isatty():
|
if sys.stdin.isatty():
|
||||||
new_value = ask(
|
new_value = ask(
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ from dataclasses import dataclass
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.completions import add_dynamic_completer, complete_machines
|
from clan_cli.completions import add_dynamic_completer, complete_machines
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
|
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ class WaypipeConfig:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class VmConfig:
|
class VmConfig:
|
||||||
machine_name: str
|
machine_name: str
|
||||||
flake_url: FlakeId
|
flake_url: Flake
|
||||||
|
|
||||||
cores: int
|
cores: int
|
||||||
memory_size: int
|
memory_size: int
|
||||||
@@ -43,7 +43,7 @@ class VmConfig:
|
|||||||
def from_json(cls: type["VmConfig"], data: dict[str, Any]) -> "VmConfig":
|
def from_json(cls: type["VmConfig"], data: dict[str, Any]) -> "VmConfig":
|
||||||
return cls(
|
return cls(
|
||||||
machine_name=data["machine_name"],
|
machine_name=data["machine_name"],
|
||||||
flake_url=FlakeId.from_json(data["flake_url"]),
|
flake_url=Flake.from_json(data["flake_url"]),
|
||||||
cores=data["cores"],
|
cores=data["cores"],
|
||||||
memory_size=data["memory_size"],
|
memory_size=data["memory_size"],
|
||||||
graphics=data["graphics"],
|
graphics=data["graphics"],
|
||||||
@@ -64,13 +64,13 @@ def inspect_vm(machine: Machine) -> VmConfig:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class InspectOptions:
|
class InspectOptions:
|
||||||
machine: str
|
machine: str
|
||||||
flake: FlakeId
|
flake: Flake
|
||||||
|
|
||||||
|
|
||||||
def inspect_command(args: argparse.Namespace) -> None:
|
def inspect_command(args: argparse.Namespace) -> None:
|
||||||
inspect_options = InspectOptions(
|
inspect_options = InspectOptions(
|
||||||
machine=args.machine,
|
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)
|
machine = Machine(inspect_options.machine, inspect_options.flake)
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ def spawn_vm(
|
|||||||
# 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, 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)
|
state_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# specify socket files for qmp and qga
|
# specify socket files for qmp and qga
|
||||||
|
|||||||
@@ -121,7 +121,6 @@ def test_all_dataclasses() -> None:
|
|||||||
"api/__init__.py",
|
"api/__init__.py",
|
||||||
"cmd.py", # We don't want the UI to have access to the cmd module anyway
|
"cmd.py", # We don't want the UI to have access to the cmd module anyway
|
||||||
"async_run.py", # We don't want the UI to have access to the async_run module anyway
|
"async_run.py", # We don't want the UI to have access to the async_run module anyway
|
||||||
"flake.py", # Not compatible yet with the UI, unclear semantics, maybe it's just an internal thing
|
|
||||||
]
|
]
|
||||||
|
|
||||||
cli_path = Path("clan_cli").resolve()
|
cli_path = Path("clan_cli").resolve()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from clan_cli.clan_uri import FlakeId
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.locked_open import locked_open
|
from clan_cli.locked_open import locked_open
|
||||||
from clan_cli.templates import get_clan_nix_attrset
|
from clan_cli.templates import get_clan_nix_attrset
|
||||||
from fixtures_flakes import FlakeForTest
|
from fixtures_flakes import FlakeForTest
|
||||||
@@ -26,7 +26,7 @@ def nix_attr_tester(
|
|||||||
test_number: int,
|
test_number: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
write_clan_attr(injected, test_flake)
|
write_clan_attr(injected, test_flake)
|
||||||
nix_attrset = get_clan_nix_attrset(FlakeId(str(test_flake.path)))
|
nix_attrset = get_clan_nix_attrset(Flake(str(test_flake.path)))
|
||||||
|
|
||||||
assert json.dumps(nix_attrset, indent=2) == json.dumps(expected, indent=2)
|
assert json.dumps(nix_attrset, indent=2) == json.dumps(expected, indent=2)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from tempfile import TemporaryDirectory
|
||||||
|
|
||||||
from clan_cli.clan_uri import ClanURI
|
from clan_cli.clan_uri import ClanURI
|
||||||
|
|
||||||
@@ -15,26 +16,28 @@ def test_get_url() -> None:
|
|||||||
assert uri.get_url() == "/home/user/Downloads"
|
assert uri.get_url() == "/home/user/Downloads"
|
||||||
|
|
||||||
uri = ClanURI.from_str("clan://file:///home/user/Downloads")
|
uri = ClanURI.from_str("clan://file:///home/user/Downloads")
|
||||||
assert uri.get_url() == "/home/user/Downloads"
|
assert uri.get_url() == "file:///home/user/Downloads"
|
||||||
|
|
||||||
|
|
||||||
def test_firefox_strip_uri() -> None:
|
def test_firefox_strip_uri() -> None:
|
||||||
uri = ClanURI.from_str("clan://https//git.clan.lol/clan/democlan")
|
|
||||||
assert uri.get_url() == "https://git.clan.lol/clan/democlan"
|
|
||||||
uri = ClanURI.from_str("clan://git+https//git.clan.lol/clan/democlan.git")
|
uri = ClanURI.from_str("clan://git+https//git.clan.lol/clan/democlan.git")
|
||||||
assert uri.get_url() == "git+https://git.clan.lol/clan/democlan.git"
|
assert uri.get_url() == "git+https://git.clan.lol/clan/democlan.git"
|
||||||
|
|
||||||
|
|
||||||
def test_local_uri() -> None:
|
def test_local_uri() -> None:
|
||||||
# Create a ClanURI object from a local URI
|
with TemporaryDirectory(prefix="clan_test") as tempdir:
|
||||||
uri = ClanURI.from_str("clan://file:///home/user/Downloads")
|
flake_nix = Path(tempdir) / "flake.nix"
|
||||||
assert uri.flake.path == Path("/home/user/Downloads")
|
flake_nix.write_text("outputs = _: {}")
|
||||||
|
|
||||||
|
# Create a ClanURI object from a local URI
|
||||||
|
uri = ClanURI.from_str(f"clan://file://{tempdir}")
|
||||||
|
assert uri.flake.path == Path(tempdir)
|
||||||
|
|
||||||
|
|
||||||
def test_is_remote() -> None:
|
def test_is_remote() -> None:
|
||||||
# Create a ClanURI object from a remote URI
|
# Create a ClanURI object from a remote URI
|
||||||
uri = ClanURI.from_str("clan://https://example.com")
|
uri = ClanURI.from_str("clan://https://example.com")
|
||||||
assert uri.flake.url == "https://example.com"
|
assert uri.flake.identifier == "https://example.com"
|
||||||
|
|
||||||
|
|
||||||
def test_direct_local_path() -> None:
|
def test_direct_local_path() -> None:
|
||||||
@@ -54,35 +57,35 @@ def test_remote_with_clanparams() -> None:
|
|||||||
uri = ClanURI.from_str("clan://https://example.com")
|
uri = ClanURI.from_str("clan://https://example.com")
|
||||||
|
|
||||||
assert uri.machine_name == "defaultVM"
|
assert uri.machine_name == "defaultVM"
|
||||||
assert uri.flake.url == "https://example.com"
|
assert uri.flake.identifier == "https://example.com"
|
||||||
|
|
||||||
|
|
||||||
def test_from_str_remote() -> None:
|
def test_from_str_remote() -> None:
|
||||||
uri = ClanURI.from_str(url="https://example.com", machine_name="myVM")
|
uri = ClanURI.from_str(url="https://example.com", machine_name="myVM")
|
||||||
assert uri.get_url() == "https://example.com"
|
assert uri.get_url() == "https://example.com"
|
||||||
assert uri.machine_name == "myVM"
|
assert uri.machine_name == "myVM"
|
||||||
assert uri.flake.url == "https://example.com"
|
assert uri.flake.identifier == "https://example.com"
|
||||||
|
|
||||||
|
|
||||||
def test_from_str_local() -> None:
|
def test_from_str_local() -> None:
|
||||||
uri = ClanURI.from_str(url="~/Projects/democlan", machine_name="myVM")
|
with TemporaryDirectory(prefix="clan_test") as tempdir:
|
||||||
assert uri.get_url().endswith("/Projects/democlan")
|
flake_nix = Path(tempdir) / "flake.nix"
|
||||||
assert uri.machine_name == "myVM"
|
flake_nix.write_text("outputs = _: {}")
|
||||||
assert uri.flake.is_local()
|
|
||||||
assert str(uri.flake).endswith("/Projects/democlan") # type: ignore
|
uri = ClanURI.from_str(url=tempdir, machine_name="myVM")
|
||||||
|
assert uri.get_url().endswith(tempdir)
|
||||||
|
assert uri.machine_name == "myVM"
|
||||||
|
assert uri.flake.is_local
|
||||||
|
assert str(uri.flake).endswith(tempdir) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def test_from_str_local_no_machine() -> None:
|
def test_from_str_local_no_machine() -> None:
|
||||||
uri = ClanURI.from_str("~/Projects/democlan")
|
with TemporaryDirectory(prefix="clan_test") as tempdir:
|
||||||
assert uri.get_url().endswith("/Projects/democlan")
|
flake_nix = Path(tempdir) / "flake.nix"
|
||||||
assert uri.machine_name == "defaultVM"
|
flake_nix.write_text("outputs = _: {}")
|
||||||
assert uri.flake.is_local()
|
|
||||||
assert str(uri.flake).endswith("/Projects/democlan") # type: ignore
|
|
||||||
|
|
||||||
|
uri = ClanURI.from_str(tempdir)
|
||||||
def test_from_str_local_no_machine2() -> None:
|
assert uri.get_url().endswith(tempdir)
|
||||||
uri = ClanURI.from_str("~/Projects/democlan#syncthing-peer1")
|
assert uri.machine_name == "defaultVM"
|
||||||
assert uri.get_url().endswith("/Projects/democlan")
|
assert uri.flake.is_local
|
||||||
assert uri.machine_name == "syncthing-peer1"
|
assert str(uri.flake).endswith(tempdir) # type: ignore
|
||||||
assert uri.flake.is_local()
|
|
||||||
assert str(uri.flake).endswith("/Projects/democlan") # type: ignore
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ def test_nested_nullable() -> None:
|
|||||||
data = {
|
data = {
|
||||||
"machine": {
|
"machine": {
|
||||||
"name": "flash-installer",
|
"name": "flash-installer",
|
||||||
"flake": {"loc": "git+https://git.clan.lol/clan/clan-core"},
|
"flake": {"identifier": "git+https://git.clan.lol/clan/clan-core"},
|
||||||
},
|
},
|
||||||
"mode": "format",
|
"mode": "format",
|
||||||
"disks": {"main": "/dev/sda"},
|
"disks": {"main": "/dev/sda"},
|
||||||
@@ -96,7 +96,7 @@ def test_nested_nullable() -> None:
|
|||||||
expected = FlashOptions(
|
expected = FlashOptions(
|
||||||
machine=machines.Machine(
|
machine=machines.Machine(
|
||||||
name="flash-installer",
|
name="flash-installer",
|
||||||
flake=machines.FlakeId("git+https://git.clan.lol/clan/clan-core"),
|
flake=machines.Flake("git+https://git.clan.lol/clan/clan-core"),
|
||||||
),
|
),
|
||||||
mode="format",
|
mode="format",
|
||||||
disks={"main": "/dev/sda"},
|
disks={"main": "/dev/sda"},
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
# (subdir / ".clan-flake").touch()
|
# (subdir / ".clan-flake").touch()
|
||||||
# assert _get_clan_flake_toplevel() == subdir
|
# assert _get_clan_flake_toplevel() == subdir
|
||||||
|
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.dirs import clan_key_safe, vm_state_dir
|
from clan_cli.dirs import clan_key_safe, vm_state_dir
|
||||||
|
|
||||||
|
|
||||||
@@ -25,12 +24,12 @@ def test_clan_key_safe() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_vm_state_dir_identity() -> None:
|
def test_vm_state_dir_identity() -> None:
|
||||||
dir1 = vm_state_dir(FlakeId("https://some.clan"), "vm1")
|
dir1 = vm_state_dir("https://some.clan", "vm1")
|
||||||
dir2 = vm_state_dir(FlakeId("https://some.clan"), "vm1")
|
dir2 = vm_state_dir("https://some.clan", "vm1")
|
||||||
assert str(dir1) == str(dir2)
|
assert str(dir1) == str(dir2)
|
||||||
|
|
||||||
|
|
||||||
def test_vm_state_dir_no_collision() -> None:
|
def test_vm_state_dir_no_collision() -> None:
|
||||||
dir1 = vm_state_dir(FlakeId("/foo/bar"), "vm1")
|
dir1 = vm_state_dir("/foo/bar", "vm1")
|
||||||
dir2 = vm_state_dir(FlakeId("https://some.clan"), "vm1")
|
dir2 = vm_state_dir("https://some.clan", "vm1")
|
||||||
assert str(dir1) != str(dir2)
|
assert str(dir1) != str(dir2)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from clan_cli.api.modules import list_modules
|
from clan_cli.api.modules import list_modules
|
||||||
from clan_cli.clan_uri import FlakeId
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.inventory import (
|
from clan_cli.inventory import (
|
||||||
Inventory,
|
Inventory,
|
||||||
Machine,
|
Machine,
|
||||||
@@ -56,7 +56,7 @@ def test_add_module_to_inventory(
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
opts = CreateOptions(
|
opts = CreateOptions(
|
||||||
clan_dir=FlakeId(str(base_path)),
|
clan_dir=Flake(str(base_path)),
|
||||||
machine=Machine(name="machine1", tags=[], deploy=MachineDeploy()),
|
machine=Machine(name="machine1", tags=[], deploy=MachineDeploy()),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ def test_add_module_to_inventory(
|
|||||||
cli.run(cmd)
|
cli.run(cmd)
|
||||||
|
|
||||||
machine = MachineMachine(
|
machine = MachineMachine(
|
||||||
name="machine1", flake=FlakeId(str(test_flake_with_core.path))
|
name="machine1", flake=Flake(str(test_flake_with_core.path))
|
||||||
)
|
)
|
||||||
|
|
||||||
generator = None
|
generator = None
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import ipaddress
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.facts.secret_modules.sops import SecretStore
|
from clan_cli.facts.secret_modules.sops import SecretStore
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.machines.facts import machine_get_fact
|
from clan_cli.machines.facts import machine_get_fact
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.secrets.folders import sops_secrets_folder
|
from clan_cli.secrets.folders import sops_secrets_folder
|
||||||
@@ -48,7 +48,7 @@ def test_generate_secret(
|
|||||||
cmd = ["facts", "generate", "--flake", str(test_flake_with_core.path), "vm1"]
|
cmd = ["facts", "generate", "--flake", str(test_flake_with_core.path), "vm1"]
|
||||||
cli.run(cmd)
|
cli.run(cmd)
|
||||||
store1 = SecretStore(
|
store1 = SecretStore(
|
||||||
Machine(name="vm1", flake=FlakeId(str(test_flake_with_core.path)))
|
Machine(name="vm1", flake=Flake(str(test_flake_with_core.path)))
|
||||||
)
|
)
|
||||||
|
|
||||||
assert store1.exists("", "age.key")
|
assert store1.exists("", "age.key")
|
||||||
@@ -78,7 +78,7 @@ def test_generate_secret(
|
|||||||
).exists()
|
).exists()
|
||||||
|
|
||||||
store2 = SecretStore(
|
store2 = SecretStore(
|
||||||
Machine(name="vm2", flake=FlakeId(str(test_flake_with_core.path)))
|
Machine(name="vm2", flake=Flake(str(test_flake_with_core.path)))
|
||||||
)
|
)
|
||||||
|
|
||||||
# Should not exist clan facts generate
|
# Should not exist clan facts generate
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import subprocess
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.facts.secret_modules.password_store import SecretStore
|
from clan_cli.facts.secret_modules.password_store import SecretStore
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.machines.facts import machine_get_fact
|
from clan_cli.machines.facts import machine_get_fact
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.nix import nix_shell
|
from clan_cli.nix import nix_shell
|
||||||
@@ -68,7 +68,7 @@ def test_upload_secret(
|
|||||||
)
|
)
|
||||||
cli.run(["facts", "generate", "vm1", "--flake", str(flake.path)])
|
cli.run(["facts", "generate", "vm1", "--flake", str(flake.path)])
|
||||||
|
|
||||||
store = SecretStore(Machine(name="vm1", flake=FlakeId(str(flake.path))))
|
store = SecretStore(Machine(name="vm1", flake=Flake(str(flake.path))))
|
||||||
|
|
||||||
network_id = machine_get_fact(flake.path, "vm1", "zerotier-network-id")
|
network_id = machine_get_fact(flake.path, "vm1", "zerotier-network-id")
|
||||||
assert len(network_id) == 16
|
assert len(network_id) == 16
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from age_keys import SopsSetup
|
from age_keys import SopsSetup
|
||||||
from clan_cli.clan_uri import FlakeId
|
|
||||||
from clan_cli.errors import ClanError
|
from clan_cli.errors import ClanError
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.nix import nix_eval, run
|
from clan_cli.nix import nix_eval, run
|
||||||
from clan_cli.vars.check import check_vars
|
from clan_cli.vars.check import check_vars
|
||||||
@@ -138,7 +138,7 @@ def test_generate_public_and_secret_vars(
|
|||||||
monkeypatch.chdir(flake.path)
|
monkeypatch.chdir(flake.path)
|
||||||
sops_setup.init()
|
sops_setup.init()
|
||||||
|
|
||||||
machine = Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
machine = Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
assert not check_vars(machine)
|
assert not check_vars(machine)
|
||||||
vars_text = stringify_all_vars(machine)
|
vars_text = stringify_all_vars(machine)
|
||||||
assert "my_generator/my_value: <not set>" in vars_text
|
assert "my_generator/my_value: <not set>" in vars_text
|
||||||
@@ -184,11 +184,11 @@ def test_generate_public_and_secret_vars(
|
|||||||
)
|
)
|
||||||
vars_text = stringify_all_vars(machine)
|
vars_text = stringify_all_vars(machine)
|
||||||
in_repo_store = in_repo.FactStore(
|
in_repo_store = in_repo.FactStore(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert not in_repo_store.exists(Generator("my_generator"), "my_secret")
|
assert not in_repo_store.exists(Generator("my_generator"), "my_secret")
|
||||||
sops_store = sops.SecretStore(
|
sops_store = sops.SecretStore(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert sops_store.exists(Generator("my_generator"), "my_secret")
|
assert sops_store.exists(Generator("my_generator"), "my_secret")
|
||||||
assert sops_store.get(Generator("my_generator"), "my_secret").decode() == "secret"
|
assert sops_store.get(Generator("my_generator"), "my_secret").decode() == "secret"
|
||||||
@@ -246,11 +246,11 @@ def test_generate_secret_var_sops_with_default_group(
|
|||||||
cli.run(["secrets", "groups", "add-user", "my_group", sops_setup.user])
|
cli.run(["secrets", "groups", "add-user", "my_group", sops_setup.user])
|
||||||
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
|
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
|
||||||
in_repo_store = in_repo.FactStore(
|
in_repo_store = in_repo.FactStore(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert not in_repo_store.exists(Generator("my_generator"), "my_secret")
|
assert not in_repo_store.exists(Generator("my_generator"), "my_secret")
|
||||||
sops_store = sops.SecretStore(
|
sops_store = sops.SecretStore(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert sops_store.exists(Generator("my_generator"), "my_secret")
|
assert sops_store.exists(Generator("my_generator"), "my_secret")
|
||||||
assert sops_store.get(Generator("my_generator"), "my_secret").decode() == "hello\n"
|
assert sops_store.get(Generator("my_generator"), "my_secret").decode() == "hello\n"
|
||||||
@@ -317,8 +317,8 @@ def test_generated_shared_secret_sops(
|
|||||||
flake.refresh()
|
flake.refresh()
|
||||||
monkeypatch.chdir(flake.path)
|
monkeypatch.chdir(flake.path)
|
||||||
sops_setup.init()
|
sops_setup.init()
|
||||||
machine1 = Machine(name="machine1", flake=FlakeId(str(flake.path)))
|
machine1 = Machine(name="machine1", flake=Flake(str(flake.path)))
|
||||||
machine2 = Machine(name="machine2", flake=FlakeId(str(flake.path)))
|
machine2 = Machine(name="machine2", flake=Flake(str(flake.path)))
|
||||||
cli.run(["vars", "generate", "--flake", str(flake.path), "machine1"])
|
cli.run(["vars", "generate", "--flake", str(flake.path), "machine1"])
|
||||||
assert check_vars(machine1)
|
assert check_vars(machine1)
|
||||||
cli.run(["vars", "generate", "--flake", str(flake.path), "machine2"])
|
cli.run(["vars", "generate", "--flake", str(flake.path), "machine2"])
|
||||||
@@ -368,12 +368,12 @@ def test_generate_secret_var_password_store(
|
|||||||
shutil.copytree(test_root / "data" / "password-store", password_store_dir)
|
shutil.copytree(test_root / "data" / "password-store", password_store_dir)
|
||||||
monkeypatch.setenv("PASSWORD_STORE_DIR", str(flake.path / "pass"))
|
monkeypatch.setenv("PASSWORD_STORE_DIR", str(flake.path / "pass"))
|
||||||
|
|
||||||
machine = Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
machine = Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
assert not check_vars(machine)
|
assert not check_vars(machine)
|
||||||
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
|
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
|
||||||
assert check_vars(machine)
|
assert check_vars(machine)
|
||||||
store = password_store.SecretStore(
|
store = password_store.SecretStore(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert store.exists(Generator("my_generator", share=False, files=[]), "my_secret")
|
assert store.exists(Generator("my_generator", share=False, files=[]), "my_secret")
|
||||||
assert not store.exists(
|
assert not store.exists(
|
||||||
@@ -432,10 +432,10 @@ def test_generate_secret_for_multiple_machines(
|
|||||||
cli.run(["vars", "generate", "--flake", str(flake.path)])
|
cli.run(["vars", "generate", "--flake", str(flake.path)])
|
||||||
# check if public vars have been created correctly
|
# check if public vars have been created correctly
|
||||||
in_repo_store1 = in_repo.FactStore(
|
in_repo_store1 = in_repo.FactStore(
|
||||||
Machine(name="machine1", flake=FlakeId(str(flake.path)))
|
Machine(name="machine1", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
in_repo_store2 = in_repo.FactStore(
|
in_repo_store2 = in_repo.FactStore(
|
||||||
Machine(name="machine2", flake=FlakeId(str(flake.path)))
|
Machine(name="machine2", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert in_repo_store1.exists(Generator("my_generator"), "my_value")
|
assert in_repo_store1.exists(Generator("my_generator"), "my_value")
|
||||||
assert in_repo_store2.exists(Generator("my_generator"), "my_value")
|
assert in_repo_store2.exists(Generator("my_generator"), "my_value")
|
||||||
@@ -449,10 +449,10 @@ def test_generate_secret_for_multiple_machines(
|
|||||||
)
|
)
|
||||||
# check if secret vars have been created correctly
|
# check if secret vars have been created correctly
|
||||||
sops_store1 = sops.SecretStore(
|
sops_store1 = sops.SecretStore(
|
||||||
Machine(name="machine1", flake=FlakeId(str(flake.path)))
|
Machine(name="machine1", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
sops_store2 = sops.SecretStore(
|
sops_store2 = sops.SecretStore(
|
||||||
Machine(name="machine2", flake=FlakeId(str(flake.path)))
|
Machine(name="machine2", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert sops_store1.exists(Generator("my_generator"), "my_secret")
|
assert sops_store1.exists(Generator("my_generator"), "my_secret")
|
||||||
assert sops_store2.exists(Generator("my_generator"), "my_secret")
|
assert sops_store2.exists(Generator("my_generator"), "my_secret")
|
||||||
@@ -498,7 +498,7 @@ def test_prompt(
|
|||||||
)
|
)
|
||||||
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
|
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
|
||||||
in_repo_store = in_repo.FactStore(
|
in_repo_store = in_repo.FactStore(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert in_repo_store.exists(Generator("my_generator"), "line_value")
|
assert in_repo_store.exists(Generator("my_generator"), "line_value")
|
||||||
assert (
|
assert (
|
||||||
@@ -512,7 +512,7 @@ def test_prompt(
|
|||||||
== "my\nmultiline\ninput\n"
|
== "my\nmultiline\ninput\n"
|
||||||
)
|
)
|
||||||
sops_store = sops.SecretStore(
|
sops_store = sops.SecretStore(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert sops_store.exists(
|
assert sops_store.exists(
|
||||||
Generator(name="my_generator", share=False, files=[]), "prompt_persist"
|
Generator(name="my_generator", share=False, files=[]), "prompt_persist"
|
||||||
@@ -553,8 +553,8 @@ def test_multi_machine_shared_vars(
|
|||||||
flake.refresh()
|
flake.refresh()
|
||||||
monkeypatch.chdir(flake.path)
|
monkeypatch.chdir(flake.path)
|
||||||
sops_setup.init()
|
sops_setup.init()
|
||||||
machine1 = Machine(name="machine1", flake=FlakeId(str(flake.path)))
|
machine1 = Machine(name="machine1", flake=Flake(str(flake.path)))
|
||||||
machine2 = Machine(name="machine2", flake=FlakeId(str(flake.path)))
|
machine2 = Machine(name="machine2", flake=Flake(str(flake.path)))
|
||||||
sops_store_1 = sops.SecretStore(machine1)
|
sops_store_1 = sops.SecretStore(machine1)
|
||||||
sops_store_2 = sops.SecretStore(machine2)
|
sops_store_2 = sops.SecretStore(machine2)
|
||||||
in_repo_store_1 = in_repo.FactStore(machine1)
|
in_repo_store_1 = in_repo.FactStore(machine1)
|
||||||
@@ -616,7 +616,7 @@ def test_api_set_prompts(
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
machine = Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
machine = Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
store = in_repo.FactStore(machine)
|
store = in_repo.FactStore(machine)
|
||||||
assert store.exists(Generator("my_generator"), "prompt1")
|
assert store.exists(Generator("my_generator"), "prompt1")
|
||||||
assert store.get(Generator("my_generator"), "prompt1").decode() == "input1"
|
assert store.get(Generator("my_generator"), "prompt1").decode() == "input1"
|
||||||
@@ -663,7 +663,7 @@ def test_stdout_of_generate(
|
|||||||
# 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=FlakeId(str(flake.path))),
|
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
||||||
"my_generator",
|
"my_generator",
|
||||||
regenerate=False,
|
regenerate=False,
|
||||||
)
|
)
|
||||||
@@ -673,10 +673,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", FlakeId(str(flake.path)))
|
set_var("my_machine", "my_generator/my_value", b"world", Flake(str(flake.path)))
|
||||||
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=FlakeId(str(flake.path))),
|
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
||||||
"my_generator",
|
"my_generator",
|
||||||
regenerate=True,
|
regenerate=True,
|
||||||
)
|
)
|
||||||
@@ -687,7 +687,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=FlakeId(str(flake.path))),
|
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
||||||
"my_generator",
|
"my_generator",
|
||||||
regenerate=True,
|
regenerate=True,
|
||||||
)
|
)
|
||||||
@@ -696,7 +696,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=FlakeId(str(flake.path))),
|
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
||||||
"my_secret_generator",
|
"my_secret_generator",
|
||||||
regenerate=False,
|
regenerate=False,
|
||||||
)
|
)
|
||||||
@@ -707,11 +707,11 @@ def test_stdout_of_generate(
|
|||||||
"my_machine",
|
"my_machine",
|
||||||
"my_secret_generator/my_secret",
|
"my_secret_generator/my_secret",
|
||||||
b"world",
|
b"world",
|
||||||
FlakeId(str(flake.path)),
|
Flake(str(flake.path)),
|
||||||
)
|
)
|
||||||
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=FlakeId(str(flake.path))),
|
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
||||||
"my_secret_generator",
|
"my_secret_generator",
|
||||||
regenerate=True,
|
regenerate=True,
|
||||||
)
|
)
|
||||||
@@ -760,10 +760,10 @@ def test_migration(
|
|||||||
assert "Migrated var my_generator/my_value" in caplog.text
|
assert "Migrated var my_generator/my_value" in caplog.text
|
||||||
assert "Migrated secret var my_generator/my_secret" in caplog.text
|
assert "Migrated secret var my_generator/my_secret" in caplog.text
|
||||||
in_repo_store = in_repo.FactStore(
|
in_repo_store = in_repo.FactStore(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
sops_store = sops.SecretStore(
|
sops_store = sops.SecretStore(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
)
|
)
|
||||||
assert in_repo_store.exists(Generator("my_generator"), "my_value")
|
assert in_repo_store.exists(Generator("my_generator"), "my_value")
|
||||||
assert in_repo_store.get(Generator("my_generator"), "my_value").decode() == "hello"
|
assert in_repo_store.get(Generator("my_generator"), "my_value").decode() == "hello"
|
||||||
@@ -800,7 +800,7 @@ def test_fails_when_files_are_left_from_other_backend(
|
|||||||
sops_setup.init()
|
sops_setup.init()
|
||||||
for generator in ["my_secret_generator", "my_value_generator"]:
|
for generator in ["my_secret_generator", "my_value_generator"]:
|
||||||
generate_vars_for_machine(
|
generate_vars_for_machine(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path))),
|
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
||||||
generator,
|
generator,
|
||||||
regenerate=False,
|
regenerate=False,
|
||||||
)
|
)
|
||||||
@@ -817,36 +817,33 @@ def test_fails_when_files_are_left_from_other_backend(
|
|||||||
if generator == "my_secret_generator":
|
if generator == "my_secret_generator":
|
||||||
with pytest.raises(ClanError):
|
with pytest.raises(ClanError):
|
||||||
generate_vars_for_machine(
|
generate_vars_for_machine(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path))),
|
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
||||||
generator,
|
generator,
|
||||||
regenerate=False,
|
regenerate=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
generate_vars_for_machine(
|
generate_vars_for_machine(
|
||||||
Machine(name="my_machine", flake=FlakeId(str(flake.path))),
|
Machine(name="my_machine", flake=Flake(str(flake.path))),
|
||||||
generator,
|
generator,
|
||||||
regenerate=False,
|
regenerate=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.with_core
|
@pytest.mark.with_core
|
||||||
def test_keygen(
|
def test_keygen(monkeypatch: pytest.MonkeyPatch, flake: ClanFlake) -> None:
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch.chdir(flake.path)
|
||||||
temporary_home: Path,
|
cli.run(["vars", "keygen", "--flake", str(flake.path), "--user", "user"])
|
||||||
) -> None:
|
|
||||||
monkeypatch.chdir(temporary_home)
|
|
||||||
cli.run(["vars", "keygen", "--flake", str(temporary_home), "--user", "user"])
|
|
||||||
# check public key exists
|
# check public key exists
|
||||||
assert (temporary_home / "sops" / "users" / "user").is_dir()
|
assert (flake.path / "sops" / "users" / "user").is_dir()
|
||||||
# check private key exists
|
# check private key exists
|
||||||
assert (temporary_home / ".config" / "sops" / "age" / "keys.txt").is_file()
|
assert (flake.temporary_home / ".config" / "sops" / "age" / "keys.txt").is_file()
|
||||||
# it should still work, even if the keys already exist
|
# it should still work, even if the keys already exist
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
shutil.rmtree(temporary_home / "sops" / "users" / "user")
|
shutil.rmtree(flake.path / "sops" / "users" / "user")
|
||||||
cli.run(["vars", "keygen", "--flake", str(temporary_home), "--user", "user"])
|
cli.run(["vars", "keygen", "--flake", str(flake.path), "--user", "user"])
|
||||||
# check public key exists
|
# check public key exists
|
||||||
assert (temporary_home / "sops" / "users" / "user").is_dir()
|
assert (flake.path / "sops" / "users" / "user").is_dir()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.with_core
|
@pytest.mark.with_core
|
||||||
@@ -862,7 +859,7 @@ def test_invalidation(
|
|||||||
flake.refresh()
|
flake.refresh()
|
||||||
monkeypatch.chdir(flake.path)
|
monkeypatch.chdir(flake.path)
|
||||||
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
|
cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"])
|
||||||
machine = Machine(name="my_machine", flake=FlakeId(str(flake.path)))
|
machine = Machine(name="my_machine", flake=Flake(str(flake.path)))
|
||||||
value1 = get_var(
|
value1 = get_var(
|
||||||
str(machine.flake.path), machine.name, "my_generator/my_value"
|
str(machine.flake.path), machine.name, "my_generator/my_value"
|
||||||
).printable_value
|
).printable_value
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from contextlib import ExitStack
|
|||||||
import pytest
|
import pytest
|
||||||
from age_keys import SopsSetup
|
from age_keys import SopsSetup
|
||||||
from clan_cli import cmd
|
from clan_cli import cmd
|
||||||
from clan_cli.clan_uri import FlakeId
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.nix import nix_eval, run
|
from clan_cli.nix import nix_eval, run
|
||||||
from clan_cli.vms.run import inspect_vm, spawn_vm
|
from clan_cli.vms.run import inspect_vm, spawn_vm
|
||||||
@@ -97,8 +97,8 @@ def test_vm_deployment(
|
|||||||
# run nix flake lock
|
# run nix flake lock
|
||||||
cmd.run(["nix", "flake", "lock"], cmd.RunOpts(cwd=flake.path))
|
cmd.run(["nix", "flake", "lock"], cmd.RunOpts(cwd=flake.path))
|
||||||
|
|
||||||
vm1_config = inspect_vm(machine=Machine("m1_machine", FlakeId(str(flake.path))))
|
vm1_config = inspect_vm(machine=Machine("m1_machine", Flake(str(flake.path))))
|
||||||
vm2_config = inspect_vm(machine=Machine("m2_machine", FlakeId(str(flake.path))))
|
vm2_config = inspect_vm(machine=Machine("m2_machine", Flake(str(flake.path))))
|
||||||
with ExitStack() as stack:
|
with ExitStack() as stack:
|
||||||
vm1 = stack.enter_context(spawn_vm(vm1_config, stdin=subprocess.DEVNULL))
|
vm1 = stack.enter_context(spawn_vm(vm1_config, stdin=subprocess.DEVNULL))
|
||||||
vm2 = stack.enter_context(spawn_vm(vm2_config, stdin=subprocess.DEVNULL))
|
vm2 = stack.enter_context(spawn_vm(vm2_config, stdin=subprocess.DEVNULL))
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from pathlib import Path
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from clan_cli.clan_uri import FlakeId
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
from clan_cli.vms.run import inspect_vm, spawn_vm
|
from clan_cli.vms.run import inspect_vm, spawn_vm
|
||||||
from fixtures_flakes import ClanFlake, FlakeForTest
|
from fixtures_flakes import ClanFlake, FlakeForTest
|
||||||
@@ -80,7 +80,7 @@ def test_vm_persistence(
|
|||||||
|
|
||||||
flake.refresh()
|
flake.refresh()
|
||||||
|
|
||||||
vm_config = inspect_vm(machine=Machine("my_machine", FlakeId(str(flake.path))))
|
vm_config = inspect_vm(machine=Machine("my_machine", Flake(str(flake.path))))
|
||||||
|
|
||||||
with spawn_vm(vm_config) as vm, vm.qga_connect() as qga:
|
with spawn_vm(vm_config) as vm, vm.qga_connect() as qga:
|
||||||
# create state via qmp command instead of systemd service
|
# create state via qmp command instead of systemd service
|
||||||
|
|||||||
@@ -147,20 +147,14 @@ class VMObject(GObject.Object):
|
|||||||
uri = ClanURI.from_str(
|
uri = ClanURI.from_str(
|
||||||
url=str(self.data.flake.flake_url), machine_name=self.data.flake.flake_attr
|
url=str(self.data.flake.flake_url), machine_name=self.data.flake.flake_attr
|
||||||
)
|
)
|
||||||
if uri.flake.is_local():
|
self.machine = Machine(
|
||||||
self.machine = Machine(
|
name=self.data.flake.flake_attr,
|
||||||
name=self.data.flake.flake_attr,
|
flake=uri.flake,
|
||||||
flake=uri.flake,
|
)
|
||||||
)
|
|
||||||
if uri.flake.is_remote():
|
|
||||||
self.machine = Machine(
|
|
||||||
name=self.data.flake.flake_attr,
|
|
||||||
flake=uri.flake,
|
|
||||||
)
|
|
||||||
assert self.machine is not None
|
assert self.machine is not None
|
||||||
|
|
||||||
state_dir = vm_state_dir(
|
state_dir = vm_state_dir(
|
||||||
flake_url=self.machine.flake, vm_name=self.machine.name
|
flake_url=self.machine.flake.identifier, vm_name=self.machine.name
|
||||||
)
|
)
|
||||||
self.qmp_wrap = QMPWrapper(state_dir)
|
self.qmp_wrap = QMPWrapper(state_dir)
|
||||||
assert self.machine is not None
|
assert self.machine is not None
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ from pathlib import Path
|
|||||||
from typing import Any, ClassVar
|
from typing import Any, ClassVar
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
from clan_cli.clan_uri import ClanURI, FlakeId
|
from clan_cli.clan_uri import ClanURI
|
||||||
|
from clan_cli.flake import Flake
|
||||||
from clan_cli.history.add import HistoryEntry
|
from clan_cli.history.add import HistoryEntry
|
||||||
from clan_cli.machines.machines import Machine
|
from clan_cli.machines.machines import Machine
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ class Emitter(GObject.GObject):
|
|||||||
|
|
||||||
class ClanStore:
|
class ClanStore:
|
||||||
_instance: "None | ClanStore" = None
|
_instance: "None | ClanStore" = None
|
||||||
_clan_store: GKVStore[FlakeId, VMStore]
|
_clan_store: GKVStore[Flake, VMStore]
|
||||||
|
|
||||||
_emitter: Emitter
|
_emitter: Emitter
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ class ClanStore:
|
|||||||
self.clan_store.register_on_change(on_clanstore_change)
|
self.clan_store.register_on_change(on_clanstore_change)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def clan_store(self) -> GKVStore[FlakeId, VMStore]:
|
def clan_store(self) -> GKVStore[Flake, VMStore]:
|
||||||
return self._clan_store
|
return self._clan_store
|
||||||
|
|
||||||
def create_vm_task(self, vm: HistoryEntry) -> bool:
|
def create_vm_task(self, vm: HistoryEntry) -> bool:
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
|
|||||||
machine: {
|
machine: {
|
||||||
name: name,
|
name: name,
|
||||||
flake: {
|
flake: {
|
||||||
loc: active_clan,
|
identifier: active_clan,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
no_reboot: true,
|
no_reboot: true,
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ export const Flash = () => {
|
|||||||
machine: {
|
machine: {
|
||||||
name: values.machine.devicePath,
|
name: values.machine.devicePath,
|
||||||
flake: {
|
flake: {
|
||||||
loc: values.machine.flake,
|
identifier: values.machine.flake,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mode: "format",
|
mode: "format",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function CreateMachine() {
|
|||||||
initialValues: {
|
initialValues: {
|
||||||
opts: {
|
opts: {
|
||||||
clan_dir: {
|
clan_dir: {
|
||||||
loc: activeURI() || "",
|
identifier: activeURI() || "",
|
||||||
},
|
},
|
||||||
machine: {
|
machine: {
|
||||||
tags: ["all"],
|
tags: ["all"],
|
||||||
@@ -49,7 +49,7 @@ export function CreateMachine() {
|
|||||||
opts: {
|
opts: {
|
||||||
...values.opts,
|
...values.opts,
|
||||||
clan_dir: {
|
clan_dir: {
|
||||||
loc: active_dir,
|
identifier: active_dir,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ const InstallMachine = (props: InstallMachineProps) => {
|
|||||||
machine: {
|
machine: {
|
||||||
name: props.name,
|
name: props.name,
|
||||||
flake: {
|
flake: {
|
||||||
loc: curr_uri,
|
identifier: curr_uri,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
target_host: target,
|
target_host: target,
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export const HWStep = (props: StepProps<HardwareValues>) => {
|
|||||||
setIsGenerating(true);
|
setIsGenerating(true);
|
||||||
const r = await callApi("generate_machine_hardware_info", {
|
const r = await callApi("generate_machine_hardware_info", {
|
||||||
opts: {
|
opts: {
|
||||||
flake: { loc: curr_uri },
|
flake: { identifier: curr_uri },
|
||||||
machine: props.machine_id,
|
machine: props.machine_id,
|
||||||
target_host: target,
|
target_host: target,
|
||||||
backend: "nixos-facter",
|
backend: "nixos-facter",
|
||||||
|
|||||||
Reference in New Issue
Block a user