Add typed settings areas to the REST API
/api/v1/settings/router/firewall, .../router/lans/<name>, .../system, down to a single option: GET reads, PUT replaces, PATCH merges, DELETE removes, with the settings' ETag/If-Match and the same limits as the whole-document edit (editSettings is now shared). Values are checked against a JSON Schema made from the option documentation (schema.go reads the types, which nixosOptionsDoc describes in words); a wrong type, a value out of range or an unknown key is refused with its place. The OpenAPI document has the area paths with their schemas; the API reference page lists every area's options. Tests: unit tests for the type reader, the validator and the paths; the real option file and a router's own settings validate (ROUTER_OPTIONS_JSON, LIVE_SETTINGS_JSON); a subtest in apply. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
@@ -296,6 +296,19 @@ pkgs.testers.runNixOSTest {
|
||||
assert client.succeed(f"curl -sk -o /dev/null -w '%{{http_code}}' {ui}/api/v1/status").strip() == "401"
|
||||
spec = json.loads(client.succeed(f"curl -sk {ui}/api/openapi.json"))
|
||||
assert spec["openapi"].startswith("3.") and "/api/v1/logs" in spec["paths"]
|
||||
# Areas of the settings, typed by the real option documentation.
|
||||
area = f"{rest} -H 'Content-Type: application/json'"
|
||||
etag = client.succeed(f"{rest} -D - -o /dev/null {ui}/api/v1/settings/router/lans/main | tr -d '\\r' | sed -n 's/^[Ee][Tt]ag: *//p'").strip()
|
||||
assert etag, "no ETag from an area"
|
||||
assert json.loads(client.succeed(f"{rest} {ui}/api/v1/settings/router/lans/main"))["interface"]
|
||||
code = client.succeed(f"{area} -o /tmp/area.json -w '%{{http_code}}' -X PUT -H 'If-Match: {etag}' -d '{{\"domian\": \"x\"}}' {ui}/api/v1/settings/router/dns").strip()
|
||||
assert code == "400" and "unknown option" in client.succeed("cat /tmp/area.json"), code
|
||||
code = client.succeed(f"{area} -o /tmp/area.json -w '%{{http_code}}' -X PUT -H 'If-Match: {etag}' -d '{{\"domain\": \"area.test\"}}' {ui}/api/v1/settings/router/dns").strip()
|
||||
assert code == "200", (code, client.succeed("cat /tmp/area.json"))
|
||||
assert "area.test" in mcp("get_pending_changes")[0]
|
||||
assert not mcp("discard_changes")[1]
|
||||
spec = json.loads(client.succeed(f"curl -sk {ui}/api/openapi.json"))
|
||||
assert "/api/v1/settings/router/lans/{name}" in spec["paths"]
|
||||
# The log shows what was done, by whom.
|
||||
assert "update_settings" in curl(f"{ui}/tokens") and "assistant" in curl(f"{ui}/tokens")
|
||||
'';
|
||||
|
||||
Reference in New Issue
Block a user