feat(ui): display machine install state and install button
This commit is contained in:
@@ -1 +1 @@
|
||||
/nix/store/q012qk78pwldxl3qjy09nwrx9jlamivm-nixpkgs
|
||||
/nix/store/apspgd56g9qy6fca8d44qnhdaiqrdf2c-nixpkgs
|
||||
@@ -1,3 +1,4 @@
|
||||
from enum import StrEnum
|
||||
from typing import TypedDict
|
||||
|
||||
from clan_lib.api import API
|
||||
@@ -25,6 +26,18 @@ class ListOptions(TypedDict):
|
||||
filter: MachineFilter
|
||||
|
||||
|
||||
class MachineStatus(StrEnum):
|
||||
NOT_INSTALLED = "not_installed"
|
||||
OFFLINE = "offline"
|
||||
OUT_OF_SYNC = "out_of_sync"
|
||||
ONLINE = "online"
|
||||
|
||||
|
||||
class MachineState(TypedDict):
|
||||
status: MachineStatus
|
||||
# add more info later when retrieving remote state
|
||||
|
||||
|
||||
@API.register
|
||||
def list_machines(
|
||||
flake: Flake, opts: ListOptions | None = None
|
||||
@@ -154,3 +167,47 @@ def get_machine_fields_schema(machine: Machine) -> dict[str, FieldSchema]:
|
||||
}
|
||||
for field in field_names
|
||||
}
|
||||
|
||||
|
||||
@API.register
|
||||
def list_machine_state(flake: Flake) -> dict[str, MachineState]:
|
||||
"""
|
||||
Retrieve the current state of all machines in the clan.
|
||||
|
||||
Args:
|
||||
flake (Flake): The flake object representing the configuration source.
|
||||
"""
|
||||
inventory_store = InventoryStore(flake=flake)
|
||||
inventory = inventory_store.read()
|
||||
|
||||
# todo integrate with remote state when implementing https://git.clan.lol/clan/clan-core/issues/4748
|
||||
machines = inventory.get("machines", {})
|
||||
|
||||
return {
|
||||
machine_name: MachineState(
|
||||
status=MachineStatus.OFFLINE
|
||||
if get_value_by_path(machine, "installedAt", None)
|
||||
else MachineStatus.NOT_INSTALLED
|
||||
)
|
||||
for machine_name, machine in machines.items()
|
||||
}
|
||||
|
||||
|
||||
@API.register
|
||||
def get_machine_state(machine: Machine) -> MachineState:
|
||||
"""
|
||||
Retrieve the current state of the machine.
|
||||
|
||||
Args:
|
||||
machine (Machine): The machine object for which we want to retrieve the latest state.
|
||||
"""
|
||||
inventory_store = InventoryStore(flake=machine.flake)
|
||||
inventory = inventory_store.read()
|
||||
|
||||
# todo integrate with remote state when implementing https://git.clan.lol/clan/clan-core/issues/4748
|
||||
|
||||
return MachineState(
|
||||
status=MachineStatus.OFFLINE
|
||||
if get_value_by_path(inventory, f"machines.{machine.name}.installedAt", None)
|
||||
else MachineStatus.NOT_INSTALLED
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import time
|
||||
from collections.abc import Callable
|
||||
from typing import cast
|
||||
from unittest.mock import ANY, patch
|
||||
@@ -12,7 +13,16 @@ from clan_lib.nix_models.clan import Clan, InventoryMachine, Unknown
|
||||
from clan_lib.persist.inventory_store import InventoryStore
|
||||
from clan_lib.persist.util import get_value_by_path, set_value_by_path
|
||||
|
||||
from .actions import get_machine, get_machine_fields_schema, list_machines, set_machine
|
||||
from .actions import (
|
||||
MachineState,
|
||||
MachineStatus,
|
||||
get_machine,
|
||||
get_machine_fields_schema,
|
||||
get_machine_state,
|
||||
list_machine_state,
|
||||
list_machines,
|
||||
set_machine,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.with_core
|
||||
@@ -219,7 +229,44 @@ def test_get_machine_writeability(clan_flake: Callable[..., Flake]) -> None:
|
||||
"deploy.buildHost",
|
||||
"description",
|
||||
"icon",
|
||||
"installedAt",
|
||||
}
|
||||
assert read_only_fields == {"machineClass", "name"}
|
||||
|
||||
assert write_info["tags"]["readonly_members"] == ["nix1", "all", "nixos"]
|
||||
|
||||
|
||||
@pytest.mark.with_core
|
||||
def test_machine_state(clan_flake: Callable[..., Flake]) -> None:
|
||||
now = int(time.time())
|
||||
yesterday = now - 86400
|
||||
last_week = now - 604800
|
||||
|
||||
flake = clan_flake(
|
||||
# clan.nix, cannot be changed
|
||||
clan={
|
||||
"inventory": {
|
||||
"machines": {
|
||||
"jon": {},
|
||||
"sara": {"installedAt": yesterday},
|
||||
"bob": {"installedAt": last_week},
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
assert list_machine_state(flake) == {
|
||||
"jon": MachineState(status=MachineStatus.NOT_INSTALLED),
|
||||
"sara": MachineState(status=MachineStatus.OFFLINE),
|
||||
"bob": MachineState(status=MachineStatus.OFFLINE),
|
||||
}
|
||||
|
||||
assert get_machine_state(Machine("jon", flake)) == MachineState(
|
||||
status=MachineStatus.NOT_INSTALLED
|
||||
)
|
||||
assert get_machine_state(Machine("sara", flake)) == MachineState(
|
||||
status=MachineStatus.OFFLINE
|
||||
)
|
||||
assert get_machine_state(Machine("bob", flake)) == MachineState(
|
||||
status=MachineStatus.OFFLINE
|
||||
)
|
||||
|
||||
@@ -72,6 +72,7 @@ class InventoryMachineDeploy(TypedDict):
|
||||
InventoryMachineDeployType = InventoryMachineDeploy
|
||||
InventoryMachineDescriptionType = str | None
|
||||
InventoryMachineIconType = str | None
|
||||
InventoryMachineInstalledatType = int | None
|
||||
InventoryMachineMachineclassType = Literal["nixos", "darwin"]
|
||||
InventoryMachineNameType = str
|
||||
InventoryMachineTagsType = list[str]
|
||||
@@ -80,6 +81,7 @@ class InventoryMachine(TypedDict):
|
||||
deploy: NotRequired[InventoryMachineDeployType]
|
||||
description: NotRequired[InventoryMachineDescriptionType]
|
||||
icon: NotRequired[InventoryMachineIconType]
|
||||
installedAt: NotRequired[InventoryMachineInstalledatType]
|
||||
machineClass: NotRequired[InventoryMachineMachineclassType]
|
||||
name: NotRequired[InventoryMachineNameType]
|
||||
tags: NotRequired[InventoryMachineTagsType]
|
||||
|
||||
Reference in New Issue
Block a user