Files
clan-core/pkgs/clan-cli/tests/test_machines_api.py
DavHau 33944cf74e api/machines: verify config by evaluating the .vm output
This fixes the problem where fileSystems were missing, or boot.loader was not set.

SInce we want VMs anyways for now, this strategy aligns well
2023-11-13 20:50:11 +07:00

240 lines
7.6 KiB
Python

import pytest
from api import TestClient
from fixtures_flakes import FlakeForTest
def test_create_and_list(api: TestClient, test_flake: FlakeForTest) -> None:
response = api.get(f"/api/{test_flake.name}/machines")
assert response.status_code == 200
assert response.json() == {"machines": []}
response = api.put(f"/api/{test_flake.name}/machines/test/config", json=dict())
assert response.status_code == 200
response = api.get(f"/api/{test_flake.name}/machines/test")
assert response.status_code == 200
assert response.json() == {"machine": {"name": "test", "status": "unknown"}}
response = api.get(f"/api/{test_flake.name}/machines")
assert response.status_code == 200
assert response.json() == {"machines": [{"name": "test", "status": "unknown"}]}
@pytest.mark.with_core
def test_schema_errors(api: TestClient, test_flake_with_core: FlakeForTest) -> None:
# make sure that eval errors do not raise an internal server error
response = api.put(
f"/api/{test_flake_with_core.name}/schema",
json={"imports": ["some-inavlid-import"]},
)
assert response.status_code == 422
assert (
"error: string 'some-inavlid-import' doesn't represent an absolute path"
in response.json()["detail"][0]["msg"]
)
@pytest.mark.with_core
def test_schema_invalid_clan_imports(
api: TestClient, test_flake_with_core: FlakeForTest
) -> None:
response = api.put(
f"/api/{test_flake_with_core.name}/schema",
json={"clanImports": ["non-existing-clan-module"]},
)
assert response.status_code == 400
assert (
"Some requested clan modules could not be found"
in response.json()["detail"]["msg"]
)
assert "non-existing-clan-module" in response.json()["detail"]["modules_not_found"]
def test_create_machine_invalid_hostname(
api: TestClient, test_flake: FlakeForTest
) -> None:
response = api.put(
f"/api/{test_flake.name}/machines/-invalid-hostname/config", json=dict()
)
assert response.status_code == 422
assert (
"Machine name must be a valid hostname" in response.json()["detail"][0]["msg"]
)
@pytest.mark.with_core
def test_configure_machine(api: TestClient, test_flake_with_core: FlakeForTest) -> None:
# ensure error 404 if machine does not exist when accessing the config
response = api.get(f"/api/{test_flake_with_core.name}/machines/machine1/config")
assert response.status_code == 404
# create the machine
response = api.put(
f"/api/{test_flake_with_core.name}/machines/machine1/config", json={}
)
assert response.status_code == 200
# ensure an empty config is returned by default for a new machine
response = api.get(f"/api/{test_flake_with_core.name}/machines/machine1/config")
assert response.status_code == 200
assert response.json() == {
"clanImports": [],
"clan": {},
}
# get jsonschema for without imports
response = api.put(
f"/api/{test_flake_with_core.name}/schema",
json={"clanImports": []},
)
assert response.status_code == 200
json_response = response.json()
assert "schema" in json_response and "properties" in json_response["schema"]
# an invalid config setting some non-existent option
invalid_config = dict(
clan=dict(),
foo=dict(
bar=True,
),
services=dict(
nginx=dict(
enable=True,
),
),
)
# verify an invalid config (foo option does not exist)
response = api.put(
f"/api/{test_flake_with_core.name}/machines/machine1/verify",
json=invalid_config,
)
assert response.status_code == 200
assert "error: The option `foo' does not exist" in response.json()["error"]
# set come invalid config (foo option does not exist)
response = api.put(
f"/api/{test_flake_with_core.name}/machines/machine1/config",
json=invalid_config,
)
assert response.status_code == 200
# ensure the config has actually been updated
response = api.get(f"/api/{test_flake_with_core.name}/machines/machine1/config")
assert response.status_code == 200
assert response.json() == dict(clanImports=[], **invalid_config)
# set some valid config
config2 = dict(
clan=dict(),
services=dict(
nginx=dict(
enable=True,
),
),
)
response = api.put(
f"/api/{test_flake_with_core.name}/machines/machine1/config",
json=config2,
)
assert response.status_code == 200
# ensure the config has been applied
response = api.get(
f"/api/{test_flake_with_core.name}/machines/machine1/config",
)
assert response.status_code == 200
assert response.json() == dict(clanImports=[], **config2)
# get the config again
response = api.get(f"/api/{test_flake_with_core.name}/machines/machine1/config")
assert response.status_code == 200
assert response.json() == {"clanImports": [], **config2}
# ensure PUT on the config is idempotent by passing the config again
# For example, this should not result in the boot.loader.grub.devices being
# set twice (eg. merged)
response = api.put(
f"/api/{test_flake_with_core.name}/machines/machine1/config",
json=config2,
)
assert response.status_code == 200
# ensure the config has been applied
response = api.get(
f"/api/{test_flake_with_core.name}/machines/machine1/config",
)
assert response.status_code == 200
assert response.json() == dict(clanImports=[], **config2)
# verify the machine config evaluates
response = api.get(f"/api/{test_flake_with_core.name}/machines/machine1/verify")
assert response.status_code == 200
assert response.json() == {"success": True, "error": None}
# get the schema with an extra module imported
response = api.put(
f"/api/{test_flake_with_core.name}/schema",
json={"clanImports": ["diskLayouts"]},
)
# expect the result schema to contain the deltachat option
assert response.status_code == 200
assert (
response.json()["schema"]["properties"]["diskLayouts"]["properties"][
"singleDiskExt4"
]["properties"]["device"]["type"]
== "string"
)
# new config importing an extra clanModule (clanModules.fake-module)
config_with_imports: dict = {
"clanImports": ["fake-module"],
"clan": {
"fake-module": {
"fake-flag": True,
},
},
}
# set the fake-module.fake-flag option to true
response = api.put(
f"/api/{test_flake_with_core.name}/machines/machine1/config",
json=config_with_imports,
)
assert response.status_code == 200
# ensure the config has been applied
response = api.get(
f"/api/{test_flake_with_core.name}/machines/machine1/config",
)
assert response.status_code == 200
assert response.json() == {
"clanImports": ["fake-module"],
"clan": {
"fake-module": {
"fake-flag": True,
},
},
}
# remove the import from the config
response = api.put(
f"/api/{test_flake_with_core.name}/machines/machine1/config",
json=dict(
clanImports=[],
),
)
assert response.status_code == 200
# ensure the config has been applied
response = api.get(
f"/api/{test_flake_with_core.name}/machines/machine1/config",
)
assert response.status_code == 200
assert response.json() == {
"clan": {},
"clanImports": [],
}