Inventory: add load_eval method

This commit is contained in:
Johannes Kirschbauer
2024-07-23 11:31:34 +02:00
parent c6466f070e
commit 679fd914e0
7 changed files with 58 additions and 28 deletions

View File

@@ -6,7 +6,7 @@ from pathlib import Path
from clan_cli.cmd import run_no_stdout from clan_cli.cmd import run_no_stdout
from clan_cli.errors import ClanCmdError, ClanError from clan_cli.errors import ClanCmdError, ClanError
from clan_cli.inventory import Inventory, load_inventory from clan_cli.inventory import Inventory, load_inventory_json
from clan_cli.nix import nix_eval from clan_cli.nix import nix_eval
from . import API from . import API
@@ -152,4 +152,4 @@ def get_module_info(
@API.register @API.register
def get_inventory(base_path: str) -> Inventory: def get_inventory(base_path: str) -> Inventory:
return load_inventory(base_path) return load_inventory_json(base_path)

View File

@@ -6,7 +6,7 @@ from pathlib import Path
from clan_cli.api import API from clan_cli.api import API
from clan_cli.arg_actions import AppendOptionAction from clan_cli.arg_actions import AppendOptionAction
from clan_cli.inventory import Meta, load_inventory, save_inventory from clan_cli.inventory import Meta, load_inventory_json, save_inventory
from ..cmd import CmdOut, run from ..cmd import CmdOut, run
from ..errors import ClanError from ..errors import ClanError
@@ -89,7 +89,7 @@ def create_clan(options: CreateOptions) -> CreateClanResponse:
) )
# Write inventory.json file # Write inventory.json file
inventory = load_inventory(directory) inventory = load_inventory_json(directory)
if options.meta is not None: if options.meta is not None:
inventory.meta = options.meta inventory.meta = options.meta
# Persist creates a commit message for each change # Persist creates a commit message for each change

View File

@@ -1,7 +1,7 @@
from dataclasses import dataclass from dataclasses import dataclass
from clan_cli.api import API from clan_cli.api import API
from clan_cli.inventory import Meta, load_inventory, save_inventory from clan_cli.inventory import Meta, load_inventory_json, save_inventory
@dataclass @dataclass
@@ -12,7 +12,7 @@ class UpdateOptions:
@API.register @API.register
def update_clan_meta(options: UpdateOptions) -> Meta: def update_clan_meta(options: UpdateOptions) -> Meta:
inventory = load_inventory(options.directory) inventory = load_inventory_json(options.directory)
inventory.meta = options.meta inventory.meta = options.meta
save_inventory(inventory, options.directory, "Update clan metadata") save_inventory(inventory, options.directory, "Update clan metadata")

View File

@@ -1,3 +1,17 @@
"""
All read/write operations MUST use the inventory.
Machine data, clan data or service data can be accessed in a performant way.
This file exports stable classnames for static & dynamic type safety.
Utilize:
- load_inventory_eval: To load the actual inventory with nix declarations merged.
Operate on the returned inventory to make changes
- save_inventory: To persist changes.
"""
import dataclasses import dataclasses
import json import json
from dataclasses import fields, is_dataclass from dataclasses import fields, is_dataclass
@@ -8,6 +22,8 @@ from typing import Any, get_args, get_origin
from clan_cli.errors import ClanError from clan_cli.errors import ClanError
from clan_cli.git import commit_file from clan_cli.git import commit_file
from ..cmd import run_no_stdout
from ..nix import nix_eval
from .classes import ( from .classes import (
Inventory, Inventory,
Machine, Machine,
@@ -165,7 +181,35 @@ default_inventory = Inventory(
) )
def load_inventory( def load_inventory_eval(flake_dir: str | Path) -> Inventory:
"""
Loads the actual inventory.
After all merge operations with eventual nix code in buildClan.
Evaluates clanInternals.inventory with nix. Which is performant.
- Contains all clan metadata
- Contains all machines
- and more
"""
cmd = nix_eval(
[
f"{flake_dir}#clanInternals.inventory",
"--json",
]
)
proc = run_no_stdout(cmd)
try:
res = proc.stdout.strip()
data = json.loads(res)
inventory = from_dict(Inventory, data)
return inventory
except json.JSONDecodeError as e:
raise ClanError(f"Error decoding inventory from flake: {e}")
def load_inventory_json(
flake_dir: str | Path, default: Inventory = default_inventory flake_dir: str | Path, default: Inventory = default_inventory
) -> Inventory: ) -> Inventory:
""" """

View File

@@ -6,12 +6,12 @@ from ..clan_uri import FlakeId
from ..completions import add_dynamic_completer, complete_machines from ..completions import add_dynamic_completer, complete_machines
from ..dirs import specific_machine_dir from ..dirs import specific_machine_dir
from ..errors import ClanError from ..errors import ClanError
from ..inventory import load_inventory, save_inventory from ..inventory import load_inventory_json, save_inventory
@API.register @API.register
def delete_machine(flake: FlakeId, name: str) -> None: def delete_machine(flake: FlakeId, name: str) -> None:
inventory = load_inventory(flake.path) inventory = load_inventory_json(flake.path)
machine = inventory.machines.pop(name, None) machine = inventory.machines.pop(name, None)
if machine is None: if machine is None:

View File

@@ -1,31 +1,17 @@
import argparse import argparse
import json
import logging import logging
from pathlib import Path from pathlib import Path
from clan_cli.api import API from clan_cli.api import API
from clan_cli.inventory import Machine, from_dict from clan_cli.inventory import Machine, load_inventory_eval
from ..cmd import run_no_stdout
from ..nix import nix_eval
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@API.register @API.register
def list_machines(flake_url: str | Path, debug: bool = False) -> dict[str, Machine]: def list_machines(flake_url: str | Path, debug: bool = False) -> dict[str, Machine]:
cmd = nix_eval( inventory = load_inventory_eval(flake_url)
[ return inventory.machines
f"{flake_url}#clanInternals.inventory.machines",
"--json",
]
)
proc = run_no_stdout(cmd)
res = proc.stdout.strip()
data = {name: from_dict(Machine, v) for name, v in json.loads(res).items()}
return data
def list_command(args: argparse.Namespace) -> None: def list_command(args: argparse.Namespace) -> None:

View File

@@ -14,7 +14,7 @@ from clan_cli.inventory import (
ServiceBorgbackupRoleClient, ServiceBorgbackupRoleClient,
ServiceBorgbackupRoleServer, ServiceBorgbackupRoleServer,
ServiceMeta, ServiceMeta,
load_inventory, load_inventory_json,
save_inventory, save_inventory,
) )
from clan_cli.machines.create import create_machine from clan_cli.machines.create import create_machine
@@ -67,7 +67,7 @@ def test_add_module_to_inventory(
), ),
) )
inventory = load_inventory(base_path) inventory = load_inventory_json(base_path)
inventory.services.borgbackup = { inventory.services.borgbackup = {
"borg1": ServiceBorgbackup( "borg1": ServiceBorgbackup(