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)
|
instances: Object.entries(serviceInstancesQuery.data)
|
||||||
.filter(
|
.filter(
|
||||||
([name, i]) =>
|
([name, i]) =>
|
||||||
i.module?.name === m.module.name &&
|
i.module.module.name === m.module.name &&
|
||||||
(!i.module?.input || i.module?.input === m.module.input),
|
(!i.module.module.input ||
|
||||||
|
i.module.module.input === m.module.input),
|
||||||
)
|
)
|
||||||
.map(([name, _]) => name),
|
.map(([name, _]) => name),
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -162,6 +162,10 @@ def list_service_modules(flake: Flake) -> list[Module]:
|
|||||||
"""Show information about a module"""
|
"""Show information about a module"""
|
||||||
modules = flake.select("clanInternals.inventoryClass.modulesPerSource")
|
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] = []
|
res: list[Module] = []
|
||||||
for input_name, module_set in modules.items():
|
for input_name, module_set in modules.items():
|
||||||
for module_name, module_info in module_set.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
|
@API.register
|
||||||
def list_service_instances(
|
def list_service_instances(flake: Flake) -> dict[str, InventoryInstanceInfo]:
|
||||||
flake: Flake,
|
"""Returns all currently present service instances including their full configuration"""
|
||||||
) -> dict[str, InventoryInstance]:
|
|
||||||
"""Show information about a module"""
|
|
||||||
inventory_store = InventoryStore(flake)
|
inventory_store = InventoryStore(flake)
|
||||||
inventory = inventory_store.read()
|
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 = {
|
inputs = {
|
||||||
clan.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
|
clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
|
||||||
nixpkgs.follows = "clan/nixpkgs";
|
nixpkgs.follows = "clan-core/nixpkgs";
|
||||||
|
|
||||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
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 =
|
outputs =
|
||||||
|
|||||||
Reference in New Issue
Block a user