Merge pull request 'API: init delete instance' (#5641) from instance-delete into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5641
This commit is contained in:
@@ -67,7 +67,7 @@ def set_value_by_path_tuple(d: DictLike, path: PathTuple, content: Any) -> None:
|
|||||||
current[keys[-1]] = content
|
current[keys[-1]] = content
|
||||||
|
|
||||||
|
|
||||||
def delete_by_path_tuple(d: dict[str, Any], path: PathTuple) -> Any:
|
def delete_by_path_tuple(d: DictLike, path: PathTuple) -> Any:
|
||||||
"""Deletes the nested entry specified by a dot-separated path from the dictionary using pop().
|
"""Deletes the nested entry specified by a dot-separated path from the dictionary using pop().
|
||||||
|
|
||||||
:param data: The dictionary to modify.
|
:param data: The dictionary to modify.
|
||||||
@@ -126,6 +126,7 @@ def delete_by_path(d: dict[str, Any], path: str) -> Any:
|
|||||||
V = TypeVar("V")
|
V = TypeVar("V")
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Use PathTuple
|
||||||
def get_value_by_path(
|
def get_value_by_path(
|
||||||
d: DictLike,
|
d: DictLike,
|
||||||
path: str,
|
path: str,
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ from clan_lib.nix_models.clan import (
|
|||||||
InventoryInstancesType,
|
InventoryInstancesType,
|
||||||
)
|
)
|
||||||
from clan_lib.persist.inventory_store import InventoryStore
|
from clan_lib.persist.inventory_store import InventoryStore
|
||||||
from clan_lib.persist.path_utils import get_value_by_path, set_value_by_path
|
from clan_lib.persist.path_utils import (
|
||||||
|
delete_by_path_tuple,
|
||||||
|
get_value_by_path,
|
||||||
|
set_value_by_path,
|
||||||
|
)
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -492,6 +496,37 @@ def list_service_instances(flake: Flake) -> dict[str, InventoryInstanceInfo]:
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
@API.register
|
||||||
|
def delete_service_instance(
|
||||||
|
flake: Flake,
|
||||||
|
instance_ref: str,
|
||||||
|
) -> None:
|
||||||
|
"""Deletes an instance
|
||||||
|
|
||||||
|
:param instance_ref: The name of the instance to update
|
||||||
|
|
||||||
|
:raises ClanError: If the instance_ref is invalid or cannot be deleted
|
||||||
|
"""
|
||||||
|
inventory_store = InventoryStore(flake)
|
||||||
|
inventory = inventory_store.read()
|
||||||
|
|
||||||
|
instance: InventoryInstance | None = get_value_by_path(
|
||||||
|
inventory, f"instances.{instance_ref}", None
|
||||||
|
)
|
||||||
|
|
||||||
|
if instance is None:
|
||||||
|
msg = f"Instance '{instance_ref}' not found"
|
||||||
|
raise ClanError(msg)
|
||||||
|
|
||||||
|
delete_by_path_tuple(inventory, ("instances", f"{instance_ref}"))
|
||||||
|
|
||||||
|
# TODO: improve error message
|
||||||
|
# "Cannot delete path 'instances.static"
|
||||||
|
inventory_store.write(
|
||||||
|
inventory, message=f"Delete service instance '{instance_ref}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@API.register
|
@API.register
|
||||||
def set_service_instance(
|
def set_service_instance(
|
||||||
flake: Flake, instance_ref: str, roles: InventoryInstanceRolesType
|
flake: Flake, instance_ref: str, roles: InventoryInstanceRolesType
|
||||||
@@ -540,6 +575,8 @@ def set_service_instance(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# override settings, machines only if passed
|
# override settings, machines only if passed
|
||||||
|
# TODO: refactor after extraModules removal
|
||||||
|
# in https://git.clan.lol/clan/clan-core/pulls/5634
|
||||||
merged = {
|
merged = {
|
||||||
**static,
|
**static,
|
||||||
**role_cfg,
|
**role_cfg,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from clan_cli.tests.fixtures_flakes import nested_dict
|
|||||||
from clan_lib.errors import ClanError
|
from clan_lib.errors import ClanError
|
||||||
from clan_lib.flake.flake import Flake
|
from clan_lib.flake.flake import Flake
|
||||||
from clan_lib.services.modules import (
|
from clan_lib.services.modules import (
|
||||||
|
delete_service_instance,
|
||||||
get_service_readmes,
|
get_service_readmes,
|
||||||
list_service_instances,
|
list_service_instances,
|
||||||
list_service_modules,
|
list_service_modules,
|
||||||
@@ -251,3 +252,67 @@ def test_update_service_instance(
|
|||||||
assert updated_machines == {
|
assert updated_machines == {
|
||||||
"sara": {"settings": {"greeting": "sara"}},
|
"sara": {"settings": {"greeting": "sara"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.with_core
|
||||||
|
def test_delete_service_instance(
|
||||||
|
clan_flake: Callable[..., Flake],
|
||||||
|
) -> None:
|
||||||
|
# Data that can be mutated via API calls
|
||||||
|
mutable_inventory_json: Inventory = {
|
||||||
|
"instances": {
|
||||||
|
"to-remain": {"module": {"name": "admin"}},
|
||||||
|
"to-delete": {"module": {"name": "admin"}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flake = clan_flake({}, mutable_inventory_json=mutable_inventory_json)
|
||||||
|
|
||||||
|
# Ensure preconditions
|
||||||
|
instances = list_service_instances(flake)
|
||||||
|
assert set(instances.keys()) == {"to-delete", "to-remain"}
|
||||||
|
|
||||||
|
# Raises for non-existing instance
|
||||||
|
with pytest.raises(ClanError) as excinfo:
|
||||||
|
delete_service_instance(flake, "non-existing-instance")
|
||||||
|
assert "Instance 'non-existing-instance' not found" in str(excinfo.value)
|
||||||
|
|
||||||
|
# Deletes instance
|
||||||
|
delete_service_instance(flake, "to-delete")
|
||||||
|
|
||||||
|
updated_instances = list_service_instances(flake)
|
||||||
|
assert set(updated_instances.keys()) == {"to-remain"}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.with_core
|
||||||
|
def test_delete_static_service_instance(
|
||||||
|
clan_flake: Callable[..., Flake],
|
||||||
|
) -> None:
|
||||||
|
# Data that can be mutated via API calls
|
||||||
|
mutable_inventory_json: Inventory = {
|
||||||
|
"instances": {
|
||||||
|
"static": {"module": {"name": "admin"}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flake = clan_flake(
|
||||||
|
{
|
||||||
|
"inventory": {
|
||||||
|
"instances": {
|
||||||
|
"static": {"roles": {"default": {}}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mutable_inventory_json=mutable_inventory_json,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure preconditions
|
||||||
|
instances = list_service_instances(flake)
|
||||||
|
assert set(instances.keys()) == {"static"}
|
||||||
|
|
||||||
|
# Raises for non-existing instance
|
||||||
|
with pytest.raises(ClanError) as excinfo:
|
||||||
|
delete_service_instance(flake, "static")
|
||||||
|
|
||||||
|
# TODO: improve error message
|
||||||
|
assert "Cannot delete path 'instances.static" in str(excinfo.value)
|
||||||
|
|||||||
Reference in New Issue
Block a user