API/list_service_instances: add module metadata (#5023)
@hsjobeki Co-authored-by: Johannes Kirschbauer <hsjobeki@gmail.com> Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5023
This commit is contained in:
@@ -78,8 +78,9 @@ const SelectService = () => {
|
||||
instances: Object.entries(serviceInstancesQuery.data)
|
||||
.filter(
|
||||
([name, i]) =>
|
||||
i.module?.name === m.module.name &&
|
||||
(!i.module?.input || i.module?.input === m.module.input),
|
||||
i.module.module.name === m.module.name &&
|
||||
(!i.module.module.input ||
|
||||
i.module.module.input === m.module.input),
|
||||
)
|
||||
.map(([name, _]) => name),
|
||||
})),
|
||||
|
||||
@@ -162,6 +162,10 @@ def list_service_modules(flake: Flake) -> list[Module]:
|
||||
"""Show information about a module"""
|
||||
modules = flake.select("clanInternals.inventoryClass.modulesPerSource")
|
||||
|
||||
if "clan-core" not in modules:
|
||||
msg = "Cannot find 'clan-core' input in the flake. Make sure your clan-core input is named 'clan-core'"
|
||||
raise ClanError(msg)
|
||||
|
||||
res: list[Module] = []
|
||||
for input_name, module_set in modules.items():
|
||||
for module_name, module_info in module_set.items():
|
||||
@@ -331,11 +335,34 @@ def create_service_instance(
|
||||
)
|
||||
|
||||
|
||||
class InventoryInstanceInfo(TypedDict):
|
||||
module: Module
|
||||
roles: InventoryInstanceRolesType
|
||||
|
||||
|
||||
@API.register
|
||||
def list_service_instances(
|
||||
flake: Flake,
|
||||
) -> dict[str, InventoryInstance]:
|
||||
"""Show information about a module"""
|
||||
def list_service_instances(flake: Flake) -> dict[str, InventoryInstanceInfo]:
|
||||
"""Returns all currently present service instances including their full configuration"""
|
||||
inventory_store = InventoryStore(flake)
|
||||
inventory = inventory_store.read()
|
||||
return inventory.get("instances", {})
|
||||
service_modules = {
|
||||
(mod["module"]["name"], mod["module"].get("input", "clan-core")): mod
|
||||
for mod in list_service_modules(flake)
|
||||
}
|
||||
instances = inventory.get("instances", {})
|
||||
res: dict[str, InventoryInstanceInfo] = {}
|
||||
for instance_name, instance in instances.items():
|
||||
module_key = (
|
||||
instance.get("module", {})["name"],
|
||||
instance.get("module", {}).get("input")
|
||||
or "clan-core", # Replace None (or falsey) with "clan-core"
|
||||
)
|
||||
module = service_modules.get(module_key)
|
||||
if module is None:
|
||||
msg = f"Module '{module_key}' for instance '{instance_name}' not found"
|
||||
raise ClanError(msg)
|
||||
res[instance_name] = InventoryInstanceInfo(
|
||||
module=module,
|
||||
roles=instance.get("roles", {}),
|
||||
)
|
||||
return res
|
||||
|
||||
35
pkgs/clan-cli/clan_lib/services/modules_test.py
Normal file
35
pkgs/clan-cli/clan_lib/services/modules_test.py
Normal file
@@ -0,0 +1,35 @@
|
||||
from collections.abc import Callable
|
||||
|
||||
import pytest
|
||||
from clan_cli.tests.fixtures_flakes import nested_dict
|
||||
from clan_lib.flake.flake import Flake
|
||||
from clan_lib.services.modules import list_service_instances
|
||||
|
||||
|
||||
@pytest.mark.with_core
|
||||
def test_list_service_instances(
|
||||
clan_flake: Callable[..., Flake],
|
||||
) -> None:
|
||||
config = nested_dict()
|
||||
config["inventory"]["machines"]["alice"] = {}
|
||||
config["inventory"]["machines"]["bob"] = {}
|
||||
# implicit module selection (defaults to clan-core/admin)
|
||||
config["inventory"]["instances"]["admin"]["roles"]["default"]["tags"]["all"] = {}
|
||||
# explicit module selection
|
||||
config["inventory"]["instances"]["my-sshd"]["module"]["input"] = "clan-core"
|
||||
config["inventory"]["instances"]["my-sshd"]["module"]["name"] = "sshd"
|
||||
# input = null
|
||||
config["inventory"]["instances"]["my-sshd-2"]["module"]["input"] = None
|
||||
config["inventory"]["instances"]["my-sshd-2"]["module"]["name"] = "sshd"
|
||||
# external input
|
||||
flake = clan_flake(config)
|
||||
|
||||
instances = list_service_instances(flake)
|
||||
|
||||
assert list(instances.keys()) == ["admin", "my-sshd", "my-sshd-2"]
|
||||
assert instances["admin"]["module"]["module"].get("input") == "clan-core"
|
||||
assert instances["admin"]["module"]["module"].get("name") == "admin"
|
||||
assert instances["my-sshd"]["module"]["module"].get("input") == "clan-core"
|
||||
assert instances["my-sshd"]["module"]["module"].get("name") == "sshd"
|
||||
assert instances["my-sshd-2"]["module"]["module"].get("input") == "clan-core"
|
||||
assert instances["my-sshd-2"]["module"]["module"].get("name") == "sshd"
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
|
||||
inputs = {
|
||||
clan.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
|
||||
nixpkgs.follows = "clan/nixpkgs";
|
||||
clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
|
||||
nixpkgs.follows = "clan-core/nixpkgs";
|
||||
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
flake-parts.inputs.nixpkgs-lib.follows = "clan/nixpkgs";
|
||||
flake-parts.inputs.nixpkgs-lib.follows = "clan-core/nixpkgs";
|
||||
};
|
||||
|
||||
outputs =
|
||||
|
||||
Reference in New Issue
Block a user