api/machines: split off config validation into separate endpoint
- This speeds up PUT /machines{name}/config as it doesn't do the expensive check anymore
- instead use PUT /machines/{name}/verify which allows a dry-run evaluation of a config which is passed without writing it to disk
This commit is contained in:
@@ -64,16 +64,13 @@ def config_for_machine(machine_name: str) -> dict:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def set_config_for_machine(machine_name: str, config: dict) -> Optional[str]:
|
||||
def set_config_for_machine(machine_name: str, config: dict) -> None:
|
||||
# write the config to a json file located at {flake}/machines/{machine_name}/settings.json
|
||||
if not machine_folder(machine_name).exists():
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail=f"Machine {machine_name} not found. Create the machine first`",
|
||||
)
|
||||
error = verify_machine_config(machine_name, config)
|
||||
if error is not None:
|
||||
return error
|
||||
settings_path = machine_settings_file(machine_name)
|
||||
settings_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(settings_path, "w") as f:
|
||||
@@ -82,7 +79,6 @@ def set_config_for_machine(machine_name: str, config: dict) -> Optional[str]:
|
||||
|
||||
if repo_dir is not None:
|
||||
commit_file(settings_path, repo_dir)
|
||||
return None
|
||||
|
||||
|
||||
def schema_for_machine(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import logging
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Body, HTTPException
|
||||
from fastapi import APIRouter, Body
|
||||
|
||||
from ...config.machine import (
|
||||
config_for_machine,
|
||||
@@ -57,9 +57,7 @@ async def get_machine_config(name: str) -> ConfigResponse:
|
||||
async def set_machine_config(
|
||||
name: str, config: Annotated[dict, Body()]
|
||||
) -> ConfigResponse:
|
||||
error = set_config_for_machine(name, config)
|
||||
if error is not None:
|
||||
raise HTTPException(status_code=400, detail=error)
|
||||
set_config_for_machine(name, config)
|
||||
return ConfigResponse(config=config)
|
||||
|
||||
|
||||
@@ -78,7 +76,17 @@ async def set_machine_schema(
|
||||
|
||||
|
||||
@router.get("/api/machines/{name}/verify")
|
||||
async def put_verify_machine_config(name: str) -> VerifyMachineResponse:
|
||||
async def get_verify_machine_config(name: str) -> VerifyMachineResponse:
|
||||
error = verify_machine_config(name)
|
||||
success = error is None
|
||||
return VerifyMachineResponse(success=success, error=error)
|
||||
|
||||
|
||||
@router.put("/api/machines/{name}/verify")
|
||||
async def put_verify_machine_config(
|
||||
name: str,
|
||||
config: Annotated[dict, Body()],
|
||||
) -> VerifyMachineResponse:
|
||||
error = verify_machine_config(name, config)
|
||||
success = error is None
|
||||
return VerifyMachineResponse(success=success, error=error)
|
||||
|
||||
@@ -45,29 +45,39 @@ def test_configure_machine(api: TestClient, test_flake: Path) -> None:
|
||||
json_response = response.json()
|
||||
assert "schema" in json_response and "properties" in json_response["schema"]
|
||||
|
||||
# set come invalid config (fileSystems missing)
|
||||
config = dict(
|
||||
# an invalid config missing the fileSystems
|
||||
invalid_config = dict(
|
||||
clan=dict(
|
||||
jitsi=dict(
|
||||
enable=True,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
# verify an invalid config (fileSystems missing) fails
|
||||
response = api.put(
|
||||
"/api/machines/machine1/config",
|
||||
json=config,
|
||||
"/api/machines/machine1/verify",
|
||||
json=invalid_config,
|
||||
)
|
||||
assert response.status_code == 400
|
||||
assert response.status_code == 200
|
||||
assert (
|
||||
"The ‘fileSystems’ option does not specify your root"
|
||||
in response.json()["detail"]
|
||||
in response.json()["error"]
|
||||
)
|
||||
|
||||
# ensure config is still empty after the invalid attempt
|
||||
# set come invalid config (fileSystems missing)
|
||||
response = api.put(
|
||||
"/api/machines/machine1/config",
|
||||
json=invalid_config,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
# ensure the config has actually been updated
|
||||
response = api.get("/api/machines/machine1/config")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"config": {}}
|
||||
assert response.json() == {"config": invalid_config}
|
||||
|
||||
# the part of the config that makes the evaluation pass
|
||||
fs_config = dict(
|
||||
fileSystems={
|
||||
"/": dict(
|
||||
|
||||
Reference in New Issue
Block a user