machines: add endpoint machines/{name}/ verify
All checks were successful
checks-impure / test (pull_request) Successful in 58s
checks / test (pull_request) Successful in 8m48s

This commit is contained in:
DavHau 2023-10-24 16:30:58 +01:00
parent a1a9c73660
commit a539fb6dc6
5 changed files with 71 additions and 12 deletions

View File

@ -28,10 +28,7 @@ def map_type(type: str) -> Any:
"16 bit unsigned integer; between 0 and 65535 (both inclusive)",
]:
return int
elif type == "string":
return str
# lib.type.passwdEntry
elif type == "string, not containing newlines or colons":
elif type.startswith("string"):
return str
elif type.startswith("null or "):
subtype = type.removeprefix("null or ")

View File

@ -12,6 +12,32 @@ from clan_cli.machines.folders import machine_folder, machine_settings_file
from clan_cli.nix import nix_eval
def verify_machine_config(
machine_name: str, flake: Optional[Path] = None
) -> tuple[bool, Optional[str]]:
"""
Verify that the machine evaluates successfully
Returns a tuple of (success, error_message)
"""
if flake is None:
flake = get_clan_flake_toplevel()
proc = subprocess.run(
nix_eval(
flags=[
"--impure",
"--show-trace",
f".#nixosConfigurations.{machine_name}.config.system.build.toplevel.outPath",
],
),
capture_output=True,
text=True,
cwd=flake,
)
if proc.returncode != 0:
return False, proc.stderr
return True, None
def config_for_machine(machine_name: str) -> dict:
# read the config from a json file located at {flake}/machines/{machine_name}/settings.json
if not machine_folder(machine_name).exists():

View File

@ -4,6 +4,8 @@ from typing import Annotated
from fastapi import APIRouter, Body
import clan_cli.config as config
from ...config.machine import (
config_for_machine,
schema_for_machine,
@ -19,6 +21,7 @@ from ..schemas import (
MachinesResponse,
SchemaResponse,
Status,
VerifyMachineResponse,
)
log = logging.getLogger(__name__)
@ -63,3 +66,9 @@ async def set_machine_config(
async def get_machine_schema(name: str) -> SchemaResponse:
schema = schema_for_machine(name)
return SchemaResponse(schema=schema)
@router.get("/api/machines/{name}/verify")
async def verify_machine_config(name: str) -> VerifyMachineResponse:
success, error = config.machine.verify_machine_config(name)
return VerifyMachineResponse(success=success, error=error)

View File

@ -38,6 +38,11 @@ class SchemaResponse(BaseModel):
schema_: dict = Field(alias="schema")
class VerifyMachineResponse(BaseModel):
success: bool
error: str | None
class VmStatusResponse(BaseModel):
error: str | None
status: TaskStatus

View File

@ -46,18 +46,40 @@ def test_configure_machine(api: TestClient, test_flake: Path) -> None:
assert "schema" in json_response and "properties" in json_response["schema"]
# set some config
response = api.put(
"/api/machines/machine1/config",
json=dict(
clan=dict(
jitsi=True,
)
config = dict(
clan=dict(
jitsi=dict(
enable=True,
),
),
fileSystems={
"/": dict(
device="/dev/fake_disk",
fsType="ext4",
),
},
# set boot.loader.grub.devices
boot=dict(
loader=dict(
grub=dict(
devices=["/dev/fake_disk"],
),
),
),
)
response = api.put(
"/api/machines/machine1/config",
json=config,
)
assert response.status_code == 200
assert response.json() == {"config": {"clan": {"jitsi": True}}}
assert response.json() == {"config": config}
# verify the machine config
response = api.get("/api/machines/machine1/verify")
assert response.status_code == 200
assert response.json() == {"success": True, "error": None}
# get the config again
response = api.get("/api/machines/machine1/config")
assert response.status_code == 200
assert response.json() == {"config": {"clan": {"jitsi": True}}}
assert response.json() == {"config": config}